Add support for droping packets when using TCP and the bandwidth is too slow for...
[sipe-libnice.git] / socket / udp-bsd.c
blobdb302ebb2d8f52f2c825ac9838be46764dd0db73
1 /*
2 * This file is part of the Nice GLib ICE library.
4 * (C) 2006, 2007 Collabora Ltd.
5 * Contact: Dafydd Harries
6 * (C) 2006, 2007 Nokia Corporation. All rights reserved.
7 * Contact: Kai Vehmanen
9 * The contents of this file are subject to the Mozilla Public License Version
10 * 1.1 (the "License"); you may not use this file except in compliance with
11 * the License. You may obtain a copy of the License at
12 * http://www.mozilla.org/MPL/
14 * Software distributed under the License is distributed on an "AS IS" basis,
15 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16 * for the specific language governing rights and limitations under the
17 * License.
19 * The Original Code is the Nice GLib ICE library.
21 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
22 * Corporation. All Rights Reserved.
24 * Contributors:
25 * Dafydd Harries, Collabora Ltd.
26 * RĂ©mi Denis-Courmont, Nokia
27 * Kai Vehmanen
29 * Alternatively, the contents of this file may be used under the terms of the
30 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
31 * case the provisions of LGPL are applicable instead of those above. If you
32 * wish to allow use of your version of this file only under the terms of the
33 * LGPL and not to allow others to use your version of this file under the
34 * MPL, indicate your decision by deleting the provisions above and replace
35 * them with the notice and other provisions required by the LGPL. If you do
36 * not delete the provisions above, a recipient may use your version of this
37 * file under either the MPL or the LGPL.
41 * Implementation of UDP socket interface using Berkeley sockets. (See
42 * http://en.wikipedia.org/wiki/Berkeley_sockets.)
44 #ifdef HAVE_CONFIG_H
45 # include "config.h"
46 #endif
49 #include <string.h>
50 #include <errno.h>
51 #include <fcntl.h>
53 #include "udp-bsd.h"
55 #ifdef G_OS_WIN32
56 typedef unsigned long ssize_t;
57 #else
58 #include <unistd.h>
59 #endif
62 static void socket_close (NiceSocket *sock);
63 static gint socket_recv (NiceSocket *sock, NiceAddress *from,
64 guint len, gchar *buf);
65 static gboolean socket_send (NiceSocket *sock, const NiceAddress *to,
66 guint len, const gchar *buf);
67 static gboolean socket_is_reliable (NiceSocket *sock);
69 NiceSocket *
70 nice_udp_bsd_socket_new (NiceAddress *addr)
72 int sockfd = -1;
73 struct sockaddr_storage name;
74 socklen_t name_len = sizeof (name);
75 NiceSocket *sock = g_slice_new0 (NiceSocket);
77 if (!sock) {
78 return NULL;
81 if (addr != NULL) {
82 nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name);
83 } else {
84 memset (&name, 0, sizeof (name));
85 name.ss_family = AF_UNSPEC;
88 if (name.ss_family == AF_UNSPEC || name.ss_family == AF_INET) {
89 sockfd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
90 name.ss_family = AF_INET;
91 #ifdef HAVE_SA_LEN
92 name.ss_len = sizeof (struct sockaddr_in);
93 #endif
96 if (sockfd == -1) {
97 g_slice_free (NiceSocket, sock);
98 return NULL;
101 #ifdef FD_CLOEXEC
102 fcntl (sockfd, F_SETFD, fcntl (sockfd, F_GETFD) | FD_CLOEXEC);
103 #endif
104 #ifdef O_NONBLOCK
105 fcntl (sockfd, F_SETFL, fcntl (sockfd, F_GETFL) | O_NONBLOCK);
106 #endif
108 if(bind (sockfd, (struct sockaddr *) &name,
109 name.ss_family == AF_INET? sizeof (struct sockaddr_in) :
110 sizeof(struct sockaddr_in6)) < 0) {
111 g_slice_free (NiceSocket, sock);
112 #ifdef G_OS_WIN32
113 closesocket(sockfd);
114 #else
115 close (sockfd);
116 #endif
117 return NULL;
120 name_len = name.ss_family == AF_INET? sizeof (struct sockaddr_in) :
121 sizeof(struct sockaddr_in6);
122 if (getsockname (sockfd, (struct sockaddr *) &name, &name_len) < 0) {
123 g_slice_free (NiceSocket, sock);
124 #ifdef G_OS_WIN32
125 closesocket(sockfd);
126 #else
127 close (sockfd);
128 #endif
129 return NULL;
132 nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name);
133 sock->fileno = sockfd;
135 sock->send = socket_send;
136 sock->recv = socket_recv;
137 sock->is_reliable = socket_is_reliable;
138 sock->close = socket_close;
140 return sock;
143 static void
144 socket_close (NiceSocket *sock)
146 #ifdef G_OS_WIN32
147 closesocket(sock->fileno);
148 #else
149 close (sock->fileno);
150 #endif
153 static gint
154 socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
156 gint recvd;
157 struct sockaddr_storage sa;
158 socklen_t from_len = sizeof (sa);
160 recvd = recvfrom (sock->fileno, buf, len, 0, (struct sockaddr *) &sa,
161 &from_len);
163 if (recvd > 0)
164 nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa);
166 return recvd;
169 static gboolean
170 socket_send (NiceSocket *sock, const NiceAddress *to,
171 guint len, const gchar *buf)
173 struct sockaddr_storage sa;
174 ssize_t sent;
176 nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa);
178 sent = sendto (sock->fileno, buf, len, 0, (struct sockaddr *) &sa,
179 sa.ss_family == AF_INET? sizeof (struct sockaddr_in) :
180 sizeof(struct sockaddr_in6));
182 return sent == (ssize_t)len;
185 static gboolean
186 socket_is_reliable (NiceSocket *sock)
188 return FALSE;