2 * This file is part of the Nice GLib ICE library.
4 * Unit test for ICE in dribble mode (adding remote candidates while gathering
7 * (C) 2012 Collabora Ltd.
11 * The contents of this file are subject to the Mozilla Public License Version
12 * 1.1 (the "License"); you may not use this file except in compliance with
13 * the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
16 * Software distributed under the License is distributed on an "AS IS" basis,
17 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
18 * for the specific language governing rights and limitations under the
21 * The Original Code is the Nice GLib ICE library.
23 * The Initial Developers of the Original Code are Collabora Ltd and 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 #include <glib-object.h>
45 #include <sys/types.h>
46 #include <arpa/inet.h>
47 #include <sys/socket.h>
49 #include <netinet/in.h>
51 #include "stunagent.h"
52 #include "agent-priv.h"
55 #define IPPORT_STUN 3456
57 #define LEFT_AGENT GINT_TO_POINTER(1)
58 #define RIGHT_AGENT GINT_TO_POINTER(2)
60 #if !GLIB_CHECK_VERSION(2,31,8)
61 static GMutex
*stun_mutex_ptr
= NULL
;
62 static GCond
*stun_signal_ptr
= NULL
;
63 static GMutex
*stun_thread_mutex_ptr
= NULL
;
64 static GCond
*stun_thread_signal_ptr
= NULL
66 static GMutex stun_mutex
;
67 static GMutex
*stun_mutex_ptr
= &stun_mutex
;
68 static GCond stun_signal
;
69 static GCond
*stun_signal_ptr
= &stun_signal
;
70 static GMutex stun_thread_mutex
;
71 static GMutex
*stun_thread_mutex_ptr
= &stun_thread_mutex
;
72 static GCond stun_thread_signal
;
73 static GCond
*stun_thread_signal_ptr
= &stun_thread_signal
;
76 static GMainLoop
*global_mainloop
;
77 static NiceComponentState global_lagent_state
= NICE_COMPONENT_STATE_LAST
;
78 static NiceComponentState global_ragent_state
= NICE_COMPONENT_STATE_LAST
;
79 static gboolean exit_stun_thread
= FALSE
;
80 static gboolean lagent_candidate_gathering_done
= FALSE
;
81 static gboolean ragent_candidate_gathering_done
= FALSE
;
82 static guint global_ls_id
, global_rs_id
;
83 static gboolean data_received
= FALSE
;
84 static gboolean drop_stun_packets
= FALSE
;
86 static const uint16_t known_attributes
[] = {
91 * Creates a listening socket
93 static int listen_socket (unsigned int port
)
95 struct sockaddr_in addr
;
96 int fd
= socket (AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
99 perror ("Error opening IP port");
103 memset (&addr
, 0, sizeof (addr
));
104 addr
.sin_family
= AF_INET
;
105 inet_pton(AF_INET
, "127.0.0.1", &addr
.sin_addr
);
106 addr
.sin_port
= htons(port
);
108 if (bind (fd
, (struct sockaddr
*)&addr
, sizeof (struct sockaddr_in
))) {
109 perror ("Error opening IP port");
120 static int dgram_process (int sock
, StunAgent
*oldagent
, StunAgent
*newagent
)
122 struct sockaddr_storage addr
;
124 uint8_t buf
[STUN_MAX_MESSAGE_SIZE
];
128 StunMessage response
;
129 StunValidationStatus validation
;
130 StunAgent
*agent
= NULL
;
133 addr_len
= sizeof (struct sockaddr_in
);
136 len
= recvfrom (sock
, buf
, sizeof(buf
), 0,
137 (struct sockaddr
*)&addr
, &addr_len
);
139 if (drop_stun_packets
) {
140 g_debug ("Dropping STUN packet as requested");
144 if (len
== (size_t)-1) {
148 validation
= stun_agent_validate (newagent
, &request
, buf
, len
, NULL
, 0);
150 if (validation
== STUN_VALIDATION_SUCCESS
) {
153 validation
= stun_agent_validate (oldagent
, &request
, buf
, len
, NULL
, 0);
157 /* Unknown attributes */
158 if (validation
== STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE
) {
159 buf_len
= stun_agent_build_unknown_attributes_error (agent
, &response
, buf
,
160 sizeof (buf
), &request
);
164 /* Mal-formatted packets */
165 if (validation
!= STUN_VALIDATION_SUCCESS
||
166 stun_message_get_class (&request
) != STUN_REQUEST
) {
170 switch (stun_message_get_method (&request
)) {
172 stun_agent_init_response (agent
, &response
, buf
, sizeof (buf
), &request
);
173 if (stun_message_has_cookie (&request
))
174 stun_message_append_xor_addr (&response
,
175 STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS
,
176 (struct sockaddr
*)&addr
, addr_len
);
178 stun_message_append_addr (&response
, STUN_ATTRIBUTE_MAPPED_ADDRESS
,
179 (struct sockaddr
*)&addr
, addr_len
);
183 if (!stun_agent_init_error (agent
, &response
, buf
, sizeof (buf
),
184 &request
, STUN_ERROR_BAD_REQUEST
)) {
185 g_debug ("STUN error message not initialized properly");
186 g_assert_not_reached();
190 buf_len
= stun_agent_finish_message (agent
, &response
, NULL
, 0);
193 g_main_loop_quit (global_mainloop
);
194 g_debug ("Ready to send a STUN response");
195 g_assert (g_mutex_trylock (stun_mutex_ptr
));
196 while (global_lagent_state
< NICE_COMPONENT_STATE_CONNECTING
) {
197 g_debug ("Waiting for signal. State is %d", global_lagent_state
);
198 g_cond_wait (stun_signal_ptr
, stun_mutex_ptr
);
200 g_mutex_unlock (stun_mutex_ptr
);
201 len
= sendto (sock
, buf
, buf_len
, 0,
202 (struct sockaddr
*)&addr
, addr_len
);
203 g_debug ("STUN response sent");
204 drop_stun_packets
= TRUE
;
205 ret
= (len
< buf_len
) ? -1 : 0;
210 static gpointer
stun_thread_func (const gpointer user_data
)
217 sock
= listen_socket (IPPORT_STUN
);
220 g_assert_not_reached ();
223 g_mutex_lock (stun_thread_mutex_ptr
);
224 g_cond_signal (stun_thread_signal_ptr
);
225 g_mutex_unlock (stun_thread_mutex_ptr
);
227 stun_agent_init (&oldagent
, known_attributes
,
228 STUN_COMPATIBILITY_RFC3489
, 0);
229 stun_agent_init (&newagent
, known_attributes
,
230 STUN_COMPATIBILITY_RFC5389
, STUN_AGENT_USAGE_USE_FINGERPRINT
);
232 while (!exit_stun_thread
) {
233 g_debug ("Ready to process next datagram");
234 dgram_process (sock
, &oldagent
, &newagent
);
237 exit_code
= close (sock
);
238 g_thread_exit (GINT_TO_POINTER (exit_code
));
242 static void set_credentials (NiceAgent
*lagent
, guint lstream
,
243 NiceAgent
*ragent
, guint rstream
)
245 gchar
*ufrag
= NULL
, *password
= NULL
;
247 nice_agent_get_local_credentials (lagent
, lstream
, &ufrag
, &password
);
248 nice_agent_set_remote_credentials (ragent
, rstream
, ufrag
, password
);
253 nice_agent_get_local_credentials (ragent
, rstream
, &ufrag
, &password
);
254 nice_agent_set_remote_credentials (lagent
, lstream
, ufrag
, password
);
260 static void cb_candidate_gathering_done(NiceAgent
*agent
, guint stream_id
, gpointer data
)
262 g_debug ("test-dribblemode:%s: %p", G_STRFUNC
, data
);
264 if (GPOINTER_TO_UINT(data
) == 1) {
265 g_debug ("lagent finished gathering candidates");
266 lagent_candidate_gathering_done
= TRUE
;
267 } else if (GPOINTER_TO_UINT(data
) == 2) {
268 g_debug ("ragent finished gathering candidates");
269 ragent_candidate_gathering_done
= TRUE
;
271 g_main_loop_quit(global_mainloop
);
274 static void cb_nice_recv (NiceAgent
*agent
, guint stream_id
, guint component_id
, guint len
, gchar
*buf
, gpointer user_data
)
278 g_debug ("test-dribblemode:%s: %p", G_STRFUNC
, user_data
);
280 ret
= strncmp ("0000", buf
, 4);
282 ret
= strncmp ("00001234567812345678", buf
, 16);
285 g_debug ("test-dribblemode:%s: ragent recieved %d bytes : quit mainloop",
287 data_received
= TRUE
;
288 g_main_loop_quit (global_mainloop
);
292 static void cb_component_state_changed (NiceAgent
*agent
, guint stream_id
, guint component_id
, guint state
, gpointer data
)
296 g_debug ("test-dribblemode:%s: %p", G_STRFUNC
, data
);
298 if(GPOINTER_TO_UINT(data
) == 1) {
299 global_lagent_state
= state
;
300 g_debug ("lagent state is %d", state
);
301 } else if (GPOINTER_TO_UINT(data
) == 2) {
302 g_debug ("ragent state is %d", state
);
303 global_ragent_state
= state
;
306 if (GPOINTER_TO_UINT(data
) == 1 && state
== NICE_COMPONENT_STATE_FAILED
) {
307 g_debug ("Signalling STUN response since connchecks failed");
308 g_mutex_lock (stun_mutex_ptr
);
309 g_cond_signal (stun_signal_ptr
);
310 g_mutex_unlock (stun_mutex_ptr
);
311 g_main_loop_quit (global_mainloop
);
314 if(GPOINTER_TO_UINT(data
) == 1 && state
== NICE_COMPONENT_STATE_READY
) {
315 /* note: test payload send and receive */
316 ret
= nice_agent_send (agent
, stream_id
, component_id
,
317 20, "00001234567812345678");
318 g_debug ("Sent %d bytes", ret
);
319 g_assert (ret
== 20);
323 static void swap_candidates(NiceAgent
*local
, guint local_id
, NiceAgent
*remote
, guint remote_id
, gboolean signal_stun_reply
)
325 GSList
*cands
= NULL
;
327 g_debug ("test-dribblemode:%s", G_STRFUNC
);
328 cands
= nice_agent_get_local_candidates(local
, local_id
,
329 NICE_COMPONENT_TYPE_RTP
);
330 g_assert(nice_agent_set_remote_candidates(remote
, remote_id
,
331 NICE_COMPONENT_TYPE_RTP
, cands
));
333 if (signal_stun_reply
) {
334 g_mutex_lock (stun_mutex_ptr
);
335 g_cond_signal (stun_signal_ptr
);
336 g_mutex_unlock (stun_mutex_ptr
);
339 g_slist_free_full (cands
, (GDestroyNotify
) nice_candidate_free
);
342 static void cb_agent_new_candidate(NiceAgent
*agent
, guint stream_id
, guint component_id
, gchar
*foundation
, gpointer user_data
)
344 NiceAgent
*other
= g_object_get_data (G_OBJECT (agent
), "other-agent");
345 GSList
*cands
= nice_agent_get_local_candidates (agent
, stream_id
,
348 GSList
*remote_cands
= NULL
;
353 g_debug ("test-dribblemode:%s: %p", G_STRFUNC
, user_data
);
355 tmp
= g_object_get_data (G_OBJECT (other
), "id");
356 id
= GPOINTER_TO_UINT (tmp
);
358 for (i
= cands
; i
; i
= i
->next
) {
359 temp
= (NiceCandidate
*) i
->data
;
360 if (g_strcmp0(temp
->foundation
, foundation
) == 0) {
361 g_debug ("Adding new local candidate to other agent's connchecks");
362 remote_cands
= g_slist_prepend (remote_cands
, nice_candidate_copy(temp
));
363 g_assert (nice_agent_set_remote_candidates (other
, id
,
364 NICE_COMPONENT_TYPE_RTP
,
369 g_slist_free_full (remote_cands
, (GDestroyNotify
) nice_candidate_free
);
370 g_slist_free_full (cands
, (GDestroyNotify
) nice_candidate_free
);
374 static void add_bad_candidate (NiceAgent
*agent
, guint stream_id
, NiceCandidate
*cand
)
376 NiceAddress bad_addr
;
377 GSList
*cand_list
= NULL
;
379 g_assert (nice_address_set_from_string (&bad_addr
, "172.1.0.1"));
381 cand
= nice_candidate_new (NICE_CANDIDATE_TYPE_HOST
);
382 cand
->stream_id
= stream_id
;
383 cand
->component_id
= NICE_COMPONENT_TYPE_RTP
;
384 cand
->addr
= bad_addr
;
386 nice_agent_get_local_credentials (agent
, stream_id
,
387 &cand
->username
, &cand
->password
);
388 cand_list
= g_slist_prepend (cand_list
, cand
);
390 g_debug ("Adding buggy candidate to the agent %p", agent
);
391 g_assert (nice_agent_set_remote_candidates (agent
, stream_id
,
392 NICE_COMPONENT_TYPE_RTP
,
395 g_slist_free_full (cand_list
, (GDestroyNotify
) nice_candidate_free
);
399 static void init_test(NiceAgent
*lagent
, NiceAgent
*ragent
, gboolean connect_new_candidate_signal
)
401 global_lagent_state
= NICE_COMPONENT_STATE_DISCONNECTED
;
402 global_ragent_state
= NICE_COMPONENT_STATE_DISCONNECTED
;
404 lagent_candidate_gathering_done
= FALSE
;
405 ragent_candidate_gathering_done
= FALSE
;
407 global_ls_id
= nice_agent_add_stream (lagent
, 1);
408 global_rs_id
= nice_agent_add_stream (ragent
, 1);
410 g_assert (global_ls_id
> 0);
411 g_assert (global_rs_id
> 0);
413 g_debug ("lagent stream is : %d and ragent stream is %d",
417 g_object_set_data (G_OBJECT (lagent
), "id", GUINT_TO_POINTER (global_ls_id
));
418 g_object_set_data (G_OBJECT (ragent
), "id", GUINT_TO_POINTER (global_rs_id
));
420 if (connect_new_candidate_signal
) {
421 g_signal_connect (G_OBJECT(lagent
), "new-candidate",
422 G_CALLBACK(cb_agent_new_candidate
), LEFT_AGENT
);
423 g_signal_connect (G_OBJECT(ragent
), "new-candidate",
424 G_CALLBACK(cb_agent_new_candidate
), RIGHT_AGENT
);
426 g_signal_handlers_disconnect_by_func (G_OBJECT(lagent
), cb_agent_new_candidate
,
428 g_signal_handlers_disconnect_by_func (G_OBJECT(ragent
), cb_agent_new_candidate
,
432 data_received
= FALSE
;
434 nice_agent_attach_recv (lagent
, global_ls_id
, NICE_COMPONENT_TYPE_RTP
,
435 g_main_loop_get_context(global_mainloop
),
436 cb_nice_recv
, LEFT_AGENT
);
437 nice_agent_attach_recv (ragent
, global_rs_id
, NICE_COMPONENT_TYPE_RTP
,
438 g_main_loop_get_context(global_mainloop
),
439 cb_nice_recv
, RIGHT_AGENT
);
442 static void cleanup(NiceAgent
*lagent
, NiceAgent
*ragent
)
444 g_debug ("Cleaning up");
445 drop_stun_packets
= FALSE
;
446 nice_agent_remove_stream (lagent
, global_ls_id
);
447 nice_agent_remove_stream (ragent
, global_rs_id
);
450 static void standard_test(NiceAgent
*lagent
, NiceAgent
*ragent
)
452 g_debug ("test-dribblemode:%s", G_STRFUNC
);
454 init_test (lagent
, ragent
, FALSE
);
456 nice_agent_gather_candidates (lagent
, global_ls_id
);
457 g_main_loop_run (global_mainloop
);
458 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_GATHERING
&&
459 !lagent_candidate_gathering_done
);
461 nice_agent_gather_candidates (ragent
, global_rs_id
);
462 if (!ragent_candidate_gathering_done
) {
463 g_main_loop_run (global_mainloop
);
464 g_assert (ragent_candidate_gathering_done
);
467 set_credentials (lagent
, global_ls_id
, ragent
, global_rs_id
);
469 g_debug ("Setting local candidates of ragent as remote candidates of lagent");
470 swap_candidates (ragent
, global_rs_id
,
471 lagent
, global_ls_id
,
474 g_main_loop_run (global_mainloop
);
475 g_assert (global_lagent_state
>= NICE_COMPONENT_STATE_CONNECTED
&&
478 g_debug ("Setting local candidates of lagent as remote candidates of ragent");
479 swap_candidates (lagent
, global_ls_id
,
480 ragent
, global_rs_id
,
482 g_main_loop_run (global_mainloop
);
484 g_assert (lagent_candidate_gathering_done
);
486 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_READY
);
487 g_assert (global_ragent_state
>= NICE_COMPONENT_STATE_CONNECTED
);
489 cleanup (lagent
, ragent
);
492 static void bad_credentials_test(NiceAgent
*lagent
, NiceAgent
*ragent
)
494 g_debug ("test-dribblemode:%s", G_STRFUNC
);
496 init_test (lagent
, ragent
, FALSE
);
498 nice_agent_set_remote_credentials (lagent
, global_ls_id
,
500 nice_agent_set_remote_credentials (ragent
, global_rs_id
,
503 nice_agent_gather_candidates (lagent
, global_ls_id
);
504 g_main_loop_run (global_mainloop
);
505 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_GATHERING
&&
506 !lagent_candidate_gathering_done
);
508 nice_agent_gather_candidates (ragent
, global_rs_id
);
509 if (!ragent_candidate_gathering_done
) {
510 g_main_loop_run (global_mainloop
);
511 g_assert (ragent_candidate_gathering_done
);
514 swap_candidates (ragent
, global_rs_id
,
515 lagent
, global_ls_id
,
517 g_main_loop_run (global_mainloop
);
518 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_FAILED
);
520 // Set the correct credentials and swap candidates
521 set_credentials (lagent
, global_ls_id
, ragent
, global_rs_id
);
522 swap_candidates (ragent
, global_rs_id
,
523 lagent
, global_ls_id
,
526 swap_candidates (lagent
, global_ls_id
,
527 ragent
, global_rs_id
,
530 g_main_loop_run (global_mainloop
);
532 g_assert (data_received
);
533 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_READY
);
534 g_assert (global_ragent_state
>= NICE_COMPONENT_STATE_CONNECTED
);
536 // Wait for lagent to finish gathering candidates
537 g_main_loop_run (global_mainloop
);
538 g_assert (lagent_candidate_gathering_done
);
540 cleanup (lagent
, ragent
);
543 static void bad_candidate_test(NiceAgent
*lagent
,NiceAgent
*ragent
)
545 NiceCandidate
*cand
= NULL
;
547 g_debug ("test-dribblemode:%s", G_STRFUNC
);
549 init_test (lagent
, ragent
, FALSE
);
551 nice_agent_gather_candidates (lagent
, global_ls_id
);
552 g_main_loop_run (global_mainloop
);
553 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_GATHERING
&&
554 !lagent_candidate_gathering_done
);
556 nice_agent_gather_candidates (ragent
, global_rs_id
);
557 if (!ragent_candidate_gathering_done
) {
558 g_main_loop_run (global_mainloop
);
559 g_assert (ragent_candidate_gathering_done
);
562 add_bad_candidate (lagent
, global_ls_id
, cand
);
564 // lagent will finish candidate gathering causing this mainloop to quit
565 g_main_loop_run (global_mainloop
);
567 // connchecks will fail causing this mainloop to quit
568 g_main_loop_run (global_mainloop
);
570 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_FAILED
&&
572 set_credentials (lagent
, global_ls_id
, ragent
, global_rs_id
);
574 swap_candidates (ragent
, global_rs_id
,
575 lagent
, global_ls_id
,
578 swap_candidates (lagent
, global_ls_id
,
579 ragent
, global_rs_id
,
582 g_main_loop_run (global_mainloop
);
584 g_assert (lagent_candidate_gathering_done
);
586 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_READY
);
587 g_assert (global_ragent_state
>= NICE_COMPONENT_STATE_CONNECTED
);
589 cleanup (lagent
, ragent
);
592 static void new_candidate_test(NiceAgent
*lagent
, NiceAgent
*ragent
)
594 g_debug ("test-dribblemode:%s", G_STRFUNC
);
596 init_test (lagent
, ragent
, TRUE
);
597 set_credentials (lagent
, global_ls_id
, ragent
, global_rs_id
);
599 nice_agent_gather_candidates (lagent
, global_ls_id
);
600 g_main_loop_run (global_mainloop
);
601 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_GATHERING
&&
602 !lagent_candidate_gathering_done
);
604 nice_agent_gather_candidates (ragent
, global_rs_id
);
605 if (!ragent_candidate_gathering_done
) {
606 g_main_loop_run (global_mainloop
);
610 g_main_loop_run (global_mainloop
);
611 g_assert (data_received
);
613 // Data arrived, signal STUN thread to send STUN response
614 g_mutex_lock (stun_mutex_ptr
);
615 g_cond_signal (stun_signal_ptr
);
616 g_mutex_unlock (stun_mutex_ptr
);
618 // Wait for lagent to finish gathering candidates
619 g_main_loop_run (global_mainloop
);
621 g_assert (lagent_candidate_gathering_done
);
622 g_assert (ragent_candidate_gathering_done
);
624 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_READY
);
625 g_assert (global_ragent_state
>= NICE_COMPONENT_STATE_CONNECTED
);
627 cleanup (lagent
, ragent
);
630 static void send_dummy_data(void)
632 int sockfd
= listen_socket (4567);
633 struct sockaddr_in addr
;
635 memset (&addr
, 0, sizeof (addr
));
636 addr
.sin_family
= AF_INET
;
637 inet_pton(AF_INET
, "127.0.0.1", &addr
.sin_addr
);
638 addr
.sin_port
= htons (IPPORT_STUN
);
640 g_debug ("Sending dummy data to close STUN thread");
641 sendto (sockfd
, "close socket", 12, 0,
642 (struct sockaddr
*)&addr
, sizeof (addr
));
647 NiceAgent
*lagent
= NULL
, *ragent
= NULL
;
648 GThread
*stun_thread
= NULL
;
649 NiceAddress baseaddr
;
653 global_mainloop
= g_main_loop_new (NULL
, FALSE
);
655 #if !GLIB_CHECK_VERSION(2,31,8)
656 g_thread_init (NULL
);
657 stun_thread
= g_thread_create (stun_thread_func
,
660 stun_mutex_ptr
= g_mutex_new ();
661 stun_signal_ptr
= g_cond_new ();
663 stun_thread
= g_thread_new ("listen for STUN requests",
664 stun_thread_func
, NULL
);
667 // Once the the thread is forked, we want to listen for a signal
668 // that the socket was opened successfully
669 g_mutex_lock (stun_thread_mutex_ptr
);
670 g_cond_wait (stun_thread_signal_ptr
, stun_thread_mutex_ptr
);
672 lagent
= nice_agent_new (g_main_loop_get_context (global_mainloop
),
673 NICE_COMPATIBILITY_RFC5245
);
674 ragent
= nice_agent_new (g_main_loop_get_context (global_mainloop
),
675 NICE_COMPATIBILITY_RFC5245
);
677 g_object_set (G_OBJECT (lagent
), "controlling-mode", TRUE
, NULL
);
678 g_object_set (G_OBJECT (ragent
), "controlling-mode", FALSE
, NULL
);
680 g_object_set (G_OBJECT (lagent
), "upnp", USE_UPNP
, NULL
);
681 g_object_set (G_OBJECT (ragent
), "upnp", USE_UPNP
, NULL
);
683 g_object_set (G_OBJECT (lagent
), "stun-server", "127.0.0.1", NULL
);
684 g_object_set (G_OBJECT (lagent
), "stun-server-port", IPPORT_STUN
, NULL
);
686 g_object_set_data (G_OBJECT (lagent
), "other-agent", ragent
);
687 g_object_set_data (G_OBJECT (ragent
), "other-agent", lagent
);
689 g_assert (nice_address_set_from_string (&baseaddr
, "127.0.0.1"));
690 nice_agent_add_local_address (lagent
, &baseaddr
);
691 nice_agent_add_local_address (ragent
, &baseaddr
);
693 g_signal_connect(G_OBJECT(lagent
), "candidate-gathering-done",
694 G_CALLBACK(cb_candidate_gathering_done
), LEFT_AGENT
);
695 g_signal_connect(G_OBJECT(ragent
), "candidate-gathering-done",
696 G_CALLBACK(cb_candidate_gathering_done
), RIGHT_AGENT
);
697 g_signal_connect(G_OBJECT(lagent
), "component-state-changed",
698 G_CALLBACK(cb_component_state_changed
), LEFT_AGENT
);
699 g_signal_connect(G_OBJECT(ragent
), "component-state-changed",
700 G_CALLBACK(cb_component_state_changed
), RIGHT_AGENT
);
702 standard_test (lagent
, ragent
);
703 bad_credentials_test (lagent
, ragent
);
704 bad_candidate_test (lagent
, ragent
);
705 new_candidate_test (lagent
, ragent
);
707 // Do this to make sure the STUN thread exits
708 exit_stun_thread
= TRUE
;
709 drop_stun_packets
= TRUE
;
712 g_object_unref (lagent
);
713 g_object_unref (ragent
);
715 g_thread_join (stun_thread
);
716 #if !GLIB_CHECK_VERSION(2,31,8)
717 g_mutex_free (stun_mutex_ptr
);
718 g_cond_free (stun_signal_ptr
);
720 g_main_loop_unref (global_mainloop
);