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
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.
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.)
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
69 GSocketAddress
*gaddr
;
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
;
83 nice_address_copy_to_sockaddr(addr
, (struct sockaddr
*)&name
);
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
;
94 name
.ss_len
= sizeof (struct sockaddr_in
);
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
;
101 name
.ss_len
= sizeof (struct sockaddr_in6
);
106 g_slice_free (NiceSocket
, sock
);
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
));
114 gret
= g_socket_bind (gsock
, gaddr
, FALSE
, NULL
);
115 g_object_unref (gaddr
);
119 g_slice_free (NiceSocket
, sock
);
120 g_socket_close (gsock
, NULL
);
121 g_object_unref (gsock
);
125 gaddr
= g_socket_get_local_address (gsock
, 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
);
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
;
151 socket_close (NiceSocket
*sock
)
153 struct UdpBsdSocketPrivate
*priv
= sock
->priv
;
156 g_object_unref (priv
->gaddr
);
157 g_slice_free (struct UdpBsdSocketPrivate
, sock
->priv
);
160 g_socket_close (sock
->fileno
, NULL
);
161 g_object_unref (sock
->fileno
);
167 socket_recv (NiceSocket
*sock
, NiceAddress
*from
, guint len
, gchar
*buf
)
169 GSocketAddress
*gaddr
= NULL
;
173 recvd
= g_socket_receive_from (sock
->fileno
, &gaddr
, buf
, len
, NULL
, &gerr
);
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
))
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
);
191 g_object_unref (gaddr
);
197 socket_send (NiceSocket
*sock
, const NiceAddress
*to
,
198 guint len
, const gchar
*buf
)
200 struct UdpBsdSocketPrivate
*priv
= sock
->priv
;
203 if (!nice_address_is_valid (&priv
->niceaddr
) ||
204 !nice_address_equal (&priv
->niceaddr
, to
)) {
205 struct sockaddr_storage sa
;
206 GSocketAddress
*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
));
215 priv
->niceaddr
= *to
;
218 sent
= g_socket_send_to (sock
->fileno
, priv
->gaddr
, buf
, len
, NULL
, NULL
);
220 return sent
== (ssize_t
)len
;
224 socket_is_reliable (NiceSocket
*sock
)