2 * This file is part of the Nice GLib ICE library.
4 * (C) 2008 Collabora Ltd.
5 * (C) 2008 Nokia Corporation
6 * Contact: Youness Alaoui
8 * The contents of this file are subject to the Mozilla Public License Version
9 * 1.1 (the "License"); you may not use this file except in compliance with
10 * the License. You may obtain a copy of the License at
11 * http://www.mozilla.org/MPL/
13 * Software distributed under the License is distributed on an "AS IS" basis,
14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
15 * for the specific language governing rights and limitations under the
18 * The Original Code is the Nice GLib ICE library.
20 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
21 * Corporation. All Rights Reserved.
24 * Dafydd Harries, Collabora Ltd.
25 * Youness Alaoui, Collabora Ltd.
26 * RĂ©mi Denis-Courmont, Nokia
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.)
48 #include <arpa/inet.h>
57 #include <stun/stunagent.h>
62 NiceUDPSocket
*udp_socket
;
63 NiceAddress server_addr
;
72 nice_udp_turn_socket_parse_recv (
77 NiceAddress
*recv_from
,
82 turn_priv
*priv
= (turn_priv
*) sock
->priv
;
83 StunValidationStatus valid
;
85 struct sockaddr_storage sa
;
86 guint from_len
= sizeof (sa
);
88 if (nice_address_equal (&priv
->server_addr
, recv_from
)) {
89 valid
= stun_agent_validate (&priv
->agent
, &msg
,
90 (uint8_t *) recv_buf
, (size_t) recv_len
, NULL
, NULL
);
92 if (valid
== STUN_VALIDATION_SUCCESS
) {
94 if (stun_message_find32 (&msg
, STUN_ATTRIBUTE_MAGIC_COOKIE
, &cookie
) != 0)
96 if (cookie
!= TURN_MAGIC_COOKIE
)
99 if (stun_message_get_class (&msg
) == STUN_RESPONSE
&&
100 stun_message_get_method (&msg
) == STUN_SEND
) {
102 } else if (stun_message_get_class (&msg
) == STUN_INDICATION
&&
103 stun_message_get_method (&msg
) == STUN_IND_DATA
) {
106 if (stun_message_find_addr (&msg
, STUN_ATTRIBUTE_REMOTE_ADDRESS
,
107 (struct sockaddr
*)&sa
, &from_len
) != 0)
110 data
= (uint8_t *) stun_message_find (&msg
, STUN_ATTRIBUTE_DATA
, &data_len
);
114 nice_address_set_from_sockaddr (from
, (struct sockaddr
*)&sa
);
116 memmove (buf
, data
, len
> data_len
? data_len
: len
);
117 return len
> data_len
? data_len
: len
;
126 memmove (buf
, recv_buf
, len
> recv_len
? recv_len
: len
);
127 return len
> recv_len
? recv_len
: len
;
137 turn_priv
*priv
= (turn_priv
*) sock
->priv
;
138 uint8_t recv_buf
[STUN_MAX_MESSAGE_SIZE
];
140 NiceAddress recv_from
;
142 recv_len
= nice_udp_socket_recv (priv
->udp_socket
, &recv_from
,
143 sizeof(recv_buf
), (gchar
*) recv_buf
);
145 return nice_udp_turn_socket_parse_recv (sock
, from
, len
, buf
, &recv_from
,
146 (gchar
*) recv_buf
, (guint
) recv_len
);
152 const NiceAddress
*to
,
156 turn_priv
*priv
= (turn_priv
*) sock
->priv
;
158 uint8_t buffer
[STUN_MAX_MESSAGE_SIZE
];
160 struct sockaddr_storage sa
;
162 nice_address_copy_to_sockaddr (to
, (struct sockaddr
*)&sa
);
164 if (!stun_agent_init_request (&priv
->agent
, &msg
, buffer
, sizeof(buffer
), STUN_SEND
))
167 if (stun_message_append32 (&msg
, STUN_ATTRIBUTE_MAGIC_COOKIE
,
168 TURN_MAGIC_COOKIE
) != 0)
171 if (priv
->username
!= NULL
&& priv
->username_len
> 0) {
172 if (stun_message_append_bytes (&msg
, STUN_ATTRIBUTE_USERNAME
,
173 priv
->username
, priv
->username_len
) != 0)
177 if (stun_message_append_addr (&msg
, STUN_ATTRIBUTE_DESTINATION_ADDRESS
,
178 (struct sockaddr
*)&sa
, sizeof(sa
)) != 0)
181 if (stun_message_append_bytes (&msg
, STUN_ATTRIBUTE_DATA
, buf
, len
) != 0)
184 stun_len
= stun_agent_finish_message (&priv
->agent
, &msg
,
185 priv
->password
, priv
->password_len
);
188 nice_udp_socket_send (priv
->udp_socket
, &priv
->server_addr
, stun_len
, (gchar
*)buffer
);
192 nice_udp_socket_send (priv
->udp_socket
, to
, len
, buf
);
198 socket_close (NiceUDPSocket
*sock
)
200 turn_priv
*priv
= (turn_priv
*) sock
->priv
;
204 /*** NiceUDPSocketFactory ***/
207 socket_factory_init_socket (
208 NiceUDPSocketFactory
*man
,
215 NICEAPI_EXPORT gboolean
216 nice_udp_turn_create_socket_full (
217 NiceUDPSocketFactory
*man
,
220 NiceUDPSocket
*udp_socket
,
221 NiceAddress
*server_addr
,
224 NiceUdpTurnSocketCompatibility compatibility
)
226 turn_priv
*priv
= g_new0 (turn_priv
, 1);
228 stun_agent_init (&priv
->agent
, STUN_ALL_KNOWN_ATTRIBUTES
,
229 STUN_COMPATIBILITY_RFC3489
,
230 STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS
|
231 STUN_AGENT_USAGE_IGNORE_CREDENTIALS
);
233 priv
->locked
= FALSE
;
234 priv
->udp_socket
= udp_socket
;
235 priv
->username
= (uint8_t *)username
;
236 priv
->username_len
= (size_t) strlen (username
);
237 priv
->password
= (uint8_t *)password
;
238 priv
->password_len
= (size_t) strlen (password
);
239 priv
->server_addr
= *server_addr
;
241 sock
->fileno
= udp_socket
->fileno
;
242 sock
->send
= socket_send
;
243 sock
->recv
= socket_recv
;
244 sock
->close
= socket_close
;
245 sock
->priv
= (void *) priv
;
250 socket_factory_close (
252 NiceUDPSocketFactory
*man
)
257 nice_udp_turn_socket_factory_init (
259 NiceUDPSocketFactory
*man
)
262 man
->init
= socket_factory_init_socket
;
263 man
->close
= socket_factory_close
;