set nonblocking mode for socket on Windows
[sipe-libnice.git] / socket / udp-bsd.c
blob6eb14ad1daa014481b75d59f002839dcaeb16be8
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 #ifndef G_OS_WIN32
55 #include <unistd.h>
56 #endif
59 static void socket_close (NiceSocket *sock);
60 static gint socket_recv (NiceSocket *sock, NiceAddress *from,
61 guint len, gchar *buf);
62 static gboolean socket_send (NiceSocket *sock, const NiceAddress *to,
63 guint len, const gchar *buf);
64 static gboolean socket_is_reliable (NiceSocket *sock);
66 NiceSocket *
67 nice_udp_bsd_socket_new (NiceAddress *addr)
69 int sockfd = -1;
70 struct sockaddr_storage name;
71 socklen_t name_len = sizeof (name);
72 NiceSocket *sock = g_slice_new0 (NiceSocket);
73 #ifdef G_OS_WIN32
74 unsigned long set_nonblock=1;
75 #endif
77 if (addr != NULL) {
78 nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name);
79 } else {
80 memset (&name, 0, sizeof (name));
81 name.ss_family = AF_UNSPEC;
84 if (name.ss_family == AF_UNSPEC || name.ss_family == AF_INET) {
85 sockfd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
86 name.ss_family = AF_INET;
87 #ifdef HAVE_SA_LEN
88 name.ss_len = sizeof (struct sockaddr_in);
89 #endif
90 } else if (name.ss_family == AF_INET6) {
91 sockfd = socket (PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
92 name.ss_family = AF_INET6;
93 #ifdef HAVE_SA_LEN
94 name.ss_len = sizeof (struct sockaddr_in6);
95 #endif
98 if (sockfd == -1) {
99 g_slice_free (NiceSocket, sock);
100 return NULL;
103 #ifdef FD_CLOEXEC
104 fcntl (sockfd, F_SETFD, fcntl (sockfd, F_GETFD) | FD_CLOEXEC);
105 #endif
106 #ifdef O_NONBLOCK
107 fcntl (sockfd, F_SETFL, fcntl (sockfd, F_GETFL) | O_NONBLOCK);
108 #elif defined G_OS_WIN32
109 ioctlsocket(sockfd, FIONBIO, &set_nonblock);
110 #endif
112 if(bind (sockfd, (struct sockaddr *) &name,
113 name.ss_family == AF_INET? sizeof (struct sockaddr_in) :
114 sizeof(struct sockaddr_in6)) < 0) {
115 g_slice_free (NiceSocket, sock);
116 #ifdef G_OS_WIN32
117 closesocket(sockfd);
118 #else
119 close (sockfd);
120 #endif
121 return NULL;
124 name_len = name.ss_family == AF_INET? sizeof (struct sockaddr_in) :
125 sizeof(struct sockaddr_in6);
126 if (getsockname (sockfd, (struct sockaddr *) &name, &name_len) < 0) {
127 g_slice_free (NiceSocket, sock);
128 #ifdef G_OS_WIN32
129 closesocket(sockfd);
130 #else
131 close (sockfd);
132 #endif
133 return NULL;
136 nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name);
137 sock->fileno = sockfd;
139 sock->send = socket_send;
140 sock->recv = socket_recv;
141 sock->is_reliable = socket_is_reliable;
142 sock->close = socket_close;
144 return sock;
147 static void
148 socket_close (NiceSocket *sock)
150 #ifdef G_OS_WIN32
151 closesocket(sock->fileno);
152 #else
153 close (sock->fileno);
154 #endif
157 static gint
158 socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
160 gint recvd;
161 struct sockaddr_storage sa;
162 socklen_t from_len = sizeof (sa);
164 recvd = recvfrom (sock->fileno, buf, len, 0, (struct sockaddr *) &sa,
165 &from_len);
167 if (recvd < 0) {
168 #ifdef G_OS_WIN32
169 if (WSAGetLastError () == WSAEWOULDBLOCK ||
170 WSAGetLastError () == WSAECONNRESET)
171 #else
172 if (errno == EAGAIN || errno == EWOULDBLOCK)
173 #endif
174 return 0;
177 if (recvd > 0)
178 nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa);
180 return recvd;
183 static gboolean
184 socket_send (NiceSocket *sock, const NiceAddress *to,
185 guint len, const gchar *buf)
187 struct sockaddr_storage sa;
188 ssize_t sent;
190 nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa);
192 sent = sendto (sock->fileno, buf, len, 0, (struct sockaddr *) &sa,
193 sa.ss_family == AF_INET? sizeof (struct sockaddr_in) :
194 sizeof(struct sockaddr_in6));
196 return sent == (ssize_t)len;
199 static gboolean
200 socket_is_reliable (NiceSocket *sock)
202 return FALSE;