Merge branch 'master' into rfc5766
[sipe-libnice.git] / socket / udp-bsd.c
blob095b2d851ef130cecccc963b6c749bc12f87cc78
1 /*
2 * This file is part of the Nice GLib ICE library.
4 * (C) 2006-2009 Collabora Ltd.
5 * Contact: Youness Alaoui
6 * (C) 2006-2009 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 * Youness Alaoui, Collabora Ltd.
28 * Alternatively, the contents of this file may be used under the terms of the
29 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
30 * case the provisions of LGPL are applicable instead of those above. If you
31 * wish to allow use of your version of this file only under the terms of the
32 * LGPL and not to allow others to use your version of this file under the
33 * MPL, indicate your decision by deleting the provisions above and replace
34 * them with the notice and other provisions required by the LGPL. If you do
35 * not delete the provisions above, a recipient may use your version of this
36 * file under either the MPL or the LGPL.
40 * Implementation of UDP socket interface using Berkeley sockets. (See
41 * http://en.wikipedia.org/wiki/Berkeley_sockets.)
43 #ifdef HAVE_CONFIG_H
44 # include "config.h"
45 #endif
48 #include <string.h>
49 #include <errno.h>
50 #include <fcntl.h>
52 #include "udp-bsd.h"
54 #ifdef G_OS_WIN32
55 typedef unsigned long ssize_t;
56 #else
57 #include <unistd.h>
58 #endif
61 static void socket_close (NiceSocket *sock);
62 static gint socket_recv (NiceSocket *sock, NiceAddress *from,
63 guint len, gchar *buf);
64 static gboolean socket_send (NiceSocket *sock, const NiceAddress *to,
65 guint len, const gchar *buf);
66 static gboolean socket_is_reliable (NiceSocket *sock);
68 NiceSocket *
69 nice_udp_bsd_socket_new (NiceAddress *addr)
71 int sockfd = -1;
72 struct sockaddr_storage name;
73 socklen_t name_len = sizeof (name);
74 NiceSocket *sock = g_slice_new0 (NiceSocket);
76 if (addr != NULL) {
77 nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name);
78 } else {
79 memset (&name, 0, sizeof (name));
80 name.ss_family = AF_UNSPEC;
83 if (name.ss_family == AF_UNSPEC || name.ss_family == AF_INET) {
84 sockfd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
85 name.ss_family = AF_INET;
86 #ifdef HAVE_SA_LEN
87 name.ss_len = sizeof (struct sockaddr_in);
88 #endif
89 } else if (name.ss_family == AF_INET6) {
90 sockfd = socket (PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
91 name.ss_family = AF_INET6;
92 #ifdef HAVE_SA_LEN
93 name.ss_len = sizeof (struct sockaddr_in6);
94 #endif
97 if (sockfd == -1) {
98 g_slice_free (NiceSocket, sock);
99 return NULL;
102 #ifdef FD_CLOEXEC
103 fcntl (sockfd, F_SETFD, fcntl (sockfd, F_GETFD) | FD_CLOEXEC);
104 #endif
105 #ifdef O_NONBLOCK
106 fcntl (sockfd, F_SETFL, fcntl (sockfd, F_GETFL) | O_NONBLOCK);
107 #endif
109 if(bind (sockfd, (struct sockaddr *) &name,
110 name.ss_family == AF_INET? sizeof (struct sockaddr_in) :
111 sizeof(struct sockaddr_in6)) < 0) {
112 g_slice_free (NiceSocket, sock);
113 #ifdef G_OS_WIN32
114 closesocket(sockfd);
115 #else
116 close (sockfd);
117 #endif
118 return NULL;
121 name_len = name.ss_family == AF_INET? sizeof (struct sockaddr_in) :
122 sizeof(struct sockaddr_in6);
123 if (getsockname (sockfd, (struct sockaddr *) &name, &name_len) < 0) {
124 g_slice_free (NiceSocket, sock);
125 #ifdef G_OS_WIN32
126 closesocket(sockfd);
127 #else
128 close (sockfd);
129 #endif
130 return NULL;
133 nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name);
134 sock->fileno = sockfd;
136 sock->send = socket_send;
137 sock->recv = socket_recv;
138 sock->is_reliable = socket_is_reliable;
139 sock->close = socket_close;
141 return sock;
144 static void
145 socket_close (NiceSocket *sock)
147 #ifdef G_OS_WIN32
148 closesocket(sock->fileno);
149 #else
150 close (sock->fileno);
151 #endif
154 static gint
155 socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
157 gint recvd;
158 struct sockaddr_storage sa;
159 socklen_t from_len = sizeof (sa);
161 recvd = recvfrom (sock->fileno, buf, len, 0, (struct sockaddr *) &sa,
162 &from_len);
164 if (recvd < 0) {
165 #ifdef G_OS_WIN32
166 if (WSAGetLastError () == WSAEWOULDBLOCK)
167 #else
168 if (errno == EAGAIN || errno == EWOULDBLOCK)
169 #endif
170 return 0;
173 if (recvd > 0)
174 nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa);
176 return recvd;
179 static gboolean
180 socket_send (NiceSocket *sock, const NiceAddress *to,
181 guint len, const gchar *buf)
183 struct sockaddr_storage sa;
184 ssize_t sent;
186 nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa);
188 sent = sendto (sock->fileno, buf, len, 0, (struct sockaddr *) &sa,
189 sa.ss_family == AF_INET? sizeof (struct sockaddr_in) :
190 sizeof(struct sockaddr_in6));
192 return sent == (ssize_t)len;
195 static gboolean
196 socket_is_reliable (NiceSocket *sock)
198 return FALSE;