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
;
64 static GMutex stun_mutex
;
65 static GMutex
*stun_mutex_ptr
= &stun_mutex
;
66 static GCond stun_signal
;
67 static GCond
*stun_signal_ptr
= &stun_signal
;
70 static GMainLoop
*global_mainloop
;
71 static NiceComponentState global_lagent_state
= NICE_COMPONENT_STATE_LAST
;
72 static NiceComponentState global_ragent_state
= NICE_COMPONENT_STATE_LAST
;
73 static gboolean exit_stun_thread
= FALSE
;
74 static gboolean lagent_candidate_gathering_done
= FALSE
;
75 static gboolean ragent_candidate_gathering_done
= FALSE
;
76 static guint global_ls_id
, global_rs_id
;
77 static gboolean data_received
= FALSE
;
78 static gboolean drop_stun_packets
= FALSE
;
80 static const uint16_t known_attributes
[] = {
85 * Creates a listening socket
87 static int listen_socket (unsigned int port
)
89 struct sockaddr_in addr
;
90 int fd
= socket (AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
93 perror ("Error opening IP port");
97 memset (&addr
, 0, sizeof (addr
));
98 addr
.sin_family
= AF_INET
;
99 inet_pton(AF_INET
, "127.0.0.1", &addr
.sin_addr
);
100 addr
.sin_port
= htons(port
);
102 if (bind (fd
, (struct sockaddr
*)&addr
, sizeof (struct sockaddr_in
))) {
103 perror ("Error opening IP port");
114 static int dgram_process (int sock
, StunAgent
*oldagent
, StunAgent
*newagent
)
116 struct sockaddr_storage addr
;
118 uint8_t buf
[STUN_MAX_MESSAGE_SIZE
];
122 StunMessage response
;
123 StunValidationStatus validation
;
124 StunAgent
*agent
= NULL
;
127 addr_len
= sizeof (struct sockaddr_in
);
130 len
= recvfrom (sock
, buf
, sizeof(buf
), 0,
131 (struct sockaddr
*)&addr
, &addr_len
);
133 if (drop_stun_packets
) {
134 g_debug ("Dropping STUN packet as requested");
138 if (len
== (size_t)-1) {
142 validation
= stun_agent_validate (newagent
, &request
, buf
, len
, NULL
, 0);
144 if (validation
== STUN_VALIDATION_SUCCESS
) {
147 validation
= stun_agent_validate (oldagent
, &request
, buf
, len
, NULL
, 0);
151 /* Unknown attributes */
152 if (validation
== STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE
) {
153 buf_len
= stun_agent_build_unknown_attributes_error (agent
, &response
, buf
,
154 sizeof (buf
), &request
);
158 /* Mal-formatted packets */
159 if (validation
!= STUN_VALIDATION_SUCCESS
||
160 stun_message_get_class (&request
) != STUN_REQUEST
) {
164 switch (stun_message_get_method (&request
)) {
166 stun_agent_init_response (agent
, &response
, buf
, sizeof (buf
), &request
);
167 if (stun_message_has_cookie (&request
))
168 stun_message_append_xor_addr (&response
,
169 STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS
,
170 (struct sockaddr
*)&addr
, addr_len
);
172 stun_message_append_addr (&response
, STUN_ATTRIBUTE_MAPPED_ADDRESS
,
173 (struct sockaddr
*)&addr
, addr_len
);
177 if (!stun_agent_init_error (agent
, &response
, buf
, sizeof (buf
),
178 &request
, STUN_ERROR_BAD_REQUEST
)) {
179 g_debug ("STUN error message not initialized properly");
180 g_assert_not_reached();
184 buf_len
= stun_agent_finish_message (agent
, &response
, NULL
, 0);
187 g_main_loop_quit (global_mainloop
);
188 g_debug ("Ready to send a STUN response");
189 g_assert (g_mutex_trylock (stun_mutex_ptr
));
190 while (global_lagent_state
< NICE_COMPONENT_STATE_CONNECTING
) {
191 g_debug ("Waiting for signal. State is %d", global_lagent_state
);
192 g_cond_wait (stun_signal_ptr
, stun_mutex_ptr
);
194 g_mutex_unlock (stun_mutex_ptr
);
195 len
= sendto (sock
, buf
, buf_len
, 0,
196 (struct sockaddr
*)&addr
, addr_len
);
197 g_debug ("STUN response sent");
198 drop_stun_packets
= TRUE
;
199 ret
= (len
< buf_len
) ? -1 : 0;
204 static gpointer
stun_thread_func (const gpointer user_data
)
211 sock
= listen_socket (IPPORT_STUN
);
214 g_assert_not_reached ();
217 stun_agent_init (&oldagent
, known_attributes
,
218 STUN_COMPATIBILITY_RFC3489
, 0);
219 stun_agent_init (&newagent
, known_attributes
,
220 STUN_COMPATIBILITY_RFC5389
, STUN_AGENT_USAGE_USE_FINGERPRINT
);
222 while (!exit_stun_thread
) {
223 g_debug ("Ready to process next datagram");
224 dgram_process (sock
, &oldagent
, &newagent
);
227 exit_code
= close (sock
);
228 g_thread_exit (GINT_TO_POINTER (exit_code
));
232 static void set_credentials (NiceAgent
*lagent
, guint lstream
,
233 NiceAgent
*ragent
, guint rstream
)
235 gchar
*ufrag
= NULL
, *password
= NULL
;
237 nice_agent_get_local_credentials (lagent
, lstream
, &ufrag
, &password
);
238 nice_agent_set_remote_credentials (ragent
, rstream
, ufrag
, password
);
243 nice_agent_get_local_credentials (ragent
, rstream
, &ufrag
, &password
);
244 nice_agent_set_remote_credentials (lagent
, lstream
, ufrag
, password
);
250 static void cb_candidate_gathering_done(NiceAgent
*agent
, guint stream_id
, gpointer data
)
252 g_debug ("test-dribblemode:%s: %p", G_STRFUNC
, data
);
254 if (GPOINTER_TO_UINT(data
) == 1) {
255 g_debug ("lagent finished gathering candidates");
256 lagent_candidate_gathering_done
= TRUE
;
257 } else if (GPOINTER_TO_UINT(data
) == 2) {
258 g_debug ("ragent finished gathering candidates");
259 ragent_candidate_gathering_done
= TRUE
;
261 g_main_loop_quit(global_mainloop
);
264 static void cb_nice_recv (NiceAgent
*agent
, guint stream_id
, guint component_id
, guint len
, gchar
*buf
, gpointer user_data
)
268 g_debug ("test-dribblemode:%s: %p", G_STRFUNC
, user_data
);
270 ret
= strncmp ("0000", buf
, 4);
272 ret
= strncmp ("00001234567812345678", buf
, 16);
275 g_debug ("test-dribblemode:%s: ragent recieved %d bytes : quit mainloop",
277 data_received
= TRUE
;
278 g_main_loop_quit (global_mainloop
);
282 static void cb_component_state_changed (NiceAgent
*agent
, guint stream_id
, guint component_id
, guint state
, gpointer data
)
286 g_debug ("test-dribblemode:%s: %p", G_STRFUNC
, data
);
288 if(GPOINTER_TO_UINT(data
) == 1) {
289 global_lagent_state
= state
;
290 g_debug ("lagent state is %d", state
);
291 } else if (GPOINTER_TO_UINT(data
) == 2) {
292 g_debug ("ragent state is %d", state
);
293 global_ragent_state
= state
;
296 if (GPOINTER_TO_UINT(data
) == 1 && state
== NICE_COMPONENT_STATE_FAILED
) {
297 g_debug ("Signalling STUN response since connchecks failed");
298 g_mutex_lock (stun_mutex_ptr
);
299 g_cond_signal (stun_signal_ptr
);
300 g_mutex_unlock (stun_mutex_ptr
);
301 g_main_loop_quit (global_mainloop
);
304 if(GPOINTER_TO_UINT(data
) == 1 && state
== NICE_COMPONENT_STATE_READY
) {
305 /* note: test payload send and receive */
306 ret
= nice_agent_send (agent
, stream_id
, component_id
,
307 20, "00001234567812345678");
308 g_debug ("Sent %d bytes", ret
);
309 g_assert (ret
== 20);
313 static void swap_candidates(NiceAgent
*local
, guint local_id
, NiceAgent
*remote
, guint remote_id
, gboolean signal_stun_reply
)
315 GSList
*cands
= NULL
;
317 g_debug ("test-dribblemode:%s", G_STRFUNC
);
318 cands
= nice_agent_get_local_candidates(local
, local_id
,
319 NICE_COMPONENT_TYPE_RTP
);
320 g_assert(nice_agent_set_remote_candidates(remote
, remote_id
,
321 NICE_COMPONENT_TYPE_RTP
, cands
));
323 if (signal_stun_reply
) {
324 g_mutex_lock (stun_mutex_ptr
);
325 g_cond_signal (stun_signal_ptr
);
326 g_mutex_unlock (stun_mutex_ptr
);
329 g_slist_free_full (cands
, (GDestroyNotify
) nice_candidate_free
);
332 static void cb_agent_new_candidate(NiceAgent
*agent
, guint stream_id
, guint component_id
, gchar
*foundation
, gpointer user_data
)
334 NiceAgent
*other
= g_object_get_data (G_OBJECT (agent
), "other-agent");
335 GSList
*cands
= nice_agent_get_local_candidates (agent
, stream_id
,
338 GSList
*remote_cands
= NULL
;
343 g_debug ("test-dribblemode:%s: %p", G_STRFUNC
, user_data
);
345 tmp
= g_object_get_data (G_OBJECT (other
), "id");
346 id
= GPOINTER_TO_UINT (tmp
);
348 for (i
= cands
; i
; i
= i
->next
) {
349 temp
= (NiceCandidate
*) i
->data
;
350 if (g_strcmp0(temp
->foundation
, foundation
) == 0) {
351 g_debug ("Adding new local candidate to other agent's connchecks");
352 remote_cands
= g_slist_prepend (remote_cands
, nice_candidate_copy(temp
));
353 g_assert (nice_agent_set_remote_candidates (other
, id
,
354 NICE_COMPONENT_TYPE_RTP
,
359 g_slist_free_full (remote_cands
, (GDestroyNotify
) nice_candidate_free
);
360 g_slist_free_full (cands
, (GDestroyNotify
) nice_candidate_free
);
364 static void add_bad_candidate (NiceAgent
*agent
, guint stream_id
, NiceCandidate
*cand
)
366 NiceAddress bad_addr
;
367 GSList
*cand_list
= NULL
;
369 g_assert (nice_address_set_from_string (&bad_addr
, "172.1.0.1"));
371 cand
= nice_candidate_new (NICE_CANDIDATE_TYPE_HOST
);
372 cand
->stream_id
= stream_id
;
373 cand
->component_id
= NICE_COMPONENT_TYPE_RTP
;
374 cand
->addr
= bad_addr
;
376 nice_agent_get_local_credentials (agent
, stream_id
,
377 &cand
->username
, &cand
->password
);
378 cand_list
= g_slist_prepend (cand_list
, cand
);
380 g_debug ("Adding buggy candidate to the agent %p", agent
);
381 g_assert (nice_agent_set_remote_candidates (agent
, stream_id
,
382 NICE_COMPONENT_TYPE_RTP
,
385 g_slist_free_full (cand_list
, (GDestroyNotify
) nice_candidate_free
);
389 static void init_test(NiceAgent
*lagent
, NiceAgent
*ragent
, gboolean connect_new_candidate_signal
)
391 global_lagent_state
= NICE_COMPONENT_STATE_DISCONNECTED
;
392 global_ragent_state
= NICE_COMPONENT_STATE_DISCONNECTED
;
394 lagent_candidate_gathering_done
= FALSE
;
395 ragent_candidate_gathering_done
= FALSE
;
397 global_ls_id
= nice_agent_add_stream (lagent
, 1);
398 global_rs_id
= nice_agent_add_stream (ragent
, 1);
400 g_assert (global_ls_id
> 0);
401 g_assert (global_rs_id
> 0);
403 g_debug ("lagent stream is : %d and ragent stream is %d",
407 g_object_set_data (G_OBJECT (lagent
), "id", GUINT_TO_POINTER (global_ls_id
));
408 g_object_set_data (G_OBJECT (ragent
), "id", GUINT_TO_POINTER (global_rs_id
));
410 if (connect_new_candidate_signal
) {
411 g_signal_connect (G_OBJECT(lagent
), "new-candidate",
412 G_CALLBACK(cb_agent_new_candidate
), LEFT_AGENT
);
413 g_signal_connect (G_OBJECT(ragent
), "new-candidate",
414 G_CALLBACK(cb_agent_new_candidate
), RIGHT_AGENT
);
416 g_signal_handlers_disconnect_by_func (G_OBJECT(lagent
), cb_agent_new_candidate
,
418 g_signal_handlers_disconnect_by_func (G_OBJECT(ragent
), cb_agent_new_candidate
,
422 data_received
= FALSE
;
424 nice_agent_attach_recv (lagent
, global_ls_id
, NICE_COMPONENT_TYPE_RTP
,
425 g_main_loop_get_context(global_mainloop
),
426 cb_nice_recv
, LEFT_AGENT
);
427 nice_agent_attach_recv (ragent
, global_rs_id
, NICE_COMPONENT_TYPE_RTP
,
428 g_main_loop_get_context(global_mainloop
),
429 cb_nice_recv
, RIGHT_AGENT
);
432 static void cleanup(NiceAgent
*lagent
, NiceAgent
*ragent
)
434 g_debug ("Cleaning up");
435 drop_stun_packets
= FALSE
;
436 nice_agent_remove_stream (lagent
, global_ls_id
);
437 nice_agent_remove_stream (ragent
, global_rs_id
);
440 static void standard_test(NiceAgent
*lagent
, NiceAgent
*ragent
)
442 g_debug ("test-dribblemode:%s", G_STRFUNC
);
444 init_test (lagent
, ragent
, FALSE
);
446 nice_agent_gather_candidates (lagent
, global_ls_id
);
447 g_main_loop_run (global_mainloop
);
448 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_GATHERING
&&
449 !lagent_candidate_gathering_done
);
451 nice_agent_gather_candidates (ragent
, global_rs_id
);
452 if (!ragent_candidate_gathering_done
) {
453 g_main_loop_run (global_mainloop
);
454 g_assert (ragent_candidate_gathering_done
);
457 set_credentials (lagent
, global_ls_id
, ragent
, global_rs_id
);
459 g_debug ("Setting local candidates of ragent as remote candidates of lagent");
460 swap_candidates (ragent
, global_rs_id
,
461 lagent
, global_ls_id
,
464 g_main_loop_run (global_mainloop
);
465 g_assert (global_lagent_state
>= NICE_COMPONENT_STATE_CONNECTED
&&
468 g_debug ("Setting local candidates of lagent as remote candidates of ragent");
469 swap_candidates (lagent
, global_ls_id
,
470 ragent
, global_rs_id
,
472 g_main_loop_run (global_mainloop
);
474 g_assert (lagent_candidate_gathering_done
);
476 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_READY
);
477 g_assert (global_ragent_state
>= NICE_COMPONENT_STATE_CONNECTED
);
479 cleanup (lagent
, ragent
);
482 static void bad_credentials_test(NiceAgent
*lagent
, NiceAgent
*ragent
)
484 g_debug ("test-dribblemode:%s", G_STRFUNC
);
486 init_test (lagent
, ragent
, FALSE
);
488 nice_agent_set_remote_credentials (lagent
, global_ls_id
,
490 nice_agent_set_remote_credentials (ragent
, global_rs_id
,
493 nice_agent_gather_candidates (lagent
, global_ls_id
);
494 g_main_loop_run (global_mainloop
);
495 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_GATHERING
&&
496 !lagent_candidate_gathering_done
);
498 nice_agent_gather_candidates (ragent
, global_rs_id
);
499 if (!ragent_candidate_gathering_done
) {
500 g_main_loop_run (global_mainloop
);
501 g_assert (ragent_candidate_gathering_done
);
504 swap_candidates (ragent
, global_rs_id
,
505 lagent
, global_ls_id
,
507 g_main_loop_run (global_mainloop
);
508 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_FAILED
);
510 // Set the correct credentials and swap candidates
511 set_credentials (lagent
, global_ls_id
, ragent
, global_rs_id
);
512 swap_candidates (ragent
, global_rs_id
,
513 lagent
, global_ls_id
,
516 swap_candidates (lagent
, global_ls_id
,
517 ragent
, global_rs_id
,
520 g_main_loop_run (global_mainloop
);
522 g_assert (data_received
);
523 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_READY
);
524 g_assert (global_ragent_state
>= NICE_COMPONENT_STATE_CONNECTED
);
526 // Wait for lagent to finish gathering candidates
527 g_main_loop_run (global_mainloop
);
528 g_assert (lagent_candidate_gathering_done
);
530 cleanup (lagent
, ragent
);
533 static void bad_candidate_test(NiceAgent
*lagent
,NiceAgent
*ragent
)
535 NiceCandidate
*cand
= NULL
;
537 g_debug ("test-dribblemode:%s", G_STRFUNC
);
539 init_test (lagent
, ragent
, FALSE
);
541 nice_agent_gather_candidates (lagent
, global_ls_id
);
542 g_main_loop_run (global_mainloop
);
543 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_GATHERING
&&
544 !lagent_candidate_gathering_done
);
546 nice_agent_gather_candidates (ragent
, global_rs_id
);
547 if (!ragent_candidate_gathering_done
) {
548 g_main_loop_run (global_mainloop
);
549 g_assert (ragent_candidate_gathering_done
);
552 add_bad_candidate (lagent
, global_ls_id
, cand
);
554 // lagent will finish candidate gathering causing this mainloop to quit
555 g_main_loop_run (global_mainloop
);
557 // connchecks will fail causing this mainloop to quit
558 g_main_loop_run (global_mainloop
);
560 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_FAILED
&&
562 set_credentials (lagent
, global_ls_id
, ragent
, global_rs_id
);
564 swap_candidates (ragent
, global_rs_id
,
565 lagent
, global_ls_id
,
568 swap_candidates (lagent
, global_ls_id
,
569 ragent
, global_rs_id
,
572 g_main_loop_run (global_mainloop
);
574 g_assert (lagent_candidate_gathering_done
);
576 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_READY
);
577 g_assert (global_ragent_state
>= NICE_COMPONENT_STATE_CONNECTED
);
579 cleanup (lagent
, ragent
);
582 static void new_candidate_test(NiceAgent
*lagent
, NiceAgent
*ragent
)
584 g_debug ("test-dribblemode:%s", G_STRFUNC
);
586 init_test (lagent
, ragent
, TRUE
);
587 set_credentials (lagent
, global_ls_id
, ragent
, global_rs_id
);
589 nice_agent_gather_candidates (lagent
, global_ls_id
);
590 g_main_loop_run (global_mainloop
);
591 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_GATHERING
&&
592 !lagent_candidate_gathering_done
);
594 nice_agent_gather_candidates (ragent
, global_rs_id
);
595 if (!ragent_candidate_gathering_done
) {
596 g_main_loop_run (global_mainloop
);
600 g_main_loop_run (global_mainloop
);
601 g_assert (data_received
);
603 // Data arrived, signal STUN thread to send STUN response
604 g_mutex_lock (stun_mutex_ptr
);
605 g_cond_signal (stun_signal_ptr
);
606 g_mutex_unlock (stun_mutex_ptr
);
608 // Wait for lagent to finish gathering candidates
609 g_main_loop_run (global_mainloop
);
611 g_assert (lagent_candidate_gathering_done
);
612 g_assert (ragent_candidate_gathering_done
);
614 g_assert (global_lagent_state
== NICE_COMPONENT_STATE_READY
);
615 g_assert (global_ragent_state
>= NICE_COMPONENT_STATE_CONNECTED
);
617 cleanup (lagent
, ragent
);
620 static void send_dummy_data(void)
622 int sockfd
= listen_socket (4567);
623 struct sockaddr_in addr
;
625 memset (&addr
, 0, sizeof (addr
));
626 addr
.sin_family
= AF_INET
;
627 inet_pton(AF_INET
, "127.0.0.1", &addr
.sin_addr
);
628 addr
.sin_port
= htons (IPPORT_STUN
);
630 g_debug ("Sending dummy data to close STUN thread");
631 sendto (sockfd
, "close socket", 12, 0,
632 (struct sockaddr
*)&addr
, sizeof (addr
));
637 NiceAgent
*lagent
= NULL
, *ragent
= NULL
;
638 GThread
*stun_thread
= NULL
;
639 NiceAddress baseaddr
;
643 global_mainloop
= g_main_loop_new (NULL
, FALSE
);
645 #if !GLIB_CHECK_VERSION(2,31,8)
646 g_thread_init (NULL
);
647 stun_thread
= g_thread_create (stun_thread_func
,
650 stun_mutex_ptr
= g_mutex_new ();
651 stun_signal_ptr
= g_cond_new ();
653 stun_thread
= g_thread_new ("listen for STUN requests",
654 stun_thread_func
, NULL
);
657 lagent
= nice_agent_new (g_main_loop_get_context (global_mainloop
),
658 NICE_COMPATIBILITY_RFC5245
);
659 ragent
= nice_agent_new (g_main_loop_get_context (global_mainloop
),
660 NICE_COMPATIBILITY_RFC5245
);
662 g_object_set (G_OBJECT (lagent
), "controlling-mode", TRUE
, NULL
);
663 g_object_set (G_OBJECT (ragent
), "controlling-mode", FALSE
, NULL
);
665 g_object_set (G_OBJECT (lagent
), "upnp", USE_UPNP
, NULL
);
666 g_object_set (G_OBJECT (ragent
), "upnp", USE_UPNP
, NULL
);
668 g_object_set (G_OBJECT (lagent
), "stun-server", "127.0.0.1", NULL
);
669 g_object_set (G_OBJECT (lagent
), "stun-server-port", IPPORT_STUN
, NULL
);
671 g_object_set_data (G_OBJECT (lagent
), "other-agent", ragent
);
672 g_object_set_data (G_OBJECT (ragent
), "other-agent", lagent
);
674 g_assert (nice_address_set_from_string (&baseaddr
, "127.0.0.1"));
675 nice_agent_add_local_address (lagent
, &baseaddr
);
676 nice_agent_add_local_address (ragent
, &baseaddr
);
678 g_signal_connect(G_OBJECT(lagent
), "candidate-gathering-done",
679 G_CALLBACK(cb_candidate_gathering_done
), LEFT_AGENT
);
680 g_signal_connect(G_OBJECT(ragent
), "candidate-gathering-done",
681 G_CALLBACK(cb_candidate_gathering_done
), RIGHT_AGENT
);
682 g_signal_connect(G_OBJECT(lagent
), "component-state-changed",
683 G_CALLBACK(cb_component_state_changed
), LEFT_AGENT
);
684 g_signal_connect(G_OBJECT(ragent
), "component-state-changed",
685 G_CALLBACK(cb_component_state_changed
), RIGHT_AGENT
);
687 standard_test (lagent
, ragent
);
688 bad_credentials_test (lagent
, ragent
);
689 bad_candidate_test (lagent
, ragent
);
690 new_candidate_test (lagent
, ragent
);
692 // Do this to make sure the STUN thread exits
693 exit_stun_thread
= TRUE
;
694 drop_stun_packets
= TRUE
;
697 g_object_unref (lagent
);
698 g_object_unref (ragent
);
700 g_thread_join (stun_thread
);
701 #if !GLIB_CHECK_VERSION(2,31,8)
702 g_mutex_free (stun_mutex_ptr
);
703 g_cond_free (stun_signal_ptr
);
705 g_main_loop_unref (global_mainloop
);