2 * This file is part of the Nice GLib ICE library.
4 * Unit test for ICE full-mode related features.
6 * (C) 2007 Nokia Corporation. All rights reserved.
7 * Contact: Kai Vehmanen
9 * The contents of this file are subject to the Mozilla Public License Version
10 * 1.1 (the "License"); you may not use this file except in compliance with
11 * the License. You may obtain a copy of the License at
12 * http://www.mozilla.org/MPL/
14 * Software distributed under the License is distributed on an "AS IS" basis,
15 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16 * for the specific language governing rights and limitations under the
19 * The Original Code is the Nice GLib ICE library.
21 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
22 * Corporation. All Rights Reserved.
27 * Alternatively, the contents of this file may be used under the terms of the
28 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
29 * case the provisions of LGPL are applicable instead of those above. If you
30 * wish to allow use of your version of this file only under the terms of the
31 * LGPL and not to allow others to use your version of this file under the
32 * MPL, indicate your decision by deleting the provisions above and replace
33 * them with the notice and other provisions required by the LGPL. If you do
34 * not delete the provisions above, a recipient may use your version of this
35 * file under either the MPL or the LGPL.
48 #define USE_LOOPBACK 1
51 #define USE_RELIABLE 0
54 #define PROXY_IP "127.0.0.1"
55 #define PROXY_PORT 1080
56 #define PROXY_USERNAME NULL
57 #define PROXY_PASSWORD NULL
60 #define PROXY_TYPE NICE_PROXY_TYPE_SOCKS5
62 #define PROXY_TYPE NICE_PROXY_TYPE_NONE
66 #define NICE_COMPATIBILITY NICE_COMPATIBILITY_GOOGLE
70 #define USE_LOOPBACK 0
72 #define TURN_IP "209.85.163.126"
74 #define TURN_USER "ih9ppiM0P6vN34DB"
76 #define TURN_USER2 TURN_USER
77 #define TURN_PASS2 TURN_PASS
78 #define TURN_TYPE NICE_RELAY_TYPE_TURN_TLS
83 #define NICE_COMPATIBILITY NICE_COMPATIBILITY_RFC5245
85 #define USE_TURN_SERVER_ORG 1
87 #define USE_TURN_SERVER_ORG 0
90 #define NUMB_IP "64.251.22.149"
91 #define NUMB_PORT 3478
92 #define NUMB_USER "youness.alaoui@collabora.co.uk"
93 #define NUMB_PASS "badger"
95 #define TSORG_IP "127.0.0.1"
96 #define TSORG_PORT 3478
97 #define TSORG_USER "toto"
98 #define TSORG_PASS "password"
101 #if USE_TURN_SERVER_ORG
102 #define TURN_IP TSORG_IP
103 #define TURN_PORT TSORG_PORT
104 #define TURN_USER TSORG_USER
105 #define TURN_PASS TSORG_PASS
106 #define TURN_USER2 TSORG_USER
107 #define TURN_PASS2 TSORG_PASS
108 #define TURN_TYPE NICE_RELAY_TYPE_TURN_TCP
110 #define TURN_IP NUMB_IP
111 #define TURN_PORT NUMB_PORT
112 #define TURN_USER NUMB_USER
113 #define TURN_PASS NUMB_PASS
114 #define TURN_USER2 NUMB_USER
115 #define TURN_PASS2 NUMB_PASS
116 #define TURN_TYPE NICE_RELAY_TYPE_TURN_UDP
122 static NiceComponentState global_lagent_state[2] = { NICE_COMPONENT_STATE_LAST, NICE_COMPONENT_STATE_LAST };
123 static NiceComponentState global_ragent_state[2] = { NICE_COMPONENT_STATE_LAST, NICE_COMPONENT_STATE_LAST };
124 static guint global_components_ready = 0;
125 static guint global_components_ready_exit = 0;
126 static guint global_components_failed = 0;
127 static guint global_components_failed_exit = 0;
128 static GMainLoop *global_mainloop = NULL;
129 static gboolean global_lagent_gathering_done = FALSE;
130 static gboolean global_ragent_gathering_done = FALSE;
131 static gboolean global_lagent_ibr_received = FALSE;
132 static gboolean global_ragent_ibr_received = FALSE;
133 static int global_lagent_cands = 0;
134 static int global_ragent_cands = 0;
135 static gint global_ragent_read = 0;
136 static guint global_exit_when_ibr_received = 0;
138 static void priv_print_global_status (void)
140 g_debug ("\tgathering_done=%d", global_lagent_gathering_done && global_ragent_gathering_done);
141 g_debug ("\tlstate[rtp]=%d [rtcp]=%d", global_lagent_state[0], global_lagent_state[1]);
142 g_debug ("\trstate[rtp]=%d [rtcp]=%d", global_ragent_state[0], global_ragent_state[1]);
143 g_debug ("\tL cands=%d R cands=%d", global_lagent_cands, global_ragent_cands);
146 static gboolean timer_cb (gpointer pointer)
148 g_debug ("test-fullmode:%s: %p", G_STRFUNC, pointer);
150 /* signal status via a global variable */
152 /* note: should not be reached, abort */
153 g_error ("ERROR: test has got stuck, aborting...");
158 static void cb_writable (NiceAgent*agent, guint stream_id, guint component_id,
161 guint *ls_id = user_data;
163 if (stream_id == *ls_id && component_id == 1) {
164 g_debug ("Transport is now writable, stopping mainloop");
169 static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
171 g_debug ("test-fullmode:%s: %p", G_STRFUNC, user_data);
173 /* XXX: dear compiler, these are for you: */
174 (void)agent; (void)stream_id; (void)component_id; (void)buf;
177 * Lets ignore stun packets that got through
181 if (strncmp ("12345678", buf, 8))
184 if (component_id == 2)
187 if (GPOINTER_TO_UINT (user_data) == 2) {
188 g_debug ("right agent received %d bytes, stopping mainloop", len);
189 global_ragent_read = len;
190 g_main_loop_quit (global_mainloop);
194 static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
196 g_debug ("test-fullmode:%s: %p", G_STRFUNC, data);
198 if (GPOINTER_TO_UINT (data) == 1)
199 global_lagent_gathering_done = TRUE;
200 else if (GPOINTER_TO_UINT (data) == 2)
201 global_ragent_gathering_done = TRUE;
203 if (global_lagent_gathering_done &&
204 global_ragent_gathering_done)
205 g_main_loop_quit (global_mainloop);
207 /* XXX: dear compiler, these are for you: */
211 static void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data)
213 gboolean ready_to_connected = FALSE;
214 g_debug ("test-fullmode:%s: %p", G_STRFUNC, data);
216 if (GPOINTER_TO_UINT (data) == 1) {
217 if (global_lagent_state[component_id - 1] == NICE_COMPONENT_STATE_READY &&
218 state == NICE_COMPONENT_STATE_CONNECTED)
219 ready_to_connected = TRUE;
220 global_lagent_state[component_id - 1] = state;
221 } else if (GPOINTER_TO_UINT (data) == 2) {
222 if (global_ragent_state[component_id - 1] == NICE_COMPONENT_STATE_READY &&
223 state == NICE_COMPONENT_STATE_CONNECTED)
224 ready_to_connected = TRUE;
225 global_ragent_state[component_id - 1] = state;
228 if (state == NICE_COMPONENT_STATE_READY)
229 global_components_ready++;
230 else if (state == NICE_COMPONENT_STATE_CONNECTED && ready_to_connected)
231 global_components_ready--;
232 if (state == NICE_COMPONENT_STATE_FAILED)
233 global_components_failed++;
235 g_debug ("test-fullmode: checks READY/EXIT-AT %u/%u.", global_components_ready, global_components_ready_exit);
236 g_debug ("test-fullmode: checks FAILED/EXIT-AT %u/%u.", global_components_failed, global_components_failed_exit);
238 /* signal status via a global variable */
239 if (global_components_ready == global_components_ready_exit &&
240 global_components_failed == global_components_failed_exit) {
241 g_debug ("Components ready/failed achieved. Stopping mailoop");
242 g_main_loop_quit (global_mainloop);
247 /* signal status via a global variable */
248 if (global_components_failed == global_components_failed_exit) {
249 g_main_loop_quit (global_mainloop);
254 /* XXX: dear compiler, these are for you: */
255 (void)agent; (void)stream_id; (void)data; (void)component_id;
258 static void cb_new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id,
259 gchar *lfoundation, gchar* rfoundation, gpointer data)
261 g_debug ("test-fullmode:%s: %p", G_STRFUNC, data);
263 if (GPOINTER_TO_UINT (data) == 1)
264 ++global_lagent_cands;
265 else if (GPOINTER_TO_UINT (data) == 2)
266 ++global_ragent_cands;
268 /* XXX: dear compiler, these are for you: */
269 (void)agent; (void)stream_id; (void)component_id; (void)lfoundation; (void)rfoundation;
272 static void cb_new_candidate(NiceAgent *agent, guint stream_id, guint component_id,
273 gchar *foundation, gpointer data)
275 g_debug ("test-fullmode:%s: %p", G_STRFUNC, data);
277 /* XXX: dear compiler, these are for you: */
278 (void)agent; (void)stream_id; (void)data; (void)component_id; (void)foundation;
281 static void cb_initial_binding_request_received(NiceAgent *agent, guint stream_id, gpointer data)
283 g_debug ("test-fullmode:%s: %p", G_STRFUNC, data);
285 if (GPOINTER_TO_UINT (data) == 1)
286 global_lagent_ibr_received = TRUE;
287 else if (GPOINTER_TO_UINT (data) == 2)
288 global_ragent_ibr_received = TRUE;
290 if (global_exit_when_ibr_received) {
291 g_debug ("Received initial binding request. Stopping mailoop");
292 g_main_loop_quit (global_mainloop);
295 /* XXX: dear compiler, these are for you: */
296 (void)agent; (void)stream_id; (void)data;
299 static void cb_closed (GObject *src, GAsyncResult *result, gpointer data)
301 NiceAgent *agent = NICE_AGENT (src);
303 g_debug ("test-fullmode:%s: %p", G_STRFUNC, agent);
305 *((gboolean *)data) = TRUE;
308 static void set_candidates (NiceAgent *from, guint from_stream,
309 NiceAgent *to, guint to_stream, guint component, gboolean remove_non_relay)
311 GSList *cands = NULL, *i;
313 cands = nice_agent_get_local_candidates (from, from_stream, component);
314 if (remove_non_relay) {
316 for (i = cands; i; i = i->next) {
317 NiceCandidate *cand = i->data;
318 if (cand->type != NICE_CANDIDATE_TYPE_RELAYED) {
319 cands = g_slist_remove (cands, cand);
320 nice_candidate_free (cand);
325 nice_agent_set_remote_candidates (to, to_stream, component, cands);
327 for (i = cands; i; i = i->next)
328 nice_candidate_free ((NiceCandidate *) i->data);
329 g_slist_free (cands);
332 static void set_credentials (NiceAgent *lagent, guint lstream,
333 NiceAgent *ragent, guint rstream)
335 gchar *ufrag = NULL, *password = NULL;
337 nice_agent_get_local_credentials(lagent, lstream, &ufrag, &password);
338 nice_agent_set_remote_credentials (ragent, rstream, ufrag, password);
341 nice_agent_get_local_credentials(ragent, rstream, &ufrag, &password);
342 nice_agent_set_remote_credentials (lagent, lstream, ufrag, password);
348 get_port (NiceAgent *agent, guint stream_id, guint component_id)
350 GSList *cands = nice_agent_get_local_candidates (agent, stream_id,
355 g_assert (cands != NULL);
357 for (item = cands; item; item = item->next) {
358 NiceCandidate *cand = item->data;
359 port = nice_address_get_port (&cand->addr);
362 g_assert (port != 0);
364 g_slist_free_full (cands, (GDestroyNotify) nice_candidate_free);
369 static int run_full_test (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr, guint ready, guint failed)
375 /* XXX: dear compiler, this is for you */
378 /* step: initialize variables modified by the callbacks */
379 global_components_ready = 0;
380 global_components_ready_exit = ready;
381 global_components_failed = 0;
382 global_components_failed_exit = failed;
383 global_lagent_gathering_done = FALSE;
384 global_ragent_gathering_done = FALSE;
385 global_lagent_ibr_received =
386 global_ragent_ibr_received = FALSE;
387 global_lagent_cands =
388 global_ragent_cands = 0;
390 g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
391 g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
393 /* step: add one stream, with RTP+RTCP components, to each agent */
394 ls_id = nice_agent_add_stream (lagent, 2);
396 rs_id = nice_agent_add_stream (ragent, 2);
397 g_assert_cmpuint (ls_id, >, 0);
398 g_assert_cmpuint (rs_id, >, 0);
400 nice_agent_set_relay_info(lagent, ls_id, 1,
401 TURN_IP, TURN_PORT, TURN_USER, TURN_PASS, TURN_TYPE);
402 nice_agent_set_relay_info(lagent, ls_id, 2,
403 TURN_IP, TURN_PORT, TURN_USER, TURN_PASS, TURN_TYPE);
404 nice_agent_set_relay_info(ragent, rs_id, 1,
405 TURN_IP, TURN_PORT, TURN_USER2, TURN_PASS2, TURN_TYPE);
406 nice_agent_set_relay_info(ragent, rs_id, 2,
407 TURN_IP, TURN_PORT, TURN_USER2, TURN_PASS2, TURN_TYPE);
411 /* Gather candidates and test nice_agent_set_port_range */
412 for (port = 10000; port < 60000; port++) {
413 nice_agent_set_port_range (lagent, ls_id, 1, port, port);
414 if (nice_agent_gather_candidates (lagent, ls_id))
418 g_assert_cmpuint (port, ==, get_port (lagent, ls_id, 1));
420 nice_agent_set_port_range (ragent, rs_id, 2, port, port);
422 g_assert (nice_agent_gather_candidates (ragent, rs_id) == FALSE);
423 g_assert (nice_agent_get_local_candidates (ragent, rs_id, 1) == NULL);
424 g_assert (nice_agent_get_local_candidates (ragent, rs_id, 2) == NULL);
425 nice_agent_set_port_range (ragent, rs_id, 2, 0, 0);
426 g_assert (nice_agent_gather_candidates (lagent, ls_id) == TRUE);
427 g_assert (nice_agent_gather_candidates (ragent, rs_id) == TRUE);
431 GSList *cands = NULL, *i;
432 NiceCandidate *cand = NULL;
434 cands = nice_agent_get_local_candidates (lagent, ls_id, 1);
435 g_assert_cmpuint (g_slist_length (cands), ==, 1);
437 g_assert_cmpint (cand->type, ==, NICE_CANDIDATE_TYPE_HOST);
438 for (i = cands; i; i = i->next)
439 nice_candidate_free ((NiceCandidate *) i->data);
440 g_slist_free (cands);
442 cands = nice_agent_get_local_candidates (lagent, ls_id, 2);
443 g_assert_cmpuint (g_slist_length (cands), ==, 1);
445 g_assert_cmpint (cand->type, ==, NICE_CANDIDATE_TYPE_HOST);
446 for (i = cands; i; i = i->next)
447 nice_candidate_free ((NiceCandidate *) i->data);
448 g_slist_free (cands);
450 cands = nice_agent_get_local_candidates (ragent, rs_id, 1);
451 g_assert_cmpuint (g_slist_length (cands), ==, 1);
453 g_assert_cmpint (cand->type, ==, NICE_CANDIDATE_TYPE_HOST);
454 for (i = cands; i; i = i->next)
455 nice_candidate_free ((NiceCandidate *) i->data);
456 g_slist_free (cands);
458 cands = nice_agent_get_local_candidates (ragent, rs_id, 2);
459 g_assert_cmpuint (g_slist_length (cands), ==, 1);
461 g_assert_cmpint (cand->type, ==, NICE_CANDIDATE_TYPE_HOST);
462 for (i = cands; i; i = i->next)
463 nice_candidate_free ((NiceCandidate *) i->data);
464 g_slist_free (cands);
469 /* step: attach to mainloop (needed to register the fds) */
470 nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
471 g_main_loop_get_context (global_mainloop), cb_nice_recv,
472 GUINT_TO_POINTER (1));
473 nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP,
474 g_main_loop_get_context (global_mainloop), cb_nice_recv,
475 GUINT_TO_POINTER (1));
476 nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
477 g_main_loop_get_context (global_mainloop), cb_nice_recv,
478 GUINT_TO_POINTER (2));
479 nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP,
480 g_main_loop_get_context (global_mainloop), cb_nice_recv,
481 GUINT_TO_POINTER (2));
483 /* step: run mainloop until local candidates are ready
484 * (see timer_cb() above) */
485 if (global_lagent_gathering_done != TRUE ||
486 global_ragent_gathering_done != TRUE) {
487 g_debug ("test-fullmode: Added streams, running mainloop until 'candidate-gathering-done'...");
488 g_main_loop_run (global_mainloop);
489 g_assert (global_lagent_gathering_done == TRUE);
490 g_assert (global_ragent_gathering_done == TRUE);
493 set_credentials (lagent, ls_id, ragent, rs_id);
495 /* step: pass the remote candidates to agents */
496 set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTP, USE_TURN);
497 set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, USE_TURN);
498 set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTP, USE_TURN);
499 set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, USE_TURN);
501 g_debug ("test-fullmode: Set properties, next running mainloop until connectivity checks succeed...");
503 /* step: run the mainloop until connectivity checks succeed
504 * (see timer_cb() above) */
505 g_main_loop_run (global_mainloop);
507 /* note: verify that STUN binding requests were sent */
508 g_assert (global_lagent_ibr_received == TRUE);
509 g_assert (global_ragent_ibr_received == TRUE);
511 /* note: test payload send and receive */
512 global_ragent_read = 0;
513 ret = nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678");
516 gboolean reliable = FALSE;
517 g_object_get (G_OBJECT (lagent), "reliable", &reliable, NULL);
518 g_debug ("Sending data returned -1 in %s mode", reliable?"Reliable":"Non-reliable");
520 gulong signal_handler;
521 guint ls_id_copy = ls_id;
523 signal_handler = g_signal_connect (G_OBJECT (lagent),
524 "reliable-transport-writable", G_CALLBACK (cb_writable), &ls_id_copy);
525 g_debug ("Running mainloop until transport is writable");
526 while (ls_id_copy == ls_id)
527 g_main_context_iteration (NULL, TRUE);
528 g_signal_handler_disconnect(G_OBJECT (lagent), signal_handler);
530 ret = nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678");
533 g_debug ("Sent %d bytes", ret);
534 g_assert_cmpint (ret, ==, 16);
535 while (global_ragent_read != 16)
536 g_main_context_iteration (NULL, TRUE);
537 g_assert_cmpint (global_ragent_read, ==, 16);
539 g_debug ("test-fullmode: Ran mainloop, removing streams...");
541 /* step: clean up resources and exit */
543 nice_agent_remove_stream (lagent, ls_id);
544 nice_agent_remove_stream (ragent, rs_id);
550 * Simulate the case where answer to the offer is delayed and
551 * some STUN connectivity checks reach the offering party
552 * before it gets the remote SDP information.
554 static int run_full_test_delayed_answer (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr, guint ready, guint failed)
559 /* XXX: dear compiler, this is for you */
562 /* step: initialize variables modified by the callbacks */
563 global_components_ready = 0;
564 global_components_ready_exit = ready;
565 global_components_failed = 0;
566 global_components_failed_exit = failed;
567 global_lagent_gathering_done = FALSE;
568 global_ragent_gathering_done = FALSE;
569 global_lagent_ibr_received =
570 global_ragent_ibr_received = FALSE;
571 global_exit_when_ibr_received = 1;
572 global_lagent_cands =
573 global_ragent_cands = 0;
575 g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
576 g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
578 /* step: add one stream, with RTP+RTCP components, to each agent */
579 ls_id = nice_agent_add_stream (lagent, 2);
581 rs_id = nice_agent_add_stream (ragent, 2);
582 g_assert_cmpuint (ls_id, >, 0);
583 g_assert_cmpuint (rs_id, >, 0);
585 /* We don't try this with TURN because as long as both agents don't
586 have the remote candidates, they won't be able to create the
587 permission on the TURN server, so the connchecks will never go through */
589 nice_agent_gather_candidates (lagent, ls_id);
590 nice_agent_gather_candidates (ragent, rs_id);
592 /* step: attach to mainloop (needed to register the fds) */
593 nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
594 g_main_loop_get_context (global_mainloop), cb_nice_recv,
595 GUINT_TO_POINTER (1));
596 nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP,
597 g_main_loop_get_context (global_mainloop), cb_nice_recv,
598 GUINT_TO_POINTER (1));
599 nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
600 g_main_loop_get_context (global_mainloop), cb_nice_recv,
601 GUINT_TO_POINTER (2));
602 nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP,
603 g_main_loop_get_context (global_mainloop), cb_nice_recv,
604 GUINT_TO_POINTER (2));
606 /* step: run mainloop until local candidates are ready
607 * (see timer_cb() above) */
608 if (global_lagent_gathering_done != TRUE ||
609 global_ragent_gathering_done != TRUE) {
610 g_debug ("test-fullmode: Added streams, running mainloop until 'candidate-gathering-done'...");
611 g_main_loop_run (global_mainloop);
612 g_assert (global_lagent_gathering_done == TRUE);
613 g_assert (global_ragent_gathering_done == TRUE);
616 set_credentials (lagent, ls_id, ragent, rs_id);
618 /* step: set remote candidates for agent R (answering party) */
619 /* We have to disable TURN for this test because with the delayed answer,
620 we can't create turn permissions, so we won't receive any connchecks */
621 set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTP, FALSE);
622 set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, FALSE);
624 g_debug ("test-fullmode: Set properties, next running mainloop until first check is received...");
626 /* step: run the mainloop until first connectivity check receveid */
627 g_main_loop_run (global_mainloop);
628 global_exit_when_ibr_received = 0;
630 /* note: verify that STUN binding requests were sent */
631 g_assert (global_lagent_ibr_received == TRUE);
633 g_debug ("test-fullmode: Delayed answer received, continuing processing..");
635 /* step: pass remove candidates to agent L (offering party) */
636 set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTP, FALSE);
637 set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, FALSE);
639 g_debug ("test-fullmode: Running mainloop until connectivity checks succeeed.");
641 g_main_loop_run (global_mainloop);
642 g_assert (global_ragent_ibr_received == TRUE);
643 g_assert_cmpuint (global_components_failed, ==, 0);
645 /* note: test payload send and receive */
646 global_ragent_read = 0;
647 ret = nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678");
649 gboolean reliable = FALSE;
650 g_object_get (G_OBJECT (lagent), "reliable", &reliable, NULL);
652 gulong signal_handler;
653 guint ls_id_copy = ls_id;
655 signal_handler = g_signal_connect (G_OBJECT (lagent),
656 "reliable-transport-writable", G_CALLBACK (cb_writable), &ls_id_copy);
657 g_debug ("Running mainloop until transport is writable");
658 while (ls_id_copy == ls_id)
659 g_main_context_iteration (NULL, TRUE);
660 g_signal_handler_disconnect(G_OBJECT (lagent), signal_handler);
662 ret = nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678");
665 global_ragent_read = 0;
666 g_assert_cmpint (ret, ==, 16);
667 g_main_loop_run (global_mainloop);
668 g_assert_cmpint (global_ragent_read, ==, 16);
670 g_debug ("test-fullmode: Ran mainloop, removing streams...");
672 /* step: clean up resources and exit */
674 nice_agent_remove_stream (lagent, ls_id);
675 nice_agent_remove_stream (ragent, rs_id);
680 static int run_full_test_wrong_password (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr)
684 /* XXX: dear compiler, this is for you */
687 global_components_ready = 0;
688 global_components_ready_exit = 0;
689 global_components_failed = 0;
690 global_components_failed_exit = 2;
691 global_lagent_state[0] = global_lagent_state[1] =
692 global_ragent_state[0] = global_ragent_state[1]
693 = NICE_COMPONENT_STATE_LAST;
694 global_lagent_gathering_done =
695 global_ragent_gathering_done = FALSE;
696 global_lagent_cands =
697 global_ragent_cands = 0;
699 g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
700 g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
702 /* step: add one stream, with one component, to each agent */
703 ls_id = nice_agent_add_stream (lagent, 1);
705 rs_id = nice_agent_add_stream (ragent, 1);
706 g_assert_cmpuint (ls_id, >, 0);
707 g_assert_cmpuint (rs_id, >, 0);
710 nice_agent_set_relay_info(lagent, ls_id, 1,
711 TURN_IP, TURN_PORT, TURN_USER, TURN_PASS, TURN_TYPE);
712 nice_agent_set_relay_info(ragent, rs_id, 1,
713 TURN_IP, TURN_PORT, TURN_USER, TURN_PASS, TURN_TYPE);
716 nice_agent_gather_candidates (lagent, ls_id);
717 nice_agent_gather_candidates (ragent, rs_id);
719 /* step: attach to mainloop (needed to register the fds) */
720 nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
721 g_main_loop_get_context (global_mainloop), cb_nice_recv,
722 GUINT_TO_POINTER (1));
723 nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
724 g_main_loop_get_context (global_mainloop), cb_nice_recv,
725 GUINT_TO_POINTER (2));
727 /* step: run mainloop until local candidates are ready
728 * (see timer_cb() above) */
729 if (global_lagent_gathering_done != TRUE ||
730 global_ragent_gathering_done != TRUE) {
731 g_debug ("test-fullmode: Added streams, running mainloop until 'candidate-gathering-done'...");
732 g_main_loop_run (global_mainloop);
733 g_assert (global_lagent_gathering_done == TRUE);
734 g_assert (global_ragent_gathering_done == TRUE);
737 g_debug ("test-fullmode: Got local candidates...");
739 set_credentials (lagent, ls_id, ragent, rs_id);
740 nice_agent_set_remote_credentials (ragent, rs_id, "wrong", "password");
741 nice_agent_set_remote_credentials (lagent, ls_id, "wrong2", "password2");
744 /* step: pass the remote candidates to agents */
745 set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTP, USE_TURN);
746 set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTP, USE_TURN);
748 g_debug ("test-fullmode: Set properties, next running mainloop until connectivity checks succeed...");
750 /* step: run the mainloop until connectivity checks succeed
751 * (see timer_cb() above) */
752 g_main_loop_run (global_mainloop);
754 /* note: verify that correct number of local candidates were reported */
755 g_assert_cmpint (global_lagent_cands, ==, 0);
756 g_assert_cmpint (global_ragent_cands, ==, 0);
758 g_debug ("test-fullmode: Ran mainloop, removing streams...");
760 /* step: clean up resources and exit */
762 nice_agent_remove_stream (lagent, ls_id);
763 nice_agent_remove_stream (ragent, rs_id);
768 static int run_full_test_control_conflict (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr, gboolean role)
772 /* XXX: dear compiler, this is for you */
775 global_components_ready = 0;
776 global_components_ready_exit = 2;
777 global_components_failed = 0;
778 global_components_failed_exit = 0;
779 global_lagent_gathering_done =
780 global_ragent_gathering_done = FALSE;
781 global_lagent_cands =
782 global_ragent_cands = 0;
783 global_lagent_ibr_received =
784 global_ragent_ibr_received = FALSE;
786 g_object_set (G_OBJECT (lagent), "controlling-mode", role, NULL);
787 g_object_set (G_OBJECT (ragent), "controlling-mode", role, NULL);
789 /* step: add one stream, with one component, to each agent */
790 ls_id = nice_agent_add_stream (lagent, 1);
792 rs_id = nice_agent_add_stream (ragent, 1);
793 g_assert_cmpuint (ls_id, >, 0);
794 g_assert_cmpuint (rs_id, >, 0);
797 nice_agent_set_relay_info(lagent, ls_id, 1,
798 TURN_IP, TURN_PORT, TURN_USER, TURN_PASS, TURN_TYPE);
799 nice_agent_set_relay_info(ragent, rs_id, 1,
800 TURN_IP, TURN_PORT, TURN_USER, TURN_PASS, TURN_TYPE);
803 nice_agent_gather_candidates (lagent, ls_id);
804 nice_agent_gather_candidates (ragent, rs_id);
806 /* step: attach to mainloop (needed to register the fds) */
807 nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
808 g_main_loop_get_context (global_mainloop), cb_nice_recv,
809 GUINT_TO_POINTER (1));
810 nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
811 g_main_loop_get_context (global_mainloop), cb_nice_recv,
812 GUINT_TO_POINTER (2));
814 /* step: run mainloop until local candidates are ready
815 * (see timer_cb() above) */
816 if (global_lagent_gathering_done != TRUE ||
817 global_ragent_gathering_done != TRUE) {
818 g_debug ("test-fullmode: Added streams, running mainloop until 'candidate-gathering-done'...");
819 g_main_loop_run (global_mainloop);
820 g_assert (global_lagent_gathering_done == TRUE);
821 g_assert (global_ragent_gathering_done == TRUE);
824 g_debug ("test-fullmode: Got local candidates...");
826 set_credentials (lagent, ls_id, ragent, rs_id);
828 /* step: pass the remote candidates to agents */
829 set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTP, USE_TURN);
830 set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTP, USE_TURN);
832 g_debug ("test-fullmode: Set properties, next running mainloop until connectivity checks succeed...");
834 /* step: run the mainloop until connectivity checks succeed
835 * (see timer_cb() above) */
836 g_main_loop_run (global_mainloop);
838 /* When using TURN, we get peer reflexive candidates for the host cands
839 that we removed so we can get another new_selected_pair signal later
840 depending on timing/racing, we could double (or not) the amount we expected
843 /* note: verify that correct number of local candidates were reported */
844 g_assert_cmpint (global_lagent_cands, ==, 1);
845 g_assert_cmpint (global_ragent_cands, ==, 1);
848 g_debug ("test-fullmode: Ran mainloop, removing streams...");
850 /* step: clean up resources and exit */
852 nice_agent_remove_stream (lagent, ls_id);
853 nice_agent_remove_stream (ragent, rs_id);
860 NiceAgent *lagent, *ragent; /* agent's L and R */
861 NiceAddress baseaddr;
864 const char *stun_server = NULL, *stun_server_port = NULL;
865 gboolean lagent_closed = FALSE;
866 gboolean ragent_closed = FALSE;
871 WSAStartup(0x0202, &w);
874 global_mainloop = g_main_loop_new (NULL, FALSE);
876 /* Note: impl limits ...
877 * - no multi-stream support
881 /* step: create the agents L and R */
883 lagent = nice_agent_new_reliable (g_main_loop_get_context (global_mainloop),
885 ragent = nice_agent_new_reliable (g_main_loop_get_context (global_mainloop),
888 lagent = nice_agent_new (g_main_loop_get_context (global_mainloop),
890 ragent = nice_agent_new (g_main_loop_get_context (global_mainloop),
894 g_object_set (G_OBJECT (lagent), "ice-tcp", FALSE, NULL);
895 g_object_set (G_OBJECT (ragent), "ice-tcp", FALSE, NULL);
898 nice_agent_set_software (lagent, "Test-fullmode, Left Agent");
899 nice_agent_set_software (ragent, "Test-fullmode, Right Agent");
901 /* step: add a timer to catch state changes triggered by signals */
903 timer_id = g_timeout_add (300000, timer_cb, NULL);
905 timer_id = g_timeout_add (30000, timer_cb, NULL);
908 /* step: specify which local interface to use */
910 if (!nice_address_set_from_string (&baseaddr, "127.0.0.1"))
911 g_assert_not_reached ();
912 nice_agent_add_local_address (lagent, &baseaddr);
913 nice_agent_add_local_address (ragent, &baseaddr);
916 g_signal_connect (G_OBJECT (lagent), "candidate-gathering-done",
917 G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER(1));
918 g_signal_connect (G_OBJECT (ragent), "candidate-gathering-done",
919 G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER (2));
920 g_signal_connect (G_OBJECT (lagent), "component-state-changed",
921 G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (1));
922 g_signal_connect (G_OBJECT (ragent), "component-state-changed",
923 G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (2));
924 g_signal_connect (G_OBJECT (lagent), "new-selected-pair",
925 G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER(1));
926 g_signal_connect (G_OBJECT (ragent), "new-selected-pair",
927 G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER (2));
928 g_signal_connect (G_OBJECT (lagent), "new-candidate",
929 G_CALLBACK (cb_new_candidate), GUINT_TO_POINTER (1));
930 g_signal_connect (G_OBJECT (ragent), "new-candidate",
931 G_CALLBACK (cb_new_candidate), GUINT_TO_POINTER (2));
932 g_signal_connect (G_OBJECT (lagent), "initial-binding-request-received",
933 G_CALLBACK (cb_initial_binding_request_received),
934 GUINT_TO_POINTER (1));
935 g_signal_connect (G_OBJECT (ragent), "initial-binding-request-received",
936 G_CALLBACK (cb_initial_binding_request_received),
937 GUINT_TO_POINTER (2));
939 stun_server = getenv ("NICE_STUN_SERVER");
940 stun_server_port = getenv ("NICE_STUN_SERVER_PORT");
942 g_object_set (G_OBJECT (lagent), "stun-server", stun_server, NULL);
943 g_object_set (G_OBJECT (lagent), "stun-server-port", atoi (stun_server_port), NULL);
944 g_object_set (G_OBJECT (ragent), "stun-server", stun_server, NULL);
945 g_object_set (G_OBJECT (ragent), "stun-server-port", atoi (stun_server_port), NULL);
948 g_object_set (G_OBJECT (lagent), "upnp", USE_UPNP, NULL);
949 g_object_set (G_OBJECT (lagent), "proxy-ip", PROXY_IP, NULL);
950 g_object_set (G_OBJECT (lagent), "proxy-port", PROXY_PORT, NULL);
951 g_object_set (G_OBJECT (lagent), "proxy-type", PROXY_TYPE, NULL);
952 g_object_set (G_OBJECT (lagent), "proxy-username", PROXY_USERNAME, NULL);
953 g_object_set (G_OBJECT (lagent), "proxy-password", PROXY_PASSWORD, NULL);
954 g_object_set (G_OBJECT (ragent), "upnp", USE_UPNP, NULL);
955 g_object_set (G_OBJECT (ragent), "proxy-ip", PROXY_IP, NULL);
956 g_object_set (G_OBJECT (ragent), "proxy-port", PROXY_PORT, NULL);
957 g_object_set (G_OBJECT (ragent), "proxy-type", PROXY_TYPE, NULL);
958 g_object_set (G_OBJECT (ragent), "proxy-username", PROXY_USERNAME, NULL);
959 g_object_set (G_OBJECT (ragent), "proxy-password", PROXY_PASSWORD, NULL);
961 /* step: test setter/getter functions for properties */
963 guint max_checks = 0;
964 gchar *string = NULL;
966 gboolean mode = FALSE;
967 g_object_get (G_OBJECT (lagent), "stun-server", &string, NULL);
968 g_assert (stun_server == NULL || strcmp (string, stun_server) == 0);
970 g_object_get (G_OBJECT (lagent), "stun-server-port", &port, NULL);
971 g_assert (stun_server_port == NULL || port == (guint)atoi (stun_server_port));
972 g_object_get (G_OBJECT (lagent), "proxy-ip", &string, NULL);
973 g_assert_cmpstr (string, ==, PROXY_IP);
975 g_object_get (G_OBJECT (lagent), "proxy-port", &port, NULL);
976 g_assert_cmpuint (port, ==, PROXY_PORT);
977 g_object_get (G_OBJECT (lagent), "controlling-mode", &mode, NULL);
978 g_assert (mode == TRUE);
979 g_object_set (G_OBJECT (lagent), "max-connectivity-checks", 300, NULL);
980 g_object_get (G_OBJECT (lagent), "max-connectivity-checks", &max_checks, NULL);
981 g_assert_cmpuint (max_checks, ==, 300);
984 /* step: run test the first time */
985 g_debug ("test-fullmode: TEST STARTS / running test for the 1st time");
986 result = run_full_test (lagent, ragent, &baseaddr, 4 ,0);
987 priv_print_global_status ();
988 g_assert_cmpint (result, ==, 0);
989 g_assert_cmpint (global_lagent_state[0], ==, NICE_COMPONENT_STATE_READY);
990 g_assert_cmpint (global_lagent_state[1], ==, NICE_COMPONENT_STATE_READY);
991 g_assert_cmpint (global_ragent_state[0], ==, NICE_COMPONENT_STATE_READY);
992 g_assert_cmpint (global_ragent_state[1], ==, NICE_COMPONENT_STATE_READY);
993 /* When using TURN, we get peer reflexive candidates for the host cands
994 that we removed so we can get another new_selected_pair signal later
995 depending on timing/racing, we could double (or not) the amount we expected
998 /* note: verify that correct number of local candidates were reported */
999 g_assert_cmpint (global_lagent_cands, ==, 2);
1000 g_assert_cmpint (global_ragent_cands, ==, 2);
1004 /* step: run test again without unref'ing agents */
1005 g_debug ("test-fullmode: TEST STARTS / running test for the 2nd time");
1006 result = run_full_test (lagent, ragent, &baseaddr, 4, 0);
1007 priv_print_global_status ();
1008 g_assert_cmpint (result, ==, 0);
1009 g_assert_cmpint (global_lagent_state[0], ==, NICE_COMPONENT_STATE_READY);
1010 g_assert_cmpint (global_lagent_state[1], ==, NICE_COMPONENT_STATE_READY);
1011 g_assert_cmpint (global_ragent_state[0], ==, NICE_COMPONENT_STATE_READY);
1012 g_assert_cmpint (global_ragent_state[1], ==, NICE_COMPONENT_STATE_READY);
1013 /* When using TURN, we get peer reflexive candidates for the host cands
1014 that we removed so we can get another new_selected_pair signal later
1015 depending on timing/racing, we could double (or not) the amount we expected
1018 /* note: verify that correct number of local candidates were reported */
1019 g_assert_cmpint (global_lagent_cands, ==, 2);
1020 g_assert_cmpint (global_ragent_cands, ==, 2);
1024 /* step: run test simulating delayed SDP answer */
1025 g_debug ("test-fullmode: TEST STARTS / delayed SDP answer");
1026 result = run_full_test_delayed_answer (lagent, ragent, &baseaddr, 4, 0);
1027 priv_print_global_status ();
1028 g_assert_cmpint (result, ==, 0);
1029 g_assert_cmpint (global_lagent_state[0], ==, NICE_COMPONENT_STATE_READY);
1030 g_assert_cmpint (global_lagent_state[1], ==, NICE_COMPONENT_STATE_READY);
1031 g_assert_cmpint (global_ragent_state[0], ==, NICE_COMPONENT_STATE_READY);
1032 g_assert_cmpint (global_ragent_state[1], ==, NICE_COMPONENT_STATE_READY);
1033 /* note: verify that correct number of local candidates were reported */
1034 /* When using TURN, we get peer reflexive candidates for the host cands
1035 that we removed so we can get another new_selected_pair signal later
1036 depending on timing/racing, we could double (or not) the amount we expected
1039 g_assert_cmpint (global_lagent_cands, ==, 2);
1040 g_assert_cmpint (global_ragent_cands, ==, 2);
1047 /* run test with incorrect credentials (make sure process fails) */
1048 g_debug ("test-fullmode: TEST STARTS / incorrect credentials");
1049 result = run_full_test_wrong_password (lagent, ragent, &baseaddr);
1050 priv_print_global_status ();
1051 g_assert_cmpint (result, ==, 0);
1052 g_assert_cmpint (global_lagent_state[0], ==, NICE_COMPONENT_STATE_FAILED);
1053 g_assert_cmpint (global_lagent_state[1], ==, NICE_COMPONENT_STATE_LAST);
1054 g_assert_cmpint (global_ragent_state[0], ==, NICE_COMPONENT_STATE_FAILED);
1055 g_assert_cmpint (global_ragent_state[1], ==, NICE_COMPONENT_STATE_LAST);
1057 /* The max connectivity checks test can't be run with TURN because
1058 we'll have 3 local candidates instead of 1 and the checks will
1059 be random, so we can't predict how many will fail/succeed */
1062 /* step: run test with a hard limit for connecitivity checks */
1063 g_debug ("test-fullmode: TEST STARTS / max connectivity checks");
1064 g_object_set (G_OBJECT (lagent), "max-connectivity-checks", 1, NULL);
1065 g_object_set (G_OBJECT (ragent), "max-connectivity-checks", 1, NULL);
1066 result = run_full_test (lagent, ragent, &baseaddr, 2, 2);
1067 priv_print_global_status ();
1068 g_assert_cmpint (result, ==, 0);
1069 /* should FAIL as agent L can't send any checks: */
1070 g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_FAILED ||
1071 global_lagent_state[1] == NICE_COMPONENT_STATE_FAILED);
1072 g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_FAILED ||
1073 global_lagent_state[1] == NICE_COMPONENT_STATE_FAILED);
1076 g_object_set (G_OBJECT (lagent), "max-connectivity-checks", 100, NULL);
1077 g_object_set (G_OBJECT (ragent), "max-connectivity-checks", 100, NULL);
1078 result = run_full_test (lagent, ragent, &baseaddr, 4, 0);
1079 priv_print_global_status ();
1080 /* should SUCCEED as agent L can send the checks: */
1081 g_assert_cmpint (result, ==, 0);
1082 g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_CONNECTED ||
1083 global_lagent_state[0] == NICE_COMPONENT_STATE_READY);
1084 g_assert (global_lagent_state[1] == NICE_COMPONENT_STATE_CONNECTED ||
1085 global_lagent_state[1] == NICE_COMPONENT_STATE_READY);
1086 g_assert (global_ragent_state[0] == NICE_COMPONENT_STATE_CONNECTED ||
1087 global_ragent_state[0] == NICE_COMPONENT_STATE_READY);
1088 g_assert(global_ragent_state[1] == NICE_COMPONENT_STATE_CONNECTED ||
1089 global_ragent_state[1] == NICE_COMPONENT_STATE_READY);
1090 g_object_set (G_OBJECT (lagent), "max-connectivity-checks", 100, NULL);
1092 /* run test with a conflict in controlling mode: controlling-controlling */
1093 g_debug ("test-fullmode: TEST STARTS / controlling mode conflict case-1");
1094 result = run_full_test_control_conflict (lagent, ragent, &baseaddr, TRUE);
1095 priv_print_global_status ();
1096 g_assert_cmpint (result, ==, 0);
1098 g_assert_cmpint (global_lagent_state[0], ==, NICE_COMPONENT_STATE_READY);
1099 g_assert_cmpint (global_lagent_state[1], ==, NICE_COMPONENT_STATE_READY);
1100 g_assert_cmpint (global_ragent_state[0], ==, NICE_COMPONENT_STATE_READY);
1101 g_assert_cmpint (global_ragent_state[1], ==, NICE_COMPONENT_STATE_READY);
1103 /* run test with a conflict in controlling mode: controlled-controlled */
1104 g_debug ("test-fullmode: TEST STARTS / controlling mode conflict case-2");
1105 result = run_full_test_control_conflict (lagent, ragent, &baseaddr, FALSE);
1106 priv_print_global_status ();
1107 g_assert_cmpint (result, ==, 0);
1108 g_assert_cmpint (global_lagent_state[0], ==, NICE_COMPONENT_STATE_READY);
1109 g_assert_cmpint (global_lagent_state[1], ==, NICE_COMPONENT_STATE_READY);
1110 g_assert_cmpint (global_ragent_state[0], ==, NICE_COMPONENT_STATE_READY);
1111 g_assert_cmpint (global_ragent_state[1], ==, NICE_COMPONENT_STATE_READY);
1113 nice_agent_close_async (lagent, cb_closed, &lagent_closed);
1114 nice_agent_close_async (ragent, cb_closed, &ragent_closed);
1115 g_object_unref (lagent);
1116 g_object_unref (ragent);
1118 while (!ragent_closed || !ragent_closed) {
1119 g_main_context_iteration (NULL, TRUE);
1123 g_main_loop_unref (global_mainloop);
1124 global_mainloop = NULL;
1126 g_source_remove (timer_id);