2 * This file is part of the Nice GLib ICE library.
4 * Unit test for ICE in trickle 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"
56 #define LEFT_AGENT GINT_TO_POINTER(1)
57 #define RIGHT_AGENT GINT_TO_POINTER(2)
59 static GMutex stun_mutex;
60 static GMutex *stun_mutex_ptr = &stun_mutex;
61 static GCond stun_signal;
62 static GCond *stun_signal_ptr = &stun_signal;
63 static GMutex stun_thread_mutex;
64 static GMutex *stun_thread_mutex_ptr = &stun_thread_mutex;
65 static GCond stun_thread_signal;
66 static GCond *stun_thread_signal_ptr = &stun_thread_signal;
68 static NiceComponentState global_lagent_state = NICE_COMPONENT_STATE_LAST;
69 static NiceComponentState global_ragent_state = NICE_COMPONENT_STATE_LAST;
70 static GCancellable *global_cancellable;
71 static gboolean exit_stun_thread = FALSE;
72 static gboolean lagent_candidate_gathering_done = FALSE;
73 static gboolean ragent_candidate_gathering_done = FALSE;
74 static guint global_ls_id, global_rs_id;
75 static gboolean data_received = FALSE;
76 static gboolean drop_stun_packets = FALSE;
77 static gboolean got_stun_packet = FALSE;
78 static gboolean send_stun = FALSE;
79 static guint stun_port;
81 static const uint16_t known_attributes[] = {
85 /* Waits about 10 seconds for @var to be NULL/FALSE */
86 #define WAIT_UNTIL_UNSET(var, context) \
91 for (_i = 0; _i < 13 && (var); _i++) \
93 g_usleep (1000 * (1 << _i)); \
94 g_main_context_iteration (context, FALSE); \
101 * Creates a listening socket
103 static int listen_socket (unsigned int *port)
106 struct sockaddr_in in;
107 struct sockaddr addr;
109 int fd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
112 perror ("Error opening IP port");
116 memset (&addr, 0, sizeof (addr));
117 addr.in.sin_family = AF_INET;
118 inet_pton(AF_INET, "127.0.0.1", &addr.in.sin_addr);
119 addr.in.sin_port = 0;
121 if (bind (fd, &addr.addr, sizeof (struct sockaddr_in))) {
122 perror ("Error opening IP port");
127 socklen_t socklen = sizeof(addr);
129 if (getsockname (fd, &addr.addr, &socklen) < 0)
130 g_error ("getsockname failed: %s", strerror (errno));
132 g_assert_cmpint (socklen, ==, sizeof(struct sockaddr_in));
133 *port = ntohs (addr.in.sin_port);
134 g_assert (*port != 0);
144 static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
147 struct sockaddr_storage storage;
148 struct sockaddr addr;
151 uint8_t buf[STUN_MAX_MESSAGE_SIZE];
155 StunMessage response;
156 StunValidationStatus validation;
157 StunAgent *agent = NULL;
160 addr_len = sizeof (struct sockaddr_in);
163 len = recvfrom (sock, buf, sizeof(buf), 0,
164 &addr.addr, &addr_len);
166 if (drop_stun_packets) {
167 g_debug ("Dropping STUN packet as requested");
171 if (len == (size_t)-1) {
175 validation = stun_agent_validate (newagent, &request, buf, len, NULL, 0);
177 if (validation == STUN_VALIDATION_SUCCESS) {
180 validation = stun_agent_validate (oldagent, &request, buf, len, NULL, 0);
184 /* Unknown attributes */
185 if (validation == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE) {
186 buf_len = stun_agent_build_unknown_attributes_error (agent, &response, buf,
187 sizeof (buf), &request);
191 /* Mal-formatted packets */
192 if (validation != STUN_VALIDATION_SUCCESS ||
193 stun_message_get_class (&request) != STUN_REQUEST) {
197 switch (stun_message_get_method (&request)) {
199 stun_agent_init_response (agent, &response, buf, sizeof (buf), &request);
200 if (stun_message_has_cookie (&request))
201 stun_message_append_xor_addr (&response,
202 STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
203 &addr.storage, addr_len);
205 stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS,
206 &addr.addr, addr_len);
209 case STUN_SHARED_SECRET:
211 case STUN_SET_ACTIVE_DST:
213 case STUN_OLD_SET_ACTIVE_DST:
215 case STUN_IND_CONNECT_STATUS:
216 case STUN_CHANNELBIND:
218 if (!stun_agent_init_error (agent, &response, buf, sizeof (buf),
219 &request, STUN_ERROR_BAD_REQUEST)) {
220 g_debug ("STUN error message not initialized properly");
221 g_assert_not_reached();
225 buf_len = stun_agent_finish_message (agent, &response, NULL, 0);
228 g_cancellable_cancel (global_cancellable);
229 g_debug ("Ready to send a STUN response");
230 g_assert (g_mutex_trylock (stun_mutex_ptr));
231 got_stun_packet = TRUE;
233 g_debug ("Waiting for signal. State is %d", global_lagent_state);
234 g_cond_wait (stun_signal_ptr, stun_mutex_ptr);
236 g_mutex_unlock (stun_mutex_ptr);
237 len = sendto (sock, buf, buf_len, 0,
238 &addr.addr, addr_len);
239 g_debug ("STUN response sent");
240 drop_stun_packets = TRUE;
241 ret = (len < buf_len) ? -1 : 0;
246 static gpointer stun_thread_func (const gpointer user_data)
250 int sock = GPOINTER_TO_INT (user_data);
253 g_mutex_lock (stun_thread_mutex_ptr);
254 g_cond_signal (stun_thread_signal_ptr);
255 g_mutex_unlock (stun_thread_mutex_ptr);
257 stun_agent_init (&oldagent, known_attributes,
258 STUN_COMPATIBILITY_RFC3489, 0);
259 stun_agent_init (&newagent, known_attributes,
260 STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT);
262 while (!exit_stun_thread) {
263 g_debug ("Ready to process next datagram");
264 dgram_process (sock, &oldagent, &newagent);
267 exit_code = close (sock);
268 g_thread_exit (GINT_TO_POINTER (exit_code));
272 static void swap_credentials (NiceAgent *lagent, guint lstream,
273 NiceAgent *ragent, guint rstream)
275 gchar *ufrag = NULL, *password = NULL;
277 nice_agent_get_local_credentials (lagent, lstream, &ufrag, &password);
278 nice_agent_set_remote_credentials (ragent, rstream, ufrag, password);
284 static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
286 g_debug ("test-tricklemode:%s: %p", G_STRFUNC, data);
288 if (GPOINTER_TO_UINT(data) == 1) {
289 g_debug ("lagent finished gathering candidates");
290 lagent_candidate_gathering_done = TRUE;
291 } else if (GPOINTER_TO_UINT(data) == 2) {
292 g_debug ("ragent finished gathering candidates");
293 ragent_candidate_gathering_done = TRUE;
295 g_cancellable_cancel (global_cancellable);
298 static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
302 g_debug ("test-tricklemode:%s: %p", G_STRFUNC, user_data);
304 ret = strncmp ("0000", buf, 4);
306 ret = strncmp ("00001234567812345678", buf, 16);
307 g_assert_cmpint (ret, ==, 0);
309 g_debug ("test-tricklemode:%s: ragent recieved %d bytes : quit mainloop",
311 data_received = TRUE;
312 g_cancellable_cancel (global_cancellable);
316 static void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data)
320 g_debug ("test-tricklemode:%s: %p", G_STRFUNC, data);
322 if(GPOINTER_TO_UINT(data) == 1) {
323 global_lagent_state = state;
324 g_debug ("lagent state is %d", state);
325 } else if (GPOINTER_TO_UINT(data) == 2) {
326 g_debug ("ragent state is %d", state);
327 global_ragent_state = state;
330 if (GPOINTER_TO_UINT(data) == 1 && state == NICE_COMPONENT_STATE_FAILED) {
331 g_debug ("Signalling STUN response since connchecks failed");
332 g_mutex_lock (stun_mutex_ptr);
334 g_cond_signal (stun_signal_ptr);
335 g_mutex_unlock (stun_mutex_ptr);
336 g_cancellable_cancel (global_cancellable);
339 if(GPOINTER_TO_UINT(data) == 1 && state == NICE_COMPONENT_STATE_READY) {
340 /* note: test payload send and receive */
341 ret = nice_agent_send (agent, stream_id, component_id,
342 20, "00001234567812345678");
343 g_debug ("Sent %d bytes", ret);
344 g_assert_cmpint (ret, ==, 20);
348 static void swap_candidates(NiceAgent *local, guint local_id, NiceAgent *remote, guint remote_id, gboolean signal_stun_reply)
350 GSList *cands = NULL;
352 g_debug ("test-tricklemode:%s", G_STRFUNC);
353 cands = nice_agent_get_local_candidates(local, local_id,
354 NICE_COMPONENT_TYPE_RTP);
355 g_assert (nice_agent_set_remote_candidates(remote, remote_id,
356 NICE_COMPONENT_TYPE_RTP, cands));
358 if (signal_stun_reply) {
359 g_mutex_lock (stun_mutex_ptr);
361 g_cond_signal (stun_signal_ptr);
362 g_mutex_unlock (stun_mutex_ptr);
365 g_slist_free_full (cands, (GDestroyNotify) nice_candidate_free);
368 static void cb_agent_new_candidate(NiceAgent *agent, guint stream_id, guint component_id, gchar *foundation, gpointer user_data)
370 NiceAgent *other = g_object_get_data (G_OBJECT (agent), "other-agent");
371 GSList *cands = nice_agent_get_local_candidates (agent, stream_id,
374 GSList *remote_cands = NULL;
379 g_debug ("test-tricklemode:%s: %p", G_STRFUNC, user_data);
381 tmp = g_object_get_data (G_OBJECT (other), "id");
382 id = GPOINTER_TO_UINT (tmp);
384 for (i = cands; i; i = i->next) {
385 temp = (NiceCandidate*) i->data;
386 if (g_strcmp0(temp->foundation, foundation) == 0) {
387 g_debug ("Adding new local candidate to other agent's connchecks");
388 remote_cands = g_slist_prepend (remote_cands, nice_candidate_copy(temp));
389 g_assert (nice_agent_set_remote_candidates (other, id,
390 NICE_COMPONENT_TYPE_RTP,
395 g_slist_free_full (remote_cands, (GDestroyNotify) nice_candidate_free);
396 g_slist_free_full (cands, (GDestroyNotify) nice_candidate_free);
400 static void add_bad_candidate (NiceAgent *agent, guint stream_id, NiceCandidate *cand)
402 NiceAddress bad_addr;
403 GSList *cand_list = NULL;
405 g_assert (nice_address_set_from_string (&bad_addr, "172.1.0.1"));
407 cand = nice_candidate_new (NICE_CANDIDATE_TYPE_HOST);
408 cand->stream_id = stream_id;
409 cand->component_id = NICE_COMPONENT_TYPE_RTP;
410 cand->addr = bad_addr;
412 nice_agent_get_local_credentials (agent, stream_id,
413 &cand->username, &cand->password);
414 cand_list = g_slist_prepend (cand_list, cand);
416 g_debug ("Adding buggy candidate to the agent %p", agent);
417 g_assert (nice_agent_set_remote_candidates (agent, stream_id,
418 NICE_COMPONENT_TYPE_RTP,
421 g_slist_free_full (cand_list, (GDestroyNotify) nice_candidate_free);
425 static void init_test(NiceAgent *lagent, NiceAgent *ragent, gboolean connect_new_candidate_signal)
427 global_lagent_state = NICE_COMPONENT_STATE_DISCONNECTED;
428 global_ragent_state = NICE_COMPONENT_STATE_DISCONNECTED;
430 lagent_candidate_gathering_done = FALSE;
431 ragent_candidate_gathering_done = FALSE;
433 global_ls_id = nice_agent_add_stream (lagent, 1);
434 global_rs_id = nice_agent_add_stream (ragent, 1);
436 g_assert_cmpuint (global_ls_id, >, 0);
437 g_assert_cmpuint (global_rs_id, >, 0);
439 g_debug ("lagent stream is : %d and ragent stream is %d",
443 g_object_set_data (G_OBJECT (lagent), "id", GUINT_TO_POINTER (global_ls_id));
444 g_object_set_data (G_OBJECT (ragent), "id", GUINT_TO_POINTER (global_rs_id));
446 if (connect_new_candidate_signal) {
447 g_signal_connect (G_OBJECT(lagent), "new-candidate",
448 G_CALLBACK(cb_agent_new_candidate), LEFT_AGENT);
449 g_signal_connect (G_OBJECT(ragent), "new-candidate",
450 G_CALLBACK(cb_agent_new_candidate), RIGHT_AGENT);
452 g_signal_handlers_disconnect_by_func (G_OBJECT(lagent), cb_agent_new_candidate,
454 g_signal_handlers_disconnect_by_func (G_OBJECT(ragent), cb_agent_new_candidate,
458 data_received = FALSE;
459 got_stun_packet = FALSE;
462 nice_agent_attach_recv (lagent, global_ls_id, NICE_COMPONENT_TYPE_RTP,
463 g_main_context_default (),
464 cb_nice_recv, LEFT_AGENT);
465 nice_agent_attach_recv (ragent, global_rs_id, NICE_COMPONENT_TYPE_RTP,
466 g_main_context_default (),
467 cb_nice_recv, RIGHT_AGENT);
470 static void cleanup(NiceAgent *lagent, NiceAgent *ragent)
472 g_debug ("Cleaning up");
473 drop_stun_packets = FALSE;
474 nice_agent_remove_stream (lagent, global_ls_id);
475 nice_agent_remove_stream (ragent, global_rs_id);
478 static void standard_test(NiceAgent *lagent, NiceAgent *ragent)
480 g_debug ("test-tricklemode:%s", G_STRFUNC);
482 got_stun_packet = FALSE;
483 init_test (lagent, ragent, FALSE);
485 nice_agent_gather_candidates (lagent, global_ls_id);
486 while (!got_stun_packet)
487 g_main_context_iteration (NULL, TRUE);
488 g_assert (global_lagent_state == NICE_COMPONENT_STATE_GATHERING &&
489 !lagent_candidate_gathering_done);
491 nice_agent_gather_candidates (ragent, global_rs_id);
492 while (!ragent_candidate_gathering_done)
493 g_main_context_iteration (NULL, TRUE);
494 g_cancellable_reset (global_cancellable);
495 g_assert (ragent_candidate_gathering_done);
496 g_assert (nice_agent_peer_candidate_gathering_done (lagent, global_ls_id));
499 g_debug ("Setting local candidates of ragent as remote candidates of lagent");
500 swap_candidates (ragent, global_rs_id, lagent, global_ls_id, TRUE);
501 swap_credentials (ragent, global_rs_id, lagent, global_ls_id);
503 while (!data_received)
504 g_main_context_iteration (NULL, TRUE);
505 g_cancellable_reset (global_cancellable);
506 g_assert (global_lagent_state >= NICE_COMPONENT_STATE_CONNECTED &&
509 g_debug ("Setting local candidates of lagent as remote candidates of ragent");
510 swap_candidates (lagent, global_ls_id, ragent, global_rs_id, FALSE);
511 swap_credentials (lagent, global_ls_id, ragent, global_rs_id);
513 while (!lagent_candidate_gathering_done)
514 g_main_context_iteration (NULL, TRUE);
515 g_cancellable_reset (global_cancellable);
517 g_assert (lagent_candidate_gathering_done);
518 g_assert (nice_agent_peer_candidate_gathering_done (ragent, global_rs_id));
520 while (global_ragent_state < NICE_COMPONENT_STATE_CONNECTED)
521 g_main_context_iteration (NULL, TRUE);
522 g_cancellable_reset (global_cancellable);
524 g_assert_cmpint (global_lagent_state, ==, NICE_COMPONENT_STATE_READY);
525 g_assert_cmpint (global_ragent_state, >=, NICE_COMPONENT_STATE_CONNECTED);
527 cleanup (lagent, ragent);
530 static void bad_credentials_test(NiceAgent *lagent, NiceAgent *ragent)
532 g_debug ("test-tricklemode:%s", G_STRFUNC);
534 init_test (lagent, ragent, FALSE);
536 nice_agent_set_remote_credentials (lagent, global_ls_id,
538 nice_agent_set_remote_credentials (ragent, global_rs_id,
541 nice_agent_gather_candidates (lagent, global_ls_id);
542 while (!got_stun_packet)
543 g_main_context_iteration (NULL, TRUE);
544 g_cancellable_reset (global_cancellable);
545 g_assert (global_lagent_state == NICE_COMPONENT_STATE_GATHERING &&
546 !lagent_candidate_gathering_done);
548 nice_agent_gather_candidates (ragent, global_rs_id);
549 while (!ragent_candidate_gathering_done)
550 g_main_context_iteration (NULL, TRUE);
551 g_cancellable_reset (global_cancellable);
552 g_assert (ragent_candidate_gathering_done);
553 g_assert (nice_agent_peer_candidate_gathering_done (lagent, global_ls_id));
555 g_debug ("Setting local candidates of ragent as remote candidates of lagent");
556 swap_candidates (ragent, global_rs_id, lagent, global_ls_id, FALSE);
558 while (global_lagent_state != NICE_COMPONENT_STATE_FAILED)
559 g_main_context_iteration (NULL, TRUE);
560 g_cancellable_reset (global_cancellable);
562 // Set the correct credentials and swap candidates
563 g_debug ("Setting local candidates of ragent as remote candidates of lagent");
564 swap_candidates (ragent, global_rs_id, lagent, global_ls_id, FALSE);
565 swap_credentials (lagent, global_ls_id, ragent, global_rs_id);
567 g_debug ("Setting local candidates of lagent as remote candidates of ragent");
568 swap_candidates (lagent, global_ls_id, ragent, global_rs_id, FALSE);
569 swap_credentials (ragent, global_rs_id, lagent, global_ls_id);
571 while (!data_received)
572 g_main_context_iteration (NULL, TRUE);
573 g_cancellable_reset (global_cancellable);
575 g_assert (data_received);
576 g_assert_cmpint (global_lagent_state, ==, NICE_COMPONENT_STATE_READY);
577 g_assert_cmpint (global_ragent_state, >=, NICE_COMPONENT_STATE_CONNECTED);
579 // Wait for lagent to finish gathering candidates
580 while (!lagent_candidate_gathering_done)
581 g_main_context_iteration (NULL, TRUE);
582 g_cancellable_reset (global_cancellable);
584 g_assert (lagent_candidate_gathering_done);
585 g_assert (nice_agent_peer_candidate_gathering_done (ragent, global_rs_id));
587 cleanup (lagent, ragent);
590 static void bad_candidate_test(NiceAgent *lagent,NiceAgent *ragent)
592 NiceCandidate *cand = NULL;
594 g_debug ("test-tricklemode:%s", G_STRFUNC);
596 init_test (lagent, ragent, FALSE);
598 nice_agent_gather_candidates (lagent, global_ls_id);
599 while (!got_stun_packet)
600 g_main_context_iteration (NULL, TRUE);
601 g_cancellable_reset (global_cancellable);
602 g_assert (global_lagent_state == NICE_COMPONENT_STATE_GATHERING &&
603 !lagent_candidate_gathering_done);
605 nice_agent_gather_candidates (ragent, global_rs_id);
606 while (!ragent_candidate_gathering_done)
607 g_main_context_iteration (NULL, TRUE);
608 g_cancellable_reset (global_cancellable);
610 g_assert (ragent_candidate_gathering_done);
611 g_assert (nice_agent_peer_candidate_gathering_done (lagent, global_ls_id));
613 add_bad_candidate (lagent, global_ls_id, cand);
615 // lagent will finish candidate gathering causing this mainloop to quit
616 while (!lagent_candidate_gathering_done)
617 g_main_context_iteration (NULL, TRUE);
618 g_cancellable_reset (global_cancellable);
620 g_assert (nice_agent_peer_candidate_gathering_done (ragent, global_rs_id));
622 // connchecks will fail causing this mainloop to quit
623 while (global_lagent_state != NICE_COMPONENT_STATE_FAILED)
624 g_main_context_iteration (NULL, TRUE);
625 g_cancellable_reset (global_cancellable);
627 g_assert (global_lagent_state == NICE_COMPONENT_STATE_FAILED &&
630 g_debug ("Setting local candidates of ragent as remote candidates of lagent");
631 swap_candidates (ragent, global_rs_id, lagent, global_ls_id, FALSE);
632 swap_credentials (ragent, global_rs_id, lagent, global_ls_id);
634 g_debug ("Setting local candidates of lagent as remote candidates of ragent");
635 swap_candidates (lagent, global_ls_id, ragent, global_rs_id, FALSE);
636 swap_credentials (lagent, global_ls_id, ragent, global_rs_id);
638 while (!data_received)
639 g_main_context_iteration (NULL, TRUE);
640 g_cancellable_reset (global_cancellable);
642 g_assert (lagent_candidate_gathering_done);
644 g_assert_cmpint (global_lagent_state, >=, NICE_COMPONENT_STATE_CONNECTED);
645 g_assert_cmpint (global_ragent_state, >=, NICE_COMPONENT_STATE_CONNECTING);
647 cleanup (lagent, ragent);
650 static void new_candidate_test(NiceAgent *lagent, NiceAgent *ragent)
652 g_debug ("test-tricklemode:%s", G_STRFUNC);
654 init_test (lagent, ragent, TRUE);
655 swap_credentials (lagent, global_ls_id, ragent, global_rs_id);
656 swap_credentials (ragent, global_rs_id, lagent, global_ls_id);
658 nice_agent_gather_candidates (lagent, global_ls_id);
659 while (!got_stun_packet)
660 g_main_context_iteration (NULL, TRUE);
661 g_cancellable_reset (global_cancellable);
662 g_assert (global_lagent_state == NICE_COMPONENT_STATE_GATHERING &&
663 !lagent_candidate_gathering_done);
665 nice_agent_gather_candidates (ragent, global_rs_id);
666 while (!ragent_candidate_gathering_done)
667 g_main_context_iteration (NULL, TRUE);
668 g_cancellable_reset (global_cancellable);
669 g_assert (nice_agent_peer_candidate_gathering_done (lagent, global_ls_id));
672 while (!data_received)
673 g_main_context_iteration (NULL, TRUE);
674 g_cancellable_reset (global_cancellable);
675 g_assert (data_received);
677 // Data arrived, signal STUN thread to send STUN response
678 g_mutex_lock (stun_mutex_ptr);
680 g_cond_signal (stun_signal_ptr);
681 g_mutex_unlock (stun_mutex_ptr);
683 // Wait for lagent to finish gathering candidates
684 while (!lagent_candidate_gathering_done)
685 g_main_context_iteration (NULL, TRUE);
686 g_cancellable_reset (global_cancellable);
687 g_assert (nice_agent_peer_candidate_gathering_done (ragent, global_rs_id));
689 g_assert (lagent_candidate_gathering_done);
690 g_assert (ragent_candidate_gathering_done);
692 g_assert_cmpint (global_lagent_state, ==, NICE_COMPONENT_STATE_READY);
693 g_assert_cmpint (global_ragent_state, >=, NICE_COMPONENT_STATE_CONNECTED);
695 cleanup (lagent, ragent);
698 static void send_dummy_data(void)
700 int sockfd = listen_socket (NULL);
702 struct sockaddr_in in;
703 struct sockaddr addr;
706 memset (&addr, 0, sizeof (addr));
707 addr.in.sin_family = AF_INET;
708 inet_pton(AF_INET, "127.0.0.1", &addr.in.sin_addr);
709 addr.in.sin_port = htons (stun_port);
711 g_debug ("Sending dummy data to close STUN thread");
712 sendto (sockfd, "close socket", 12, 0,
713 &addr.addr, sizeof (addr));
718 NiceAgent *lagent = NULL, *ragent = NULL;
719 GThread *stun_thread = NULL;
720 NiceAddress baseaddr;
724 global_cancellable = g_cancellable_new ();
725 src = g_cancellable_source_new (global_cancellable);
726 g_source_set_dummy_callback (src);
727 g_source_attach (src, NULL);
729 sock = listen_socket (&stun_port);
732 g_assert_not_reached ();
736 stun_thread = g_thread_new ("listen for STUN requests",
737 stun_thread_func, GINT_TO_POINTER (sock));
739 // Once the the thread is forked, we want to listen for a signal
740 // that the socket was opened successfully
741 g_mutex_lock (stun_thread_mutex_ptr);
742 g_cond_wait (stun_thread_signal_ptr, stun_thread_mutex_ptr);
744 lagent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
745 ragent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
747 g_object_set (G_OBJECT (lagent), "ice-tcp", FALSE, NULL);
748 g_object_set (G_OBJECT (ragent), "ice-tcp", FALSE, NULL);
750 g_object_set (G_OBJECT (lagent), "ice-trickle", TRUE, NULL);
751 g_object_set (G_OBJECT (ragent), "ice-trickle", TRUE, NULL);
753 g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
754 g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
756 g_object_set (G_OBJECT (lagent), "upnp", USE_UPNP, NULL);
757 g_object_set (G_OBJECT (ragent), "upnp", USE_UPNP, NULL);
759 g_object_set (G_OBJECT (lagent), "stun-server", "127.0.0.1", NULL);
760 g_object_set (G_OBJECT (lagent), "stun-server-port", stun_port, NULL);
762 g_object_set_data (G_OBJECT (lagent), "other-agent", ragent);
763 g_object_set_data (G_OBJECT (ragent), "other-agent", lagent);
765 g_assert (nice_address_set_from_string (&baseaddr, "127.0.0.1"));
766 nice_agent_add_local_address (lagent, &baseaddr);
767 nice_agent_add_local_address (ragent, &baseaddr);
769 g_signal_connect(G_OBJECT(lagent), "candidate-gathering-done",
770 G_CALLBACK(cb_candidate_gathering_done), LEFT_AGENT);
771 g_signal_connect(G_OBJECT(ragent), "candidate-gathering-done",
772 G_CALLBACK(cb_candidate_gathering_done), RIGHT_AGENT);
773 g_signal_connect(G_OBJECT(lagent), "component-state-changed",
774 G_CALLBACK(cb_component_state_changed), LEFT_AGENT);
775 g_signal_connect(G_OBJECT(ragent), "component-state-changed",
776 G_CALLBACK(cb_component_state_changed), RIGHT_AGENT);
778 standard_test (lagent, ragent);
779 bad_credentials_test (lagent, ragent);
780 bad_candidate_test (lagent, ragent);
781 new_candidate_test (lagent, ragent);
783 // Do this to make sure the STUN thread exits
784 exit_stun_thread = TRUE;
785 drop_stun_packets = TRUE;
788 g_cond_signal (stun_signal_ptr);
790 g_object_add_weak_pointer (G_OBJECT (lagent), (gpointer *) &lagent);
791 g_object_add_weak_pointer (G_OBJECT (ragent), (gpointer *) &ragent);
793 g_object_unref (lagent);
794 g_object_unref (ragent);
796 g_thread_join (stun_thread);
797 g_object_unref (global_cancellable);
799 g_source_destroy (src);
800 g_source_unref (src);
802 WAIT_UNTIL_UNSET (lagent, NULL);
803 WAIT_UNTIL_UNSET (ragent, NULL);