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
;
96 static void socket_close (NiceSocket
*sock
);
97 static gint
socket_recv (NiceSocket
*sock
, NiceAddress
*from
,
98 guint len
, gchar
*buf
);
99 static gboolean
socket_send (NiceSocket
*sock
, const NiceAddress
*to
,
100 guint len
, const gchar
*buf
);
101 static gboolean
socket_is_reliable (NiceSocket
*sock
);
103 static void priv_process_pending_bindings (TurnPriv
*priv
);
104 static gboolean
priv_retransmissions_tick_unlocked (TurnPriv
*priv
);
105 static gboolean
priv_retransmissions_tick (gpointer pointer
);
106 static void priv_schedule_tick (TurnPriv
*priv
);
107 static void priv_send_turn_message (TurnPriv
*priv
, TURNMessage
*msg
);
108 static gboolean
priv_send_channel_bind (TurnPriv
*priv
, StunMessage
*resp
,
109 uint16_t channel
, NiceAddress
*peer
);
110 static gboolean
priv_add_channel_binding (TurnPriv
*priv
, NiceAddress
*peer
);
111 static gboolean
priv_forget_send_request (gpointer pointer
);
115 nice_turn_socket_new (NiceAgent
*agent
, NiceAddress
*addr
,
116 NiceSocket
*base_socket
, NiceAddress
*server_addr
,
117 gchar
*username
, gchar
*password
, NiceTurnSocketCompatibility compatibility
)
119 TurnPriv
*priv
= g_new0 (TurnPriv
, 1);
120 NiceSocket
*sock
= g_slice_new0 (NiceSocket
);
126 if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
127 stun_agent_init (&priv
->agent
, STUN_ALL_KNOWN_ATTRIBUTES
,
128 STUN_COMPATIBILITY_RFC5389
,
129 STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS
);
130 } else if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_MSN
) {
131 stun_agent_init (&priv
->agent
, STUN_ALL_KNOWN_ATTRIBUTES
,
132 STUN_COMPATIBILITY_RFC3489
,
133 STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS
|
134 STUN_AGENT_USAGE_NO_INDICATION_AUTH
);
135 } else if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
) {
136 stun_agent_init (&priv
->agent
, STUN_ALL_KNOWN_ATTRIBUTES
,
137 STUN_COMPATIBILITY_RFC3489
,
138 STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS
|
139 STUN_AGENT_USAGE_IGNORE_CREDENTIALS
);
143 priv
->channels
= NULL
;
144 priv
->current_binding
= NULL
;
145 priv
->base_socket
= base_socket
;
147 if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_MSN
) {
148 priv
->username
= g_base64_decode (username
, &priv
->username_len
);
149 priv
->password
= g_base64_decode (password
, &priv
->password_len
);
151 priv
->username
= (uint8_t *)g_strdup (username
);
152 priv
->username_len
= (size_t) strlen (username
);
153 if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
) {
154 priv
->password
= NULL
;
155 priv
->password_len
= 0;
157 priv
->password
= (uint8_t *)g_strdup (password
);
158 priv
->password_len
= (size_t) strlen (password
);
161 priv
->server_addr
= *server_addr
;
162 priv
->compatibility
= compatibility
;
163 priv
->send_requests
= g_queue_new ();
165 sock
->fileno
= base_socket
->fileno
;
166 sock
->send
= socket_send
;
167 sock
->recv
= socket_recv
;
168 sock
->is_reliable
= socket_is_reliable
;
169 sock
->close
= socket_close
;
170 sock
->priv
= (void *) priv
;
176 socket_close (NiceSocket
*sock
)
178 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
181 for (i
= priv
->channels
; i
; i
= i
->next
) {
182 ChannelBinding
*b
= i
->data
;
185 g_list_free (priv
->channels
);
187 for (i
= priv
->pending_bindings
; i
; i
= i
->next
) {
188 ChannelBinding
*b
= i
->data
;
191 g_list_free (priv
->pending_bindings
);
193 if (priv
->tick_source
!= NULL
) {
194 g_source_destroy (priv
->tick_source
);
195 g_source_unref (priv
->tick_source
);
196 priv
->tick_source
= NULL
;
199 for (i
= g_queue_peek_head_link (priv
->send_requests
); i
; i
= i
->next
) {
200 SendRequest
*r
= i
->data
;
201 g_source_destroy (r
->source
);
202 g_source_unref (r
->source
);
205 stun_agent_forget_transaction (&priv
->agent
, r
->id
);
208 if (g_atomic_int_dec_and_test (&r
->ref
))
209 g_slice_free (SendRequest
, r
);
212 g_queue_free (priv
->send_requests
);
215 g_free (priv
->current_binding
);
216 g_free (priv
->current_binding_msg
);
217 g_free (priv
->username
);
218 g_free (priv
->password
);
223 socket_recv (NiceSocket
*sock
, NiceAddress
*from
, guint len
, gchar
*buf
)
225 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
226 uint8_t recv_buf
[STUN_MAX_MESSAGE_SIZE
];
228 NiceAddress recv_from
;
231 recv_len
= nice_socket_recv (priv
->base_socket
, &recv_from
,
232 sizeof(recv_buf
), (gchar
*) recv_buf
);
235 return nice_turn_socket_parse_recv (sock
, &dummy
, from
, len
, buf
,
236 &recv_from
, (gchar
*) recv_buf
, (guint
) recv_len
);
242 socket_send (NiceSocket
*sock
, const NiceAddress
*to
,
243 guint len
, const gchar
*buf
)
245 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
247 uint8_t buffer
[STUN_MAX_MESSAGE_SIZE
];
249 struct sockaddr_storage sa
;
250 GList
*i
= priv
->channels
;
251 ChannelBinding
*binding
= NULL
;
253 for (; i
; i
= i
->next
) {
254 ChannelBinding
*b
= i
->data
;
255 if (nice_address_equal (&b
->peer
, to
)) {
261 nice_address_copy_to_sockaddr (to
, (struct sockaddr
*)&sa
);
264 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
265 if (len
+ sizeof(uint32_t) <= sizeof(buffer
)) {
266 uint16_t len16
= htons ((uint16_t) len
);
267 uint16_t channel16
= htons (binding
->channel
);
268 memcpy (buffer
, &channel16
, sizeof(uint16_t));
269 memcpy (buffer
+ sizeof(uint16_t), &len16
,sizeof(uint16_t));
270 memcpy (buffer
+ sizeof(uint32_t), buf
, len
);
271 msg_len
= len
+ sizeof(uint32_t);
276 return nice_socket_send (priv
->base_socket
, &priv
->server_addr
, len
, buf
);
279 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
280 if (!stun_agent_init_indication (&priv
->agent
, &msg
,
281 buffer
, sizeof(buffer
), STUN_IND_SEND
))
283 if (stun_message_append_xor_addr (&msg
, STUN_ATTRIBUTE_PEER_ADDRESS
,
284 (struct sockaddr
*)&sa
, sizeof(sa
)) !=
285 STUN_MESSAGE_RETURN_SUCCESS
)
288 if (!stun_agent_init_request (&priv
->agent
, &msg
,
289 buffer
, sizeof(buffer
), STUN_SEND
))
292 if (stun_message_append32 (&msg
, STUN_ATTRIBUTE_MAGIC_COOKIE
,
293 TURN_MAGIC_COOKIE
) != STUN_MESSAGE_RETURN_SUCCESS
)
295 if (priv
->username
!= NULL
&& priv
->username_len
> 0) {
296 if (stun_message_append_bytes (&msg
, STUN_ATTRIBUTE_USERNAME
,
297 priv
->username
, priv
->username_len
) !=
298 STUN_MESSAGE_RETURN_SUCCESS
)
301 if (stun_message_append_addr (&msg
, STUN_ATTRIBUTE_DESTINATION_ADDRESS
,
302 (struct sockaddr
*)&sa
, sizeof(sa
)) != STUN_MESSAGE_RETURN_SUCCESS
)
305 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
&&
306 priv
->current_binding
&&
307 nice_address_equal (&priv
->current_binding
->peer
, to
)) {
308 stun_message_append32 (&msg
, STUN_ATTRIBUTE_OPTIONS
, 1);
312 if (stun_message_append_bytes (&msg
, STUN_ATTRIBUTE_DATA
,
313 buf
, len
) != STUN_MESSAGE_RETURN_SUCCESS
)
316 msg_len
= stun_agent_finish_message (&priv
->agent
, &msg
,
317 priv
->password
, priv
->password_len
);
318 if (msg_len
> 0 && stun_message_get_class (&msg
) == STUN_REQUEST
) {
319 SendRequest
*req
= g_slice_new0 (SendRequest
);
322 stun_message_id (&msg
, req
->id
);
323 req
->source
= agent_timeout_add_with_context (priv
->nice
, STUN_END_TIMEOUT
,
324 priv_forget_send_request
, req
);
325 g_queue_push_tail (priv
->send_requests
, req
);
326 g_atomic_int_inc (&req
->ref
);
331 return nice_socket_send (priv
->base_socket
, &priv
->server_addr
,
332 msg_len
, (gchar
*)buffer
);
335 return nice_socket_send (priv
->base_socket
, to
, len
, buf
);
339 socket_is_reliable (NiceSocket
*sock
)
341 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
342 return nice_socket_is_reliable (priv
->base_socket
);
346 priv_forget_send_request (gpointer pointer
)
348 SendRequest
*req
= pointer
;
349 GStaticRecMutex
*mutex
= NULL
;
351 if (req
->priv
== NULL
)
354 g_atomic_int_inc (&req
->ref
);
356 mutex
= &req
->priv
->nice
->mutex
;
358 g_static_rec_mutex_lock (mutex
);
361 stun_agent_forget_transaction (&req
->priv
->agent
, req
->id
);
363 if (g_queue_index (req
->priv
->send_requests
, req
) != -1) {
364 g_queue_remove (req
->priv
->send_requests
, req
);
365 (void)g_atomic_int_dec_and_test (&req
->ref
);
368 g_source_destroy (req
->source
);
369 g_source_unref (req
->source
);
373 g_static_rec_mutex_unlock (mutex
);
375 if (g_atomic_int_dec_and_test (&req
->ref
))
376 g_slice_free (SendRequest
, req
);
383 nice_turn_socket_parse_recv (NiceSocket
*sock
, NiceSocket
**from_sock
,
384 NiceAddress
*from
, guint len
, gchar
*buf
,
385 NiceAddress
*recv_from
, gchar
*recv_buf
, guint recv_len
)
388 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
389 StunValidationStatus valid
;
391 struct sockaddr_storage sa
;
392 socklen_t from_len
= sizeof (sa
);
393 GList
*i
= priv
->channels
;
394 ChannelBinding
*binding
= NULL
;
396 if (nice_address_equal (&priv
->server_addr
, recv_from
)) {
397 valid
= stun_agent_validate (&priv
->agent
, &msg
,
398 (uint8_t *) recv_buf
, (size_t) recv_len
, NULL
, NULL
);
400 if (valid
== STUN_VALIDATION_SUCCESS
) {
401 if (priv
->compatibility
!= NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
403 if (stun_message_find32 (&msg
, STUN_ATTRIBUTE_MAGIC_COOKIE
,
404 &cookie
) != STUN_MESSAGE_RETURN_SUCCESS
)
406 if (cookie
!= TURN_MAGIC_COOKIE
)
410 if (stun_message_get_method (&msg
) == STUN_SEND
) {
411 if (stun_message_get_class (&msg
) == STUN_RESPONSE
) {
412 SendRequest
*req
= NULL
;
413 GList
*i
= g_queue_peek_head_link (priv
->send_requests
);
414 StunTransactionId msg_id
;
416 stun_message_id (&msg
, msg_id
);
418 for (; i
; i
= i
->next
) {
419 SendRequest
*r
= i
->data
;
420 if (memcmp (&r
->id
, msg_id
, sizeof(StunTransactionId
)) == 0) {
427 g_source_destroy (req
->source
);
428 g_source_unref (req
->source
);
431 g_queue_remove (priv
->send_requests
, req
);
433 if (g_atomic_int_dec_and_test (&req
->ref
))
434 g_slice_free (SendRequest
, req
);
437 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
) {
439 if (stun_message_find32 (&msg
, STUN_ATTRIBUTE_OPTIONS
, &opts
) ==
440 STUN_MESSAGE_RETURN_SUCCESS
&& opts
& 0x1)
441 goto msn_google_lock
;
445 } else if (stun_message_get_method (&msg
) == STUN_OLD_SET_ACTIVE_DST
) {
446 StunTransactionId request_id
;
447 StunTransactionId response_id
;
448 if (priv
->current_binding
&& priv
->current_binding_msg
) {
449 stun_message_id (&msg
, response_id
);
450 stun_message_id (&priv
->current_binding_msg
->message
, request_id
);
451 if (memcmp (request_id
, response_id
, sizeof(StunTransactionId
)) == 0) {
452 g_free (priv
->current_binding_msg
);
453 priv
->current_binding_msg
= NULL
;
455 if (stun_message_get_class (&msg
) == STUN_RESPONSE
&&
456 priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_MSN
) {
457 goto msn_google_lock
;
459 g_free (priv
->current_binding
);
460 priv
->current_binding
= NULL
;
466 } else if (stun_message_get_method (&msg
) == STUN_CHANNELBIND
) {
467 StunTransactionId request_id
;
468 StunTransactionId response_id
;
469 if (priv
->current_binding
&& priv
->current_binding_msg
) {
470 stun_message_id (&msg
, response_id
);
471 stun_message_id (&priv
->current_binding_msg
->message
, request_id
);
472 if (memcmp (request_id
, response_id
, sizeof(StunTransactionId
)) == 0) {
473 if (stun_message_get_class (&msg
) == STUN_ERROR
) {
475 uint8_t *sent_realm
= NULL
;
476 uint8_t *recv_realm
= NULL
;
477 uint16_t sent_realm_len
= 0;
478 uint16_t recv_realm_len
= 0;
480 sent_realm
= (uint8_t *) stun_message_find (
481 &priv
->current_binding_msg
->message
,
482 STUN_ATTRIBUTE_REALM
, &sent_realm_len
);
483 recv_realm
= (uint8_t *) stun_message_find (&msg
,
484 STUN_ATTRIBUTE_REALM
, &recv_realm_len
);
486 /* check for unauthorized error response */
487 if (stun_message_find_error (&msg
, &code
) ==
488 STUN_MESSAGE_RETURN_SUCCESS
&&
489 (code
== 438 || (code
== 401 &&
490 !(recv_realm
!= NULL
&&
491 recv_realm_len
> 0 &&
492 recv_realm_len
== sent_realm_len
&&
493 sent_realm
!= NULL
&&
494 memcmp (sent_realm
, recv_realm
, sent_realm_len
) == 0)))) {
495 g_free (priv
->current_binding_msg
);
496 priv
->current_binding_msg
= NULL
;
497 if (priv
->current_binding
) {
498 priv_send_channel_bind (priv
, &msg
,
499 priv
->current_binding
->channel
,
500 &priv
->current_binding
->peer
);
503 g_free (priv
->current_binding
);
504 priv
->current_binding
= NULL
;
505 g_free (priv
->current_binding_msg
);
506 priv
->current_binding_msg
= NULL
;
507 priv_process_pending_bindings (priv
);
509 } else if (stun_message_get_class (&msg
) == STUN_RESPONSE
) {
510 g_free (priv
->current_binding_msg
);
511 priv
->current_binding_msg
= NULL
;
512 if (priv
->current_binding
) {
513 priv
->channels
= g_list_append (priv
->channels
,
514 priv
->current_binding
);
515 priv
->current_binding
= NULL
;
517 priv_process_pending_bindings (priv
);
522 } else if (stun_message_get_class (&msg
) == STUN_INDICATION
&&
523 stun_message_get_method (&msg
) == STUN_IND_DATA
) {
527 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
528 if (stun_message_find_xor_addr (&msg
, STUN_ATTRIBUTE_REMOTE_ADDRESS
,
529 (struct sockaddr
*)&sa
, &from_len
) !=
530 STUN_MESSAGE_RETURN_SUCCESS
)
533 if (stun_message_find_addr (&msg
, STUN_ATTRIBUTE_REMOTE_ADDRESS
,
534 (struct sockaddr
*)&sa
, &from_len
) !=
535 STUN_MESSAGE_RETURN_SUCCESS
)
539 data
= (uint8_t *) stun_message_find (&msg
, STUN_ATTRIBUTE_DATA
,
545 nice_address_set_from_sockaddr (from
, (struct sockaddr
*)&sa
);
548 memmove (buf
, data
, len
> data_len
? data_len
: len
);
549 return len
> data_len
? data_len
: len
;
557 for (i
= priv
->channels
; i
; i
= i
->next
) {
558 ChannelBinding
*b
= i
->data
;
559 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
560 if (b
->channel
== ntohs(((uint16_t *)recv_buf
)[0])) {
561 recv_len
= ntohs (((uint16_t *)recv_buf
)[1]);
562 recv_buf
+= sizeof(uint32_t);
573 *from
= binding
->peer
;
579 memmove (buf
, recv_buf
, len
> recv_len
? recv_len
: len
);
580 return len
> recv_len
? recv_len
: len
;
584 if (priv
->current_binding
) {
585 GList
*i
= priv
->channels
;
586 for (; i
; i
= i
->next
) {
587 ChannelBinding
*b
= i
->data
;
590 g_list_free (priv
->channels
);
591 priv
->channels
= g_list_append (NULL
, priv
->current_binding
);
592 priv
->current_binding
= NULL
;
593 priv_process_pending_bindings (priv
);
600 nice_turn_socket_set_peer (NiceSocket
*sock
, NiceAddress
*peer
)
602 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
603 return priv_add_channel_binding (priv
, peer
);
607 priv_process_pending_bindings (TurnPriv
*priv
)
609 gboolean ret
= FALSE
;
610 while (priv
->pending_bindings
!= NULL
&& ret
== FALSE
) {
611 NiceAddress
*peer
= priv
->pending_bindings
->data
;
612 ret
= priv_add_channel_binding (priv
, peer
);
613 priv
->pending_bindings
= g_list_remove (priv
->pending_bindings
, peer
);
614 nice_address_free (peer
);
619 priv_retransmissions_tick_unlocked (TurnPriv
*priv
)
621 if (priv
->current_binding_msg
) {
622 switch (stun_timer_refresh (&priv
->current_binding_msg
->timer
)) {
623 case STUN_USAGE_TIMER_RETURN_TIMEOUT
:
626 StunTransactionId id
;
628 g_free (priv
->current_binding
);
629 priv
->current_binding
= NULL
;
630 g_free (priv
->current_binding_msg
);
631 priv
->current_binding_msg
= NULL
;
633 stun_message_id (&priv
->current_binding_msg
->message
, id
);
634 stun_agent_forget_transaction (&priv
->agent
, id
);
636 priv_process_pending_bindings (priv
);
639 case STUN_USAGE_TIMER_RETURN_RETRANSMIT
:
641 nice_socket_send (priv
->base_socket
, &priv
->server_addr
,
642 stun_message_length (&priv
->current_binding_msg
->message
),
643 (gchar
*)priv
->current_binding_msg
->buffer
);
645 case STUN_USAGE_TIMER_RETURN_SUCCESS
:
650 priv_schedule_tick (priv
);
656 priv_retransmissions_tick (gpointer pointer
)
658 TurnPriv
*priv
= pointer
;
661 g_static_rec_mutex_lock (&priv
->nice
->mutex
);
662 ret
= priv_retransmissions_tick_unlocked (priv
);
663 g_static_rec_mutex_unlock (&priv
->nice
->mutex
);
669 priv_schedule_tick (TurnPriv
*priv
)
671 if (priv
->tick_source
!= NULL
) {
672 g_source_destroy (priv
->tick_source
);
673 g_source_unref (priv
->tick_source
);
674 priv
->tick_source
= NULL
;
677 if (priv
->current_binding_msg
) {
678 guint timeout
= stun_timer_remainder (&priv
->current_binding_msg
->timer
);
680 priv
->tick_source
= agent_timeout_add_with_context (priv
->nice
, timeout
,
681 priv_retransmissions_tick
, priv
);
683 priv_retransmissions_tick_unlocked (priv
);
689 priv_send_turn_message (TurnPriv
*priv
, TURNMessage
*msg
)
691 size_t stun_len
= stun_message_length (&msg
->message
);
693 if (priv
->current_binding_msg
) {
694 g_free (priv
->current_binding_msg
);
695 priv
->current_binding_msg
= NULL
;
698 nice_socket_send (priv
->base_socket
, &priv
->server_addr
,
699 stun_len
, (gchar
*)msg
->buffer
);
701 if (nice_socket_is_reliable (priv
->base_socket
)) {
702 stun_timer_start_reliable (&msg
->timer
);
704 stun_timer_start (&msg
->timer
);
707 priv
->current_binding_msg
= msg
;
708 priv_schedule_tick (priv
);
712 priv_send_channel_bind (TurnPriv
*priv
, StunMessage
*resp
,
713 uint16_t channel
, NiceAddress
*peer
)
715 uint32_t channel_attr
= channel
<< 16;
717 struct sockaddr_storage sa
;
718 TURNMessage
*msg
= g_new0 (TURNMessage
, 1);
720 nice_address_copy_to_sockaddr (peer
, (struct sockaddr
*)&sa
);
722 if (!stun_agent_init_request (&priv
->agent
, &msg
->message
,
723 msg
->buffer
, sizeof(msg
->buffer
), STUN_CHANNELBIND
)) {
728 if (stun_message_append32 (&msg
->message
, STUN_ATTRIBUTE_CHANNEL_NUMBER
,
729 channel_attr
) != STUN_MESSAGE_RETURN_SUCCESS
) {
734 if (stun_message_append_xor_addr (&msg
->message
, STUN_ATTRIBUTE_PEER_ADDRESS
,
735 (struct sockaddr
*)&sa
, sizeof(sa
)) != STUN_MESSAGE_RETURN_SUCCESS
) {
740 if (priv
->username
!= NULL
&& priv
->username_len
> 0) {
741 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_USERNAME
,
742 priv
->username
, priv
->username_len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
753 realm
= (uint8_t *) stun_message_find (resp
, STUN_ATTRIBUTE_REALM
, &len
);
755 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_REALM
,
756 realm
, len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
761 nonce
= (uint8_t *) stun_message_find (resp
, STUN_ATTRIBUTE_NONCE
, &len
);
763 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_NONCE
,
764 nonce
, len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
771 stun_len
= stun_agent_finish_message (&priv
->agent
, &msg
->message
,
772 priv
->password
, priv
->password_len
);
775 priv_send_turn_message (priv
, msg
);
784 priv_add_channel_binding (TurnPriv
*priv
, NiceAddress
*peer
)
787 struct sockaddr_storage sa
;
789 nice_address_copy_to_sockaddr (peer
, (struct sockaddr
*)&sa
);
791 if (priv
->current_binding
) {
792 NiceAddress
* pending
= nice_address_new ();
794 priv
->pending_bindings
= g_list_append (priv
->pending_bindings
, pending
);
798 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
799 uint16_t channel
= 0x4000;
800 GList
*i
= priv
->channels
;
801 for (; i
; i
= i
->next
) {
802 ChannelBinding
*b
= i
->data
;
803 if (channel
== b
->channel
) {
810 if (channel
>= 0x4000 && channel
< 0xffff) {
811 gboolean ret
= priv_send_channel_bind (priv
, NULL
, channel
, peer
);
813 priv
->current_binding
= g_new0 (ChannelBinding
, 1);
814 priv
->current_binding
->channel
= channel
;
815 priv
->current_binding
->peer
= *peer
;
820 } else if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_MSN
) {
821 TURNMessage
*msg
= g_new0 (TURNMessage
, 1);
822 if (!stun_agent_init_request (&priv
->agent
, &msg
->message
,
823 msg
->buffer
, sizeof(msg
->buffer
), STUN_OLD_SET_ACTIVE_DST
)) {
828 if (stun_message_append32 (&msg
->message
, STUN_ATTRIBUTE_MAGIC_COOKIE
,
829 TURN_MAGIC_COOKIE
) != STUN_MESSAGE_RETURN_SUCCESS
) {
834 if (priv
->username
!= NULL
&& priv
->username_len
> 0) {
835 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_USERNAME
,
836 priv
->username
, priv
->username_len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
842 if (stun_message_append_addr (&msg
->message
,
843 STUN_ATTRIBUTE_DESTINATION_ADDRESS
,
844 (struct sockaddr
*)&sa
, sizeof(sa
)) != STUN_MESSAGE_RETURN_SUCCESS
) {
849 stun_len
= stun_agent_finish_message (&priv
->agent
, &msg
->message
,
850 priv
->password
, priv
->password_len
);
853 priv
->current_binding
= g_new0 (ChannelBinding
, 1);
854 priv
->current_binding
->channel
= 0;
855 priv
->current_binding
->peer
= *peer
;
856 priv_send_turn_message (priv
, msg
);
861 } else if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
) {
862 priv
->current_binding
= g_new0 (ChannelBinding
, 1);
863 priv
->current_binding
->channel
= 0;
864 priv
->current_binding
->peer
= *peer
;