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
5576d7e8
Commit
5576d7e8
authored
Sep 10, 2008
by
Youness Alaoui
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
(WIP) Add TURN support to libnice
parent
b9749015
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
208 additions
and
16 deletions
+208
-16
agent/agent.c
agent/agent.c
+58
-9
agent/conncheck.c
agent/conncheck.c
+89
-0
agent/discovery.c
agent/discovery.c
+13
-6
agent/discovery.h
agent/discovery.h
+3
-0
agent/test-fullmode.c
agent/test-fullmode.c
+45
-1
No files found.
agent/agent.c
View file @
5576d7e8
...
...
@@ -640,10 +640,10 @@ agent_candidate_pair_priority (NiceAgent *agent, NiceCandidate *local, NiceCandi
}
static
gboolean
priv_add_new_candidate_discovery
(
NiceAgent
*
agent
,
priv_add_new_candidate_discovery
_stun
(
NiceAgent
*
agent
,
NiceCandidate
*
host_candidate
,
NiceAddress
server
,
Stream
*
stream
,
guint
component_id
,
NiceAddress
*
addr
,
NiceCandidateType
type
)
NiceAddress
*
addr
)
{
CandidateDiscovery
*
cdisco
;
GSList
*
modified_list
;
...
...
@@ -656,7 +656,7 @@ priv_add_new_candidate_discovery (NiceAgent *agent,
modified_list
=
g_slist_append
(
agent
->
discovery_list
,
cdisco
);
if
(
modified_list
)
{
cdisco
->
type
=
type
;
cdisco
->
type
=
NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE
;
cdisco
->
socket
=
host_candidate
->
sockptr
->
fileno
;
cdisco
->
nicesock
=
host_candidate
->
sockptr
;
cdisco
->
server
=
server
;
...
...
@@ -675,6 +675,55 @@ priv_add_new_candidate_discovery (NiceAgent *agent,
return
FALSE
;
}
static
gboolean
priv_add_new_candidate_discovery_turn
(
NiceAgent
*
agent
,
NiceCandidate
*
host_candidate
,
NiceAddress
server
,
Stream
*
stream
,
guint
component_id
,
NiceAddress
*
addr
,
gboolean
long_term
)
{
CandidateDiscovery
*
cdisco
;
GSList
*
modified_list
;
/* note: no need to check for redundant candidates, as this is
* done later on in the process */
cdisco
=
g_slice_new0
(
CandidateDiscovery
);
if
(
cdisco
)
{
modified_list
=
g_slist_append
(
agent
->
discovery_list
,
cdisco
);
if
(
modified_list
)
{
cdisco
->
type
=
NICE_CANDIDATE_TYPE_RELAYED
;
cdisco
->
socket
=
host_candidate
->
sockptr
->
fileno
;
cdisco
->
nicesock
=
host_candidate
->
sockptr
;
cdisco
->
server
=
server
;
cdisco
->
interface
=
addr
;
cdisco
->
stream
=
stream
;
cdisco
->
component
=
stream_find_component_by_id
(
stream
,
component_id
);
cdisco
->
agent
=
agent
;
if
(
agent
->
compatibility
==
NICE_COMPATIBILITY_ID19
)
{
stun_agent_init
(
&
cdisco
->
turn_agent
,
STUN_ALL_KNOWN_ATTRIBUTES
,
STUN_COMPATIBILITY_3489BIS
,
long_term
?
STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS
:
STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS
);
}
else
{
stun_agent_init
(
&
cdisco
->
turn_agent
,
STUN_ALL_KNOWN_ATTRIBUTES
,
STUN_COMPATIBILITY_RFC3489
,
long_term
?
STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS
:
STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS
);
}
nice_debug
(
"Agent %p : Adding new srv-rflx candidate discovery %p
\n
"
,
agent
,
cdisco
);
agent
->
discovery_list
=
modified_list
;
++
agent
->
discovery_unsched_items
;
}
return
TRUE
;
}
return
FALSE
;
}
/**
* nice_agent_add_stream:
...
...
@@ -802,17 +851,16 @@ nice_agent_gather_candidates (
if
(
agent
->
full_mode
&&
agent
->
stun_server_ip
)
{
NiceAddress
stun_server
;
if
(
nice_address_set_from_string
(
&
stun_server
,
agent
->
stun_server_ip
))
{
if
(
nice_address_set_from_string
(
&
stun_server
,
agent
->
stun_server_ip
))
{
nice_address_set_port
(
&
stun_server
,
agent
->
stun_server_port
);
gboolean
res
=
priv_add_new_candidate_discovery
(
agent
,
priv_add_new_candidate_discovery
_stun
(
agent
,
host_candidate
,
stun_server
,
stream
,
n
+
1
/* component-id */
,
addr
,
NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE
);
addr
);
if
(
res
!=
TRUE
)
{
/* note: memory allocation failure, return error */
...
...
@@ -820,17 +868,18 @@ nice_agent_gather_candidates (
}
}
}
if
(
agent
->
full_mode
&&
component
&&
nice_address_is_valid
(
&
component
->
turn_server
))
{
gboolean
res
=
priv_add_new_candidate_discovery
(
agent
,
priv_add_new_candidate_discovery
_turn
(
agent
,
host_candidate
,
component
->
turn_server
,
stream
,
n
+
1
/* component-id */
,
addr
,
NICE_CANDIDATE_TYPE_RELAYED
);
component
->
turn_long_term
);
if
(
res
!=
TRUE
)
{
/* note: memory allocation failure, return error */
...
...
agent/conncheck.c
View file @
5576d7e8
...
...
@@ -1726,6 +1726,88 @@ static gboolean priv_map_reply_to_discovery_request (NiceAgent *agent, StunMessa
}
/**
* Tries to match STUN reply in 'buf' to an existing STUN discovery
* transaction. If found, a reply is sent.
*
* @return TRUE if a matching transaction is found
*/
static
gboolean
priv_map_reply_to_relay_request
(
NiceAgent
*
agent
,
StunMessage
*
resp
)
{
struct
sockaddr
sockaddr
;
socklen_t
socklen
=
sizeof
(
sockaddr
);
struct
sockaddr
alternate
;
socklen_t
alternatelen
=
sizeof
(
alternate
);
struct
sockaddr
relayaddr
;
socklen_t
relayaddrlen
=
sizeof
(
relayaddr
);
uint32_t
lifetime
;
uint32_t
bandwidth
;
GSList
*
i
;
StunUsageTurnReturn
res
;
gboolean
trans_found
=
FALSE
;
stun_transid_t
discovery_id
;
stun_transid_t
response_id
;
stun_message_id
(
resp
,
response_id
);
for
(
i
=
agent
->
discovery_list
;
i
&&
trans_found
!=
TRUE
;
i
=
i
->
next
)
{
CandidateDiscovery
*
d
=
i
->
data
;
if
(
d
->
type
==
NICE_CANDIDATE_TYPE_RELAYED
&&
d
->
stun_message
.
buffer
)
{
stun_message_id
(
&
d
->
stun_message
,
discovery_id
);
if
(
memcmp
(
discovery_id
,
response_id
,
sizeof
(
stun_transid_t
))
==
0
)
{
res
=
stun_usage_turn_process
(
resp
,
&
relayaddr
,
&
relayaddrlen
,
&
sockaddr
,
&
socklen
,
&
alternate
,
&
alternatelen
,
&
bandwidth
,
&
lifetime
,
priv_agent_to_turn_compatibility
(
agent
));
nice_debug
(
"Agent %p : stun_bind_process/disc for %p res %d."
,
agent
,
d
,
(
int
)
res
);
if
(
res
==
STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER
)
{
/* TODO : handle alternate server */
}
else
if
(
res
==
STUN_USAGE_TURN_RETURN_RELAY_SUCCESS
||
res
==
STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS
)
{
/* case: succesful allocate, create a new local candidate */
NiceAddress
niceaddr
;
/* We also received our mapped address */
if
(
res
==
STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS
)
{
nice_address_set_from_sockaddr
(
&
niceaddr
,
&
sockaddr
);
discovery_add_server_reflexive_candidate
(
d
->
agent
,
d
->
stream
->
id
,
d
->
component
->
id
,
&
niceaddr
,
d
->
nicesock
);
}
nice_address_set_from_sockaddr
(
&
niceaddr
,
&
relayaddr
);
discovery_add_relay_candidate
(
d
->
agent
,
d
->
stream
->
id
,
d
->
component
->
id
,
&
niceaddr
,
d
->
nicesock
);
d
->
stun_message
.
buffer
=
NULL
;
d
->
stun_message
.
buffer_len
=
0
;
d
->
done
=
TRUE
;
trans_found
=
TRUE
;
}
else
if
(
res
==
STUN_USAGE_BIND_RETURN_ERROR
)
{
/* case: STUN error, the check STUN context was freed */
d
->
stun_message
.
buffer
=
NULL
;
d
->
stun_message
.
buffer_len
=
0
;
d
->
done
=
TRUE
;
trans_found
=
TRUE
;
}
}
}
}
return
trans_found
;
}
/**
* Processing an incoming STUN message.
*
...
...
@@ -1773,9 +1855,11 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream,
}
}
/* TODO : if we get a peer reflexive, we should check all local:remote possibilities */
validater_data
=
g_new0
(
stun_validater_data
,
g_slist_length
(
component
->
local_candidates
)
+
1
);
/* We have to check all the local candidates into our validater_data because a
server reflexive candidate shares the same socket as the host candidate,
so we have no idea the user/pass is coming from which candidate */
...
...
@@ -1798,6 +1882,7 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream,
validater_data
[
j
].
password_len
=
strlen
(
stream
->
local_password
);
}
if
(
agent
->
compatibility
==
NICE_COMPATIBILITY_MSN
)
{
validater_data
[
j
].
password
=
g_base64_decode
((
gchar
*
)
validater_data
[
j
].
password
,
...
...
@@ -1995,6 +2080,10 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream,
if
(
trans_found
!=
TRUE
)
trans_found
=
priv_map_reply_to_discovery_request
(
agent
,
&
req
);
/* step: let's try to match the response to an existing discovery */
if
(
trans_found
!=
TRUE
)
trans_found
=
priv_map_reply_to_relay_request
(
agent
,
&
req
);
if
(
trans_found
!=
TRUE
)
nice_debug
(
"Agent %p : Unable to match to an existing transaction, "
"probably a keepalive."
,
agent
);
...
...
agent/discovery.c
View file @
5576d7e8
...
...
@@ -69,6 +69,15 @@ static inline int priv_timer_expired (GTimeVal *restrict timer, GTimeVal *restri
now
->
tv_sec
>=
timer
->
tv_sec
;
}
static
StunUsageTurnCompatibility
priv_agent_to_turn_compatibility
(
NiceAgent
*
agent
)
{
return
agent
->
compatibility
==
NICE_COMPATIBILITY_ID19
?
STUN_USAGE_TURN_COMPATIBILITY_TD9
:
agent
->
compatibility
==
NICE_COMPATIBILITY_GOOGLE
?
STUN_USAGE_TURN_COMPATIBILITY_GOOGLE
:
agent
->
compatibility
==
NICE_COMPATIBILITY_MSN
?
STUN_USAGE_TURN_COMPATIBILITY_MSN
:
STUN_USAGE_TURN_COMPATIBILITY_TD9
;
}
/**
* Frees the CandidateDiscovery structure pointed to
* by 'user data'. Compatible with g_slist_foreach().
...
...
@@ -587,14 +596,14 @@ NiceCandidate *discovery_learn_remote_peer_reflexive_candidate (
gsize local_size;
gsize remote_size;
g_free(candidate->username);
decoded_local = g_base64_decode (local->username, &local_size);
decoded_remote = g_base64_decode (remote->username, &remote_size);
new_username = g_new0(gchar, local_size + remote_size);
memcpy(new_username, decoded_remote, remote_size);
memcpy(new_username + remote_size, decoded_local, local_size);
candidate->username = g_base64_encode (new_username, local_size + remote_size);
g_free(new_username);
g_free(decoded_local);
...
...
@@ -604,7 +613,7 @@ NiceCandidate *discovery_learn_remote_peer_reflexive_candidate (
candidate
->
sockptr
=
NULL
;
/* not stored for remote candidates */
/* note: candidate username and password are left NULL as stream
level ufrag/password are used */
modified_list
=
g_slist_append
(
component
->
remote_candidates
,
candidate
);
if
(
modified_list
)
{
...
...
@@ -653,14 +662,12 @@ static gboolean priv_discovery_tick_unlocked (gpointer pointer)
if
(
agent
->
discovery_unsched_items
)
--
agent
->
discovery_unsched_items
;
#ifndef NDEBUG
{
gchar
tmpbuf
[
INET6_ADDRSTRLEN
];
nice_address_to_string
(
&
cand
->
server
,
tmpbuf
);
nice_debug
(
"Agent %p : discovery - scheduling cand type %u addr %s and socket %d.
\n
"
,
agent
,
cand
->
type
,
tmpbuf
,
cand
->
socket
);
}
#endif
if
(
nice_address_is_valid
(
&
cand
->
server
)
&&
(
cand
->
type
==
NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE
||
cand
->
type
==
NICE_CANDIDATE_TYPE_RELAYED
))
{
...
...
@@ -683,7 +690,7 @@ static gboolean priv_discovery_tick_unlocked (gpointer pointer)
(
size_t
)
strlen
(
cand
->
component
->
turn_username
),
(
uint8_t
*
)
cand
->
component
->
turn_password
,
(
size_t
)
strlen
(
cand
->
component
->
turn_password
),
STUN_USAGE_TURN_COMPATIBILITY_GOOGLE
);
priv_agent_to_turn_compatibility
(
agent
)
);
}
if
(
buffer_len
>
0
)
{
...
...
agent/discovery.h
View file @
5576d7e8
...
...
@@ -56,9 +56,12 @@ struct _CandidateDiscovery
gboolean
done
;
/**< is discovery complete? */
Stream
*
stream
;
Component
*
component
;
StunAgent
turn_agent
;
stun_timer_t
timer
;
uint8_t
stun_buffer
[
STUN_MAX_MESSAGE_SIZE
];
StunMessage
stun_message
;
uint8_t
stun_resp_buffer
[
STUN_MAX_MESSAGE_SIZE
];
StunMessage
stun_resp_message
;
};
void
discovery_free_item
(
gpointer
data
,
gpointer
user_data
);
...
...
agent/test-fullmode.c
View file @
5576d7e8
...
...
@@ -43,6 +43,8 @@
#include "agent.h"
#define USE_TURN 0
static
NiceComponentState
global_lagent_state
[
2
]
=
{
NICE_COMPONENT_STATE_LAST
,
NICE_COMPONENT_STATE_LAST
};
static
NiceComponentState
global_ragent_state
[
2
]
=
{
NICE_COMPONENT_STATE_LAST
,
NICE_COMPONENT_STATE_LAST
};
static
guint
global_components_ready
=
0
;
...
...
@@ -244,9 +246,21 @@ static int run_full_test (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *bas
/* step: add one stream, with RTP+RTCP components, to each agent */
ls_id
=
nice_agent_add_stream
(
lagent
,
2
);
rs_id
=
nice_agent_add_stream
(
ragent
,
2
);
g_assert
(
ls_id
>
0
);
g_assert
(
rs_id
>
0
);
#if USE_TURN
nice_agent_set_relay_info
(
lagent
,
ls_id
,
1
,
"64.251.22.149"
,
3478
,
"youness.alaoui@collabora.co.uk"
,
"badger"
,
TRUE
);
nice_agent_set_relay_info
(
lagent
,
ls_id
,
2
,
"64.251.22.149"
,
3478
,
"youness.alaoui@collabora.co.uk"
,
"badger"
,
TRUE
);
nice_agent_set_relay_info
(
ragent
,
rs_id
,
1
,
"64.251.22.149"
,
3478
,
"youness.alaoui@collabora.co.uk"
,
"badger"
,
TRUE
);
nice_agent_set_relay_info
(
ragent
,
rs_id
,
2
,
"64.251.22.149"
,
3478
,
"youness.alaoui@collabora.co.uk"
,
"badger"
,
TRUE
);
#endif
nice_agent_gather_candidates
(
lagent
,
ls_id
);
nice_agent_gather_candidates
(
ragent
,
rs_id
);
...
...
@@ -374,9 +388,21 @@ static int run_full_test_delayed_answer (NiceAgent *lagent, NiceAgent *ragent, N
/* step: add one stream, with RTP+RTCP components, to each agent */
ls_id
=
nice_agent_add_stream
(
lagent
,
2
);
rs_id
=
nice_agent_add_stream
(
ragent
,
2
);
g_assert
(
ls_id
>
0
);
g_assert
(
rs_id
>
0
);
#if USE_TURN
nice_agent_set_relay_info
(
lagent
,
ls_id
,
1
,
"64.251.22.149"
,
3478
,
"youness.alaoui@collabora.co.uk"
,
"badger"
,
TRUE
);
nice_agent_set_relay_info
(
lagent
,
ls_id
,
2
,
"64.251.22.149"
,
3478
,
"youness.alaoui@collabora.co.uk"
,
"badger"
,
TRUE
);
nice_agent_set_relay_info
(
ragent
,
rs_id
,
1
,
"64.251.22.149"
,
3478
,
"youness.alaoui@collabora.co.uk"
,
"badger"
,
TRUE
);
nice_agent_set_relay_info
(
ragent
,
rs_id
,
2
,
"64.251.22.149"
,
3478
,
"youness.alaoui@collabora.co.uk"
,
"badger"
,
TRUE
);
#endif
nice_agent_gather_candidates
(
lagent
,
ls_id
);
nice_agent_gather_candidates
(
ragent
,
rs_id
);
...
...
@@ -521,9 +547,16 @@ static int run_full_test_wrong_password (NiceAgent *lagent, NiceAgent *ragent, N
/* step: add one stream, with one component, to each agent */
ls_id
=
nice_agent_add_stream
(
lagent
,
1
);
rs_id
=
nice_agent_add_stream
(
ragent
,
1
);
g_assert
(
ls_id
>
0
);
g_assert
(
rs_id
>
0
);
#if USE_TURN
nice_agent_set_relay_info
(
lagent
,
ls_id
,
1
,
"64.251.22.149"
,
3478
,
"youness.alaoui@collabora.co.uk"
,
"badger"
,
TRUE
);
nice_agent_set_relay_info
(
ragent
,
rs_id
,
1
,
"64.251.22.149"
,
3478
,
"youness.alaoui@collabora.co.uk"
,
"badger"
,
TRUE
);
#endif
nice_agent_gather_candidates
(
lagent
,
ls_id
);
nice_agent_gather_candidates
(
ragent
,
rs_id
);
...
...
@@ -633,9 +666,16 @@ static int run_full_test_control_conflict (NiceAgent *lagent, NiceAgent *ragent,
/* step: add one stream, with one component, to each agent */
ls_id
=
nice_agent_add_stream
(
lagent
,
1
);
rs_id
=
nice_agent_add_stream
(
ragent
,
1
);
g_assert
(
ls_id
>
0
);
g_assert
(
rs_id
>
0
);
#if USE_TURN
nice_agent_set_relay_info
(
lagent
,
ls_id
,
1
,
"64.251.22.149"
,
3478
,
"youness.alaoui@collabora.co.uk"
,
"badger"
,
TRUE
);
nice_agent_set_relay_info
(
ragent
,
rs_id
,
1
,
"64.251.22.149"
,
3478
,
"youness.alaoui@collabora.co.uk"
,
"badger"
,
TRUE
);
#endif
nice_agent_gather_candidates
(
lagent
,
ls_id
);
nice_agent_gather_candidates
(
ragent
,
rs_id
);
...
...
@@ -739,13 +779,17 @@ int main (void)
ragent
=
nice_agent_new
(
g_main_loop_get_context
(
global_mainloop
),
NICE_COMPATIBILITY_ID19
);
/* step: add a timer to catch state changes triggered by signals */
timer_id
=
g_timeout_add
(
3
0000
,
timer_cb
,
NULL
);
timer_id
=
g_timeout_add
(
6
0000
,
timer_cb
,
NULL
);
/* step: specify which local interface to use */
if
(
!
nice_address_set_from_string
(
&
baseaddr
,
"127.0.0.1"
))
g_assert_not_reached
();
nice_agent_add_local_address
(
lagent
,
&
baseaddr
);
nice_agent_add_local_address
(
ragent
,
&
baseaddr
);
/* if (!nice_address_set_from_string (&baseaddr, "192.168.1.106"))
g_assert_not_reached ();
nice_agent_add_local_address (lagent, &baseaddr);
nice_agent_add_local_address (ragent, &baseaddr);*/
g_signal_connect
(
G_OBJECT
(
lagent
),
"candidate-gathering-done"
,
G_CALLBACK
(
cb_candidate_gathering_done
),
(
gpointer
)
1
);
...
...
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