static int perform_test(const char *title, pj_stun_config *stun_cfg, unsigned server_flag, struct test_cfg *caller_cfg, struct test_cfg *callee_cfg) { pjlib_state pjlib_state; struct test_sess *sess; int rc; PJ_LOG(3,("", INDENT "%s", title)); capture_pjlib_state(stun_cfg, &pjlib_state); rc = create_sess(stun_cfg, server_flag, caller_cfg, callee_cfg, &sess); if (rc != 0) return rc; #define ALL_READY (sess->caller.result.init_status!=PJ_EPENDING && \ sess->callee.result.init_status!=PJ_EPENDING) /* Wait until both ICE transports are initialized */ WAIT_UNTIL(30, ALL_READY, rc); if (!ALL_READY) { PJ_LOG(3,("", INDENT "err: init timed-out")); destroy_sess(sess, 500); return -100; } if (sess->caller.result.init_status != sess->caller.cfg.expected.init_status) { app_perror(INDENT "err: caller init", sess->caller.result.init_status); destroy_sess(sess, 500); return -102; } if (sess->callee.result.init_status != sess->callee.cfg.expected.init_status) { app_perror(INDENT "err: callee init", sess->callee.result.init_status); destroy_sess(sess, 500); return -104; } /* Failure condition */ if (sess->caller.result.init_status != PJ_SUCCESS || sess->callee.result.init_status != PJ_SUCCESS) { rc = 0; goto on_return; } /* Init ICE on caller */ rc = pj_ice_strans_init_ice(sess->caller.ice, sess->caller.cfg.role, &sess->caller.ufrag, &sess->caller.pass); if (rc != PJ_SUCCESS) { app_perror(INDENT "err: caller pj_ice_strans_init_ice()", rc); destroy_sess(sess, 500); return -100; } /* Init ICE on callee */ rc = pj_ice_strans_init_ice(sess->callee.ice, sess->callee.cfg.role, &sess->callee.ufrag, &sess->callee.pass); if (rc != PJ_SUCCESS) { app_perror(INDENT "err: callee pj_ice_strans_init_ice()", rc); destroy_sess(sess, 500); return -110; } /* Start ICE on callee */ rc = start_ice(&sess->callee, &sess->caller); if (rc != PJ_SUCCESS) { destroy_sess(sess, 500); return -120; } /* Wait for callee's answer_delay */ poll_events(stun_cfg, sess->callee.cfg.answer_delay, PJ_FALSE); /* Start ICE on caller */ rc = start_ice(&sess->caller, &sess->callee); if (rc != PJ_SUCCESS) { destroy_sess(sess, 500); return -130; } /* Wait until negotiation is complete on both endpoints */ #define ALL_DONE (sess->caller.result.nego_status!=PJ_EPENDING && \ sess->callee.result.nego_status!=PJ_EPENDING) WAIT_UNTIL(30, ALL_DONE, rc); if (!ALL_DONE) { PJ_LOG(3,("", INDENT "err: negotiation timed-out")); destroy_sess(sess, 500); return -140; } if (sess->caller.result.nego_status != sess->caller.cfg.expected.nego_status) { app_perror(INDENT "err: caller negotiation failed", sess->caller.result.nego_status); destroy_sess(sess, 500); return -150; } if (sess->callee.result.nego_status != sess->callee.cfg.expected.nego_status) { app_perror(INDENT "err: callee negotiation failed", sess->callee.result.nego_status); destroy_sess(sess, 500); return -160; } /* Verify that both agents have agreed on the same pair */ rc = check_pair(&sess->caller, &sess->callee, -170); if (rc != 0) { destroy_sess(sess, 500); return rc; } rc = check_pair(&sess->callee, &sess->caller, -180); if (rc != 0) { destroy_sess(sess, 500); return rc; } /* Looks like everything is okay */ /* Destroy ICE stream transports first to let it de-allocate * TURN relay (otherwise there'll be timer/memory leak, unless * we wait for long time in the last poll_events() below). */ if (sess->caller.ice) { pj_ice_strans_destroy(sess->caller.ice); sess->caller.ice = NULL; } if (sess->callee.ice) { pj_ice_strans_destroy(sess->callee.ice); sess->callee.ice = NULL; } on_return: /* Wait.. */ poll_events(stun_cfg, 500, PJ_FALSE); /* Now destroy everything */ destroy_sess(sess, 500); /* Flush events */ poll_events(stun_cfg, 100, PJ_FALSE); rc = check_pjlib_state(stun_cfg, &pjlib_state); if (rc != 0) { return rc; } return 0; }
static int perform_test2(const char *title, pj_stun_config *stun_cfg, unsigned server_flag, struct test_cfg *caller_cfg, struct test_cfg *callee_cfg, struct sess_param *test_param) { pjlib_state pjlib_state; struct test_sess *sess; unsigned i; int rc; PJ_LOG(3,(THIS_FILE, INDENT "%s", title)); capture_pjlib_state(stun_cfg, &pjlib_state); rc = create_sess(stun_cfg, server_flag, caller_cfg, callee_cfg, test_param, &sess); if (rc != 0) return rc; #define ALL_READY (sess->caller.result.init_status!=PJ_EPENDING && \ sess->callee.result.init_status!=PJ_EPENDING) /* Wait until both ICE transports are initialized */ WAIT_UNTIL(30000, ALL_READY, rc); if (!ALL_READY) { PJ_LOG(3,(THIS_FILE, INDENT "err: init timed-out")); destroy_sess(sess, 500); return -100; } if (sess->caller.result.init_status != sess->caller.cfg.expected.init_status) { app_perror(INDENT "err: caller init", sess->caller.result.init_status); destroy_sess(sess, 500); return -102; } if (sess->callee.result.init_status != sess->callee.cfg.expected.init_status) { app_perror(INDENT "err: callee init", sess->callee.result.init_status); destroy_sess(sess, 500); return -104; } /* Failure condition */ if (sess->caller.result.init_status != PJ_SUCCESS || sess->callee.result.init_status != PJ_SUCCESS) { rc = 0; goto on_return; } /* Init ICE on caller */ rc = pj_ice_strans_init_ice(sess->caller.ice, sess->caller.cfg.role, &sess->caller.ufrag, &sess->caller.pass); if (rc != PJ_SUCCESS) { app_perror(INDENT "err: caller pj_ice_strans_init_ice()", rc); destroy_sess(sess, 500); return -100; } /* Init ICE on callee */ rc = pj_ice_strans_init_ice(sess->callee.ice, sess->callee.cfg.role, &sess->callee.ufrag, &sess->callee.pass); if (rc != PJ_SUCCESS) { app_perror(INDENT "err: callee pj_ice_strans_init_ice()", rc); destroy_sess(sess, 500); return -110; } /* Start ICE on callee */ rc = start_ice(&sess->callee, &sess->caller); if (rc != PJ_SUCCESS) { destroy_sess(sess, 500); return -120; } /* Wait for callee's answer_delay */ poll_events(stun_cfg, sess->callee.cfg.answer_delay, PJ_FALSE); /* Start ICE on caller */ rc = start_ice(&sess->caller, &sess->callee); if (rc != PJ_SUCCESS) { destroy_sess(sess, 500); return -130; } for (i=0; i<sess->param->worker_cnt; ++i) { pj_status_t status; status = pj_thread_create(sess->pool, "worker_thread", worker_thread_proc, sess, 0, 0, &sess->worker_threads[i]); if (status != PJ_SUCCESS) { PJ_LOG(3,(THIS_FILE, INDENT "err: create thread")); destroy_sess(sess, 500); return -135; } } if (sess->param->destroy_after_create) goto on_destroy; if (sess->param->destroy_after_one_done) { while (sess->caller.result.init_status==PJ_EPENDING && sess->callee.result.init_status==PJ_EPENDING) { if (sess->param->worker_cnt) pj_thread_sleep(0); else poll_events(stun_cfg, 0, PJ_FALSE); } goto on_destroy; } WAIT_UNTIL(30000, ALL_DONE, rc); if (!ALL_DONE) { PJ_LOG(3,(THIS_FILE, INDENT "err: negotiation timed-out")); destroy_sess(sess, 500); return -140; } if (sess->caller.result.nego_status != sess->caller.cfg.expected.nego_status) { app_perror(INDENT "err: caller negotiation failed", sess->caller.result.nego_status); destroy_sess(sess, 500); return -150; } if (sess->callee.result.nego_status != sess->callee.cfg.expected.nego_status) { app_perror(INDENT "err: callee negotiation failed", sess->callee.result.nego_status); destroy_sess(sess, 500); return -160; } /* Verify that both agents have agreed on the same pair */ rc = check_pair(&sess->caller, &sess->callee, -170); if (rc != 0) { destroy_sess(sess, 500); return rc; } rc = check_pair(&sess->callee, &sess->caller, -180); if (rc != 0) { destroy_sess(sess, 500); return rc; } /* Looks like everything is okay */ on_destroy: /* Destroy ICE stream transports first to let it de-allocate * TURN relay (otherwise there'll be timer/memory leak, unless * we wait for long time in the last poll_events() below). */ if (sess->caller.ice) { pj_ice_strans_destroy(sess->caller.ice); sess->caller.ice = NULL; } if (sess->callee.ice) { pj_ice_strans_destroy(sess->callee.ice); sess->callee.ice = NULL; } on_return: /* Wait.. */ poll_events(stun_cfg, 200, PJ_FALSE); /* Now destroy everything */ destroy_sess(sess, 500); /* Flush events */ poll_events(stun_cfg, 100, PJ_FALSE); rc = check_pjlib_state(stun_cfg, &pjlib_state); if (rc != 0) { return rc; } return rc; }