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
);
203 g_slice_free (SendRequest
, r
);
205 g_queue_free (priv
->send_requests
);
208 g_free (priv
->current_binding
);
209 g_free (priv
->current_binding_msg
);
210 g_free (priv
->username
);
211 g_free (priv
->password
);
216 socket_recv (NiceSocket
*sock
, NiceAddress
*from
, guint len
, gchar
*buf
)
218 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
219 uint8_t recv_buf
[STUN_MAX_MESSAGE_SIZE
];
221 NiceAddress recv_from
;
224 recv_len
= nice_socket_recv (priv
->base_socket
, &recv_from
,
225 sizeof(recv_buf
), (gchar
*) recv_buf
);
228 return nice_turn_socket_parse_recv (sock
, &dummy
, from
, len
, buf
,
229 &recv_from
, (gchar
*) recv_buf
, (guint
) recv_len
);
235 socket_send (NiceSocket
*sock
, const NiceAddress
*to
,
236 guint len
, const gchar
*buf
)
238 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
240 uint8_t buffer
[STUN_MAX_MESSAGE_SIZE
];
242 struct sockaddr_storage sa
;
243 GList
*i
= priv
->channels
;
244 ChannelBinding
*binding
= NULL
;
246 for (; i
; i
= i
->next
) {
247 ChannelBinding
*b
= i
->data
;
248 if (nice_address_equal (&b
->peer
, to
)) {
254 nice_address_copy_to_sockaddr (to
, (struct sockaddr
*)&sa
);
257 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
258 if (len
+ sizeof(uint32_t) <= sizeof(buffer
)) {
259 uint16_t len16
= htons ((uint16_t) len
);
260 uint16_t channel16
= htons (binding
->channel
);
261 memcpy (buffer
, &channel16
, sizeof(uint16_t));
262 memcpy (buffer
+ sizeof(uint16_t), &len16
,sizeof(uint16_t));
263 memcpy (buffer
+ sizeof(uint32_t), buf
, len
);
264 msg_len
= len
+ sizeof(uint32_t);
269 return nice_socket_send (priv
->base_socket
, &priv
->server_addr
, len
, buf
);
272 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
273 if (!stun_agent_init_indication (&priv
->agent
, &msg
,
274 buffer
, sizeof(buffer
), STUN_IND_SEND
))
276 if (stun_message_append_xor_addr (&msg
, STUN_ATTRIBUTE_PEER_ADDRESS
,
277 (struct sockaddr
*)&sa
, sizeof(sa
)) !=
278 STUN_MESSAGE_RETURN_SUCCESS
)
281 if (!stun_agent_init_request (&priv
->agent
, &msg
,
282 buffer
, sizeof(buffer
), STUN_SEND
))
285 if (stun_message_append32 (&msg
, STUN_ATTRIBUTE_MAGIC_COOKIE
,
286 TURN_MAGIC_COOKIE
) != STUN_MESSAGE_RETURN_SUCCESS
)
288 if (priv
->username
!= NULL
&& priv
->username_len
> 0) {
289 if (stun_message_append_bytes (&msg
, STUN_ATTRIBUTE_USERNAME
,
290 priv
->username
, priv
->username_len
) !=
291 STUN_MESSAGE_RETURN_SUCCESS
)
294 if (stun_message_append_addr (&msg
, STUN_ATTRIBUTE_DESTINATION_ADDRESS
,
295 (struct sockaddr
*)&sa
, sizeof(sa
)) != STUN_MESSAGE_RETURN_SUCCESS
)
298 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
&&
299 priv
->current_binding
&&
300 nice_address_equal (&priv
->current_binding
->peer
, to
)) {
301 stun_message_append32 (&msg
, STUN_ATTRIBUTE_OPTIONS
, 1);
305 if (stun_message_append_bytes (&msg
, STUN_ATTRIBUTE_DATA
,
306 buf
, len
) != STUN_MESSAGE_RETURN_SUCCESS
)
309 msg_len
= stun_agent_finish_message (&priv
->agent
, &msg
,
310 priv
->password
, priv
->password_len
);
311 if (msg_len
> 0 && stun_message_get_class (&msg
) == STUN_REQUEST
) {
312 SendRequest
*req
= g_slice_new0 (SendRequest
);
315 stun_message_id (&msg
, req
->id
);
316 req
->source
= agent_timeout_add_with_context (priv
->nice
, STUN_END_TIMEOUT
,
317 priv_forget_send_request
, req
);
318 g_queue_push_tail (priv
->send_requests
, req
);
319 g_atomic_int_inc (&req
->ref
);
324 return nice_socket_send (priv
->base_socket
, &priv
->server_addr
,
325 msg_len
, (gchar
*)buffer
);
328 return nice_socket_send (priv
->base_socket
, to
, len
, buf
);
332 socket_is_reliable (NiceSocket
*sock
)
334 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
335 return nice_socket_is_reliable (priv
->base_socket
);
339 priv_forget_send_request (gpointer pointer
)
341 SendRequest
*req
= pointer
;
343 g_atomic_int_inc (&req
->ref
);
345 g_static_rec_mutex_lock (&req
->priv
->nice
->mutex
);
347 stun_agent_forget_transaction (&req
->priv
->agent
, req
->id
);
349 g_source_destroy (req
->source
);
350 g_source_unref (req
->source
);
352 if (g_queue_index (req
->priv
->send_requests
, req
) != -1) {
353 g_queue_remove (req
->priv
->send_requests
, req
);
354 (void)g_atomic_int_dec_and_test (&req
->ref
);
357 g_static_rec_mutex_unlock (&req
->priv
->nice
->mutex
);
359 if (g_atomic_int_dec_and_test (&req
->ref
))
360 g_slice_free (SendRequest
, req
);
367 nice_turn_socket_parse_recv (NiceSocket
*sock
, NiceSocket
**from_sock
,
368 NiceAddress
*from
, guint len
, gchar
*buf
,
369 NiceAddress
*recv_from
, gchar
*recv_buf
, guint recv_len
)
372 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
373 StunValidationStatus valid
;
375 struct sockaddr_storage sa
;
376 socklen_t from_len
= sizeof (sa
);
377 GList
*i
= priv
->channels
;
378 ChannelBinding
*binding
= NULL
;
380 if (nice_address_equal (&priv
->server_addr
, recv_from
)) {
381 valid
= stun_agent_validate (&priv
->agent
, &msg
,
382 (uint8_t *) recv_buf
, (size_t) recv_len
, NULL
, NULL
);
384 if (valid
== STUN_VALIDATION_SUCCESS
) {
385 if (priv
->compatibility
!= NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
387 if (stun_message_find32 (&msg
, STUN_ATTRIBUTE_MAGIC_COOKIE
,
388 &cookie
) != STUN_MESSAGE_RETURN_SUCCESS
)
390 if (cookie
!= TURN_MAGIC_COOKIE
)
394 if (stun_message_get_method (&msg
) == STUN_SEND
) {
395 if (stun_message_get_class (&msg
) == STUN_RESPONSE
) {
396 SendRequest
*req
= NULL
;
397 GList
*i
= g_queue_peek_head_link (priv
->send_requests
);
398 StunTransactionId msg_id
;
400 stun_message_id (&msg
, msg_id
);
402 for (; i
; i
= i
->next
) {
403 SendRequest
*r
= i
->data
;
404 if (memcmp (&r
->id
, msg_id
, sizeof(StunTransactionId
)) == 0) {
411 g_source_destroy (req
->source
);
412 g_source_unref (req
->source
);
414 g_queue_remove (priv
->send_requests
, req
);
416 if (g_atomic_int_dec_and_test (&req
->ref
))
417 g_slice_free (SendRequest
, req
);
420 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
) {
422 if (stun_message_find32 (&msg
, STUN_ATTRIBUTE_OPTIONS
, &opts
) ==
423 STUN_MESSAGE_RETURN_SUCCESS
&& opts
& 0x1)
424 goto msn_google_lock
;
428 } else if (stun_message_get_method (&msg
) == STUN_OLD_SET_ACTIVE_DST
) {
429 StunTransactionId request_id
;
430 StunTransactionId response_id
;
431 if (priv
->current_binding
&& priv
->current_binding_msg
) {
432 stun_message_id (&msg
, response_id
);
433 stun_message_id (&priv
->current_binding_msg
->message
, request_id
);
434 if (memcmp (request_id
, response_id
, sizeof(StunTransactionId
)) == 0) {
435 g_free (priv
->current_binding_msg
);
436 priv
->current_binding_msg
= NULL
;
438 if (stun_message_get_class (&msg
) == STUN_RESPONSE
&&
439 priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_MSN
) {
440 goto msn_google_lock
;
442 g_free (priv
->current_binding
);
443 priv
->current_binding
= NULL
;
449 } else if (stun_message_get_method (&msg
) == STUN_CHANNELBIND
) {
450 StunTransactionId request_id
;
451 StunTransactionId response_id
;
452 if (priv
->current_binding
&& priv
->current_binding_msg
) {
453 stun_message_id (&msg
, response_id
);
454 stun_message_id (&priv
->current_binding_msg
->message
, request_id
);
455 if (memcmp (request_id
, response_id
, sizeof(StunTransactionId
)) == 0) {
456 if (stun_message_get_class (&msg
) == STUN_ERROR
) {
458 uint8_t *sent_realm
= NULL
;
459 uint8_t *recv_realm
= NULL
;
460 uint16_t sent_realm_len
= 0;
461 uint16_t recv_realm_len
= 0;
463 sent_realm
= (uint8_t *) stun_message_find (
464 &priv
->current_binding_msg
->message
,
465 STUN_ATTRIBUTE_REALM
, &sent_realm_len
);
466 recv_realm
= (uint8_t *) stun_message_find (&msg
,
467 STUN_ATTRIBUTE_REALM
, &recv_realm_len
);
469 /* check for unauthorized error response */
470 if (stun_message_find_error (&msg
, &code
) ==
471 STUN_MESSAGE_RETURN_SUCCESS
&&
472 (code
== 438 || (code
== 401 &&
473 !(recv_realm
!= NULL
&&
474 recv_realm_len
> 0 &&
475 recv_realm_len
== sent_realm_len
&&
476 sent_realm
!= NULL
&&
477 memcmp (sent_realm
, recv_realm
, sent_realm_len
) == 0)))) {
478 g_free (priv
->current_binding_msg
);
479 priv
->current_binding_msg
= NULL
;
480 if (priv
->current_binding
) {
481 priv_send_channel_bind (priv
, &msg
,
482 priv
->current_binding
->channel
,
483 &priv
->current_binding
->peer
);
486 g_free (priv
->current_binding
);
487 priv
->current_binding
= NULL
;
488 g_free (priv
->current_binding_msg
);
489 priv
->current_binding_msg
= NULL
;
490 priv_process_pending_bindings (priv
);
492 } else if (stun_message_get_class (&msg
) == STUN_RESPONSE
) {
493 g_free (priv
->current_binding_msg
);
494 priv
->current_binding_msg
= NULL
;
495 if (priv
->current_binding
) {
496 priv
->channels
= g_list_append (priv
->channels
,
497 priv
->current_binding
);
498 priv
->current_binding
= NULL
;
500 priv_process_pending_bindings (priv
);
505 } else if (stun_message_get_class (&msg
) == STUN_INDICATION
&&
506 stun_message_get_method (&msg
) == STUN_IND_DATA
) {
510 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
511 if (stun_message_find_xor_addr (&msg
, STUN_ATTRIBUTE_REMOTE_ADDRESS
,
512 (struct sockaddr
*)&sa
, &from_len
) !=
513 STUN_MESSAGE_RETURN_SUCCESS
)
516 if (stun_message_find_addr (&msg
, STUN_ATTRIBUTE_REMOTE_ADDRESS
,
517 (struct sockaddr
*)&sa
, &from_len
) !=
518 STUN_MESSAGE_RETURN_SUCCESS
)
522 data
= (uint8_t *) stun_message_find (&msg
, STUN_ATTRIBUTE_DATA
,
528 nice_address_set_from_sockaddr (from
, (struct sockaddr
*)&sa
);
531 memmove (buf
, data
, len
> data_len
? data_len
: len
);
532 return len
> data_len
? data_len
: len
;
540 for (i
= priv
->channels
; i
; i
= i
->next
) {
541 ChannelBinding
*b
= i
->data
;
542 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
543 if (b
->channel
== ntohs(((uint16_t *)recv_buf
)[0])) {
544 recv_len
= ntohs (((uint16_t *)recv_buf
)[1]);
545 recv_buf
+= sizeof(uint32_t);
556 *from
= binding
->peer
;
562 memmove (buf
, recv_buf
, len
> recv_len
? recv_len
: len
);
563 return len
> recv_len
? recv_len
: len
;
567 if (priv
->current_binding
) {
568 GList
*i
= priv
->channels
;
569 for (; i
; i
= i
->next
) {
570 ChannelBinding
*b
= i
->data
;
573 g_list_free (priv
->channels
);
574 priv
->channels
= g_list_append (NULL
, priv
->current_binding
);
575 priv
->current_binding
= NULL
;
576 priv_process_pending_bindings (priv
);
583 nice_turn_socket_set_peer (NiceSocket
*sock
, NiceAddress
*peer
)
585 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
586 return priv_add_channel_binding (priv
, peer
);
590 priv_process_pending_bindings (TurnPriv
*priv
)
592 gboolean ret
= FALSE
;
593 while (priv
->pending_bindings
!= NULL
&& ret
== FALSE
) {
594 NiceAddress
*peer
= priv
->pending_bindings
->data
;
595 ret
= priv_add_channel_binding (priv
, peer
);
596 priv
->pending_bindings
= g_list_remove (priv
->pending_bindings
, peer
);
597 nice_address_free (peer
);
602 priv_retransmissions_tick_unlocked (TurnPriv
*priv
)
604 if (priv
->current_binding_msg
) {
605 switch (stun_timer_refresh (&priv
->current_binding_msg
->timer
)) {
606 case STUN_USAGE_TIMER_RETURN_TIMEOUT
:
609 StunTransactionId id
;
611 g_free (priv
->current_binding
);
612 priv
->current_binding
= NULL
;
613 g_free (priv
->current_binding_msg
);
614 priv
->current_binding_msg
= NULL
;
616 stun_message_id (&priv
->current_binding_msg
->message
, id
);
617 stun_agent_forget_transaction (&priv
->agent
, id
);
619 priv_process_pending_bindings (priv
);
622 case STUN_USAGE_TIMER_RETURN_RETRANSMIT
:
624 nice_socket_send (priv
->base_socket
, &priv
->server_addr
,
625 stun_message_length (&priv
->current_binding_msg
->message
),
626 (gchar
*)priv
->current_binding_msg
->buffer
);
628 case STUN_USAGE_TIMER_RETURN_SUCCESS
:
633 priv_schedule_tick (priv
);
639 priv_retransmissions_tick (gpointer pointer
)
641 TurnPriv
*priv
= pointer
;
644 g_static_rec_mutex_lock (&priv
->nice
->mutex
);
645 ret
= priv_retransmissions_tick_unlocked (priv
);
646 g_static_rec_mutex_unlock (&priv
->nice
->mutex
);
652 priv_schedule_tick (TurnPriv
*priv
)
654 if (priv
->tick_source
!= NULL
) {
655 g_source_destroy (priv
->tick_source
);
656 g_source_unref (priv
->tick_source
);
657 priv
->tick_source
= NULL
;
660 if (priv
->current_binding_msg
) {
661 guint timeout
= stun_timer_remainder (&priv
->current_binding_msg
->timer
);
663 priv
->tick_source
= agent_timeout_add_with_context (priv
->nice
, timeout
,
664 priv_retransmissions_tick
, priv
);
666 priv_retransmissions_tick_unlocked (priv
);
672 priv_send_turn_message (TurnPriv
*priv
, TURNMessage
*msg
)
674 size_t stun_len
= stun_message_length (&msg
->message
);
676 if (priv
->current_binding_msg
) {
677 g_free (priv
->current_binding_msg
);
678 priv
->current_binding_msg
= NULL
;
681 nice_socket_send (priv
->base_socket
, &priv
->server_addr
,
682 stun_len
, (gchar
*)msg
->buffer
);
684 if (nice_socket_is_reliable (priv
->base_socket
)) {
685 stun_timer_start_reliable (&msg
->timer
);
687 stun_timer_start (&msg
->timer
);
690 priv
->current_binding_msg
= msg
;
691 priv_schedule_tick (priv
);
695 priv_send_channel_bind (TurnPriv
*priv
, StunMessage
*resp
,
696 uint16_t channel
, NiceAddress
*peer
)
698 uint32_t channel_attr
= channel
<< 16;
700 struct sockaddr_storage sa
;
701 TURNMessage
*msg
= g_new0 (TURNMessage
, 1);
703 nice_address_copy_to_sockaddr (peer
, (struct sockaddr
*)&sa
);
705 if (!stun_agent_init_request (&priv
->agent
, &msg
->message
,
706 msg
->buffer
, sizeof(msg
->buffer
), STUN_CHANNELBIND
)) {
711 if (stun_message_append32 (&msg
->message
, STUN_ATTRIBUTE_CHANNEL_NUMBER
,
712 channel_attr
) != STUN_MESSAGE_RETURN_SUCCESS
) {
717 if (stun_message_append_xor_addr (&msg
->message
, STUN_ATTRIBUTE_PEER_ADDRESS
,
718 (struct sockaddr
*)&sa
, sizeof(sa
)) != STUN_MESSAGE_RETURN_SUCCESS
) {
723 if (priv
->username
!= NULL
&& priv
->username_len
> 0) {
724 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_USERNAME
,
725 priv
->username
, priv
->username_len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
736 realm
= (uint8_t *) stun_message_find (resp
, STUN_ATTRIBUTE_REALM
, &len
);
738 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_REALM
,
739 realm
, len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
744 nonce
= (uint8_t *) stun_message_find (resp
, STUN_ATTRIBUTE_NONCE
, &len
);
746 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_NONCE
,
747 nonce
, len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
754 stun_len
= stun_agent_finish_message (&priv
->agent
, &msg
->message
,
755 priv
->password
, priv
->password_len
);
758 priv_send_turn_message (priv
, msg
);
767 priv_add_channel_binding (TurnPriv
*priv
, NiceAddress
*peer
)
770 struct sockaddr_storage sa
;
772 nice_address_copy_to_sockaddr (peer
, (struct sockaddr
*)&sa
);
774 if (priv
->current_binding
) {
775 NiceAddress
* pending
= nice_address_new ();
777 priv
->pending_bindings
= g_list_append (priv
->pending_bindings
, pending
);
781 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
782 uint16_t channel
= 0x4000;
783 GList
*i
= priv
->channels
;
784 for (; i
; i
= i
->next
) {
785 ChannelBinding
*b
= i
->data
;
786 if (channel
== b
->channel
) {
793 if (channel
>= 0x4000 && channel
< 0xffff) {
794 gboolean ret
= priv_send_channel_bind (priv
, NULL
, channel
, peer
);
796 priv
->current_binding
= g_new0 (ChannelBinding
, 1);
797 priv
->current_binding
->channel
= channel
;
798 priv
->current_binding
->peer
= *peer
;
803 } else if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_MSN
) {
804 TURNMessage
*msg
= g_new0 (TURNMessage
, 1);
805 if (!stun_agent_init_request (&priv
->agent
, &msg
->message
,
806 msg
->buffer
, sizeof(msg
->buffer
), STUN_OLD_SET_ACTIVE_DST
)) {
811 if (stun_message_append32 (&msg
->message
, STUN_ATTRIBUTE_MAGIC_COOKIE
,
812 TURN_MAGIC_COOKIE
) != STUN_MESSAGE_RETURN_SUCCESS
) {
817 if (priv
->username
!= NULL
&& priv
->username_len
> 0) {
818 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_USERNAME
,
819 priv
->username
, priv
->username_len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
825 if (stun_message_append_addr (&msg
->message
,
826 STUN_ATTRIBUTE_DESTINATION_ADDRESS
,
827 (struct sockaddr
*)&sa
, sizeof(sa
)) != STUN_MESSAGE_RETURN_SUCCESS
) {
832 stun_len
= stun_agent_finish_message (&priv
->agent
, &msg
->message
,
833 priv
->password
, priv
->password_len
);
836 priv
->current_binding
= g_new0 (ChannelBinding
, 1);
837 priv
->current_binding
->channel
= 0;
838 priv
->current_binding
->peer
= *peer
;
839 priv_send_turn_message (priv
, msg
);
844 } else if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
) {
845 priv
->current_binding
= g_new0 (ChannelBinding
, 1);
846 priv
->current_binding
->channel
= 0;
847 priv
->current_binding
->peer
= *peer
;