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 TURN
52 #include "stun/stunagent.h"
53 #include "stun/usages/timer.h"
54 #include "agent-priv.h"
56 #define STUN_END_TIMEOUT 8000
61 uint8_t buffer
[STUN_MAX_MESSAGE_SIZE
];
74 GList
*pending_bindings
;
75 ChannelBinding
*current_binding
;
76 TURNMessage
*current_binding_msg
;
78 NiceSocket
*base_socket
;
79 NiceAddress server_addr
;
84 NiceTurnSocketCompatibility compatibility
;
85 GQueue
*send_requests
;
95 static void socket_close (NiceSocket
*sock
);
96 static gint
socket_recv (NiceSocket
*sock
, NiceAddress
*from
,
97 guint len
, gchar
*buf
);
98 static gboolean
socket_send (NiceSocket
*sock
, const NiceAddress
*to
,
99 guint len
, const gchar
*buf
);
100 static gboolean
socket_is_reliable (NiceSocket
*sock
);
102 static void priv_process_pending_bindings (TurnPriv
*priv
);
103 static gboolean
priv_retransmissions_tick_unlocked (TurnPriv
*priv
);
104 static gboolean
priv_retransmissions_tick (gpointer pointer
);
105 static void priv_schedule_tick (TurnPriv
*priv
);
106 static void priv_send_turn_message (TurnPriv
*priv
, TURNMessage
*msg
);
107 static gboolean
priv_send_channel_bind (TurnPriv
*priv
, StunMessage
*resp
,
108 uint16_t channel
, NiceAddress
*peer
);
109 static gboolean
priv_add_channel_binding (TurnPriv
*priv
, NiceAddress
*peer
);
110 static gboolean
priv_forget_send_request (gpointer pointer
);
114 nice_turn_socket_new (NiceAgent
*agent
, NiceAddress
*addr
,
115 NiceSocket
*base_socket
, NiceAddress
*server_addr
,
116 gchar
*username
, gchar
*password
, NiceTurnSocketCompatibility compatibility
)
118 TurnPriv
*priv
= g_new0 (TurnPriv
, 1);
119 NiceSocket
*sock
= g_slice_new0 (NiceSocket
);
125 if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
126 stun_agent_init (&priv
->agent
, STUN_ALL_KNOWN_ATTRIBUTES
,
127 STUN_COMPATIBILITY_RFC5389
,
128 STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS
);
129 } else if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_MSN
) {
130 stun_agent_init (&priv
->agent
, STUN_ALL_KNOWN_ATTRIBUTES
,
131 STUN_COMPATIBILITY_RFC3489
,
132 STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS
|
133 STUN_AGENT_USAGE_NO_INDICATION_AUTH
);
134 } else if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
) {
135 stun_agent_init (&priv
->agent
, STUN_ALL_KNOWN_ATTRIBUTES
,
136 STUN_COMPATIBILITY_RFC3489
,
137 STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS
|
138 STUN_AGENT_USAGE_IGNORE_CREDENTIALS
);
142 priv
->channels
= NULL
;
143 priv
->current_binding
= NULL
;
144 priv
->base_socket
= base_socket
;
146 if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_MSN
) {
147 priv
->username
= g_base64_decode (username
, &priv
->username_len
);
148 priv
->password
= g_base64_decode (password
, &priv
->password_len
);
150 priv
->username
= (uint8_t *)g_strdup (username
);
151 priv
->username_len
= (size_t) strlen (username
);
152 if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
) {
153 priv
->password
= NULL
;
154 priv
->password_len
= 0;
156 priv
->password
= (uint8_t *)g_strdup (password
);
157 priv
->password_len
= (size_t) strlen (password
);
160 priv
->server_addr
= *server_addr
;
161 priv
->compatibility
= compatibility
;
162 priv
->send_requests
= g_queue_new ();
164 sock
->fileno
= base_socket
->fileno
;
165 sock
->send
= socket_send
;
166 sock
->recv
= socket_recv
;
167 sock
->is_reliable
= socket_is_reliable
;
168 sock
->close
= socket_close
;
169 sock
->priv
= (void *) priv
;
175 socket_close (NiceSocket
*sock
)
177 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
180 for (i
= priv
->channels
; i
; i
= i
->next
) {
181 ChannelBinding
*b
= i
->data
;
184 g_list_free (priv
->channels
);
186 for (i
= priv
->pending_bindings
; i
; i
= i
->next
) {
187 ChannelBinding
*b
= i
->data
;
190 g_list_free (priv
->pending_bindings
);
192 if (priv
->tick_source
!= NULL
) {
193 g_source_destroy (priv
->tick_source
);
194 g_source_unref (priv
->tick_source
);
195 priv
->tick_source
= NULL
;
198 for (i
= g_queue_peek_head_link (priv
->send_requests
); i
; i
= i
->next
) {
199 SendRequest
*r
= i
->data
;
200 g_source_destroy (r
->source
);
201 g_source_unref (r
->source
);
204 stun_agent_forget_transaction (&priv
->agent
, r
->id
);
206 g_slice_free (SendRequest
, r
);
209 g_queue_free (priv
->send_requests
);
212 g_free (priv
->current_binding
);
213 g_free (priv
->current_binding_msg
);
214 g_free (priv
->username
);
215 g_free (priv
->password
);
220 socket_recv (NiceSocket
*sock
, NiceAddress
*from
, guint len
, gchar
*buf
)
222 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
223 uint8_t recv_buf
[STUN_MAX_MESSAGE_SIZE
];
225 NiceAddress recv_from
;
228 recv_len
= nice_socket_recv (priv
->base_socket
, &recv_from
,
229 sizeof(recv_buf
), (gchar
*) recv_buf
);
232 return nice_turn_socket_parse_recv (sock
, &dummy
, from
, len
, buf
,
233 &recv_from
, (gchar
*) recv_buf
, (guint
) recv_len
);
239 socket_send (NiceSocket
*sock
, const NiceAddress
*to
,
240 guint len
, const gchar
*buf
)
242 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
244 uint8_t buffer
[STUN_MAX_MESSAGE_SIZE
];
246 struct sockaddr_storage sa
;
247 GList
*i
= priv
->channels
;
248 ChannelBinding
*binding
= NULL
;
250 for (; i
; i
= i
->next
) {
251 ChannelBinding
*b
= i
->data
;
252 if (nice_address_equal (&b
->peer
, to
)) {
258 nice_address_copy_to_sockaddr (to
, (struct sockaddr
*)&sa
);
261 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
262 if (len
+ sizeof(uint32_t) <= sizeof(buffer
)) {
263 uint16_t len16
= htons ((uint16_t) len
);
264 uint16_t channel16
= htons (binding
->channel
);
265 memcpy (buffer
, &channel16
, sizeof(uint16_t));
266 memcpy (buffer
+ sizeof(uint16_t), &len16
,sizeof(uint16_t));
267 memcpy (buffer
+ sizeof(uint32_t), buf
, len
);
268 msg_len
= len
+ sizeof(uint32_t);
273 return nice_socket_send (priv
->base_socket
, &priv
->server_addr
, len
, buf
);
276 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
277 if (!stun_agent_init_indication (&priv
->agent
, &msg
,
278 buffer
, sizeof(buffer
), STUN_IND_SEND
))
280 if (stun_message_append_xor_addr (&msg
, STUN_ATTRIBUTE_PEER_ADDRESS
,
281 (struct sockaddr
*)&sa
, sizeof(sa
)) !=
282 STUN_MESSAGE_RETURN_SUCCESS
)
285 if (!stun_agent_init_request (&priv
->agent
, &msg
,
286 buffer
, sizeof(buffer
), STUN_SEND
))
289 if (stun_message_append32 (&msg
, STUN_ATTRIBUTE_MAGIC_COOKIE
,
290 TURN_MAGIC_COOKIE
) != STUN_MESSAGE_RETURN_SUCCESS
)
292 if (priv
->username
!= NULL
&& priv
->username_len
> 0) {
293 if (stun_message_append_bytes (&msg
, STUN_ATTRIBUTE_USERNAME
,
294 priv
->username
, priv
->username_len
) !=
295 STUN_MESSAGE_RETURN_SUCCESS
)
298 if (stun_message_append_addr (&msg
, STUN_ATTRIBUTE_DESTINATION_ADDRESS
,
299 (struct sockaddr
*)&sa
, sizeof(sa
)) != STUN_MESSAGE_RETURN_SUCCESS
)
302 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
&&
303 priv
->current_binding
&&
304 nice_address_equal (&priv
->current_binding
->peer
, to
)) {
305 stun_message_append32 (&msg
, STUN_ATTRIBUTE_OPTIONS
, 1);
309 if (stun_message_append_bytes (&msg
, STUN_ATTRIBUTE_DATA
,
310 buf
, len
) != STUN_MESSAGE_RETURN_SUCCESS
)
313 msg_len
= stun_agent_finish_message (&priv
->agent
, &msg
,
314 priv
->password
, priv
->password_len
);
315 if (msg_len
> 0 && stun_message_get_class (&msg
) == STUN_REQUEST
) {
316 SendRequest
*req
= g_slice_new0 (SendRequest
);
319 stun_message_id (&msg
, req
->id
);
320 req
->source
= agent_timeout_add_with_context (priv
->nice
, STUN_END_TIMEOUT
,
321 priv_forget_send_request
, req
);
322 g_queue_push_tail (priv
->send_requests
, req
);
327 return nice_socket_send (priv
->base_socket
, &priv
->server_addr
,
328 msg_len
, (gchar
*)buffer
);
331 return nice_socket_send (priv
->base_socket
, to
, len
, buf
);
335 socket_is_reliable (NiceSocket
*sock
)
337 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
338 return nice_socket_is_reliable (priv
->base_socket
);
342 priv_forget_send_request (gpointer pointer
)
344 SendRequest
*req
= pointer
;
348 if (g_source_is_destroyed (g_main_current_source ())) {
349 nice_debug ("Source was destroyed. "
350 "Avoided race condition in turn.c:priv_forget_send_request");
355 stun_agent_forget_transaction (&req
->priv
->agent
, req
->id
);
357 g_queue_remove (req
->priv
->send_requests
, req
);
359 g_source_destroy (req
->source
);
360 g_source_unref (req
->source
);
365 g_slice_free (SendRequest
, req
);
372 nice_turn_socket_parse_recv (NiceSocket
*sock
, NiceSocket
**from_sock
,
373 NiceAddress
*from
, guint len
, gchar
*buf
,
374 NiceAddress
*recv_from
, gchar
*recv_buf
, guint recv_len
)
377 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
378 StunValidationStatus valid
;
380 struct sockaddr_storage sa
;
381 socklen_t from_len
= sizeof (sa
);
382 GList
*i
= priv
->channels
;
383 ChannelBinding
*binding
= NULL
;
385 if (nice_address_equal (&priv
->server_addr
, recv_from
)) {
386 valid
= stun_agent_validate (&priv
->agent
, &msg
,
387 (uint8_t *) recv_buf
, (size_t) recv_len
, NULL
, NULL
);
389 if (valid
== STUN_VALIDATION_SUCCESS
) {
390 if (priv
->compatibility
!= NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
392 if (stun_message_find32 (&msg
, STUN_ATTRIBUTE_MAGIC_COOKIE
,
393 &cookie
) != STUN_MESSAGE_RETURN_SUCCESS
)
395 if (cookie
!= TURN_MAGIC_COOKIE
)
399 if (stun_message_get_method (&msg
) == STUN_SEND
) {
400 if (stun_message_get_class (&msg
) == STUN_RESPONSE
) {
401 SendRequest
*req
= NULL
;
402 GList
*i
= g_queue_peek_head_link (priv
->send_requests
);
403 StunTransactionId msg_id
;
405 stun_message_id (&msg
, msg_id
);
407 for (; i
; i
= i
->next
) {
408 SendRequest
*r
= i
->data
;
409 if (memcmp (&r
->id
, msg_id
, sizeof(StunTransactionId
)) == 0) {
416 g_source_destroy (req
->source
);
417 g_source_unref (req
->source
);
420 g_queue_remove (priv
->send_requests
, req
);
422 g_slice_free (SendRequest
, req
);
425 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
) {
427 if (stun_message_find32 (&msg
, STUN_ATTRIBUTE_OPTIONS
, &opts
) ==
428 STUN_MESSAGE_RETURN_SUCCESS
&& opts
& 0x1)
429 goto msn_google_lock
;
433 } else if (stun_message_get_method (&msg
) == STUN_OLD_SET_ACTIVE_DST
) {
434 StunTransactionId request_id
;
435 StunTransactionId response_id
;
436 if (priv
->current_binding
&& priv
->current_binding_msg
) {
437 stun_message_id (&msg
, response_id
);
438 stun_message_id (&priv
->current_binding_msg
->message
, request_id
);
439 if (memcmp (request_id
, response_id
, sizeof(StunTransactionId
)) == 0) {
440 g_free (priv
->current_binding_msg
);
441 priv
->current_binding_msg
= NULL
;
443 if (stun_message_get_class (&msg
) == STUN_RESPONSE
&&
444 priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_MSN
) {
445 goto msn_google_lock
;
447 g_free (priv
->current_binding
);
448 priv
->current_binding
= NULL
;
454 } else if (stun_message_get_method (&msg
) == STUN_CHANNELBIND
) {
455 StunTransactionId request_id
;
456 StunTransactionId response_id
;
457 if (priv
->current_binding
&& priv
->current_binding_msg
) {
458 stun_message_id (&msg
, response_id
);
459 stun_message_id (&priv
->current_binding_msg
->message
, request_id
);
460 if (memcmp (request_id
, response_id
, sizeof(StunTransactionId
)) == 0) {
461 if (stun_message_get_class (&msg
) == STUN_ERROR
) {
463 uint8_t *sent_realm
= NULL
;
464 uint8_t *recv_realm
= NULL
;
465 uint16_t sent_realm_len
= 0;
466 uint16_t recv_realm_len
= 0;
468 sent_realm
= (uint8_t *) stun_message_find (
469 &priv
->current_binding_msg
->message
,
470 STUN_ATTRIBUTE_REALM
, &sent_realm_len
);
471 recv_realm
= (uint8_t *) stun_message_find (&msg
,
472 STUN_ATTRIBUTE_REALM
, &recv_realm_len
);
474 /* check for unauthorized error response */
475 if (stun_message_find_error (&msg
, &code
) ==
476 STUN_MESSAGE_RETURN_SUCCESS
&&
477 (code
== 438 || (code
== 401 &&
478 !(recv_realm
!= NULL
&&
479 recv_realm_len
> 0 &&
480 recv_realm_len
== sent_realm_len
&&
481 sent_realm
!= NULL
&&
482 memcmp (sent_realm
, recv_realm
, sent_realm_len
) == 0)))) {
483 g_free (priv
->current_binding_msg
);
484 priv
->current_binding_msg
= NULL
;
485 if (priv
->current_binding
) {
486 priv_send_channel_bind (priv
, &msg
,
487 priv
->current_binding
->channel
,
488 &priv
->current_binding
->peer
);
491 g_free (priv
->current_binding
);
492 priv
->current_binding
= NULL
;
493 g_free (priv
->current_binding_msg
);
494 priv
->current_binding_msg
= NULL
;
495 priv_process_pending_bindings (priv
);
497 } else if (stun_message_get_class (&msg
) == STUN_RESPONSE
) {
498 g_free (priv
->current_binding_msg
);
499 priv
->current_binding_msg
= NULL
;
500 if (priv
->current_binding
) {
501 priv
->channels
= g_list_append (priv
->channels
,
502 priv
->current_binding
);
503 priv
->current_binding
= NULL
;
505 priv_process_pending_bindings (priv
);
510 } else if (stun_message_get_class (&msg
) == STUN_INDICATION
&&
511 stun_message_get_method (&msg
) == STUN_IND_DATA
) {
515 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
516 if (stun_message_find_xor_addr (&msg
, STUN_ATTRIBUTE_REMOTE_ADDRESS
,
517 (struct sockaddr
*)&sa
, &from_len
) !=
518 STUN_MESSAGE_RETURN_SUCCESS
)
521 if (stun_message_find_addr (&msg
, STUN_ATTRIBUTE_REMOTE_ADDRESS
,
522 (struct sockaddr
*)&sa
, &from_len
) !=
523 STUN_MESSAGE_RETURN_SUCCESS
)
527 data
= (uint8_t *) stun_message_find (&msg
, STUN_ATTRIBUTE_DATA
,
533 nice_address_set_from_sockaddr (from
, (struct sockaddr
*)&sa
);
536 memmove (buf
, data
, len
> data_len
? data_len
: len
);
537 return len
> data_len
? data_len
: len
;
545 for (i
= priv
->channels
; i
; i
= i
->next
) {
546 ChannelBinding
*b
= i
->data
;
547 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
548 if (b
->channel
== ntohs(((uint16_t *)recv_buf
)[0])) {
549 recv_len
= ntohs (((uint16_t *)recv_buf
)[1]);
550 recv_buf
+= sizeof(uint32_t);
561 *from
= binding
->peer
;
567 memmove (buf
, recv_buf
, len
> recv_len
? recv_len
: len
);
568 return len
> recv_len
? recv_len
: len
;
572 if (priv
->current_binding
) {
573 GList
*i
= priv
->channels
;
574 for (; i
; i
= i
->next
) {
575 ChannelBinding
*b
= i
->data
;
578 g_list_free (priv
->channels
);
579 priv
->channels
= g_list_append (NULL
, priv
->current_binding
);
580 priv
->current_binding
= NULL
;
581 priv_process_pending_bindings (priv
);
588 nice_turn_socket_set_peer (NiceSocket
*sock
, NiceAddress
*peer
)
590 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
591 return priv_add_channel_binding (priv
, peer
);
595 priv_process_pending_bindings (TurnPriv
*priv
)
597 gboolean ret
= FALSE
;
598 while (priv
->pending_bindings
!= NULL
&& ret
== FALSE
) {
599 NiceAddress
*peer
= priv
->pending_bindings
->data
;
600 ret
= priv_add_channel_binding (priv
, peer
);
601 priv
->pending_bindings
= g_list_remove (priv
->pending_bindings
, peer
);
602 nice_address_free (peer
);
607 priv_retransmissions_tick_unlocked (TurnPriv
*priv
)
609 if (priv
->current_binding_msg
) {
610 switch (stun_timer_refresh (&priv
->current_binding_msg
->timer
)) {
611 case STUN_USAGE_TIMER_RETURN_TIMEOUT
:
614 StunTransactionId id
;
616 g_free (priv
->current_binding
);
617 priv
->current_binding
= NULL
;
618 g_free (priv
->current_binding_msg
);
619 priv
->current_binding_msg
= NULL
;
621 stun_message_id (&priv
->current_binding_msg
->message
, id
);
622 stun_agent_forget_transaction (&priv
->agent
, id
);
624 priv_process_pending_bindings (priv
);
627 case STUN_USAGE_TIMER_RETURN_RETRANSMIT
:
629 nice_socket_send (priv
->base_socket
, &priv
->server_addr
,
630 stun_message_length (&priv
->current_binding_msg
->message
),
631 (gchar
*)priv
->current_binding_msg
->buffer
);
633 case STUN_USAGE_TIMER_RETURN_SUCCESS
:
638 priv_schedule_tick (priv
);
644 priv_retransmissions_tick (gpointer pointer
)
646 TurnPriv
*priv
= pointer
;
650 if (g_source_is_destroyed (g_main_current_source ())) {
651 nice_debug ("Source was destroyed. "
652 "Avoided race condition in turn.c:priv_retransmissions_tick");
657 ret
= priv_retransmissions_tick_unlocked (priv
);
659 if (priv
->tick_source
!= NULL
) {
660 g_source_destroy (priv
->tick_source
);
661 g_source_unref (priv
->tick_source
);
662 priv
->tick_source
= NULL
;
671 priv_schedule_tick (TurnPriv
*priv
)
673 if (priv
->tick_source
!= NULL
) {
674 g_source_destroy (priv
->tick_source
);
675 g_source_unref (priv
->tick_source
);
676 priv
->tick_source
= NULL
;
679 if (priv
->current_binding_msg
) {
680 guint timeout
= stun_timer_remainder (&priv
->current_binding_msg
->timer
);
682 priv
->tick_source
= agent_timeout_add_with_context (priv
->nice
, timeout
,
683 priv_retransmissions_tick
, priv
);
685 priv_retransmissions_tick_unlocked (priv
);
691 priv_send_turn_message (TurnPriv
*priv
, TURNMessage
*msg
)
693 size_t stun_len
= stun_message_length (&msg
->message
);
695 if (priv
->current_binding_msg
) {
696 g_free (priv
->current_binding_msg
);
697 priv
->current_binding_msg
= NULL
;
700 nice_socket_send (priv
->base_socket
, &priv
->server_addr
,
701 stun_len
, (gchar
*)msg
->buffer
);
703 if (nice_socket_is_reliable (priv
->base_socket
)) {
704 stun_timer_start_reliable (&msg
->timer
);
706 stun_timer_start (&msg
->timer
);
709 priv
->current_binding_msg
= msg
;
710 priv_schedule_tick (priv
);
714 priv_send_channel_bind (TurnPriv
*priv
, StunMessage
*resp
,
715 uint16_t channel
, NiceAddress
*peer
)
717 uint32_t channel_attr
= channel
<< 16;
719 struct sockaddr_storage sa
;
720 TURNMessage
*msg
= g_new0 (TURNMessage
, 1);
722 nice_address_copy_to_sockaddr (peer
, (struct sockaddr
*)&sa
);
724 if (!stun_agent_init_request (&priv
->agent
, &msg
->message
,
725 msg
->buffer
, sizeof(msg
->buffer
), STUN_CHANNELBIND
)) {
730 if (stun_message_append32 (&msg
->message
, STUN_ATTRIBUTE_CHANNEL_NUMBER
,
731 channel_attr
) != STUN_MESSAGE_RETURN_SUCCESS
) {
736 if (stun_message_append_xor_addr (&msg
->message
, STUN_ATTRIBUTE_PEER_ADDRESS
,
737 (struct sockaddr
*)&sa
, sizeof(sa
)) != STUN_MESSAGE_RETURN_SUCCESS
) {
742 if (priv
->username
!= NULL
&& priv
->username_len
> 0) {
743 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_USERNAME
,
744 priv
->username
, priv
->username_len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
755 realm
= (uint8_t *) stun_message_find (resp
, STUN_ATTRIBUTE_REALM
, &len
);
757 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_REALM
,
758 realm
, len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
763 nonce
= (uint8_t *) stun_message_find (resp
, STUN_ATTRIBUTE_NONCE
, &len
);
765 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_NONCE
,
766 nonce
, len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
773 stun_len
= stun_agent_finish_message (&priv
->agent
, &msg
->message
,
774 priv
->password
, priv
->password_len
);
777 priv_send_turn_message (priv
, msg
);
786 priv_add_channel_binding (TurnPriv
*priv
, NiceAddress
*peer
)
789 struct sockaddr_storage sa
;
791 nice_address_copy_to_sockaddr (peer
, (struct sockaddr
*)&sa
);
793 if (priv
->current_binding
) {
794 NiceAddress
* pending
= nice_address_new ();
796 priv
->pending_bindings
= g_list_append (priv
->pending_bindings
, pending
);
800 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
801 uint16_t channel
= 0x4000;
802 GList
*i
= priv
->channels
;
803 for (; i
; i
= i
->next
) {
804 ChannelBinding
*b
= i
->data
;
805 if (channel
== b
->channel
) {
812 if (channel
>= 0x4000 && channel
< 0xffff) {
813 gboolean ret
= priv_send_channel_bind (priv
, NULL
, channel
, peer
);
815 priv
->current_binding
= g_new0 (ChannelBinding
, 1);
816 priv
->current_binding
->channel
= channel
;
817 priv
->current_binding
->peer
= *peer
;
822 } else if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_MSN
) {
823 TURNMessage
*msg
= g_new0 (TURNMessage
, 1);
824 if (!stun_agent_init_request (&priv
->agent
, &msg
->message
,
825 msg
->buffer
, sizeof(msg
->buffer
), STUN_OLD_SET_ACTIVE_DST
)) {
830 if (stun_message_append32 (&msg
->message
, STUN_ATTRIBUTE_MAGIC_COOKIE
,
831 TURN_MAGIC_COOKIE
) != STUN_MESSAGE_RETURN_SUCCESS
) {
836 if (priv
->username
!= NULL
&& priv
->username_len
> 0) {
837 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_USERNAME
,
838 priv
->username
, priv
->username_len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
844 if (stun_message_append_addr (&msg
->message
,
845 STUN_ATTRIBUTE_DESTINATION_ADDRESS
,
846 (struct sockaddr
*)&sa
, sizeof(sa
)) != STUN_MESSAGE_RETURN_SUCCESS
) {
851 stun_len
= stun_agent_finish_message (&priv
->agent
, &msg
->message
,
852 priv
->password
, priv
->password_len
);
855 priv
->current_binding
= g_new0 (ChannelBinding
, 1);
856 priv
->current_binding
->channel
= 0;
857 priv
->current_binding
->peer
= *peer
;
858 priv_send_turn_message (priv
, msg
);
863 } else if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
) {
864 priv
->current_binding
= g_new0 (ChannelBinding
, 1);
865 priv
->current_binding
->channel
= 0;
866 priv
->current_binding
->peer
= *peer
;