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"
58 uint8_t buffer
[STUN_MAX_MESSAGE_SIZE
];
72 GList
*pending_bindings
;
73 ChannelBinding
*current_binding
;
74 TURNMessage
*current_binding_msg
;
76 NiceSocket
*base_socket
;
77 NiceAddress server_addr
;
82 NiceTurnSocketCompatibility compatibility
;
87 static void socket_close (NiceSocket
*sock
);
88 static gint
socket_recv (NiceSocket
*sock
, NiceAddress
*from
,
89 guint len
, gchar
*buf
);
90 static gboolean
socket_send (NiceSocket
*sock
, const NiceAddress
*to
,
91 guint len
, const gchar
*buf
);
92 static gboolean
socket_is_reliable (NiceSocket
*sock
);
94 static void priv_process_pending_bindings (TurnPriv
*priv
);
95 static gboolean
priv_retransmissions_tick_unlocked (TurnPriv
*priv
);
96 static gboolean
priv_retransmissions_tick (gpointer pointer
);
97 static void priv_schedule_tick (TurnPriv
*priv
);
98 static void priv_send_turn_message (TurnPriv
*priv
, TURNMessage
*msg
);
99 static gboolean
priv_send_channel_bind (TurnPriv
*priv
, StunMessage
*resp
,
100 uint16_t channel
, NiceAddress
*peer
);
101 static gboolean
priv_add_channel_binding (TurnPriv
*priv
, NiceAddress
*peer
);
106 nice_turn_socket_new (NiceAgent
*agent
, NiceAddress
*addr
,
107 NiceSocket
*base_socket
, NiceAddress
*server_addr
,
108 gchar
*username
, gchar
*password
, NiceTurnSocketCompatibility compatibility
)
110 TurnPriv
*priv
= g_new0 (TurnPriv
, 1);
111 NiceSocket
*sock
= g_slice_new0 (NiceSocket
);
117 if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
118 stun_agent_init (&priv
->agent
, STUN_ALL_KNOWN_ATTRIBUTES
,
119 STUN_COMPATIBILITY_RFC5389
,
120 STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS
);
121 } else if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_MSN
) {
122 stun_agent_init (&priv
->agent
, STUN_ALL_KNOWN_ATTRIBUTES
,
123 STUN_COMPATIBILITY_RFC3489
,
124 STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS
|
125 STUN_AGENT_USAGE_NO_INDICATION_AUTH
);
126 } else if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
) {
127 stun_agent_init (&priv
->agent
, STUN_ALL_KNOWN_ATTRIBUTES
,
128 STUN_COMPATIBILITY_RFC3489
,
129 STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS
|
130 STUN_AGENT_USAGE_IGNORE_CREDENTIALS
);
134 priv
->channels
= NULL
;
135 priv
->current_binding
= NULL
;
136 priv
->base_socket
= base_socket
;
138 if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_MSN
) {
139 priv
->username
= g_base64_decode (username
, &priv
->username_len
);
140 priv
->password
= g_base64_decode (password
, &priv
->password_len
);
142 priv
->username
= (uint8_t *)g_strdup (username
);
143 priv
->username_len
= (size_t) strlen (username
);
144 if (compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
) {
145 priv
->password
= NULL
;
146 priv
->password_len
= 0;
148 priv
->password
= (uint8_t *)g_strdup (password
);
149 priv
->password_len
= (size_t) strlen (password
);
152 priv
->server_addr
= *server_addr
;
153 priv
->compatibility
= compatibility
;
155 sock
->fileno
= base_socket
->fileno
;
156 sock
->send
= socket_send
;
157 sock
->recv
= socket_recv
;
158 sock
->is_reliable
= socket_is_reliable
;
159 sock
->close
= socket_close
;
160 sock
->priv
= (void *) priv
;
166 socket_close (NiceSocket
*sock
)
168 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
170 for (i
= priv
->channels
; i
; i
= i
->next
) {
171 ChannelBinding
*b
= i
->data
;
174 g_list_free (priv
->channels
);
176 for (i
= priv
->pending_bindings
; i
; i
= i
->next
) {
177 ChannelBinding
*b
= i
->data
;
180 g_list_free (priv
->pending_bindings
);
182 if (priv
->tick_source
!= NULL
) {
183 g_source_destroy (priv
->tick_source
);
184 g_source_unref (priv
->tick_source
);
185 priv
->tick_source
= NULL
;
188 g_free (priv
->current_binding
);
189 g_free (priv
->current_binding_msg
);
190 g_free (priv
->username
);
191 g_free (priv
->password
);
196 socket_recv (NiceSocket
*sock
, NiceAddress
*from
, guint len
, gchar
*buf
)
198 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
199 uint8_t recv_buf
[STUN_MAX_MESSAGE_SIZE
];
201 NiceAddress recv_from
;
204 recv_len
= nice_socket_recv (priv
->base_socket
, &recv_from
,
205 sizeof(recv_buf
), (gchar
*) recv_buf
);
207 return nice_turn_socket_parse_recv (sock
, &dummy
, from
, len
, buf
,
208 &recv_from
, (gchar
*) recv_buf
, (guint
) recv_len
);
212 socket_send (NiceSocket
*sock
, const NiceAddress
*to
,
213 guint len
, const gchar
*buf
)
215 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
217 uint8_t buffer
[STUN_MAX_MESSAGE_SIZE
];
219 struct sockaddr_storage sa
;
220 GList
*i
= priv
->channels
;
221 ChannelBinding
*binding
= NULL
;
223 for (; i
; i
= i
->next
) {
224 ChannelBinding
*b
= i
->data
;
225 if (nice_address_equal (&b
->peer
, to
)) {
231 nice_address_copy_to_sockaddr (to
, (struct sockaddr
*)&sa
);
234 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
&&
235 len
+ sizeof(uint32_t) <= sizeof(buffer
)) {
236 uint16_t len16
= htons ((uint16_t) len
);
237 uint16_t channel16
= htons (binding
->channel
);
238 memcpy (buffer
, &channel16
, sizeof(uint16_t));
239 memcpy (buffer
+ sizeof(uint16_t), &len16
,sizeof(uint16_t));
240 memcpy (buffer
+ sizeof(uint32_t), buf
, len
);
241 msg_len
= len
+ sizeof(uint32_t);
243 return nice_socket_send (priv
->base_socket
, &priv
->server_addr
, len
, buf
);
246 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
247 if (!stun_agent_init_indication (&priv
->agent
, &msg
,
248 buffer
, sizeof(buffer
), STUN_IND_SEND
))
250 if (stun_message_append_xor_addr (&msg
, STUN_ATTRIBUTE_PEER_ADDRESS
,
251 (struct sockaddr
*)&sa
, sizeof(sa
)) !=
252 STUN_MESSAGE_RETURN_SUCCESS
)
255 if (!stun_agent_init_request (&priv
->agent
, &msg
,
256 buffer
, sizeof(buffer
), STUN_SEND
))
259 if (stun_message_append32 (&msg
, STUN_ATTRIBUTE_MAGIC_COOKIE
,
260 TURN_MAGIC_COOKIE
) != STUN_MESSAGE_RETURN_SUCCESS
)
262 if (priv
->username
!= NULL
&& priv
->username_len
> 0) {
263 if (stun_message_append_bytes (&msg
, STUN_ATTRIBUTE_USERNAME
,
264 priv
->username
, priv
->username_len
) !=
265 STUN_MESSAGE_RETURN_SUCCESS
)
268 if (stun_message_append_addr (&msg
, STUN_ATTRIBUTE_DESTINATION_ADDRESS
,
269 (struct sockaddr
*)&sa
, sizeof(sa
)) != STUN_MESSAGE_RETURN_SUCCESS
)
272 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
&&
273 priv
->current_binding
&&
274 nice_address_equal (&priv
->current_binding
->peer
, to
)) {
275 stun_message_append32 (&msg
, STUN_ATTRIBUTE_OPTIONS
, 1);
279 if (stun_message_append_bytes (&msg
, STUN_ATTRIBUTE_DATA
,
280 buf
, len
) != STUN_MESSAGE_RETURN_SUCCESS
)
283 msg_len
= stun_agent_finish_message (&priv
->agent
, &msg
,
284 priv
->password
, priv
->password_len
);
288 return nice_socket_send (priv
->base_socket
, &priv
->server_addr
,
289 msg_len
, (gchar
*)buffer
);
292 return nice_socket_send (priv
->base_socket
, to
, len
, buf
);
296 socket_is_reliable (NiceSocket
*sock
)
298 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
299 return nice_socket_is_reliable (priv
->base_socket
);
305 nice_turn_socket_parse_recv (NiceSocket
*sock
, NiceSocket
**from_sock
,
306 NiceAddress
*from
, guint len
, gchar
*buf
,
307 NiceAddress
*recv_from
, gchar
*recv_buf
, guint recv_len
)
310 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
311 StunValidationStatus valid
;
313 struct sockaddr_storage sa
;
314 socklen_t from_len
= sizeof (sa
);
315 GList
*i
= priv
->channels
;
316 ChannelBinding
*binding
= NULL
;
318 if (nice_address_equal (&priv
->server_addr
, recv_from
)) {
319 valid
= stun_agent_validate (&priv
->agent
, &msg
,
320 (uint8_t *) recv_buf
, (size_t) recv_len
, NULL
, NULL
);
322 if (valid
== STUN_VALIDATION_SUCCESS
) {
323 if (priv
->compatibility
!= NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
325 if (stun_message_find32 (&msg
, STUN_ATTRIBUTE_MAGIC_COOKIE
,
326 &cookie
) != STUN_MESSAGE_RETURN_SUCCESS
)
328 if (cookie
!= TURN_MAGIC_COOKIE
)
332 if (stun_message_get_method (&msg
) == STUN_SEND
) {
333 if (stun_message_get_class (&msg
) == STUN_RESPONSE
&&
334 priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
) {
336 if (stun_message_find32 (&msg
, STUN_ATTRIBUTE_OPTIONS
, &opts
) ==
337 STUN_MESSAGE_RETURN_SUCCESS
&& opts
& 0x1)
338 goto msn_google_lock
;
341 } else if (stun_message_get_method (&msg
) == STUN_OLD_SET_ACTIVE_DST
) {
342 StunTransactionId request_id
;
343 StunTransactionId response_id
;
344 if (priv
->current_binding
&& priv
->current_binding_msg
) {
345 stun_message_id (&msg
, response_id
);
346 stun_message_id (&priv
->current_binding_msg
->message
, request_id
);
347 if (memcmp (request_id
, response_id
, sizeof(StunTransactionId
)) == 0) {
348 g_free (priv
->current_binding_msg
);
349 priv
->current_binding_msg
= NULL
;
351 if (stun_message_get_class (&msg
) == STUN_RESPONSE
&&
352 priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_MSN
) {
353 goto msn_google_lock
;
355 g_free (priv
->current_binding
);
356 priv
->current_binding
= NULL
;
362 } else if (stun_message_get_method (&msg
) == STUN_CHANNELBIND
) {
363 StunTransactionId request_id
;
364 StunTransactionId response_id
;
365 if (priv
->current_binding
&& priv
->current_binding_msg
) {
366 stun_message_id (&msg
, response_id
);
367 stun_message_id (&priv
->current_binding_msg
->message
, request_id
);
368 if (memcmp (request_id
, response_id
, sizeof(StunTransactionId
)) == 0) {
369 if (stun_message_get_class (&msg
) == STUN_ERROR
) {
371 uint8_t *sent_realm
= NULL
;
372 uint8_t *recv_realm
= NULL
;
373 uint16_t sent_realm_len
= 0;
374 uint16_t recv_realm_len
= 0;
376 sent_realm
= (uint8_t *) stun_message_find (
377 &priv
->current_binding_msg
->message
,
378 STUN_ATTRIBUTE_REALM
, &sent_realm_len
);
379 recv_realm
= (uint8_t *) stun_message_find (&msg
,
380 STUN_ATTRIBUTE_REALM
, &recv_realm_len
);
382 /* check for unauthorized error response */
383 if (stun_message_find_error (&msg
, &code
) ==
384 STUN_MESSAGE_RETURN_SUCCESS
&&
385 (code
== 438 || (code
== 401 &&
386 !(recv_realm
!= NULL
&&
387 recv_realm_len
> 0 &&
388 recv_realm_len
== sent_realm_len
&&
389 sent_realm
!= NULL
&&
390 memcmp (sent_realm
, recv_realm
, sent_realm_len
) == 0)))) {
391 g_free (priv
->current_binding_msg
);
392 priv
->current_binding_msg
= NULL
;
393 if (priv
->current_binding
) {
394 priv_send_channel_bind (priv
, &msg
,
395 priv
->current_binding
->channel
,
396 &priv
->current_binding
->peer
);
399 g_free (priv
->current_binding
);
400 priv
->current_binding
= NULL
;
401 g_free (priv
->current_binding_msg
);
402 priv
->current_binding_msg
= NULL
;
403 priv_process_pending_bindings (priv
);
405 } else if (stun_message_get_class (&msg
) == STUN_RESPONSE
) {
406 g_free (priv
->current_binding_msg
);
407 priv
->current_binding_msg
= NULL
;
408 if (priv
->current_binding
) {
409 priv
->channels
= g_list_append (priv
->channels
,
410 priv
->current_binding
);
411 priv
->current_binding
= NULL
;
413 priv_process_pending_bindings (priv
);
418 } else if (stun_message_get_class (&msg
) == STUN_INDICATION
&&
419 stun_message_get_method (&msg
) == STUN_IND_DATA
) {
423 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
424 if (stun_message_find_xor_addr (&msg
, STUN_ATTRIBUTE_REMOTE_ADDRESS
,
425 (struct sockaddr
*)&sa
, &from_len
) !=
426 STUN_MESSAGE_RETURN_SUCCESS
)
429 if (stun_message_find_addr (&msg
, STUN_ATTRIBUTE_REMOTE_ADDRESS
,
430 (struct sockaddr
*)&sa
, &from_len
) !=
431 STUN_MESSAGE_RETURN_SUCCESS
)
435 data
= (uint8_t *) stun_message_find (&msg
, STUN_ATTRIBUTE_DATA
,
441 nice_address_set_from_sockaddr (from
, (struct sockaddr
*)&sa
);
444 memmove (buf
, data
, len
> data_len
? data_len
: len
);
445 return len
> data_len
? data_len
: len
;
453 for (i
= priv
->channels
; i
; i
= i
->next
) {
454 ChannelBinding
*b
= i
->data
;
455 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
456 if (b
->channel
== ntohs(((uint16_t *)recv_buf
)[0])) {
457 recv_len
= ntohs (((uint16_t *)recv_buf
)[1]);
458 recv_buf
+= sizeof(uint32_t);
469 *from
= binding
->peer
;
475 memmove (buf
, recv_buf
, len
> recv_len
? recv_len
: len
);
476 return len
> recv_len
? recv_len
: len
;
480 if (priv
->current_binding
) {
481 GList
*i
= priv
->channels
;
482 for (; i
; i
= i
->next
) {
483 ChannelBinding
*b
= i
->data
;
486 g_list_free (priv
->channels
);
487 priv
->channels
= g_list_append (NULL
, priv
->current_binding
);
488 priv
->current_binding
= NULL
;
489 priv_process_pending_bindings (priv
);
496 nice_turn_socket_set_peer (NiceSocket
*sock
, NiceAddress
*peer
)
498 TurnPriv
*priv
= (TurnPriv
*) sock
->priv
;
499 return priv_add_channel_binding (priv
, peer
);
503 priv_process_pending_bindings (TurnPriv
*priv
)
505 gboolean ret
= FALSE
;
506 while (priv
->pending_bindings
!= NULL
&& ret
== FALSE
) {
507 NiceAddress
*peer
= priv
->pending_bindings
->data
;
508 ret
= priv_add_channel_binding (priv
, peer
);
509 priv
->pending_bindings
= g_list_remove (priv
->pending_bindings
, peer
);
510 nice_address_free (peer
);
515 priv_retransmissions_tick_unlocked (TurnPriv
*priv
)
517 if (priv
->current_binding_msg
) {
518 switch (stun_timer_refresh (&priv
->current_binding_msg
->timer
)) {
519 case STUN_USAGE_TIMER_RETURN_TIMEOUT
:
521 g_free (priv
->current_binding
);
522 priv
->current_binding
= NULL
;
523 g_free (priv
->current_binding_msg
);
524 priv
->current_binding_msg
= NULL
;
525 priv_process_pending_bindings (priv
);
527 case STUN_USAGE_TIMER_RETURN_RETRANSMIT
:
529 nice_socket_send (priv
->base_socket
, &priv
->server_addr
,
530 stun_message_length (&priv
->current_binding_msg
->message
),
531 (gchar
*)priv
->current_binding_msg
->buffer
);
533 case STUN_USAGE_TIMER_RETURN_SUCCESS
:
538 priv_schedule_tick (priv
);
544 priv_retransmissions_tick (gpointer pointer
)
546 TurnPriv
*priv
= pointer
;
549 g_static_rec_mutex_lock (&priv
->nice
->mutex
);
550 ret
= priv_retransmissions_tick_unlocked (priv
);
551 g_static_rec_mutex_unlock (&priv
->nice
->mutex
);
557 priv_schedule_tick (TurnPriv
*priv
)
559 if (priv
->tick_source
!= NULL
) {
560 g_source_destroy (priv
->tick_source
);
561 g_source_unref (priv
->tick_source
);
562 priv
->tick_source
= NULL
;
565 if (priv
->current_binding_msg
) {
566 guint timeout
= stun_timer_remainder (&priv
->current_binding_msg
->timer
);
568 priv
->tick_source
= agent_timeout_add_with_context (priv
->nice
, timeout
,
569 priv_retransmissions_tick
, priv
);
571 priv_retransmissions_tick_unlocked (priv
);
577 priv_send_turn_message (TurnPriv
*priv
, TURNMessage
*msg
)
579 size_t stun_len
= stun_message_length (&msg
->message
);
581 if (priv
->current_binding_msg
) {
582 g_free (priv
->current_binding_msg
);
583 priv
->current_binding_msg
= NULL
;
586 nice_socket_send (priv
->base_socket
, &priv
->server_addr
,
587 stun_len
, (gchar
*)msg
->buffer
);
589 if (nice_socket_is_reliable (priv
->base_socket
)) {
590 stun_timer_start_reliable (&msg
->timer
);
592 stun_timer_start (&msg
->timer
);
595 priv
->current_binding_msg
= msg
;
596 priv_schedule_tick (priv
);
600 priv_send_channel_bind (TurnPriv
*priv
, StunMessage
*resp
,
601 uint16_t channel
, NiceAddress
*peer
)
603 uint32_t channel_attr
= channel
<< 16;
605 struct sockaddr_storage sa
;
606 TURNMessage
*msg
= g_new0 (TURNMessage
, 1);
608 nice_address_copy_to_sockaddr (peer
, (struct sockaddr
*)&sa
);
610 if (!stun_agent_init_request (&priv
->agent
, &msg
->message
,
611 msg
->buffer
, sizeof(msg
->buffer
), STUN_CHANNELBIND
)) {
616 if (stun_message_append32 (&msg
->message
, STUN_ATTRIBUTE_CHANNEL_NUMBER
,
617 channel_attr
) != STUN_MESSAGE_RETURN_SUCCESS
) {
622 if (stun_message_append_xor_addr (&msg
->message
, STUN_ATTRIBUTE_PEER_ADDRESS
,
623 (struct sockaddr
*)&sa
, sizeof(sa
)) != STUN_MESSAGE_RETURN_SUCCESS
) {
628 if (priv
->username
!= NULL
&& priv
->username_len
> 0) {
629 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_USERNAME
,
630 priv
->username
, priv
->username_len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
641 realm
= (uint8_t *) stun_message_find (resp
, STUN_ATTRIBUTE_REALM
, &len
);
643 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_REALM
,
644 realm
, len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
649 nonce
= (uint8_t *) stun_message_find (resp
, STUN_ATTRIBUTE_NONCE
, &len
);
651 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_NONCE
,
652 nonce
, len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
659 stun_len
= stun_agent_finish_message (&priv
->agent
, &msg
->message
,
660 priv
->password
, priv
->password_len
);
663 priv_send_turn_message (priv
, msg
);
672 priv_add_channel_binding (TurnPriv
*priv
, NiceAddress
*peer
)
675 struct sockaddr_storage sa
;
677 nice_address_copy_to_sockaddr (peer
, (struct sockaddr
*)&sa
);
679 if (priv
->current_binding
) {
680 NiceAddress
* pending
= nice_address_new ();
682 priv
->pending_bindings
= g_list_append (priv
->pending_bindings
, pending
);
686 if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
) {
687 uint16_t channel
= 0x4000;
688 GList
*i
= priv
->channels
;
689 for (; i
; i
= i
->next
) {
690 ChannelBinding
*b
= i
->data
;
691 if (channel
== b
->channel
) {
698 if (channel
>= 0x4000 && channel
< 0xffff) {
699 gboolean ret
= priv_send_channel_bind (priv
, NULL
, channel
, peer
);
701 priv
->current_binding
= g_new0 (ChannelBinding
, 1);
702 priv
->current_binding
->channel
= channel
;
703 priv
->current_binding
->peer
= *peer
;
708 } else if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_MSN
) {
709 TURNMessage
*msg
= g_new0 (TURNMessage
, 1);
710 if (!stun_agent_init_request (&priv
->agent
, &msg
->message
,
711 msg
->buffer
, sizeof(msg
->buffer
), STUN_OLD_SET_ACTIVE_DST
)) {
716 if (stun_message_append32 (&msg
->message
, STUN_ATTRIBUTE_MAGIC_COOKIE
,
717 TURN_MAGIC_COOKIE
) != STUN_MESSAGE_RETURN_SUCCESS
) {
722 if (priv
->username
!= NULL
&& priv
->username_len
> 0) {
723 if (stun_message_append_bytes (&msg
->message
, STUN_ATTRIBUTE_USERNAME
,
724 priv
->username
, priv
->username_len
) != STUN_MESSAGE_RETURN_SUCCESS
) {
730 if (stun_message_append_addr (&msg
->message
,
731 STUN_ATTRIBUTE_DESTINATION_ADDRESS
,
732 (struct sockaddr
*)&sa
, sizeof(sa
)) != STUN_MESSAGE_RETURN_SUCCESS
) {
737 stun_len
= stun_agent_finish_message (&priv
->agent
, &msg
->message
,
738 priv
->password
, priv
->password_len
);
741 priv
->current_binding
= g_new0 (ChannelBinding
, 1);
742 priv
->current_binding
->channel
= 0;
743 priv
->current_binding
->peer
= *peer
;
744 priv_send_turn_message (priv
, msg
);
749 } else if (priv
->compatibility
== NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
) {
750 priv
->current_binding
= g_new0 (ChannelBinding
, 1);
751 priv
->current_binding
->channel
= 0;
752 priv
->current_binding
->peer
= *peer
;