Fix gaddr initialization
[sipe-libnice.git] / socket / udp-bsd.c
blob553f0fedb5ce4fa179c704ceec45cc114d0367a1
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 struct UdpBsdSocketPrivate
68 NiceAddress niceaddr;
69 GSocketAddress *gaddr;
72 NiceSocket *
73 nice_udp_bsd_socket_new (NiceAddress *addr)
75 struct sockaddr_storage name;
76 NiceSocket *sock = g_slice_new0 (NiceSocket);
77 GSocket *gsock = NULL;
78 gboolean gret = FALSE;
79 GSocketAddress *gaddr;
80 struct UdpBsdSocketPrivate *priv;
82 if (addr != NULL) {
83 nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name);
84 } else {
85 memset (&name, 0, sizeof (name));
86 name.ss_family = AF_UNSPEC;
89 if (name.ss_family == AF_UNSPEC || name.ss_family == AF_INET) {
90 gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
91 G_SOCKET_PROTOCOL_UDP, NULL);
92 name.ss_family = AF_INET;
93 #ifdef HAVE_SA_LEN
94 name.ss_len = sizeof (struct sockaddr_in);
95 #endif
96 } else if (name.ss_family == AF_INET6) {
97 gsock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_DATAGRAM,
98 G_SOCKET_PROTOCOL_UDP, NULL);
99 name.ss_family = AF_INET6;
100 #ifdef HAVE_SA_LEN
101 name.ss_len = sizeof (struct sockaddr_in6);
102 #endif
105 if (gsock == NULL) {
106 g_slice_free (NiceSocket, sock);
107 return NULL;
110 /* GSocket: All socket file descriptors are set to be close-on-exec. */
111 g_socket_set_blocking (gsock, false);
112 gaddr = g_socket_address_new_from_native (&name, sizeof (name));
113 if (gaddr != NULL) {
114 gret = g_socket_bind (gsock, gaddr, FALSE, NULL);
115 g_object_unref (gaddr);
118 if (gret == FALSE) {
119 g_slice_free (NiceSocket, sock);
120 g_socket_close (gsock, NULL);
121 g_object_unref (gsock);
122 return NULL;
125 gaddr = g_socket_get_local_address (gsock, NULL);
126 if (gaddr == NULL ||
127 !g_socket_address_to_native (gaddr, &name, sizeof(name), NULL)) {
128 g_slice_free (NiceSocket, sock);
129 g_socket_close (gsock, NULL);
130 g_object_unref (gsock);
131 return NULL;
134 g_object_unref (gaddr);
136 nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name);
138 priv = sock->priv = g_slice_new0 (struct UdpBsdSocketPrivate);
139 nice_address_init (&priv->niceaddr);
141 sock->fileno = gsock;
142 sock->send = socket_send;
143 sock->recv = socket_recv;
144 sock->is_reliable = socket_is_reliable;
145 sock->close = socket_close;
147 return sock;
150 static void
151 socket_close (NiceSocket *sock)
153 struct UdpBsdSocketPrivate *priv = sock->priv;
155 if (priv->gaddr)
156 g_object_unref (priv->gaddr);
157 g_slice_free (struct UdpBsdSocketPrivate, sock->priv);
159 if (sock->fileno) {
160 g_socket_close (sock->fileno, NULL);
161 g_object_unref (sock->fileno);
162 sock->fileno = NULL;
166 static gint
167 socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
169 GSocketAddress *gaddr = NULL;
170 GError *gerr = NULL;
171 gint recvd;
173 recvd = g_socket_receive_from (sock->fileno, &gaddr, buf, len, NULL, &gerr);
175 if (recvd < 0) {
176 if (g_error_matches(gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)
177 || g_error_matches(gerr, G_IO_ERROR, G_IO_ERROR_FAILED))
178 recvd = 0;
180 g_error_free (gerr);
183 if (recvd > 0 && from != NULL && gaddr != NULL) {
184 struct sockaddr_storage sa;
186 g_socket_address_to_native (gaddr, &sa, sizeof (sa), NULL);
187 nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa);
190 if (gaddr != NULL)
191 g_object_unref (gaddr);
193 return recvd;
196 static gboolean
197 socket_send (NiceSocket *sock, const NiceAddress *to,
198 guint len, const gchar *buf)
200 struct UdpBsdSocketPrivate *priv = sock->priv;
201 ssize_t sent;
203 if (!nice_address_is_valid (&priv->niceaddr) ||
204 !nice_address_equal (&priv->niceaddr, to)) {
205 struct sockaddr_storage sa;
206 GSocketAddress *gaddr;
208 if (priv->gaddr)
209 g_object_unref (priv->gaddr);
210 nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa);
211 gaddr = g_socket_address_new_from_native (&sa, sizeof(sa));
212 if (gaddr == NULL)
213 return -1;
214 priv->gaddr = gaddr;
215 priv->niceaddr = *to;
218 sent = g_socket_send_to (sock->fileno, priv->gaddr, buf, len, NULL, NULL);
220 return sent == (ssize_t)len;
223 static gboolean
224 socket_is_reliable (NiceSocket *sock)
226 return FALSE;