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
6dda75c7
Commit
6dda75c7
authored
Jul 16, 2012
by
Youness Alaoui
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'shadeslayer/dribble_mode'
parents
428f7028
ebc7313f
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
794 additions
and
38 deletions
+794
-38
.gitignore
.gitignore
+1
-0
agent/agent.c
agent/agent.c
+0
-6
agent/agent.h
agent/agent.h
+6
-0
agent/conncheck.c
agent/conncheck.c
+65
-23
agent/conncheck.h
agent/conncheck.h
+1
-0
agent/discovery.c
agent/discovery.c
+7
-6
stun/tests/test-parse.c
stun/tests/test-parse.c
+1
-1
tests/Makefile.am
tests/Makefile.am
+4
-1
tests/test-dribble.c
tests/test-dribble.c
+1
-1
tests/test-new-dribble.c
tests/test-new-dribble.c
+708
-0
No files found.
.gitignore
View file @
6dda75c7
...
...
@@ -130,6 +130,7 @@ tests/test-priority
tests/test-pseudotcp
tests/test-restart
tests/test-thread
tests/test-new-dribble
docs/reference/libnice/libnice*.txt
docs/reference/libnice/libnice.args
...
...
agent/agent.c
View file @
6dda75c7
...
...
@@ -2220,12 +2220,6 @@ nice_agent_set_remote_candidates (NiceAgent *agent, guint stream_id, guint compo
goto
done
;
}
if
(
stream
->
gathering
)
{
nice_debug
(
"Agent %p: Remote candidates refused for stream %d because "
"we are still gathering our own candidates"
,
agent
,
stream_id
);
added
=
-
1
;
goto
done
;
}
if
(
agent
->
reliable
&&
component
->
tcp
==
NULL
)
{
nice_debug
(
"Agent %p: not setting remote candidate for s%d:%d because "
...
...
agent/agent.h
View file @
6dda75c7
...
...
@@ -505,6 +505,12 @@ nice_agent_get_local_credentials (
#NiceAgent::candidate-gathering-done signale before
calling nice_agent_set_remote_candidates()
</para>
<para>
Since 0.1.3, there is no need to wait for the candidate-gathering-done signal.
Remote candidates can be set even while gathering local candidates.
Newly discovered local candidates will automatically be paired with
existing remote candidates.
</para>
</note>
*
* Returns: The number of candidates added, negative on errors (memory allocation
...
...
agent/conncheck.c
View file @
6dda75c7
...
...
@@ -1286,6 +1286,40 @@ static void priv_add_new_check_pair (NiceAgent *agent, guint stream_id, Componen
}
}
static
gboolean
priv_conn_check_add_for_candidate_pair
(
NiceAgent
*
agent
,
guint
stream_id
,
Component
*
component
,
NiceCandidate
*
local
,
NiceCandidate
*
remote
)
{
gboolean
ret
=
FALSE
;
/* note: do not create pairs where the local candidate is
* a srv-reflexive (ICE 5.7.3. "Pruning the pairs" ID-9) */
if
((
agent
->
compatibility
==
NICE_COMPATIBILITY_RFC5245
||
agent
->
compatibility
==
NICE_COMPATIBILITY_WLM2009
||
agent
->
compatibility
==
NICE_COMPATIBILITY_OC2007R2
)
&&
local
->
type
==
NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE
)
{
return
FALSE
;
}
/* note: match pairs only if transport and address family are the same */
if
(
local
->
transport
==
remote
->
transport
&&
local
->
addr
.
s
.
addr
.
sa_family
==
remote
->
addr
.
s
.
addr
.
sa_family
)
{
priv_add_new_check_pair
(
agent
,
stream_id
,
component
,
local
,
remote
,
NICE_CHECK_FROZEN
,
FALSE
);
ret
=
TRUE
;
if
(
component
->
state
<
NICE_COMPONENT_STATE_CONNECTED
)
{
agent_signal_component_state_change
(
agent
,
stream_id
,
component
->
id
,
NICE_COMPONENT_STATE_CONNECTING
);
}
else
{
agent_signal_component_state_change
(
agent
,
stream_id
,
component
->
id
,
NICE_COMPONENT_STATE_CONNECTED
);
}
}
return
ret
;
}
/*
* Forms new candidate pairs by matching the new remote candidate
* 'remote_cand' with all existing local candidates of 'component'.
...
...
@@ -1302,36 +1336,44 @@ int conn_check_add_for_candidate (NiceAgent *agent, guint stream_id, Component *
{
GSList
*
i
;
int
added
=
0
;
int
ret
=
0
;
for
(
i
=
component
->
local_candidates
;
i
;
i
=
i
->
next
)
{
NiceCandidate
*
local
=
i
->
data
;
ret
=
priv_conn_check_add_for_candidate_pair
(
agent
,
stream_id
,
component
,
local
,
remote
);
/* note: match pairs only if transport and address family are the same */
if
(
local
->
transport
==
remote
->
transport
&&
local
->
addr
.
s
.
addr
.
sa_family
==
remote
->
addr
.
s
.
addr
.
sa_family
)
{
if
(
ret
)
{
++
added
;
}
}
/* note: do not create pairs where local candidate is
* a srv-reflexive (ICE 5.7.3. "Pruning the Pairs" ID-19) */
if
((
agent
->
compatibility
==
NICE_COMPATIBILITY_RFC5245
||
agent
->
compatibility
==
NICE_COMPATIBILITY_WLM2009
||
agent
->
compatibility
==
NICE_COMPATIBILITY_OC2007R2
)
&&
local
->
type
==
NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE
)
continue
;
return
added
;
}
priv_add_new_check_pair
(
agent
,
stream_id
,
component
,
local
,
remote
,
NICE_CHECK_FROZEN
,
FALSE
);
/*
* Forms new candidate pairs by matching the new local candidate
* 'local_cand' with all existing remote candidates of 'component'.
*
* @param agent context
* @param component pointer to the component
* @param local local candidate to match with
*
* @return number of checks added, negative on fatal errors
*/
int
conn_check_add_for_local_candidate
(
NiceAgent
*
agent
,
guint
stream_id
,
Component
*
component
,
NiceCandidate
*
local
)
{
GSList
*
i
;
int
added
=
0
;
int
ret
=
0
;
for
(
i
=
component
->
remote_candidates
;
i
;
i
=
i
->
next
)
{
NiceCandidate
*
remote
=
i
->
data
;
ret
=
priv_conn_check_add_for_candidate_pair
(
agent
,
stream_id
,
component
,
local
,
remote
);
if
(
ret
)
{
++
added
;
if
(
component
->
state
<
NICE_COMPONENT_STATE_CONNECTED
)
{
agent_signal_component_state_change
(
agent
,
stream_id
,
component
->
id
,
NICE_COMPONENT_STATE_CONNECTING
);
}
else
{
agent_signal_component_state_change
(
agent
,
stream_id
,
component
->
id
,
NICE_COMPONENT_STATE_CONNECTED
);
}
}
}
...
...
agent/conncheck.h
View file @
6dda75c7
...
...
@@ -82,6 +82,7 @@ struct _CandidateCheckPair
};
int
conn_check_add_for_candidate
(
NiceAgent
*
agent
,
guint
stream_id
,
Component
*
component
,
NiceCandidate
*
remote
);
int
conn_check_add_for_local_candidate
(
NiceAgent
*
agent
,
guint
stream_id
,
Component
*
component
,
NiceCandidate
*
local
);
void
conn_check_free_item
(
gpointer
data
,
gpointer
user_data
);
void
conn_check_free
(
NiceAgent
*
agent
);
gboolean
conn_check_schedule_next
(
NiceAgent
*
agent
);
...
...
agent/discovery.c
View file @
6dda75c7
...
...
@@ -247,7 +247,7 @@ void refresh_cancel (CandidateRefresh *refresh)
* defined in ICE spec section 4.1.3 "Eliminating Redundant
* Candidates" (ID-19).
*/
static
gboolean
priv_add_local_candidate_pruned
(
Component
*
component
,
NiceCandidate
*
candidate
)
static
gboolean
priv_add_local_candidate_pruned
(
NiceAgent
*
agent
,
guint
stream_id
,
Component
*
component
,
NiceCandidate
*
candidate
)
{
GSList
*
i
;
...
...
@@ -263,6 +263,7 @@ static gboolean priv_add_local_candidate_pruned (Component *component, NiceCandi
component
->
local_candidates
=
g_slist_append
(
component
->
local_candidates
,
candidate
);
conn_check_add_for_local_candidate
(
agent
,
stream_id
,
component
,
candidate
);
return
TRUE
;
}
...
...
@@ -489,7 +490,7 @@ NiceCandidate *discovery_add_local_host_candidate (
candidate
->
addr
=
udp_socket
->
addr
;
candidate
->
base_addr
=
udp_socket
->
addr
;
if
(
!
priv_add_local_candidate_pruned
(
component
,
candidate
))
if
(
!
priv_add_local_candidate_pruned
(
agent
,
stream_id
,
component
,
candidate
))
goto
errors
;
component
->
sockets
=
g_slist_append
(
component
->
sockets
,
udp_socket
);
...
...
@@ -547,7 +548,7 @@ discovery_add_server_reflexive_candidate (
priv_generate_candidate_credentials
(
agent
,
candidate
);
priv_assign_foundation
(
agent
,
candidate
);
result
=
priv_add_local_candidate_pruned
(
component
,
candidate
);
result
=
priv_add_local_candidate_pruned
(
agent
,
stream_id
,
component
,
candidate
);
if
(
result
)
{
agent_signal_new_candidate
(
agent
,
candidate
);
}
...
...
@@ -620,7 +621,7 @@ discovery_add_relay_candidate (
priv_assign_foundation
(
agent
,
candidate
);
if
(
!
priv_add_local_candidate_pruned
(
component
,
candidate
))
if
(
!
priv_add_local_candidate_pruned
(
agent
,
stream_id
,
component
,
candidate
))
goto
errors
;
component
->
sockets
=
g_slist_append
(
component
->
sockets
,
relay_socket
);
...
...
@@ -715,9 +716,9 @@ discovery_add_peer_reflexive_candidate (
candidate
->
sockptr
=
base_socket
;
candidate
->
base_addr
=
base_socket
->
addr
;
result
=
priv_add_local_candidate_pruned
(
component
,
candidate
);
result
=
priv_add_local_candidate_pruned
(
agent
,
stream_id
,
component
,
candidate
);
if
(
result
!=
TRUE
)
{
/* error: memory allocation, or duplicate candidate
t
*/
/* error: memory allocation, or duplicate candidate */
nice_candidate_free
(
candidate
),
candidate
=
NULL
;
}
...
...
stun/tests/test-parse.c
View file @
6dda75c7
...
...
@@ -368,7 +368,7 @@ static void test_attribute (void)
StunMessage
msg
;
uint16_t
known_attributes
[]
=
{
STUN_ATTRIBUTE_MESSAGE_INTEGRITY
,
STUN_ATTRIBUTE_USERNAME
,
0
};
printf
(
"Attribute test message length: %u
\n
"
,
sizeof
(
acme
));
printf
(
"Attribute test message length: %
l
u
\n
"
,
sizeof
(
acme
));
stun_agent_init
(
&
agent
,
known_attributes
,
STUN_COMPATIBILITY_RFC5389
,
STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS
);
...
...
tests/Makefile.am
View file @
6dda75c7
...
...
@@ -32,7 +32,8 @@ check_PROGRAMS = \
test-restart
\
test-fallback
\
test-thread
\
test-dribble
test-dribble
\
test-new-dribble
dist_check_SCRIPTS
=
\
check-test-fullmode-with-stun.sh
\
...
...
@@ -64,6 +65,8 @@ test_fallback_LDADD = $(COMMON_LDADD)
test_dribble_LDADD
=
$(COMMON_LDADD)
test_new_dribble_LDADD
=
$(COMMON_LDADD)
all-local
:
chmod
a+x
$(srcdir)
/check-test-fullmode-with-stun.sh
chmod
a+x
$(srcdir)
/test-pseudotcp-random.sh
tests/test-dribble.c
View file @
6dda75c7
...
...
@@ -381,7 +381,7 @@ int main (void)
nice_agent_remove_stream
(
ragent
,
rs_id
);
priv_print_global_status
();
g_assert
(
global_lagent_state
==
NICE_COMPONENT_STATE_READY
);
g_assert
(
global_ragent_state
==
NICE_COMPONENT_STATE_READY
);
g_assert
(
global_ragent_state
>=
NICE_COMPONENT_STATE_CONNECTED
);
/* note: verify that correct number of local candidates were reported */
g_assert
(
global_lagent_cands
==
1
);
g_assert
(
global_ragent_cands
==
1
);
...
...
tests/test-new-dribble.c
0 → 100644
View file @
6dda75c7
/*
* This file is part of the Nice GLib ICE library.
*
* Unit test for ICE in dribble mode (adding remote candidates while gathering
* local candidates).
*
* (C) 2012 Collabora Ltd.
* Contact: Rohan Garg
* Youness Alaoui
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Nice GLib ICE library.
*
* The Initial Developers of the Original Code are Collabora Ltd and Nokia
* Corporation.
*
* Contributors:
* Rohan Garg
*
* Alternatively, the contents of this file may be used under the terms of the
* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
* case the provisions of LGPL are applicable instead of those above. If you
* wish to allow use of your version of this file only under the terms of the
* LGPL and not to allow others to use your version of this file under the
* MPL, indicate your decision by deleting the provisions above and replace
* them with the notice and other provisions required by the LGPL. If you do
* not delete the provisions above, a recipient may use your version of this
* file under either the MPL or the LGPL.
*/
#include <glib.h>
#include <glib-object.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include "stunagent.h"
#include "agent-priv.h"
#include "agent.h"
#define IPPORT_STUN 3456
#define USE_UPNP 0
#define LEFT_AGENT GINT_TO_POINTER(1)
#define RIGHT_AGENT GINT_TO_POINTER(2)
#if !GLIB_CHECK_VERSION(2,31,8)
static
GMutex
*
stun_mutex_ptr
=
NULL
;
static
GCond
*
stun_signal_ptr
=
NULL
;
#else
static
GMutex
stun_mutex
;
static
GMutex
*
stun_mutex_ptr
=
&
stun_mutex
;
static
GCond
stun_signal
;
static
GCond
*
stun_signal_ptr
=
&
stun_signal
;
#endif
static
GMainLoop
*
global_mainloop
;
static
NiceComponentState
global_lagent_state
=
NICE_COMPONENT_STATE_LAST
;
static
NiceComponentState
global_ragent_state
=
NICE_COMPONENT_STATE_LAST
;
static
gboolean
exit_stun_thread
=
FALSE
;
static
gboolean
lagent_candidate_gathering_done
=
FALSE
;
static
gboolean
ragent_candidate_gathering_done
=
FALSE
;
static
guint
global_ls_id
,
global_rs_id
;
static
gboolean
data_received
=
FALSE
;
static
gboolean
drop_stun_packets
=
FALSE
;
static
const
uint16_t
known_attributes
[]
=
{
0
};
/*
* Creates a listening socket
*/
static
int
listen_socket
(
unsigned
int
port
)
{
struct
sockaddr_in
addr
;
int
fd
=
socket
(
AF_INET
,
SOCK_DGRAM
,
IPPROTO_UDP
);
if
(
fd
==
-
1
)
{
perror
(
"Error opening IP port"
);
return
-
1
;
}
memset
(
&
addr
,
0
,
sizeof
(
addr
));
addr
.
sin_family
=
AF_INET
;
inet_pton
(
AF_INET
,
"127.0.0.1"
,
&
addr
.
sin_addr
);
addr
.
sin_port
=
htons
(
port
);
if
(
bind
(
fd
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
struct
sockaddr_in
)))
{
perror
(
"Error opening IP port"
);
goto
error
;
}
return
fd
;
error:
close
(
fd
);
return
-
1
;
}
static
int
dgram_process
(
int
sock
,
StunAgent
*
oldagent
,
StunAgent
*
newagent
)
{
struct
sockaddr_storage
addr
;
socklen_t
addr_len
;
uint8_t
buf
[
STUN_MAX_MESSAGE_SIZE
];
size_t
buf_len
=
0
;
size_t
len
=
0
;
StunMessage
request
;
StunMessage
response
;
StunValidationStatus
validation
;
StunAgent
*
agent
=
NULL
;
gint
ret
;
addr_len
=
sizeof
(
struct
sockaddr_in
);
recv_packet:
len
=
recvfrom
(
sock
,
buf
,
sizeof
(
buf
),
0
,
(
struct
sockaddr
*
)
&
addr
,
&
addr_len
);
if
(
drop_stun_packets
)
{
g_debug
(
"Dropping STUN packet as requested"
);
return
-
1
;
}
if
(
len
==
(
size_t
)
-
1
)
{
return
-
1
;
}
validation
=
stun_agent_validate
(
newagent
,
&
request
,
buf
,
len
,
NULL
,
0
);
if
(
validation
==
STUN_VALIDATION_SUCCESS
)
{
agent
=
newagent
;
}
else
{
validation
=
stun_agent_validate
(
oldagent
,
&
request
,
buf
,
len
,
NULL
,
0
);
agent
=
oldagent
;
}
/* Unknown attributes */
if
(
validation
==
STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE
)
{
buf_len
=
stun_agent_build_unknown_attributes_error
(
agent
,
&
response
,
buf
,
sizeof
(
buf
),
&
request
);
goto
send_buf
;
}
/* Mal-formatted packets */
if
(
validation
!=
STUN_VALIDATION_SUCCESS
||
stun_message_get_class
(
&
request
)
!=
STUN_REQUEST
)
{
goto
recv_packet
;
}
switch
(
stun_message_get_method
(
&
request
))
{
case
STUN_BINDING
:
stun_agent_init_response
(
agent
,
&
response
,
buf
,
sizeof
(
buf
),
&
request
);
if
(
stun_message_has_cookie
(
&
request
))
stun_message_append_xor_addr
(
&
response
,
STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS
,
(
struct
sockaddr
*
)
&
addr
,
addr_len
);
else
stun_message_append_addr
(
&
response
,
STUN_ATTRIBUTE_MAPPED_ADDRESS
,
(
struct
sockaddr
*
)
&
addr
,
addr_len
);
break
;
default:
if
(
!
stun_agent_init_error
(
agent
,
&
response
,
buf
,
sizeof
(
buf
),
&
request
,
STUN_ERROR_BAD_REQUEST
))
{
g_debug
(
"STUN error message not initialized properly"
);
g_assert_not_reached
();
}
}
buf_len
=
stun_agent_finish_message
(
agent
,
&
response
,
NULL
,
0
);
send_buf:
g_main_loop_quit
(
global_mainloop
);
g_debug
(
"Ready to send a STUN response"
);
g_assert
(
g_mutex_trylock
(
stun_mutex_ptr
));
while
(
global_lagent_state
<
NICE_COMPONENT_STATE_CONNECTING
)
{
g_debug
(
"Waiting for signal. State is %d"
,
global_lagent_state
);
g_cond_wait
(
stun_signal_ptr
,
stun_mutex_ptr
);
}
g_mutex_unlock
(
stun_mutex_ptr
);
len
=
sendto
(
sock
,
buf
,
buf_len
,
0
,
(
struct
sockaddr
*
)
&
addr
,
addr_len
);
g_debug
(
"STUN response sent"
);
drop_stun_packets
=
TRUE
;
ret
=
(
len
<
buf_len
)
?
-
1
:
0
;
return
ret
;
}
static
gpointer
stun_thread_func
(
const
gpointer
user_data
)
{
StunAgent
oldagent
;
StunAgent
newagent
;
int
sock
;
int
exit_code
=
-
1
;
sock
=
listen_socket
(
IPPORT_STUN
);
if
(
sock
==
-
1
)
{
g_assert_not_reached
();
}
stun_agent_init
(
&
oldagent
,
known_attributes
,
STUN_COMPATIBILITY_RFC3489
,
0
);
stun_agent_init
(
&
newagent
,
known_attributes
,
STUN_COMPATIBILITY_RFC5389
,
STUN_AGENT_USAGE_USE_FINGERPRINT
);
while
(
!
exit_stun_thread
)
{
g_debug
(
"Ready to process next datagram"
);
dgram_process
(
sock
,
&
oldagent
,
&
newagent
);
}
exit_code
=
close
(
sock
);
g_thread_exit
(
GINT_TO_POINTER
(
exit_code
));
return
NULL
;
}
static
void
set_credentials
(
NiceAgent
*
lagent
,
guint
lstream
,
NiceAgent
*
ragent
,
guint
rstream
)
{
gchar
*
ufrag
=
NULL
,
*
password
=
NULL
;
nice_agent_get_local_credentials
(
lagent
,
lstream
,
&
ufrag
,
&
password
);
nice_agent_set_remote_credentials
(
ragent
,
rstream
,
ufrag
,
password
);
g_free
(
ufrag
);
g_free
(
password
);
nice_agent_get_local_credentials
(
ragent
,
rstream
,
&
ufrag
,
&
password
);
nice_agent_set_remote_credentials
(
lagent
,
lstream
,
ufrag
,
password
);
g_free
(
ufrag
);
g_free
(
password
);
}
static
void
cb_candidate_gathering_done
(
NiceAgent
*
agent
,
guint
stream_id
,
gpointer
data
)
{
g_debug
(
"test-dribblemode:%s: %p"
,
G_STRFUNC
,
data
);
if
(
GPOINTER_TO_UINT
(
data
)
==
1
)
{
g_debug
(
"lagent finished gathering candidates"
);
lagent_candidate_gathering_done
=
TRUE
;
}
else
if
(
GPOINTER_TO_UINT
(
data
)
==
2
)
{
g_debug
(
"ragent finished gathering candidates"
);
ragent_candidate_gathering_done
=
TRUE
;
}
g_main_loop_quit
(
global_mainloop
);
}
static
void
cb_nice_recv
(
NiceAgent
*
agent
,
guint
stream_id
,
guint
component_id
,
guint
len
,
gchar
*
buf
,
gpointer
user_data
)
{
gint
ret
;
g_debug
(
"test-dribblemode:%s: %p"
,
G_STRFUNC
,
user_data
);
ret
=
strncmp
(
"0000"
,
buf
,
4
);
if
(
ret
==
0
)
{
ret
=
strncmp
(
"00001234567812345678"
,
buf
,
16
);
g_assert
(
ret
==
0
);
g_debug
(
"test-dribblemode:%s: ragent recieved %d bytes : quit mainloop"
,
G_STRFUNC
,
len
);
data_received
=
TRUE
;
g_main_loop_quit
(
global_mainloop
);
}
}
static
void
cb_component_state_changed
(
NiceAgent
*
agent
,
guint
stream_id
,
guint
component_id
,
guint
state
,
gpointer
data
)
{
gint
ret
;
g_debug
(
"test-dribblemode:%s: %p"
,
G_STRFUNC
,
data
);
if
(
GPOINTER_TO_UINT
(
data
)
==
1
)
{
global_lagent_state
=
state
;
g_debug
(
"lagent state is %d"
,
state
);
}
else
if
(
GPOINTER_TO_UINT
(
data
)
==
2
)
{
g_debug
(
"ragent state is %d"
,
state
);
global_ragent_state
=
state
;
}
if
(
GPOINTER_TO_UINT
(
data
)
==
1
&&
state
==
NICE_COMPONENT_STATE_FAILED
)
{
g_debug
(
"Signalling STUN response since connchecks failed"
);
g_mutex_lock
(
stun_mutex_ptr
);
g_cond_signal
(
stun_signal_ptr
);
g_mutex_unlock
(
stun_mutex_ptr
);
g_main_loop_quit
(
global_mainloop
);
}
if
(
GPOINTER_TO_UINT
(
data
)
==
1
&&
state
==
NICE_COMPONENT_STATE_READY
)
{
/* note: test payload send and receive */
ret
=
nice_agent_send
(
agent
,
stream_id
,
component_id
,
20
,
"00001234567812345678"
);
g_debug
(
"Sent %d bytes"
,
ret
);
g_assert
(
ret
==
20
);
}
}
static
void
swap_candidates
(
NiceAgent
*
local
,
guint
local_id
,
NiceAgent
*
remote
,
guint
remote_id
,
gboolean
signal_stun_reply
)
{
GSList
*
cands
=
NULL
;
g_debug
(
"test-dribblemode:%s"
,
G_STRFUNC
);
cands
=
nice_agent_get_local_candidates
(
local
,
local_id
,
NICE_COMPONENT_TYPE_RTP
);
g_assert
(
nice_agent_set_remote_candidates
(
remote
,
remote_id
,
NICE_COMPONENT_TYPE_RTP
,
cands
));
if
(
signal_stun_reply
)
{
g_mutex_lock
(
stun_mutex_ptr
);
g_cond_signal
(
stun_signal_ptr
);
g_mutex_unlock
(
stun_mutex_ptr
);
}
g_slist_free_full
(
cands
,
(
GDestroyNotify
)
nice_candidate_free
);
}
static
void
cb_agent_new_candidate
(
NiceAgent
*
agent
,
guint
stream_id
,
guint
component_id
,
gchar
*
foundation
,
gpointer
user_data
)
{
NiceAgent
*
other
=
g_object_get_data
(
G_OBJECT
(
agent
),
"other-agent"
);
GSList
*
cands
=
nice_agent_get_local_candidates
(
agent
,
stream_id
,
component_id
);
GSList
*
i
=
NULL
;
GSList
*
remote_cands
=
NULL
;
NiceCandidate
*
temp
;
gpointer
tmp
;
guint
id
;
g_debug
(
"test-dribblemode:%s: %p"
,
G_STRFUNC
,
user_data
);
tmp
=
g_object_get_data
(
G_OBJECT
(
other
),
"id"
);
id
=
GPOINTER_TO_UINT
(
tmp
);
for
(
i
=
cands
;
i
;
i
=
i
->
next
)
{
temp
=
(
NiceCandidate
*
)
i
->
data
;
if
(
g_strcmp0
(
temp
->
foundation
,
foundation
)
==
0
)
{
g_debug
(
"Adding new local candidate to other agent's connchecks"
);
remote_cands
=
g_slist_prepend
(
remote_cands
,
nice_candidate_copy
(
temp
));
g_assert
(
nice_agent_set_remote_candidates
(
other
,
id
,
NICE_COMPONENT_TYPE_RTP
,
remote_cands
));
}
}
g_slist_free_full
(
remote_cands
,
(
GDestroyNotify
)
nice_candidate_free
);
g_slist_free_full
(
cands
,
(
GDestroyNotify
)
nice_candidate_free
);
}
static
void
add_bad_candidate
(
NiceAgent
*
agent
,
guint
stream_id
,
NiceCandidate
*
cand
)
{
NiceAddress
bad_addr
;
GSList
*
cand_list
=
NULL
;
g_assert
(
nice_address_set_from_string
(
&
bad_addr
,
"172.1.0.1"
));
cand
=
nice_candidate_new
(
NICE_CANDIDATE_TYPE_HOST
);
cand
->
stream_id
=
stream_id
;
cand
->
component_id
=
NICE_COMPONENT_TYPE_RTP
;
cand
->
addr
=
bad_addr
;
nice_agent_get_local_credentials
(
agent
,
stream_id
,
&
cand
->
username
,
&
cand
->
password
);
cand_list
=
g_slist_prepend
(
cand_list
,
cand
);
g_debug
(
"Adding buggy candidate to the agent %p"
,
agent
);
g_assert
(
nice_agent_set_remote_candidates
(
agent
,
stream_id
,
NICE_COMPONENT_TYPE_RTP
,
cand_list
));
g_slist_free_full
(
cand_list
,
(
GDestroyNotify
)
nice_candidate_free
);
}
static
void
init_test
(
NiceAgent
*
lagent
,
NiceAgent
*
ragent
,
gboolean
connect_new_candidate_signal
)
{
global_lagent_state
=
NICE_COMPONENT_STATE_DISCONNECTED
;
global_ragent_state
=
NICE_COMPONENT_STATE_DISCONNECTED
;
lagent_candidate_gathering_done
=
FALSE
;
ragent_candidate_gathering_done
=
FALSE
;
global_ls_id
=
nice_agent_add_stream
(
lagent
,
1
);
global_rs_id
=
nice_agent_add_stream
(
ragent
,
1
);
g_assert
(
global_ls_id
>
0
);
g_assert
(
global_rs_id
>
0
);
g_debug
(
"lagent stream is : %d and ragent stream is %d"
,
global_ls_id
,
global_rs_id
);
g_object_set_data
(
G_OBJECT
(
lagent
),
"id"
,
GUINT_TO_POINTER
(
global_ls_id
));
g_object_set_data
(
G_OBJECT
(
ragent
),
"id"
,
GUINT_TO_POINTER
(
global_rs_id
));
if
(
connect_new_candidate_signal
)
{
g_signal_connect
(
G_OBJECT
(
lagent
),
"new-candidate"
,
G_CALLBACK
(
cb_agent_new_candidate
),
LEFT_AGENT
);
g_signal_connect
(
G_OBJECT
(
ragent
),
"new-candidate"
,
G_CALLBACK
(
cb_agent_new_candidate
),
RIGHT_AGENT
);
}
else
{
g_signal_handlers_disconnect_by_func
(
G_OBJECT
(
lagent
),
cb_agent_new_candidate
,
LEFT_AGENT
);
g_signal_handlers_disconnect_by_func
(
G_OBJECT
(
ragent
),
cb_agent_new_candidate
,
RIGHT_AGENT
);
}
data_received
=
FALSE
;
nice_agent_attach_recv
(
lagent
,
global_ls_id
,
NICE_COMPONENT_TYPE_RTP
,
g_main_loop_get_context
(
global_mainloop
),
cb_nice_recv
,
LEFT_AGENT
);
nice_agent_attach_recv
(
ragent
,
global_rs_id
,
NICE_COMPONENT_TYPE_RTP
,
g_main_loop_get_context
(
global_mainloop
),
cb_nice_recv
,
RIGHT_AGENT
);
}
static
void
cleanup
(
NiceAgent
*
lagent
,
NiceAgent
*
ragent
)
{
g_debug
(
"Cleaning up"
);
drop_stun_packets
=
FALSE
;
nice_agent_remove_stream
(
lagent
,
global_ls_id
);
nice_agent_remove_stream
(
ragent
,
global_rs_id
);
}
static
void
standard_test
(
NiceAgent
*
lagent
,
NiceAgent
*
ragent
)
{
g_debug
(
"test-dribblemode:%s"
,
G_STRFUNC
);
init_test
(
lagent
,
ragent
,
FALSE
);
nice_agent_gather_candidates
(
lagent
,
global_ls_id
);
g_main_loop_run
(
global_mainloop
);
g_assert
(
global_lagent_state
==
NICE_COMPONENT_STATE_GATHERING
&&
!
lagent_candidate_gathering_done
);
nice_agent_gather_candidates
(
ragent
,
global_rs_id
);
if
(
!
ragent_candidate_gathering_done
)
{
g_main_loop_run
(
global_mainloop
);
g_assert
(
ragent_candidate_gathering_done
);
}
set_credentials
(
lagent
,
global_ls_id
,
ragent
,
global_rs_id
);
g_debug
(
"Setting local candidates of ragent as remote candidates of lagent"
);
swap_candidates
(
ragent
,
global_rs_id
,
lagent
,
global_ls_id
,
TRUE
);
g_main_loop_run
(
global_mainloop
);
g_assert
(
global_lagent_state
>=
NICE_COMPONENT_STATE_CONNECTED
&&
data_received
);
g_debug
(
"Setting local candidates of lagent as remote candidates of ragent"
);
swap_candidates
(
lagent
,
global_ls_id
,
ragent
,
global_rs_id
,
FALSE
);
g_main_loop_run
(
global_mainloop
);
g_assert
(
lagent_candidate_gathering_done
);
g_assert
(
global_lagent_state
==
NICE_COMPONENT_STATE_READY
);
g_assert
(
global_ragent_state
>=
NICE_COMPONENT_STATE_CONNECTED
);
cleanup
(
lagent
,
ragent
);
}
static
void
bad_credentials_test
(
NiceAgent
*
lagent
,
NiceAgent
*
ragent
)
{
g_debug
(
"test-dribblemode:%s"
,
G_STRFUNC
);
init_test
(
lagent
,
ragent
,
FALSE
);
nice_agent_set_remote_credentials
(
lagent
,
global_ls_id
,
"wrong"
,
"wrong"
);
nice_agent_set_remote_credentials
(
ragent
,
global_rs_id
,
"wrong2"
,
"wrong2"
);
nice_agent_gather_candidates
(
lagent
,
global_ls_id
);
g_main_loop_run
(
global_mainloop
);
g_assert
(
global_lagent_state
==
NICE_COMPONENT_STATE_GATHERING
&&
!
lagent_candidate_gathering_done
);
nice_agent_gather_candidates
(
ragent
,
global_rs_id
);
if
(
!
ragent_candidate_gathering_done
)
{
g_main_loop_run
(
global_mainloop
);
g_assert
(
ragent_candidate_gathering_done
);
}
swap_candidates
(
ragent
,
global_rs_id
,
lagent
,
global_ls_id
,
FALSE
);
g_main_loop_run
(
global_mainloop
);
g_assert
(
global_lagent_state
==
NICE_COMPONENT_STATE_FAILED
);
// Set the correct credentials and swap candidates
set_credentials
(
lagent
,
global_ls_id
,
ragent
,
global_rs_id
);
swap_candidates
(
ragent
,
global_rs_id
,
lagent
,
global_ls_id
,
FALSE
);
swap_candidates
(
lagent
,
global_ls_id
,
ragent
,
global_rs_id
,
FALSE
);
g_main_loop_run
(
global_mainloop
);
g_assert
(
data_received
);
g_assert
(
global_lagent_state
==
NICE_COMPONENT_STATE_READY
);
g_assert
(
global_ragent_state
>=
NICE_COMPONENT_STATE_CONNECTED
);
// Wait for lagent to finish gathering candidates
g_main_loop_run
(
global_mainloop
);
g_assert
(
lagent_candidate_gathering_done
);
cleanup
(
lagent
,
ragent
);
}
static
void
bad_candidate_test
(
NiceAgent
*
lagent
,
NiceAgent
*
ragent
)
{
NiceCandidate
*
cand
=
NULL
;
g_debug
(
"test-dribblemode:%s"
,
G_STRFUNC
);
init_test
(
lagent
,
ragent
,
FALSE
);
nice_agent_gather_candidates
(
lagent
,
global_ls_id
);
g_main_loop_run
(
global_mainloop
);
g_assert
(
global_lagent_state
==
NICE_COMPONENT_STATE_GATHERING
&&
!
lagent_candidate_gathering_done
);
nice_agent_gather_candidates
(
ragent
,
global_rs_id
);
if
(
!
ragent_candidate_gathering_done
)
{
g_main_loop_run
(
global_mainloop
);
g_assert
(
ragent_candidate_gathering_done
);
}
add_bad_candidate
(
lagent
,
global_ls_id
,
cand
);
// lagent will finish candidate gathering causing this mainloop to quit
g_main_loop_run
(
global_mainloop
);
// connchecks will fail causing this mainloop to quit
g_main_loop_run
(
global_mainloop
);
g_assert
(
global_lagent_state
==
NICE_COMPONENT_STATE_FAILED
&&
!
data_received
);
set_credentials
(
lagent
,
global_ls_id
,
ragent
,
global_rs_id
);
swap_candidates
(
ragent
,
global_rs_id
,
lagent
,
global_ls_id
,
FALSE
);
swap_candidates
(
lagent
,
global_ls_id
,
ragent
,
global_rs_id
,
FALSE
);
g_main_loop_run
(
global_mainloop
);
g_assert
(
lagent_candidate_gathering_done
);
g_assert
(
global_lagent_state
==
NICE_COMPONENT_STATE_READY
);
g_assert
(
global_ragent_state
>=
NICE_COMPONENT_STATE_CONNECTED
);
cleanup
(
lagent
,
ragent
);
}
static
void
new_candidate_test
(
NiceAgent
*
lagent
,
NiceAgent
*
ragent
)
{
g_debug
(
"test-dribblemode:%s"
,
G_STRFUNC
);
init_test
(
lagent
,
ragent
,
TRUE
);
set_credentials
(
lagent
,
global_ls_id
,
ragent
,
global_rs_id
);
nice_agent_gather_candidates
(
lagent
,
global_ls_id
);
g_main_loop_run
(
global_mainloop
);
g_assert
(
global_lagent_state
==
NICE_COMPONENT_STATE_GATHERING
&&
!
lagent_candidate_gathering_done
);
nice_agent_gather_candidates
(
ragent
,
global_rs_id
);
if
(
!
ragent_candidate_gathering_done
)
{
g_main_loop_run
(
global_mainloop
);
}
// Wait for data
g_main_loop_run
(
global_mainloop
);
g_assert
(
data_received
);
// Data arrived, signal STUN thread to send STUN response
g_mutex_lock
(
stun_mutex_ptr
);
g_cond_signal
(
stun_signal_ptr
);
g_mutex_unlock
(
stun_mutex_ptr
);
// Wait for lagent to finish gathering candidates
g_main_loop_run
(
global_mainloop
);
g_assert
(
lagent_candidate_gathering_done
);
g_assert
(
ragent_candidate_gathering_done
);
g_assert
(
global_lagent_state
==
NICE_COMPONENT_STATE_READY
);
g_assert
(
global_ragent_state
>=
NICE_COMPONENT_STATE_CONNECTED
);
cleanup
(
lagent
,
ragent
);
}
static
void
send_dummy_data
(
void
)
{
int
sockfd
=
listen_socket
(
4567
);
struct
sockaddr_in
addr
;
memset
(
&
addr
,
0
,
sizeof
(
addr
));
addr
.
sin_family
=
AF_INET
;
inet_pton
(
AF_INET
,
"127.0.0.1"
,
&
addr
.
sin_addr
);
addr
.
sin_port
=
htons
(
IPPORT_STUN
);
g_debug
(
"Sending dummy data to close STUN thread"
);
sendto
(
sockfd
,
"close socket"
,
12
,
0
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
));
}
int
main
(
void
)
{
NiceAgent
*
lagent
=
NULL
,
*
ragent
=
NULL
;
GThread
*
stun_thread
=
NULL
;
NiceAddress
baseaddr
;
g_type_init
();
global_mainloop
=
g_main_loop_new
(
NULL
,
FALSE
);
#if !GLIB_CHECK_VERSION(2,31,8)
g_thread_init
(
NULL
);
stun_thread
=
g_thread_create
(
stun_thread_func
,
global_mainloop
,
TRUE
,
NULL
);
stun_mutex_ptr
=
g_mutex_new
();
stun_signal_ptr
=
g_cond_new
();
#else
stun_thread
=
g_thread_new
(
"listen for STUN requests"
,
stun_thread_func
,
NULL
);
#endif
lagent
=
nice_agent_new
(
g_main_loop_get_context
(
global_mainloop
),
NICE_COMPATIBILITY_RFC5245
);
ragent
=
nice_agent_new
(
g_main_loop_get_context
(
global_mainloop
),
NICE_COMPATIBILITY_RFC5245
);
g_object_set
(
G_OBJECT
(
lagent
),
"controlling-mode"
,
TRUE
,
NULL
);
g_object_set
(
G_OBJECT
(
ragent
),
"controlling-mode"
,
FALSE
,
NULL
);
g_object_set
(
G_OBJECT
(
lagent
),
"upnp"
,
USE_UPNP
,
NULL
);
g_object_set
(
G_OBJECT
(
ragent
),
"upnp"
,
USE_UPNP
,
NULL
);
g_object_set
(
G_OBJECT
(
lagent
),
"stun-server"
,
"127.0.0.1"
,
NULL
);
g_object_set
(
G_OBJECT
(
lagent
),
"stun-server-port"
,
IPPORT_STUN
,
NULL
);
g_object_set_data
(
G_OBJECT
(
lagent
),
"other-agent"
,
ragent
);
g_object_set_data
(
G_OBJECT
(
ragent
),
"other-agent"
,
lagent
);
g_assert
(
nice_address_set_from_string
(
&
baseaddr
,
"127.0.0.1"
));
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
),
LEFT_AGENT
);
g_signal_connect
(
G_OBJECT
(
ragent
),
"candidate-gathering-done"
,
G_CALLBACK
(
cb_candidate_gathering_done
),
RIGHT_AGENT
);
g_signal_connect
(
G_OBJECT
(
lagent
),
"component-state-changed"
,
G_CALLBACK
(
cb_component_state_changed
),
LEFT_AGENT
);
g_signal_connect
(
G_OBJECT
(
ragent
),
"component-state-changed"
,
G_CALLBACK
(
cb_component_state_changed
),
RIGHT_AGENT
);
standard_test
(
lagent
,
ragent
);
bad_credentials_test
(
lagent
,
ragent
);
bad_candidate_test
(
lagent
,
ragent
);
new_candidate_test
(
lagent
,
ragent
);
// Do this to make sure the STUN thread exits
exit_stun_thread
=
TRUE
;
drop_stun_packets
=
TRUE
;
send_dummy_data
();
g_object_unref
(
lagent
);
g_object_unref
(
ragent
);
g_thread_join
(
stun_thread
);
#if !GLIB_CHECK_VERSION(2,31,8)
g_mutex_free
(
stun_mutex_ptr
);
g_cond_free
(
stun_signal_ptr
);
#endif
g_main_loop_unref
(
global_mainloop
);
return
0
;
}
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