// // Destroy event object. // void destroy() { if (event_) { pj_event_destroy(event_); event_ = NULL; } }
static int stun_destroy_test(void) { enum { LOOP = 500 }; struct stun_test_session test_sess; pj_sockaddr bind_addr; int addr_len; pj_caching_pool cp; pj_pool_t *pool; unsigned i; pj_status_t status; int rc = 0; PJ_LOG(3,(THIS_FILE, " STUN destroy concurrency test")); pj_bzero(&test_sess, sizeof(test_sess)); pj_caching_pool_init(&cp, NULL, 0); pool = pj_pool_create(&cp.factory, "testsess", 512, 512, NULL); pj_stun_config_init(&test_sess.stun_cfg, &cp.factory, 0, NULL, NULL); status = pj_timer_heap_create(pool, 1023, &test_sess.stun_cfg.timer_heap); pj_assert(status == PJ_SUCCESS); status = pj_lock_create_recursive_mutex(pool, NULL, &test_sess.lock); pj_assert(status == PJ_SUCCESS); pj_timer_heap_set_lock(test_sess.stun_cfg.timer_heap, test_sess.lock, PJ_TRUE); pj_assert(status == PJ_SUCCESS); status = pj_ioqueue_create(pool, 512, &test_sess.stun_cfg.ioqueue); pj_assert(status == PJ_SUCCESS); pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &test_sess.server_sock); pj_sockaddr_init(pj_AF_INET(), &bind_addr, NULL, 0); status = pj_sock_bind(test_sess.server_sock, &bind_addr, pj_sockaddr_get_len(&bind_addr)); pj_assert(status == PJ_SUCCESS); addr_len = sizeof(bind_addr); status = pj_sock_getsockname(test_sess.server_sock, &bind_addr, &addr_len); pj_assert(status == PJ_SUCCESS); test_sess.server_port = pj_sockaddr_get_port(&bind_addr); status = pj_event_create(pool, NULL, PJ_TRUE, PJ_FALSE, &test_sess.server_event); pj_assert(status == PJ_SUCCESS); for (i=0; i<SERVER_THREAD_CNT; ++i) { status = pj_thread_create(pool, NULL, &server_thread_proc, &test_sess, 0, 0, &test_sess.server_threads[i]); pj_assert(status == PJ_SUCCESS); } for (i=0; i<WORKER_THREAD_CNT; ++i) { status = pj_thread_create(pool, NULL, &worker_thread_proc, &test_sess, 0, 0, &test_sess.worker_threads[i]); pj_assert(status == PJ_SUCCESS); } /* Test 1: Main thread calls destroy while callback is processing response */ PJ_LOG(3,(THIS_FILE, " Destroy in main thread while callback is running")); for (i=0; i<LOOP; ++i) { int sleep = pj_rand() % 5; PJ_LOG(3,(THIS_FILE, " Try %-3d of %d", i+1, LOOP)); /* Test 1: destroy at the same time when receiving response */ pj_bzero(&test_sess.param, sizeof(test_sess.param)); test_sess.param.client_sleep_after_start = 20; test_sess.param.client_sleep_before_destroy = sleep; test_sess.param.server_wait_for_event = PJ_TRUE; stun_destroy_test_session(&test_sess); PJ_LOG(3,(THIS_FILE, " stun test a: sleep delay:%d: clients with response: %d", sleep, test_sess.param.client_got_response)); /* Test 2: destroy at the same time with STUN retransmit timer */ test_sess.param.server_drop_request = PJ_TRUE; test_sess.param.client_sleep_after_start = 0; test_sess.param.client_sleep_before_destroy = PJ_STUN_RTO_VALUE; test_sess.param.server_wait_for_event = PJ_FALSE; stun_destroy_test_session(&test_sess); PJ_LOG(3,(THIS_FILE, " stun test b: retransmit concurrency")); /* Test 3: destroy at the same time with receiving response * AND STUN retransmit timer */ test_sess.param.client_got_response = 0; test_sess.param.server_drop_request = PJ_FALSE; test_sess.param.client_sleep_after_start = PJ_STUN_RTO_VALUE; test_sess.param.client_sleep_before_destroy = 0; test_sess.param.server_wait_for_event = PJ_TRUE; stun_destroy_test_session(&test_sess); PJ_LOG(3,(THIS_FILE, " stun test c: clients with response: %d", test_sess.param.client_got_response)); pj_thread_sleep(10); ice_one_conc_test(&test_sess.stun_cfg, PJ_FALSE); pj_thread_sleep(10); } /* Avoid compiler warning */ goto on_return; on_return: test_sess.thread_quit_flag = PJ_TRUE; for (i=0; i<SERVER_THREAD_CNT; ++i) { pj_thread_join(test_sess.server_threads[i]); } for (i=0; i<WORKER_THREAD_CNT; ++i) { pj_thread_join(test_sess.worker_threads[i]); } pj_event_destroy(test_sess.server_event); pj_sock_close(test_sess.server_sock); pj_ioqueue_destroy(test_sess.stun_cfg.ioqueue); pj_timer_heap_destroy(test_sess.stun_cfg.timer_heap); pj_pool_release(pool); pj_caching_pool_destroy(&cp); PJ_LOG(3,(THIS_FILE, " Done. rc=%d", rc)); return rc; }
static int thread_proc(void *data) { dupsock_t *p_dupsock = (dupsock_t *)data; pj_thread_t *thread; pj_thread_desc desc; struct pj_time_val tv; int ret; pj_ssize_t ntemp; int sock_len; // pj_bzero(desc, sizeof(desc)); // CHECK(__FILE__, pj_thread_register("dupsock", desc, &thread)); PJ_FD_ZERO(&(p_dupsock->rfds)); PJ_FD_ZERO(&(p_dupsock->wfds)); PJ_FD_SET(*(p_dupsock->p_sock), &(p_dupsock->rfds)); tv.sec = 0; tv.msec = 20; // MAIN LOOP p_dupsock->b_quit = 0; while( (!p_dupsock->b_quit) || (p_dupsock->wait_cnt > 0) || (p_dupsock->to_send != NULL) ) { if(p_dupsock->wait_cnt > 0) { p_dupsock->wait_cnt--; pj_event_pulse(p_dupsock->p_event); } pj_thread_sleep(10); PJ_FD_ZERO(&(p_dupsock->rfds)); PJ_FD_ZERO(&(p_dupsock->wfds)); PJ_FD_SET(*(p_dupsock->p_sock), &(p_dupsock->rfds)); if(p_dupsock->to_send != NULL) PJ_FD_SET(*(p_dupsock->p_sock), &(p_dupsock->wfds)); ret = pj_sock_select(*(p_dupsock->p_sock) + 1, &(p_dupsock->rfds), &(p_dupsock->wfds), NULL, &tv); if( ret < 0 ) { PJ_LOG(2, (__FILE__, "Error in select")); } else if (ret > 0) { if( PJ_FD_ISSET( *(p_dupsock->p_sock), &(p_dupsock->rfds)) ) { ntemp = sizeof(p_dupsock->in_buffer); sock_len = sizeof(p_dupsock->in_packet.addr); pj_sock_recvfrom(*(p_dupsock->p_sock), p_dupsock->in_packet.data, &ntemp, 0, (pj_sockaddr_t *)(&(p_dupsock->in_packet.addr)), &sock_len); p_dupsock->in_packet.len = ntemp; if(p_dupsock->recv_callback != NULL) { p_dupsock->recv_callback(p_dupsock); } p_dupsock->in_packet.len = 0; } if( PJ_FD_ISSET( *(p_dupsock->p_sock), &(p_dupsock->wfds)) ) { ntemp = p_dupsock->to_send->len - p_dupsock->to_send->sent; pj_sock_sendto(*(p_dupsock->p_sock), p_dupsock->to_send->data + p_dupsock->to_send->sent, &ntemp, 0, (pj_sockaddr_t *)(&(p_dupsock->to_send->addr)), sizeof(p_dupsock->to_send->addr)); p_dupsock->to_send->sent += ntemp; if(p_dupsock->to_send->len == p_dupsock->to_send->sent) { if(p_dupsock->send_callback != NULL) { p_dupsock->send_callback(p_dupsock); } p_dupsock->to_send = NULL; PJ_FD_CLR(*(p_dupsock->p_sock), &(p_dupsock->wfds)); } } } //PJ_LOG(5, (__FILE__, "end of a loop")); } pj_event_destroy(p_dupsock->p_event); pj_sock_close(*(p_dupsock->p_sock)); return 0; }