02aa22e82c821d66bd447c2fd9bf7f4491970213
[platform/upstream/libnice.git] / tests / test-fallback.c
1 /*
2  * This file is part of the Nice GLib ICE library.
3  *
4  * Contains a unit test for functionality to fallback to non-ICE 
5  * operation if remote party does not support ICE.
6  *
7  * (C) 2007 Nokia Corporation. All rights reserved.
8  *  Contact: Kai Vehmanen
9  *
10  * The contents of this file are subject to the Mozilla Public License Version
11  * 1.1 (the "License"); you may not use this file except in compliance with
12  * the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS" basis,
16  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17  * for the specific language governing rights and limitations under the
18  * License.
19  *
20  * The Original Code is the Nice GLib ICE library.
21  *
22  * The Initial Developers of the Original Code are Collabora Ltd and Nokia
23  * Corporation. All Rights Reserved.
24  *
25  * Contributors:
26  *   Kai Vehmanen, Nokia
27  *
28  * Alternatively, the contents of this file may be used under the terms of the
29  * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
30  * case the provisions of LGPL are applicable instead of those above. If you
31  * wish to allow use of your version of this file only under the terms of the
32  * LGPL and not to allow others to use your version of this file under the
33  * MPL, indicate your decision by deleting the provisions above and replace
34  * them with the notice and other provisions required by the LGPL. If you do
35  * not delete the provisions above, a recipient may use your version of this
36  * file under either the MPL or the LGPL.
37  */
38 #ifdef HAVE_CONFIG_H
39 # include <config.h>
40 #endif
41
42 #include "agent.h"
43 #include "agent-priv.h" /* for testing purposes */
44
45 #include <stdlib.h>
46 #include <string.h>
47 #ifdef _WIN32
48 #include <io.h>
49 #endif
50
51
52 static NiceComponentState global_lagent_state = NICE_COMPONENT_STATE_LAST;
53 static NiceComponentState global_ragent_state = NICE_COMPONENT_STATE_LAST;
54 static guint global_components_ready = 0;
55 static guint global_components_ready_exit = 0;
56 static guint global_components_failed = 0;
57 static guint global_components_failed_exit = 0;
58 static GMainLoop *global_mainloop = NULL;
59 static gboolean global_lagent_gathering_done = FALSE;
60 static gboolean global_ragent_gathering_done = FALSE;
61 static gboolean global_lagent_ibr_received = FALSE;
62 static gboolean global_ragent_ibr_received = FALSE;
63 static int global_lagent_cands = 0;
64 static int global_ragent_cands = 0;
65 static gint global_ragent_read = 0;
66 static gint global_ragent_read_exit = 0;
67 static gboolean global_accept_non_data = TRUE;
68
69 static void priv_print_global_status (void)
70 {
71   g_debug ("\tgathering_done=%d", global_lagent_gathering_done && global_ragent_gathering_done);
72   g_debug ("\tlstate=%d", global_lagent_state);
73   g_debug ("\trstate=%d", global_ragent_state);
74 }
75
76 static gboolean timer_cb (gpointer pointer)
77 {
78   g_debug ("test-fallback:%s: %p", G_STRFUNC, pointer);
79
80   /* signal status via a global variable */
81
82   /* note: should not be reached, abort */
83   g_error ("ERROR: test has got stuck, aborting...");
84
85   return FALSE;
86 }
87
88 static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
89 {
90   g_debug ("test-fallback:%s: %p", G_STRFUNC, user_data);
91
92   /* XXX: dear compiler, these are for you: */
93   (void)agent; (void)stream_id; (void)component_id; (void)buf;
94
95   /*
96    * Lets ignore stun packets that got through
97    */
98   if (len != 16 || strncmp ("1234567812345678", buf, 16)) {
99     if (global_accept_non_data)
100       return;
101     else
102       g_error ("Got non-data packet of lenght %u", len);
103   }
104
105   if ((intptr_t)user_data == 2) {
106     global_ragent_read += len;
107
108     if (global_ragent_read == global_ragent_read_exit)
109       g_main_loop_quit (global_mainloop);
110   }
111 }
112
113 static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
114 {
115   g_debug ("test-fallback:%s: %p", G_STRFUNC, data);
116
117   if ((intptr_t)data == 1)
118     global_lagent_gathering_done = TRUE;
119   else if ((intptr_t)data == 2)
120     global_ragent_gathering_done = TRUE;
121
122   if (global_lagent_gathering_done &&
123       global_ragent_gathering_done)
124     g_main_loop_quit (global_mainloop);
125
126   /* XXX: dear compiler, these are for you: */
127   (void)agent;
128 }
129
130 static void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data)
131 {
132   g_debug ("test-fallback:%s: %p", G_STRFUNC, data);
133
134   if ((intptr_t)data == 1)
135     global_lagent_state = state;
136   else if ((intptr_t)data == 2)
137     global_ragent_state = state;
138   
139   if (state == NICE_COMPONENT_STATE_READY)
140     global_components_ready++;
141   if (state == NICE_COMPONENT_STATE_FAILED)
142     global_components_failed++;
143
144   g_debug ("test-fallback: READY %u exit at %u.", global_components_ready, global_components_ready_exit);
145
146   /* signal status via a global variable */
147   if (global_components_ready == global_components_ready_exit) {
148     g_main_loop_quit (global_mainloop); 
149     return;
150   }
151
152   /* signal status via a global variable */
153   if (global_components_failed == global_components_failed_exit) {
154     g_main_loop_quit (global_mainloop); 
155     return;
156   }
157
158   /* XXX: dear compiler, these are for you: */
159   (void)agent; (void)stream_id; (void)data; (void)component_id;
160 }
161
162 static void cb_new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id, 
163                                  gchar *lfoundation, gchar* rfoundation, gpointer data)
164 {
165   g_debug ("test-fallback:%s: %p", G_STRFUNC, data);
166
167   if ((intptr_t)data == 1)
168     ++global_lagent_cands;
169   else if ((intptr_t)data == 2)
170     ++global_ragent_cands;
171
172   /* XXX: dear compiler, these are for you: */
173   (void)agent; (void)stream_id; (void)component_id; (void)lfoundation; (void)rfoundation;
174 }
175
176 static void cb_new_candidate(NiceAgent *agent, guint stream_id, guint component_id, 
177                              gchar *foundation, gpointer data)
178 {
179   g_debug ("test-fallback:%s: %p", G_STRFUNC, data);
180
181   /* XXX: dear compiler, these are for you: */
182   (void)agent; (void)stream_id; (void)data; (void)component_id; (void)foundation;
183 }
184
185 static void cb_initial_binding_request_received(NiceAgent *agent, guint stream_id, gpointer data)
186 {
187   g_debug ("test-fallback:%s: %p", G_STRFUNC, data);
188
189   if ((intptr_t)data == 1)
190     global_lagent_ibr_received = TRUE;
191   else if ((intptr_t)data == 2)
192     global_ragent_ibr_received = TRUE;
193
194   /* XXX: dear compiler, these are for you: */
195   (void)agent; (void)stream_id; (void)data;
196 }
197
198 static void priv_get_local_addr (NiceAgent *agent, guint stream_id, guint component_id, NiceAddress *dstaddr)
199 {
200   GSList *cands, *i;
201   cands = nice_agent_get_local_candidates(agent, stream_id, component_id);
202   for (i = cands; i; i = i->next) {
203     NiceCandidate *cand = i->data;
204     if (cand) {
205       g_assert (dstaddr);
206       *dstaddr = cand->addr;
207       break;
208     }
209   }
210   for (i = cands; i; i = i->next)
211     nice_candidate_free ((NiceCandidate *) i->data);
212   g_slist_free (cands);
213 }
214
215 static int run_fallback_test (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr)
216 {
217   NiceAddress laddr, raddr, laddr_rtcp, raddr_rtcp;   
218   NiceCandidate cdes;
219   GSList *cands;
220   guint ls_id, rs_id;
221
222   memset (&cdes, 0, sizeof(NiceCandidate));
223   cdes.priority = 100000;
224   strcpy (cdes.foundation, "1");
225   cdes.type = NICE_CANDIDATE_TYPE_HOST;
226   cdes.transport = NICE_CANDIDATE_TRANSPORT_UDP;
227   cdes.base_addr = *baseaddr;
228
229   /* step: initialize variables modified by the callbacks */
230   global_components_ready = 0;
231   global_components_ready_exit = 4;
232   global_components_failed = 0;
233   global_components_failed_exit = 4;
234   global_lagent_gathering_done = FALSE;
235   global_ragent_gathering_done = FALSE;
236   global_lagent_ibr_received =
237     global_ragent_ibr_received = FALSE;
238   global_lagent_cands = 
239     global_ragent_cands = 0;
240   global_ragent_read_exit = -1;
241
242   g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
243   g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
244
245   /* step: add one stream, with RTP+RTCP components, to each agent */
246   ls_id = nice_agent_add_stream (lagent, 2);
247   rs_id = nice_agent_add_stream (ragent, 2);
248   g_assert_cmpuint (ls_id, >, 0);
249   g_assert_cmpuint (rs_id, >, 0);
250
251   nice_agent_gather_candidates (lagent, ls_id);
252   nice_agent_gather_candidates (ragent, rs_id);
253
254   /* step: attach to mainloop (needed to register the fds) */
255   nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
256       g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1);
257   nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP,
258       g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1);
259   nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
260       g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2);
261   nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP,
262       g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2);
263
264   /* step: run mainloop until local candidates are ready 
265    *       (see timer_cb() above) */
266   if (global_lagent_gathering_done != TRUE ||
267       global_ragent_gathering_done != TRUE) {
268     g_debug ("test-fallback: Added streams, running mainloop until 'candidate-gathering-done'...");
269     g_main_loop_run (global_mainloop);
270     g_assert (global_lagent_gathering_done == TRUE);
271     g_assert (global_ragent_gathering_done == TRUE);
272   }
273
274   /* step: find out the local candidates of each agent */
275
276   priv_get_local_addr (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, &raddr);
277   g_debug ("test-fallback: local RTP port R %u",
278            nice_address_get_port (&raddr));
279
280   priv_get_local_addr (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, &laddr);
281   g_debug ("test-fallback: local RTP port L %u",
282            nice_address_get_port (&laddr));
283
284   priv_get_local_addr (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, &raddr_rtcp);
285   g_debug ("test-fallback: local RTCP port R %u",
286            nice_address_get_port (&raddr_rtcp));
287
288   priv_get_local_addr (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, &laddr_rtcp);
289   g_debug ("test-fallback: local RTCP port L %u",
290            nice_address_get_port (&laddr_rtcp));
291
292   /* step: exchange candidate information but not the credentials */
293
294   cands = g_slist_append (NULL, &cdes);
295   cdes.component_id = NICE_COMPONENT_TYPE_RTP;
296   cdes.addr = raddr;
297   nice_agent_set_remote_candidates (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, cands);
298   cdes.addr = laddr;
299   nice_agent_set_remote_candidates (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, cands);
300   cdes.component_id = NICE_COMPONENT_TYPE_RTCP;
301   cdes.addr = raddr_rtcp;
302   nice_agent_set_remote_candidates (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, cands);
303   cdes.addr = laddr_rtcp;
304   nice_agent_set_remote_candidates (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, cands);
305
306   /* step: fall back to non-ICE mode on both sides */
307   g_assert (nice_agent_set_selected_pair (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, "1", "1") == TRUE);
308   g_assert (nice_agent_set_selected_pair (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, "1", "1") == TRUE);
309   g_assert (nice_agent_set_selected_pair (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, "1", "1") == TRUE);
310   g_assert (nice_agent_set_selected_pair (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, "1", "1") == TRUE);
311
312   g_debug ("test-fallback: Requested for fallback, running mainloop until component state change is completed...");
313
314   /* step: run the mainloop until connectivity checks succeed 
315    *       (see timer_cb() above) */
316   if (global_components_ready < global_components_ready_exit)
317     g_main_loop_run (global_mainloop);
318
319   /* note: verify that agents are in correct state */
320   g_assert_cmpint (global_lagent_state, ==, NICE_COMPONENT_STATE_READY);
321   g_assert_cmpint (global_ragent_state, ==, NICE_COMPONENT_STATE_READY);
322
323   /* step: next send a packet -> should work even if no ICE processing
324    *       has been done */
325
326   g_debug ("test-fallback: Sent a payload packet, run mainloop until packet received.");
327
328   /* step: send a new test packet from L ot R */
329   global_ragent_read = 0;
330   g_assert_cmpint (nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678"), ==, 16);
331   global_ragent_read_exit = 16;
332   g_main_loop_run (global_mainloop);
333
334   /* note: verify that payload was succesfully received */
335   g_assert_cmpint (global_ragent_read, ==, 16);
336
337   g_debug ("test-fallback: Ran mainloop, removing streams...");
338
339   /* step: clean up resources and exit */
340
341   g_slist_free (cands);
342   nice_agent_remove_stream (lagent, ls_id);
343   nice_agent_remove_stream (ragent, rs_id);
344
345   g_debug ("test-fallback: test COMPLETED");
346
347   return 0;
348 }
349
350
351 static int run_safe_fallback_test (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr)
352 {
353   NiceAddress laddr, raddr, laddr_rtcp, raddr_rtcp;
354   NiceCandidate cdes;
355   guint ls_id, rs_id;
356
357   memset (&cdes, 0, sizeof(NiceCandidate));
358   cdes.priority = 100000;
359   strcpy (cdes.foundation, "1");
360   cdes.type = NICE_CANDIDATE_TYPE_HOST;
361   cdes.transport = NICE_CANDIDATE_TRANSPORT_UDP;
362   cdes.base_addr = *baseaddr;
363
364   /* step: initialize variables modified by the callbacks */
365   global_components_ready = 0;
366   global_components_ready_exit = 4;
367   global_components_failed = 0;
368   global_components_failed_exit = 4;
369   global_lagent_gathering_done = FALSE;
370   global_ragent_gathering_done = FALSE;
371   global_lagent_ibr_received =
372     global_ragent_ibr_received = FALSE;
373   global_lagent_cands =
374     global_ragent_cands = 0;
375   global_ragent_read_exit = -1;
376   global_accept_non_data = FALSE;
377
378   g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
379   g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
380
381   /* step: add one stream, with RTP+RTCP components, to each agent */
382   ls_id = nice_agent_add_stream (lagent, 2);
383   rs_id = nice_agent_add_stream (ragent, 2);
384   g_assert_cmpuint (ls_id, >, 0);
385   g_assert_cmpuint (rs_id, >, 0);
386
387   nice_agent_gather_candidates (lagent, ls_id);
388   nice_agent_gather_candidates (ragent, rs_id);
389
390   /* step: attach to mainloop (needed to register the fds) */
391   nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
392       g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1);
393   nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP,
394       g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1);
395   nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
396       g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2);
397   nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP,
398       g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2);
399
400   /* step: run mainloop until local candidates are ready
401    *       (see timer_cb() above) */
402   if (global_lagent_gathering_done != TRUE ||
403       global_ragent_gathering_done != TRUE) {
404     g_debug ("test-fallback: Added streams, running mainloop until 'candidate-gathering-done'...");
405     g_main_loop_run (global_mainloop);
406     g_assert (global_lagent_gathering_done == TRUE);
407     g_assert (global_ragent_gathering_done == TRUE);
408   }
409
410   /* step: find out the local candidates of each agent */
411
412   priv_get_local_addr (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, &raddr);
413   g_debug ("test-fallback: local RTP port R %u",
414            nice_address_get_port (&raddr));
415
416   priv_get_local_addr (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, &laddr);
417   g_debug ("test-fallback: local RTP port L %u",
418            nice_address_get_port (&laddr));
419
420   priv_get_local_addr (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, &raddr_rtcp);
421   g_debug ("test-fallback: local RTCP port R %u",
422            nice_address_get_port (&raddr_rtcp));
423
424   priv_get_local_addr (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, &laddr_rtcp);
425   g_debug ("test-fallback: local RTCP port L %u",
426            nice_address_get_port (&laddr_rtcp));
427
428   /* step: exchange candidate information but not the credentials */
429
430   cdes.component_id = NICE_COMPONENT_TYPE_RTP;
431   cdes.addr = raddr;
432   g_assert (nice_agent_set_selected_remote_candidate (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, &cdes));
433
434   cdes.addr = laddr;
435   g_assert (nice_agent_set_selected_remote_candidate (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, &cdes));
436
437   cdes.component_id = NICE_COMPONENT_TYPE_RTCP;
438   cdes.addr = raddr_rtcp;
439   g_assert (nice_agent_set_selected_remote_candidate (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, &cdes));
440
441   cdes.addr = laddr_rtcp;
442   g_assert (nice_agent_set_selected_remote_candidate (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, &cdes));
443
444   g_debug ("test-fallback: Requested for fallback, running mainloop until component state change is completed...");
445
446   /* step: run the mainloop until connectivity checks succeed
447    *       (see timer_cb() above) */
448   if (global_components_ready < global_components_ready_exit)
449     g_main_loop_run (global_mainloop);
450
451   /* note: verify that agents are in correct state */
452   g_assert_cmpint (global_lagent_state, ==, NICE_COMPONENT_STATE_READY);
453   g_assert_cmpint (global_ragent_state, ==, NICE_COMPONENT_STATE_READY);
454
455   /* step: next send a packet -> should work even if no ICE processing
456    *       has been done */
457
458   g_debug ("test-fallback: Sent a payload packet, run mainloop until packet received.");
459
460   /* step: send a new test packet from L ot R */
461   global_ragent_read = 0;
462   g_assert_cmpint (nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678"), ==, 16);
463   global_ragent_read_exit = 16;
464   g_main_loop_run (global_mainloop);
465
466   /* note: verify that payload was succesfully received */
467   g_assert_cmpint (global_ragent_read, ==, 16);
468
469   g_debug ("test-fallback: Ran mainloop, removing streams...");
470
471   /* step: clean up resources and exit */
472
473   nice_agent_remove_stream (lagent, ls_id);
474   nice_agent_remove_stream (ragent, rs_id);
475
476   g_debug ("test-fallback: test COMPLETED");
477
478   return 0;
479 }
480
481 int main (void)
482 {
483   NiceAgent *lagent, *ragent;      /* agent's L and R */
484   NiceAddress baseaddr;
485   int result;
486   guint timer_id;
487   const char *stun_server = NULL, *stun_server_port = NULL;
488
489 #ifdef G_OS_WIN32
490   WSADATA w;
491
492   WSAStartup(0x0202, &w);
493 #endif
494
495   global_mainloop = g_main_loop_new (NULL, FALSE);
496
497   /* Note: impl limits ...
498    * - no multi-stream support
499    * - no IPv6 support
500    */
501
502   /* step: create the agents L and R */
503   lagent = nice_agent_new (g_main_loop_get_context (global_mainloop), NICE_COMPATIBILITY_RFC5245);
504   ragent = nice_agent_new (g_main_loop_get_context (global_mainloop), NICE_COMPATIBILITY_RFC5245);
505
506   g_object_set (G_OBJECT (lagent), "upnp", FALSE, NULL);
507   g_object_set (G_OBJECT (ragent), "upnp", FALSE, NULL);
508
509   /* step: add a timer to catch state changes triggered by signals */
510   timer_id = g_timeout_add (30000, timer_cb, NULL);
511
512   /* step: specify which local interface to use */
513   if (!nice_address_set_from_string (&baseaddr, "127.0.0.1"))
514     g_assert_not_reached ();
515   nice_agent_add_local_address (lagent, &baseaddr);
516   nice_agent_add_local_address (ragent, &baseaddr);
517
518   g_signal_connect (G_OBJECT (lagent), "candidate-gathering-done", 
519                     G_CALLBACK (cb_candidate_gathering_done), (gpointer)1);
520   g_signal_connect (G_OBJECT (ragent), "candidate-gathering-done", 
521                     G_CALLBACK (cb_candidate_gathering_done), (gpointer)2);
522   g_signal_connect (G_OBJECT (lagent), "component-state-changed", 
523                     G_CALLBACK (cb_component_state_changed), (gpointer)1);
524   g_signal_connect (G_OBJECT (ragent), "component-state-changed", 
525                     G_CALLBACK (cb_component_state_changed), (gpointer)2);
526   g_signal_connect (G_OBJECT (lagent), "new-selected-pair", 
527                     G_CALLBACK (cb_new_selected_pair), (gpointer)1);
528   g_signal_connect (G_OBJECT (ragent), "new-selected-pair", 
529                     G_CALLBACK (cb_new_selected_pair), (gpointer)2);
530   g_signal_connect (G_OBJECT (lagent), "new-candidate", 
531                     G_CALLBACK (cb_new_candidate), (gpointer)1);
532   g_signal_connect (G_OBJECT (ragent), "new-candidate", 
533                     G_CALLBACK (cb_new_candidate), (gpointer)2);
534   g_signal_connect (G_OBJECT (lagent), "initial-binding-request-received", 
535                     G_CALLBACK (cb_initial_binding_request_received), (gpointer)1);
536   g_signal_connect (G_OBJECT (ragent), "initial-binding-request-received", 
537                     G_CALLBACK (cb_initial_binding_request_received), (gpointer)2);
538
539   stun_server = getenv ("NICE_STUN_SERVER");
540   stun_server_port = getenv ("NICE_STUN_SERVER_PORT");
541   if (stun_server) {
542     g_object_set (G_OBJECT (lagent), "stun-server", stun_server,  NULL);
543     g_object_set (G_OBJECT (lagent), "stun-server-port", atoi (stun_server_port),  NULL);
544     g_object_set (G_OBJECT (ragent), "stun-server", stun_server,  NULL);
545     g_object_set (G_OBJECT (ragent), "stun-server-port", atoi (stun_server_port),  NULL);
546   }
547
548   /* step: run test the first time */
549   g_debug ("test-fallback: TEST STARTS / fallback test");
550   result = run_fallback_test (lagent, ragent, &baseaddr);
551   priv_print_global_status ();
552   g_assert_cmpint (result, ==, 0);
553   g_assert_cmpint (global_lagent_state, ==, NICE_COMPONENT_STATE_READY);
554   g_assert_cmpint (global_ragent_state, ==, NICE_COMPONENT_STATE_READY);
555
556   /* step: run the safe test without sending any stnu */
557   g_debug ("test-fallback: TEST STARTS / safe fallback test");
558   result = run_safe_fallback_test (lagent, ragent, &baseaddr);
559   priv_print_global_status ();
560   g_assert_cmpint (result, ==, 0);
561   g_assert_cmpint (global_lagent_state, ==, NICE_COMPONENT_STATE_READY);
562   g_assert_cmpint (global_ragent_state, ==, NICE_COMPONENT_STATE_READY);
563
564   g_object_unref (lagent);
565   g_object_unref (ragent);
566
567   g_main_loop_unref (global_mainloop);
568   global_mainloop = NULL;
569
570   g_source_remove (timer_id);
571 #ifdef G_OS_WIN32
572   WSACleanup();
573 #endif
574   return result;
575 }