Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
libnice
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
libnice
Commits
bbd1d93e
Commit
bbd1d93e
authored
Aug 23, 2010
by
Marcus Lundblad
Committed by
Youness Alaoui
Dec 14, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remaining changes for RFC 5766
parent
a58b6e00
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
465 additions
and
47 deletions
+465
-47
agent/interfaces.c
agent/interfaces.c
+1
-1
socket/turn.c
socket/turn.c
+376
-32
socket/turn.h
socket/turn.h
+1
-0
stun/stunagent.c
stun/stunagent.c
+5
-1
stun/stunmessage.c
stun/stunmessage.c
+0
-1
stun/tests/test-turn.c
stun/tests/test-turn.c
+1
-1
stun/usages/turn.c
stun/usages/turn.c
+56
-5
stun/usages/turn.h
stun/usages/turn.h
+18
-1
tests/test-fullmode.c
tests/test-fullmode.c
+7
-5
No files found.
agent/interfaces.c
View file @
bbd1d93e
...
...
@@ -172,7 +172,7 @@ nice_interfaces_get_local_ips (gboolean include_loopback)
GList
*
ips
=
NULL
;
struct
ifaddrs
*
ifa
,
*
results
;
GList
*
loopbacks
=
NULL
;
int
ret
;
if
(
getifaddrs
(
&
results
)
<
0
)
return
NULL
;
...
...
socket/turn.c
View file @
bbd1d93e
...
...
@@ -44,6 +44,7 @@
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include "turn.h"
#include "stun/stunagent.h"
...
...
@@ -52,7 +53,8 @@
#define STUN_END_TIMEOUT 8000
#define STUN_MAX_MS_REALM_LEN 128 // as defined in [MS-TURN]
#define STUN_PERMISSION_TIMEOUT 240
/* 300-60 s */
#define STUN_BINDING_TIMEOUT 540
/* 600-60 s */
typedef
struct
{
StunMessage
message
;
...
...
@@ -72,8 +74,9 @@ typedef struct {
GList
*
pending_bindings
;
ChannelBinding
*
current_binding
;
TURNMessage
*
current_binding_msg
;
GSource
*
tick_source
;
TURNMessage
*
current_create_permission_msg
;
GSource
*
tick_source_channel_bind
;
GSource
*
tick_source_create_permission
;
NiceSocket
*
base_socket
;
NiceAddress
server_addr
;
uint8_t
*
username
;
...
...
@@ -86,6 +89,14 @@ typedef struct {
uint8_t
ms_connection_id
[
20
];
uint32_t
ms_sequence_num
;
bool
ms_connection_id_valid
;
gboolean
has_permission
;
gboolean
sent_permission
;
guint
num_sent_permission
;
GQueue
*
send_data
;
guint
permission_timeout_source
;
gboolean
has_binding
;
gboolean
sent_binding
;
guint
binding_timeout_source
;
}
TurnPriv
;
...
...
@@ -95,6 +106,12 @@ typedef struct {
TurnPriv
*
priv
;
}
SendRequest
;
typedef
struct
{
gchar
*
data
;
guint
data_len
;
NiceAddress
*
to
;
}
SendData
;
static
void
socket_close
(
NiceSocket
*
sock
);
static
gint
socket_recv
(
NiceSocket
*
sock
,
NiceAddress
*
from
,
guint
len
,
gchar
*
buf
);
...
...
@@ -107,9 +124,12 @@ static gboolean priv_retransmissions_tick_unlocked (TurnPriv *priv);
static
gboolean
priv_retransmissions_tick
(
gpointer
pointer
);
static
void
priv_schedule_tick
(
TurnPriv
*
priv
);
static
void
priv_send_turn_message
(
TurnPriv
*
priv
,
TURNMessage
*
msg
);
static
gboolean
priv_send_create_permission
(
TurnPriv
*
priv
,
uint8_t
*
realm
,
gsize
realm_len
,
uint8_t
*
nonce
,
gsize
nonce_len
,
struct
sockaddr
*
peer
);
static
gboolean
priv_send_channel_bind
(
TurnPriv
*
priv
,
StunMessage
*
resp
,
uint16_t
channel
,
NiceAddress
*
peer
);
static
gboolean
priv_add_channel_binding
(
TurnPriv
*
priv
,
NiceAddress
*
peer
);
uint16_t
channel
,
const
NiceAddress
*
peer
);
static
gboolean
priv_add_channel_binding
(
TurnPriv
*
priv
,
const
NiceAddress
*
peer
);
static
gboolean
priv_forget_send_request
(
gpointer
pointer
);
...
...
@@ -125,7 +145,8 @@ nice_turn_socket_new (NiceAgent *agent, NiceAddress *addr,
return
NULL
;
}
if
(
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
)
{
if
(
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
||
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_RFC5766
)
{
stun_agent_init
(
&
priv
->
agent
,
STUN_ALL_KNOWN_ATTRIBUTES
,
STUN_COMPATIBILITY_RFC5389
,
STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS
);
...
...
@@ -170,6 +191,7 @@ nice_turn_socket_new (NiceAgent *agent, NiceAddress *addr,
priv
->
server_addr
=
*
server_addr
;
priv
->
compatibility
=
compatibility
;
priv
->
send_requests
=
g_queue_new
();
priv
->
send_data
=
g_queue_new
();
sock
->
addr
=
*
addr
;
sock
->
fileno
=
base_socket
->
fileno
;
sock
->
send
=
socket_send
;
...
...
@@ -216,9 +238,18 @@ socket_close (NiceSocket *sock)
}
g_queue_free
(
priv
->
send_requests
);
for
(
i
=
g_queue_peek_head_link
(
priv
->
send_data
)
;
i
;
i
=
i
->
next
)
{
SendData
*
d
=
i
->
data
;
nice_address_free
(
d
->
to
);
g_slice_free
(
SendData
,
d
);
}
g_queue_free
(
priv
->
send_data
);
g_source_remove
(
priv
->
permission_timeout_source
);
g_free
(
priv
->
current_binding
);
g_free
(
priv
->
current_binding_msg
);
g_free
(
priv
->
current_create_permission_msg
);
g_free
(
priv
->
username
);
g_free
(
priv
->
password
);
g_free
(
priv
);
...
...
@@ -233,6 +264,8 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
NiceAddress
recv_from
;
NiceSocket
*
dummy
;;
nice_debug
(
"received message on TURN socket"
);
recv_len
=
nice_socket_recv
(
priv
->
base_socket
,
&
recv_from
,
sizeof
(
recv_buf
),
(
gchar
*
)
recv_buf
);
...
...
@@ -270,6 +303,40 @@ stun_message_ensure_ms_realm(StunMessage *msg, uint8_t *realm)
}
}
static
void
socket_enqueue_data
(
NiceSocket
*
sock
,
const
NiceAddress
*
to
,
guint
len
,
const
gchar
*
buf
)
{
SendData
*
data
=
g_slice_new0
(
SendData
);
data
->
data
=
g_memdup
(
buf
,
len
);
data
->
data_len
=
len
;
data
->
to
=
nice_address_dup
(
to
);
g_queue_push_tail
(((
TurnPriv
*
)
sock
->
priv
)
->
send_data
,
data
);
}
static
gboolean
socket_has_enqueued_data
(
NiceSocket
*
sock
)
{
return
g_queue_get_length
(((
TurnPriv
*
)
sock
->
priv
)
->
send_data
)
>
0
;
}
static
void
socket_dequeue_data
(
NiceSocket
*
sock
)
{
SendData
*
data
=
(
SendData
*
)
g_queue_pop_head
(((
TurnPriv
*
)
sock
->
priv
)
->
send_data
);
nice_debug
(
"dequeing data enqueued when installing permission or binding"
);
socket_send
(
sock
,
data
->
to
,
data
->
data_len
,
data
->
data
);
g_free
(
data
->
data
);
nice_address_free
(
data
->
to
);
g_slice_free
(
SendData
,
data
);
}
static
gboolean
socket_send
(
NiceSocket
*
sock
,
const
NiceAddress
*
to
,
guint
len
,
const
gchar
*
buf
)
...
...
@@ -290,10 +357,13 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
}
}
nice_debug
(
"in turn.c:socket_send"
);
nice_address_copy_to_sockaddr
(
to
,
(
struct
sockaddr
*
)
&
sa
);
if
(
binding
)
{
if
(
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
)
{
if
(
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
||
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_RFC5766
)
{
if
(
len
+
sizeof
(
uint32_t
)
<=
sizeof
(
buffer
))
{
uint16_t
len16
=
htons
((
uint16_t
)
len
);
uint16_t
channel16
=
htons
(
binding
->
channel
);
...
...
@@ -308,7 +378,9 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
return
nice_socket_send
(
priv
->
base_socket
,
&
priv
->
server_addr
,
len
,
buf
);
}
}
else
{
if
(
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
)
{
nice_debug
(
"no binding"
);
if
(
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
||
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_RFC5766
)
{
if
(
!
stun_agent_init_indication
(
&
priv
->
agent
,
&
msg
,
buffer
,
sizeof
(
buffer
),
STUN_IND_SEND
))
goto
send
;
...
...
@@ -369,9 +441,34 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
}
if
(
msg_len
>
0
)
{
nice_debug
(
"before send"
);
if
(
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_RFC5766
)
{
if
(
!
priv
->
has_permission
&&
!
priv
->
sent_permission
)
{
nice_debug
(
"no permission installed for peer"
);
priv_send_create_permission
(
priv
,
NULL
,
0
,
NULL
,
0
,
(
struct
sockaddr
*
)
&
sa
);
}
}
if
(
!
priv
->
has_binding
&&
!
priv
->
sent_binding
&&
binding
)
{
nice_debug
(
"renewing channel binding"
);
priv_send_channel_bind
(
priv
,
NULL
,
binding
->
channel
,
to
);
}
nice_debug
(
"about to send: permission %d, binding %d"
,
priv
->
has_permission
,
priv
->
has_binding
);
if
(
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_RFC5766
&&
!
priv
->
has_permission
)
{
/* enque data */
nice_debug
(
"enqueing data to be sent when aquiring permission or binding"
);
socket_enqueue_data
(
sock
,
to
,
msg_len
,
(
gchar
*
)
buffer
);
return
TRUE
;
}
else
{
return
nice_socket_send
(
priv
->
base_socket
,
&
priv
->
server_addr
,
msg_len
,
(
gchar
*
)
buffer
);
}
}
send:
return
nice_socket_send
(
priv
->
base_socket
,
to
,
len
,
buf
);
}
...
...
@@ -412,6 +509,33 @@ priv_forget_send_request (gpointer pointer)
return
FALSE
;
}
static
gboolean
priv_permission_timeout
(
gpointer
data
)
{
TurnPriv
*
priv
=
(
TurnPriv
*
)
data
;
nice_debug
(
"Permission is about to timeout, schedule renewal"
);
agent_lock
();
priv
->
has_permission
=
FALSE
;
agent_unlock
();
return
TRUE
;
}
static
gboolean
priv_binding_timeout
(
gpointer
data
)
{
TurnPriv
*
priv
=
(
TurnPriv
*
)
data
;
nice_debug
(
"Permission is about to timeout, schedule renewal"
);
agent_lock
();
priv
->
has_binding
=
FALSE
;
agent_unlock
();
return
TRUE
;
}
gint
nice_turn_socket_parse_recv
(
NiceSocket
*
sock
,
NiceSocket
**
from_sock
,
...
...
@@ -432,7 +556,8 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
(
uint8_t
*
)
recv_buf
,
(
size_t
)
recv_len
,
NULL
,
NULL
);
if
(
valid
==
STUN_VALIDATION_SUCCESS
)
{
if
(
priv
->
compatibility
!=
NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
)
{
if
(
priv
->
compatibility
!=
NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
&&
priv
->
compatibility
!=
NICE_TURN_SOCKET_COMPATIBILITY_RFC5766
)
{
uint32_t
cookie
;
if
(
stun_message_find32
(
&
msg
,
STUN_ATTRIBUTE_MAGIC_COOKIE
,
&
cookie
)
!=
STUN_MESSAGE_RETURN_SUCCESS
)
...
...
@@ -500,7 +625,8 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
}
else
if
(
stun_message_get_method
(
&
msg
)
==
STUN_CHANNELBIND
)
{
StunTransactionId
request_id
;
StunTransactionId
response_id
;
if
(
priv
->
current_binding
&&
priv
->
current_binding_msg
)
{
if
(
priv
->
current_binding_msg
)
{
stun_message_id
(
&
msg
,
response_id
);
stun_message_id
(
&
priv
->
current_binding_msg
->
message
,
request_id
);
if
(
memcmp
(
request_id
,
response_id
,
sizeof
(
StunTransactionId
))
==
0
)
{
...
...
@@ -517,6 +643,11 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
recv_realm
=
(
uint8_t
*
)
stun_message_find
(
&
msg
,
STUN_ATTRIBUTE_REALM
,
&
recv_realm_len
);
if
(
!
priv
->
has_binding
)
{
nice_debug
(
"sent realm: %s
\n
"
,
sent_realm
);
nice_debug
(
"recv realm: %s
\n
"
,
recv_realm
);
}
/* check for unauthorized error response */
if
(
stun_message_find_error
(
&
msg
,
&
code
)
==
STUN_MESSAGE_RETURN_SUCCESS
&&
...
...
@@ -526,12 +657,39 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
recv_realm_len
==
sent_realm_len
&&
sent_realm
!=
NULL
&&
memcmp
(
sent_realm
,
recv_realm
,
sent_realm_len
)
==
0
))))
{
if
(
priv
->
current_binding
)
{
g_free
(
priv
->
current_binding_msg
);
priv
->
current_binding_msg
=
NULL
;
if
(
priv
->
current_binding
)
{
priv_send_channel_bind
(
priv
,
&
msg
,
priv
->
current_binding
->
channel
,
&
priv
->
current_binding
->
peer
);
}
else
{
/* look up binding associated with peer */
GList
*
i
=
priv
->
channels
;
ChannelBinding
*
binding
=
NULL
;
struct
sockaddr
sa
;
socklen_t
sa_len
=
sizeof
(
sa
);
NiceAddress
to
;
stun_message_find_xor_addr
(
&
priv
->
current_binding_msg
->
message
,
STUN_ATTRIBUTE_XOR_PEER_ADDRESS
,
&
sa
,
&
sa_len
);
nice_address_set_from_sockaddr
(
&
to
,
&
sa
);
for
(;
i
;
i
=
i
->
next
)
{
ChannelBinding
*
b
=
i
->
data
;
if
(
nice_address_equal
(
&
b
->
peer
,
&
to
))
{
binding
=
b
;
break
;
}
}
g_free
(
priv
->
current_binding_msg
);
priv
->
current_binding_msg
=
NULL
;
if
(
binding
)
priv_send_channel_bind
(
priv
,
&
msg
,
binding
->
channel
,
&
to
);
}
}
else
{
g_free
(
priv
->
current_binding
);
...
...
@@ -543,22 +701,92 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
}
else
if
(
stun_message_get_class
(
&
msg
)
==
STUN_RESPONSE
)
{
g_free
(
priv
->
current_binding_msg
);
priv
->
current_binding_msg
=
NULL
;
priv
->
has_binding
=
TRUE
;
priv
->
sent_binding
=
FALSE
;
if
(
priv
->
current_binding
)
{
priv
->
channels
=
g_list_append
(
priv
->
channels
,
priv
->
current_binding
);
priv
->
current_binding
=
NULL
;
}
priv_process_pending_bindings
(
priv
);
/* install timer to schedule refresh of the permission */
if
(
!
priv
->
binding_timeout_source
)
{
priv
->
binding_timeout_source
=
g_timeout_add_seconds
(
STUN_BINDING_TIMEOUT
,
priv_binding_timeout
,
priv
);
}
}
}
}
return
0
;
}
else
if
(
stun_message_get_method
(
&
msg
)
==
STUN_CREATEPERMISSION
)
{
StunTransactionId
request_id
;
StunTransactionId
response_id
;
if
(
priv
->
current_create_permission_msg
)
{
stun_message_id
(
&
msg
,
response_id
);
stun_message_id
(
&
priv
->
current_create_permission_msg
->
message
,
request_id
);
if
(
memcmp
(
request_id
,
response_id
,
sizeof
(
StunTransactionId
))
==
0
)
{
struct
sockaddr
peer
;
socklen_t
peer_len
=
sizeof
(
peer
);
nice_debug
(
"got response for CreatePermission"
);
stun_message_find_xor_addr
(
&
priv
->
current_create_permission_msg
->
message
,
STUN_ATTRIBUTE_XOR_PEER_ADDRESS
,
&
peer
,
&
peer_len
);
g_free
(
priv
->
current_create_permission_msg
);
priv
->
current_create_permission_msg
=
NULL
;
if
(
stun_message_get_class
(
&
msg
)
==
STUN_ERROR
)
{
uint8_t
*
recv_realm
=
NULL
;
uint16_t
recv_realm_len
=
0
;
uint8_t
*
recv_nonce
=
NULL
;
uint16_t
recv_nonce_len
=
0
;
recv_realm
=
(
uint8_t
*
)
stun_message_find
(
&
msg
,
STUN_ATTRIBUTE_REALM
,
&
recv_realm_len
);
recv_nonce
=
(
uint8_t
*
)
stun_message_find
(
&
msg
,
STUN_ATTRIBUTE_NONCE
,
&
recv_nonce_len
);
nice_debug
(
"got realm: %s"
,
recv_realm
);
nice_debug
(
"got nonce: %s"
,
recv_nonce
);
/* resend CreatePermission */
if
(
priv
->
num_sent_permission
<
2
)
priv_send_create_permission
(
priv
,
recv_realm
,
recv_realm_len
,
recv_nonce
,
recv_nonce_len
,
&
peer
);
}
else
{
priv
->
has_permission
=
TRUE
;
priv
->
sent_permission
=
FALSE
;
priv
->
num_sent_permission
=
0
;
/* install timer to schedule refresh of the permission */
if
(
!
priv
->
permission_timeout_source
)
{
priv
->
permission_timeout_source
=
g_timeout_add_seconds
(
STUN_PERMISSION_TIMEOUT
,
priv_permission_timeout
,
priv
);
}
/* send enqued data, unless there is also an ongoing channel bind */
nice_debug
(
"about to dequeue data: sent_binding: %d"
,
priv
->
sent_binding
);
while
(
socket_has_enqueued_data
(
sock
))
{
socket_dequeue_data
(
sock
);
}
}
}
}
return
0
;
}
else
if
(
stun_message_get_class
(
&
msg
)
==
STUN_INDICATION
&&
stun_message_get_method
(
&
msg
)
==
STUN_IND_DATA
)
{
uint16_t
data_len
;
uint8_t
*
data
;
if
(
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
)
{
if
(
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
||
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_RFC5766
)
{
if
(
stun_message_find_xor_addr
(
&
msg
,
STUN_ATTRIBUTE_REMOTE_ADDRESS
,
(
struct
sockaddr
*
)
&
sa
,
&
from_len
)
!=
STUN_MESSAGE_RETURN_SUCCESS
)
...
...
@@ -590,7 +818,8 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
recv:
for
(
i
=
priv
->
channels
;
i
;
i
=
i
->
next
)
{
ChannelBinding
*
b
=
i
->
data
;
if
(
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
)
{
if
(
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
||
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_RFC5766
)
{
if
(
b
->
channel
==
ntohs
(((
uint16_t
*
)
recv_buf
)[
0
]))
{
recv_len
=
ntohs
(((
uint16_t
*
)
recv_buf
)[
1
]);
recv_buf
+=
sizeof
(
uint32_t
);
...
...
@@ -634,6 +863,7 @@ gboolean
nice_turn_socket_set_peer
(
NiceSocket
*
sock
,
NiceAddress
*
peer
)
{
TurnPriv
*
priv
=
(
TurnPriv
*
)
sock
->
priv
;
return
priv_add_channel_binding
(
priv
,
peer
);
}
...
...
@@ -649,6 +879,7 @@ priv_process_pending_bindings (TurnPriv *priv)
}
}
static
gboolean
priv_retransmissions_tick_unlocked
(
TurnPriv
*
priv
)
{
...
...
@@ -686,6 +917,38 @@ priv_retransmissions_tick_unlocked (TurnPriv *priv)
return
FALSE
;
}
static
gboolean
priv_retransmissions_create_permission_tick_unlocked
(
TurnPriv
*
priv
)
{
if
(
priv
->
current_create_permission_msg
)
{
switch
(
stun_timer_refresh
(
&
priv
->
current_create_permission_msg
->
timer
))
{
case
STUN_USAGE_TIMER_RETURN_TIMEOUT
:
{
/* Time out */
StunTransactionId
id
;
stun_message_id
(
&
priv
->
current_create_permission_msg
->
message
,
id
);
stun_agent_forget_transaction
(
&
priv
->
agent
,
id
);
g_free
(
priv
->
current_create_permission_msg
);
priv
->
current_create_permission_msg
=
NULL
;
break
;
}
case
STUN_USAGE_TIMER_RETURN_RETRANSMIT
:
/* Retransmit */
nice_socket_send
(
priv
->
base_socket
,
&
priv
->
server_addr
,
stun_message_length
(
&
priv
->
current_create_permission_msg
->
message
),
(
gchar
*
)
priv
->
current_create_permission_msg
->
buffer
);
break
;
case
STUN_USAGE_TIMER_RETURN_SUCCESS
:
break
;
}
}
priv_schedule_tick
(
priv
);
return
FALSE
;
}
static
gboolean
priv_retransmissions_tick
(
gpointer
pointer
)
...
...
@@ -714,6 +977,33 @@ priv_retransmissions_tick (gpointer pointer)
return
ret
;
}
static
gboolean
priv_retransmissions_create_permission_tick
(
gpointer
pointer
)
{
TurnPriv
*
priv
=
pointer
;
gboolean
ret
;
agent_lock
();
if
(
g_source_is_destroyed
(
g_main_current_source
()))
{
nice_debug
(
"Source was destroyed. "
"Avoided race condition in turn.c:priv_retransmissions_create_permission_tick"
);
agent_unlock
();
return
FALSE
;
}
ret
=
priv_retransmissions_create_permission_tick_unlocked
(
priv
);
if
(
ret
==
FALSE
)
{
if
(
priv
->
tick_source_create_permission
!=
NULL
)
{
g_source_destroy
(
priv
->
tick_source_create_permission
);
g_source_unref
(
priv
->
tick_source_create_permission
);
priv
->
tick_source_create_permission
=
NULL
;
}
}
agent_unlock
();
return
ret
;
}
static
void
priv_schedule_tick
(
TurnPriv
*
priv
)
{
...
...
@@ -733,6 +1023,16 @@ priv_schedule_tick (TurnPriv *priv)
priv_retransmissions_tick_unlocked
(
priv
);
}
}
if
(
priv
->
current_create_permission_msg
)
{
guint
timeout
=
stun_timer_remainder
(
&
priv
->
current_create_permission_msg
->
timer
);
if
(
timeout
>
0
)
{
priv
->
tick_source_create_permission
=
agent_timeout_add_with_context
(
priv
->
nice
,
timeout
,
priv_retransmissions_create_permission_tick
,
priv
);
}
else
{
priv_retransmissions_create_permission_tick_unlocked
(
priv
);
}
}
}
static
void
...
...
@@ -760,15 +1060,57 @@ priv_send_turn_message (TurnPriv *priv, TURNMessage *msg)
priv_schedule_tick
(
priv
);
}
static
gboolean
priv_send_create_permission
(
TurnPriv
*
priv
,
uint8_t
*
realm
,
gsize
realm_len
,
uint8_t
*
nonce
,
gsize
nonce_len
,
struct
sockaddr
*
peer
)
{
guint
msg_buf_len
;
gboolean
res
=
FALSE
;
TURNMessage
*
msg
=
g_new0
(
TURNMessage
,
1
);
nice_debug
(
"creating CreatePermission message"
);
priv
->
sent_permission
=
TRUE
;
priv
->
num_sent_permission
++
;
/* send CreatePermission */
msg_buf_len
=
stun_usage_turn_create_permission
(
&
priv
->
agent
,
&
msg
->
message
,
msg
->
buffer
,
sizeof
(
msg
->
buffer
),
priv
->
username
,
priv
->
username_len
,
priv
->
password
,
priv
->
password_len
,
realm
,
realm_len
,
nonce
,
nonce_len
,
peer
,
NICE_TURN_SOCKET_COMPATIBILITY_RFC5766
);
if
(
msg_buf_len
>
0
)
{
nice_debug
(
"sending CreatePermission message, lenght: %d"
,
msg_buf_len
);
res
=
nice_socket_send
(
priv
->
base_socket
,
&
priv
->
server_addr
,
msg_buf_len
,
(
gchar
*
)
msg
->
buffer
);
nice_debug
(
"sent CreatePermission message, result: %d"
,
res
);
if
(
nice_socket_is_reliable
(
priv
->
base_socket
))
{
stun_timer_start_reliable
(
&
msg
->
timer
);
}
else
{
stun_timer_start
(
&
msg
->
timer
);
}
priv_schedule_tick
(
priv
);
priv
->
current_create_permission_msg
=
msg
;
}
else
{
g_free
(
msg
);
}
return
res
;
}
static
gboolean
priv_send_channel_bind
(
TurnPriv
*
priv
,
StunMessage
*
resp
,
uint16_t
channel
,
NiceAddress
*
peer
)
uint16_t
channel
,
const
NiceAddress
*
peer
)
{
uint32_t
channel_attr
=
channel
<<
16
;
size_t
stun_len
;
struct
sockaddr_storage
sa
;
TURNMessage
*
msg
=
g_new0
(
TURNMessage
,
1
);
priv
->
sent_binding
=
TRUE
;
nice_address_copy_to_sockaddr
(
peer
,
(
struct
sockaddr
*
)
&
sa
);
if
(
!
stun_agent_init_request
(
&
priv
->
agent
,
&
msg
->
message
,
...
...
@@ -833,11 +1175,12 @@ priv_send_channel_bind (TurnPriv *priv, StunMessage *resp,
}
static
gboolean
priv_add_channel_binding
(
TurnPriv
*
priv
,
NiceAddress
*
peer
)
priv_add_channel_binding
(
TurnPriv
*
priv
,
const
NiceAddress
*
peer
)
{
size_t
stun_len
;
struct
sockaddr_storage
sa
;
priv
->
sent_binding
=
TRUE
;
nice_address_copy_to_sockaddr
(
peer
,
(
struct
sockaddr
*
)
&
sa
);
if
(
priv
->
current_binding
)
{
...
...
@@ -847,7 +1190,8 @@ priv_add_channel_binding (TurnPriv *priv, NiceAddress *peer)
return
FALSE
;
}
if
(
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
)
{
if
(
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9
||
priv
->
compatibility
==
NICE_TURN_SOCKET_COMPATIBILITY_RFC5766
)
{
uint16_t
channel
=
0x4000
;
GList
*
i
=
priv
->
channels
;
for
(;
i
;
i
=
i
->
next
)
{
...
...
socket/turn.h
View file @
bbd1d93e
...
...
@@ -43,6 +43,7 @@ typedef enum {
NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE
,
NICE_TURN_SOCKET_COMPATIBILITY_MSN
,
NICE_TURN_SOCKET_COMPATIBILITY_OC2007
,
NICE_TURN_SOCKET_COMPATIBILITY_RFC5766
,
}
NiceTurnSocketCompatibility
;
#include "socket.h"
...
...
stun/stunagent.c
View file @
bbd1d93e
...
...
@@ -43,6 +43,7 @@
#include "stunhmac.h"
#include "stun5389.h"
#include "utils.h"
#include "debug.h"
#include <string.h>
#include <stdlib.h>
...
...
@@ -548,6 +549,7 @@ size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg,
STUN_ATTRIBUTE_REALM
,
&
realm_len
);
username
=
(
uint8_t
*
)
stun_message_find
(
msg
,
STUN_ATTRIBUTE_USERNAME
,
&
username_len
);
if
(
username
==
NULL
||
realm
==
NULL
)
{
skip
=
TRUE
;
}
else
{
...
...
@@ -640,6 +642,8 @@ size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg,
msg
->
key
=
(
uint8_t
*
)
key
;
msg
->
key_len
=
key_len
;
stun_debug
(
"stun_agent_finish_message, returning lenght: %d
\n
"
,
stun_message_length
(
msg
));
return
stun_message_length
(
msg
);
}
...
...
stun/stunmessage.c
View file @
bbd1d93e
...
...
@@ -59,7 +59,6 @@
bool
stun_message_init
(
StunMessage
*
msg
,
StunClass
c
,
StunMethod
m
,
const
StunTransactionId
id
)
{
if
(
msg
->
buffer_len
<
STUN_MESSAGE_HEADER_LENGTH
)
return
FALSE
;
...
...
stun/tests/test-turn.c
View file @
bbd1d93e
...
...
@@ -238,7 +238,7 @@ static void test_turn (char *username, char *password, char *hostname, int port)
static
void
turnserver
(
void
)
{
test_turn
(
"
toto"
,
"password"
,
"127.0.0.1"
,
"3478
"
);
test_turn
(
"
anonymous"
,
"anonymous"
,
"91.121.109.155"
,
"3480
"
);
}
static
void
numb
(
void
)
...
...
stun/usages/turn.c
View file @
bbd1d93e
...
...
@@ -79,7 +79,8 @@ size_t stun_usage_turn_create (StunAgent *agent, StunMessage *msg,
{
stun_agent_init_request
(
agent
,
msg
,
buffer
,
buffer_len
,
STUN_ALLOCATE
);
if
(
compatibility
==
STUN_USAGE_TURN_COMPATIBILITY_DRAFT9
)
{
if
(
compatibility
==
STUN_USAGE_TURN_COMPATIBILITY_DRAFT9
||
compatibility
==
STUN_USAGE_TURN_COMPATIBILITY_RFC5766
)
{
if
(
stun_message_append32
(
msg
,
STUN_ATTRIBUTE_REQUESTED_TRANSPORT
,
TURN_REQUESTED_TRANSPORT_UDP
)
!=
STUN_MESSAGE_RETURN_SUCCESS
)
return
0
;
...
...
@@ -104,7 +105,8 @@ size_t stun_usage_turn_create (StunAgent *agent, StunMessage *msg,
return
0
;
}
if
(
compatibility
==
STUN_USAGE_TURN_COMPATIBILITY_DRAFT9
&&
if
((
compatibility
==
STUN_USAGE_TURN_COMPATIBILITY_DRAFT9
||
compatibility
==
STUN_USAGE_TURN_COMPATIBILITY_RFC5766
)
&&
request_props
!=
STUN_USAGE_TURN_REQUEST_PORT_NORMAL
)
{
uint32_t
req
=
0
;
...
...
@@ -166,7 +168,8 @@ size_t stun_usage_turn_create_refresh (StunAgent *agent, StunMessage *msg,
StunUsageTurnCompatibility
compatibility
)
{
if
(
compatibility
!=
STUN_USAGE_TURN_COMPATIBILITY_DRAFT9
)
{
if
(
compatibility
!=
STUN_USAGE_TURN_COMPATIBILITY_DRAFT9
&&
compatibility
!=
STUN_USAGE_TURN_COMPATIBILITY_RFC5766
)
{
return
stun_usage_turn_create
(
agent
,
msg
,
buffer
,
buffer_len
,
previous_response
,
STUN_USAGE_TURN_REQUEST_PORT_NORMAL
,
0
,
lifetime
,
username
,
username_len
,
password
,
password_len
,
compatibility
);
...
...
@@ -211,6 +214,52 @@ size_t stun_usage_turn_create_refresh (StunAgent *agent, StunMessage *msg,
return
stun_agent_finish_message
(
agent
,
msg
,
password
,
password_len
);
}
size_t
stun_usage_turn_create_permission
(
StunAgent
*
agent
,
StunMessage
*
msg
,
uint8_t
*
buffer
,
size_t
buffer_len
,
uint8_t
*
username
,
size_t
username_len
,
uint8_t
*
password
,
size_t
password_len
,
uint8_t
*
realm
,
size_t
realm_len
,
uint8_t
*
nonce
,
size_t
nonce_len
,
struct
sockaddr
*
peer
,
StunUsageTurnCompatibility
compatibility
)
{
stun_agent_init_request
(
agent
,
msg
,
buffer
,
buffer_len
,
STUN_CREATEPERMISSION
);
/* PEER address */
if
(
peer
)
{
if
(
stun_message_append_xor_addr
(
msg
,
STUN_ATTRIBUTE_XOR_PEER_ADDRESS
,
peer
,
sizeof
(
*
peer
))
!=
STUN_MESSAGE_RETURN_SUCCESS
)
{
return
0
;
}
}
/* nonce */
if
(
nonce
!=
NULL
)
{
if
(
stun_message_append_bytes
(
msg
,
STUN_ATTRIBUTE_NONCE
,
nonce
,
nonce_len
)
!=
STUN_MESSAGE_RETURN_SUCCESS
)
return
0
;
}
/* realm */
if
(
realm
!=
NULL
)
{
if
(
stun_message_append_bytes
(
msg
,
STUN_ATTRIBUTE_REALM
,
realm
,
realm_len
)
!=
STUN_MESSAGE_RETURN_SUCCESS
)
return
0
;
}
/* username */
if
(
username
!=
NULL
)
{
if
(
stun_message_append_bytes
(
msg
,
STUN_ATTRIBUTE_USERNAME
,
username
,
username_len
)
!=
STUN_MESSAGE_RETURN_SUCCESS
)
return
0
;
}
stun_debug
(
"before stun_agent_finish_message
\n
"
);
return
stun_agent_finish_message
(
agent
,
msg
,
password
,
password_len
);
}
StunUsageTurnReturn
stun_usage_turn_process
(
StunMessage
*
msg
,
struct
sockaddr
*
relay_addr
,
socklen_t
*
relay_addrlen
,
struct
sockaddr
*
addr
,
socklen_t
*
addrlen
,
...
...
@@ -269,7 +318,8 @@ StunUsageTurnReturn stun_usage_turn_process (StunMessage *msg,
stun_debug
(
"Received %u-bytes STUN message
\n
"
,
stun_message_length
(
msg
));
if
(
compatibility
==
STUN_USAGE_TURN_COMPATIBILITY_DRAFT9
)
{
if
(
compatibility
==
STUN_USAGE_TURN_COMPATIBILITY_DRAFT9
||
compatibility
==
STUN_USAGE_TURN_COMPATIBILITY_RFC5766
)
{
val
=
stun_message_find_xor_addr
(
msg
,
STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS
,
addr
,
addrlen
);
...
...
@@ -320,7 +370,8 @@ StunUsageTurnReturn stun_usage_turn_refresh_process (StunMessage *msg,
int
code
=
-
1
;
StunUsageTurnReturn
ret
=
STUN_USAGE_TURN_RETURN_RELAY_SUCCESS
;
if
(
compatibility
==
STUN_USAGE_TURN_COMPATIBILITY_DRAFT9
)
{
if
(
compatibility
==
STUN_USAGE_TURN_COMPATIBILITY_DRAFT9
||
compatibility
==
STUN_USAGE_TURN_COMPATIBILITY_RFC5766
)
{
if
(
stun_message_get_method
(
msg
)
!=
STUN_REFRESH
)
return
STUN_USAGE_TURN_RETURN_INVALID
;
}
else
{
...
...
stun/usages/turn.h
View file @
bbd1d93e
...
...
@@ -59,8 +59,14 @@
# include <stdint.h>
#endif
# include "stun/stunagent.h"
#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#endif
# include "stun/stunagent.h"
# ifdef __cplusplus
extern
"C"
{
# endif
...
...
@@ -97,6 +103,7 @@ typedef enum {
STUN_USAGE_TURN_COMPATIBILITY_GOOGLE
,
STUN_USAGE_TURN_COMPATIBILITY_MSN
,
STUN_USAGE_TURN_COMPATIBILITY_OC2007
STUN_USAGE_TURN_COMPATIBILITY_RFC5766
,
}
StunUsageTurnCompatibility
;
/**
...
...
@@ -197,6 +204,16 @@ size_t stun_usage_turn_create_refresh (StunAgent *agent, StunMessage *msg,
uint8_t
*
password
,
size_t
password_len
,
StunUsageTurnCompatibility
compatibility
);
size_t
stun_usage_turn_create_permission
(
StunAgent
*
agent
,
StunMessage
*
msg
,
uint8_t
*
buffer
,
size_t
buffer_len
,
uint8_t
*
username
,
size_t
username_len
,
uint8_t
*
password
,
size_t
password_len
,
uint8_t
*
realm
,
size_t
realm_len
,
uint8_t
*
nonce
,
size_t
nonce_len
,
struct
sockaddr
*
peer
,
StunUsageTurnCompatibility
compatibility
);
/**
* stun_usage_turn_process:
* @msg: The message containing the response
...
...
tests/test-fullmode.c
View file @
bbd1d93e
...
...
@@ -44,9 +44,10 @@
#include <string.h>
#define USE_TURN
0
#define USE_TURN
1
#define USE_LOOPBACK 1
#define TEST_GOOGLE 0
#define USE_TURN_SERVER_ORG 1
#define PROXY_IP "127.0.0.1"
#define PROXY_PORT 1080
...
...
@@ -85,10 +86,10 @@
#define NUMB_USER "youness.alaoui@collabora.co.uk"
#define NUMB_PASS "badger"
#define TSORG_IP "
127.0.0.1
"
#define TSORG_PORT 34
78
#define TSORG_USER "
toto
"
#define TSORG_PASS "
password
"
#define TSORG_IP "
91.121.109.155
"
#define TSORG_PORT 34
80
#define TSORG_USER "
anonymous
"
#define TSORG_PASS "
anonymous
"
#if USE_TURN_SERVER_ORG
...
...
@@ -348,6 +349,7 @@ static int run_full_test (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *bas
g_assert
(
ls_id
>
0
);
g_assert
(
rs_id
>
0
);
#if USE_TURN
nice_debug
(
"TURN_IP: %s
\n
"
,
TURN_IP
);
nice_agent_set_relay_info
(
lagent
,
ls_id
,
1
,
TURN_IP
,
TURN_PORT
,
TURN_USER
,
TURN_PASS
,
TURN_TYPE
);
nice_agent_set_relay_info
(
lagent
,
ls_id
,
2
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment