/* * Benchmarking IOQueue */ static int bench_test(pj_bool_t allow_concur, int bufsize, int inactive_sock_count) { pj_sock_t ssock=-1, csock=-1; pj_sockaddr_in addr; pj_pool_t *pool = NULL; pj_sock_t *inactive_sock=NULL; pj_ioqueue_op_key_t *inactive_read_op; char *send_buf, *recv_buf; pj_ioqueue_t *ioque = NULL; pj_ioqueue_key_t *skey, *ckey, *keys[SOCK_INACTIVE_MAX+2]; pj_timestamp t1, t2, t_elapsed; int rc=0, i; /* i must be signed */ pj_str_t temp; char errbuf[PJ_ERR_MSG_SIZE]; TRACE__((THIS_FILE, " bench test %d", inactive_sock_count)); // Create pool. pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL); // Allocate buffers for send and receive. send_buf = (char*)pj_pool_alloc(pool, bufsize); recv_buf = (char*)pj_pool_alloc(pool, bufsize); // Allocate sockets for sending and receiving. rc = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &ssock); if (rc == PJ_SUCCESS) { rc = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &csock); } else csock = PJ_INVALID_SOCKET; if (rc != PJ_SUCCESS) { app_perror("...error: pj_sock_socket()", rc); goto on_error; } // Bind server socket. pj_bzero(&addr, sizeof(addr)); addr.sin_family = pj_AF_INET(); addr.sin_port = pj_htons(PORT); if (pj_sock_bind(ssock, &addr, sizeof(addr))) goto on_error; pj_assert(inactive_sock_count+2 <= PJ_IOQUEUE_MAX_HANDLES); // Create I/O Queue. rc = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioque); if (rc != PJ_SUCCESS) { app_perror("...error: pj_ioqueue_create()", rc); goto on_error; } // Set concurrency rc = pj_ioqueue_set_default_concurrency(ioque, allow_concur); if (rc != PJ_SUCCESS) { app_perror("...error: pj_ioqueue_set_default_concurrency()", rc); goto on_error; } // Allocate inactive sockets, and bind them to some arbitrary address. // Then register them to the I/O queue, and start a read operation. inactive_sock = (pj_sock_t*)pj_pool_alloc(pool, inactive_sock_count*sizeof(pj_sock_t)); inactive_read_op = (pj_ioqueue_op_key_t*)pj_pool_alloc(pool, inactive_sock_count*sizeof(pj_ioqueue_op_key_t)); pj_bzero(&addr, sizeof(addr)); addr.sin_family = pj_AF_INET(); for (i=0; i<inactive_sock_count; ++i) { pj_ssize_t bytes; rc = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &inactive_sock[i]); if (rc != PJ_SUCCESS || inactive_sock[i] < 0) { app_perror("...error: pj_sock_socket()", rc); goto on_error; } if ((rc=pj_sock_bind(inactive_sock[i], &addr, sizeof(addr))) != 0) { pj_sock_close(inactive_sock[i]); inactive_sock[i] = PJ_INVALID_SOCKET; app_perror("...error: pj_sock_bind()", rc); goto on_error; } rc = pj_ioqueue_register_sock(pool, ioque, inactive_sock[i], NULL, &test_cb, &keys[i]); if (rc != PJ_SUCCESS) { pj_sock_close(inactive_sock[i]); inactive_sock[i] = PJ_INVALID_SOCKET; app_perror("...error(1): pj_ioqueue_register_sock()", rc); PJ_LOG(3,(THIS_FILE, "....i=%d", i)); goto on_error; } bytes = bufsize; rc = pj_ioqueue_recv(keys[i], &inactive_read_op[i], recv_buf, &bytes, 0); if (rc != PJ_EPENDING) { pj_sock_close(inactive_sock[i]); inactive_sock[i] = PJ_INVALID_SOCKET; app_perror("...error: pj_ioqueue_read()", rc); goto on_error; } } // Register server and client socket. // We put this after inactivity socket, hopefully this can represent the // worst waiting time. rc = pj_ioqueue_register_sock(pool, ioque, ssock, NULL, &test_cb, &skey); if (rc != PJ_SUCCESS) { app_perror("...error(2): pj_ioqueue_register_sock()", rc); goto on_error; } rc = pj_ioqueue_register_sock(pool, ioque, csock, NULL, &test_cb, &ckey); if (rc != PJ_SUCCESS) { app_perror("...error(3): pj_ioqueue_register_sock()", rc); goto on_error; } // Set destination address to send the packet. pj_sockaddr_in_init(&addr, pj_cstr(&temp, "127.0.0.1"), PORT); // Test loop. t_elapsed.u64 = 0; for (i=0; i<LOOP; ++i) { pj_ssize_t bytes; pj_ioqueue_op_key_t read_op, write_op; // Randomize send buffer. pj_create_random_string(send_buf, bufsize); // Start reading on the server side. bytes = bufsize; rc = pj_ioqueue_recv(skey, &read_op, recv_buf, &bytes, 0); if (rc != PJ_EPENDING) { app_perror("...error: pj_ioqueue_read()", rc); break; } // Starts send on the client side. bytes = bufsize; rc = pj_ioqueue_sendto(ckey, &write_op, send_buf, &bytes, 0, &addr, sizeof(addr)); if (rc != PJ_SUCCESS && rc != PJ_EPENDING) { app_perror("...error: pj_ioqueue_write()", rc); break; } if (rc == PJ_SUCCESS) { if (bytes < 0) { app_perror("...error: pj_ioqueue_sendto()", -bytes); break; } } // Begin time. pj_get_timestamp(&t1); // Poll the queue until we've got completion event in the server side. callback_read_key = NULL; callback_read_size = 0; TRACE__((THIS_FILE, " waiting for key = %p", skey)); do { pj_time_val timeout = { 1, 0 }; #ifdef PJ_SYMBIAN rc = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout)); #else rc = pj_ioqueue_poll(ioque, &timeout); #endif TRACE__((THIS_FILE, " poll rc=%d", rc)); } while (rc >= 0 && callback_read_key != skey); // End time. pj_get_timestamp(&t2); t_elapsed.u64 += (t2.u64 - t1.u64); if (rc < 0) { app_perror(" error: pj_ioqueue_poll", -rc); break; } // Compare recv buffer with send buffer. if (callback_read_size != bufsize || pj_memcmp(send_buf, recv_buf, bufsize)) { rc = -10; PJ_LOG(3,(THIS_FILE, " error: size/buffer mismatch")); break; } // Poll until all events are exhausted, before we start the next loop. do { pj_time_val timeout = { 0, 10 }; #ifdef PJ_SYMBIAN PJ_UNUSED_ARG(timeout); rc = pj_symbianos_poll(-1, 100); #else rc = pj_ioqueue_poll(ioque, &timeout); #endif } while (rc>0); rc = 0; } // Print results if (rc == 0) { pj_timestamp tzero; pj_uint32_t usec_delay; tzero.u32.hi = tzero.u32.lo = 0; usec_delay = pj_elapsed_usec( &tzero, &t_elapsed); PJ_LOG(3, (THIS_FILE, "...%10d %15d % 9d", bufsize, inactive_sock_count, usec_delay)); } else { PJ_LOG(2, (THIS_FILE, "...ERROR rc=%d (buf:%d, fds:%d)", rc, bufsize, inactive_sock_count+2)); } // Cleaning up. for (i=inactive_sock_count-1; i>=0; --i) { pj_ioqueue_unregister(keys[i]); } pj_ioqueue_unregister(skey); pj_ioqueue_unregister(ckey); pj_ioqueue_destroy(ioque); pj_pool_release( pool); return rc; on_error: PJ_LOG(1,(THIS_FILE, "...ERROR: %s", pj_strerror(pj_get_netos_error(), errbuf, sizeof(errbuf)))); if (ssock) pj_sock_close(ssock); if (csock) pj_sock_close(csock); for (i=0; i<inactive_sock_count && inactive_sock && inactive_sock[i]!=PJ_INVALID_SOCKET; ++i) { pj_sock_close(inactive_sock[i]); } if (ioque != NULL) pj_ioqueue_destroy(ioque); pj_pool_release( pool); return -1; }
/* * fake_udp_destroy() * * This function is called by transport manager (by transport->destroy()). */ static pj_status_t fake_udp_destroy( pjsip_transport *transport ) { struct fake_udp_transport *tp = (struct fake_udp_transport*)transport; int i; /* Mark this transport as closing. */ tp->is_closing = 1; /* Cancel all pending operations. */ /* blp: NO NO NO... * No need to post queued completion as we poll the ioqueue until * we've got events anyway. Posting completion will only cause * callback to be called twice with IOCP: one for the post completion * and another one for closing the socket. * for (i=0; i<tp->rdata_cnt; ++i) { pj_ioqueue_post_completion(tp->key, &tp->rdata[i]->tp_info.op_key.op_key, -1); } */ /* Unregister from ioqueue. */ if (tp->key) { pj_ioqueue_unregister(tp->key); tp->key = NULL; } else { /* Close socket. */ if (tp->sock && tp->sock != PJ_INVALID_SOCKET) { pj_sock_close(tp->sock); tp->sock = PJ_INVALID_SOCKET; } } /* Must poll ioqueue because IOCP calls the callback when socket * is closed. We poll the ioqueue until all pending callbacks * have been called. */ for (i=0; i<50 && tp->is_closing < 1+tp->rdata_cnt; ++i) { int cnt; pj_time_val timeout = {0, 1}; cnt = pj_ioqueue_poll(pjsip_endpt_get_ioqueue(transport->endpt), &timeout); if (cnt == 0) break; } /* Destroy rdata */ for (i=0; i<tp->rdata_cnt; ++i) { pj_pool_release(tp->rdata[i]->tp_info.pool); } /* Destroy reference counter. */ if (tp->base.ref_cnt) pj_atomic_destroy(tp->base.ref_cnt); /* Destroy lock */ if (tp->base.lock) pj_lock_destroy(tp->base.lock); /* Destroy pool. */ pjsip_endpt_release_pool(tp->base.endpt, tp->base.pool); return PJ_SUCCESS; }
static int udp_ioqueue_unreg_test_imp(pj_bool_t allow_concur) { enum { LOOP = 10 }; int i, rc; char title[30]; pj_ioqueue_t *ioqueue; pj_pool_t *test_pool; PJ_LOG(3,(THIS_FILE, "..testing with concurency=%d", allow_concur)); test_method = UNREGISTER_IN_APP; test_pool = pj_pool_create(mem, "unregtest", 4000, 4000, NULL); rc = pj_ioqueue_create(test_pool, 16, &ioqueue); if (rc != PJ_SUCCESS) { app_perror("Error creating ioqueue", rc); return -10; } rc = pj_ioqueue_set_default_concurrency(ioqueue, allow_concur); if (rc != PJ_SUCCESS) { app_perror("Error in pj_ioqueue_set_default_concurrency()", rc); return -12; } PJ_LOG(3, (THIS_FILE, "...ioqueue unregister stress test 0/3, unregister in app (%s)", pj_ioqueue_name())); for (i=0; i<LOOP; ++i) { pj_ansi_sprintf(title, "repeat %d/%d", i, LOOP); rc = perform_unreg_test(ioqueue, test_pool, title, 0); if (rc != 0) return rc; } PJ_LOG(3, (THIS_FILE, "...ioqueue unregister stress test 1/3, unregister in app (%s)", pj_ioqueue_name())); for (i=0; i<LOOP; ++i) { pj_ansi_sprintf(title, "repeat %d/%d", i, LOOP); rc = perform_unreg_test(ioqueue, test_pool, title, 1); if (rc != 0) return rc; } test_method = UNREGISTER_IN_CALLBACK; PJ_LOG(3, (THIS_FILE, "...ioqueue unregister stress test 2/3, unregister in cb (%s)", pj_ioqueue_name())); for (i=0; i<LOOP; ++i) { pj_ansi_sprintf(title, "repeat %d/%d", i, LOOP); rc = perform_unreg_test(ioqueue, test_pool, title, 0); if (rc != 0) return rc; } PJ_LOG(3, (THIS_FILE, "...ioqueue unregister stress test 3/3, unregister in cb (%s)", pj_ioqueue_name())); for (i=0; i<LOOP; ++i) { pj_ansi_sprintf(title, "repeat %d/%d", i, LOOP); rc = perform_unreg_test(ioqueue, test_pool, title, 1); if (rc != 0) return rc; } pj_ioqueue_destroy(ioqueue); pj_pool_release(test_pool); return 0; }
/* * main() */ int main() { pj_caching_pool cp; pjmedia_endpt *med_endpt; pj_pool_t *pool; pjmedia_port *port; unsigned i; pj_status_t status; /* Must init PJLIB first: */ status = pj_init(); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Must create a pool factory before we can allocate any memory. */ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0); /* * Initialize media endpoint. * This will implicitly initialize PJMEDIA too. */ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Create memory pool for our file player */ pool = pj_pool_create( &cp.factory, /* pool factory */ "app", /* pool name. */ 4000, /* init size */ 4000, /* increment size */ NULL /* callback on error */ ); status = pjmedia_tonegen_create(pool, 8000, 1, SAMPLES_PER_FRAME, 16, 0, &port); if (status != PJ_SUCCESS) return 1; { pjmedia_tone_desc tones[3]; tones[0].freq1 = 200; tones[0].freq2 = 0; tones[0].on_msec = ON_DURATION; tones[0].off_msec = OFF_DURATION; tones[1].freq1 = 400; tones[1].freq2 = 0; tones[1].on_msec = ON_DURATION; tones[1].off_msec = OFF_DURATION; tones[2].freq1 = 800; tones[2].freq2 = 0; tones[2].on_msec = ON_DURATION; tones[2].off_msec = OFF_DURATION; status = pjmedia_tonegen_play(port, 3, tones, 0); PJ_ASSERT_RETURN(status==PJ_SUCCESS, 1); } { pjmedia_tone_digit digits[2]; digits[0].digit = '0'; digits[0].on_msec = ON_DURATION; digits[0].off_msec = OFF_DURATION; digits[1].digit = '0'; digits[1].on_msec = ON_DURATION; digits[1].off_msec = OFF_DURATION; status = pjmedia_tonegen_play_digits(port, 2, digits, 0); PJ_ASSERT_RETURN(status==PJ_SUCCESS, 1); } { pjmedia_frame frm; FILE *f; void *buf; buf = pj_pool_alloc(pool, 2*8000); frm.buf = buf; f = fopen("tonegen.pcm", "wb"); for (i=0; i<8000/SAMPLES_PER_FRAME; ++i) { int count; pjmedia_port_get_frame(port, &frm); count = fwrite(buf, SAMPLES_PER_FRAME, 2, f); if (count != 2) break; } pj_assert(pjmedia_tonegen_is_busy(port) == 0); fclose(f); } /* Delete port */ pjmedia_port_destroy(port); /* Release application pool */ pj_pool_release( pool ); /* Destroy media endpoint. */ pjmedia_endpt_destroy( med_endpt ); /* Destroy pool factory */ pj_caching_pool_destroy( &cp ); /* Shutdown PJLIB */ pj_shutdown(); /* Done. */ return 0; }
static pj_status_t enc_dec_test(const char *codec_id, const char *filein, const char *fileout) { pj_pool_t *pool; pjmedia_codec_mgr *cm; pjmedia_codec *codec; const pjmedia_codec_info *pci; pjmedia_codec_param param; unsigned cnt, samples_per_frame; pj_str_t tmp; pjmedia_port *wavin, *wavout; unsigned lost_pct; pj_status_t status; #define T file_msec_duration/1000, file_msec_duration%1000 pool = pjmedia_endpt_create_pool(mept, "encdec", 1000, 1000); cm = pjmedia_endpt_get_codec_mgr(mept); #ifdef LOST_PCT lost_pct = LOST_PCT; #else lost_pct = 0; #endif cnt = 1; CHECK( pjmedia_codec_mgr_find_codecs_by_id(cm, pj_cstr(&tmp, codec_id), &cnt, &pci, NULL) ); CHECK( pjmedia_codec_mgr_get_default_param(cm, pci, ¶m) ); samples_per_frame = param.info.clock_rate * param.info.frm_ptime / 1000; /* Control VAD */ param.setting.vad = 1; /* Open wav for reading */ CHECK( pjmedia_wav_player_port_create(pool, filein, param.info.frm_ptime, PJMEDIA_FILE_NO_LOOP, 0, &wavin) ); /* Open wav for writing */ CHECK( pjmedia_wav_writer_port_create(pool, fileout, param.info.clock_rate, param.info.channel_cnt, samples_per_frame, 16, 0, 0, &wavout) ); /* Alloc codec */ CHECK( pjmedia_codec_mgr_alloc_codec(cm, pci, &codec) ); CHECK( codec->op->init(codec, pool) ); CHECK( codec->op->open(codec, ¶m) ); for (;;) { pjmedia_frame frm_pcm, frm_bit, out_frm, frames[4]; pj_int16_t pcmbuf[320]; pj_timestamp ts; pj_uint8_t bitstream[160]; frm_pcm.buf = (char*)pcmbuf; frm_pcm.size = samples_per_frame * 2; /* Read from WAV */ if (pjmedia_port_get_frame(wavin, &frm_pcm) != PJ_SUCCESS) break; if (frm_pcm.type != PJMEDIA_FRAME_TYPE_AUDIO) break;; /* Update duration */ file_msec_duration += samples_per_frame * 1000 / param.info.clock_rate; /* Encode */ frm_bit.buf = bitstream; frm_bit.size = sizeof(bitstream); CHECK(codec->op->encode(codec, &frm_pcm, sizeof(bitstream), &frm_bit)); /* On DTX, write zero frame to wavout to maintain duration */ if (frm_bit.size == 0 || frm_bit.type != PJMEDIA_FRAME_TYPE_AUDIO) { out_frm.buf = (char*)pcmbuf; out_frm.size = 160; CHECK( pjmedia_port_put_frame(wavout, &out_frm) ); TRACE_((THIS_FILE, "%d.%03d read: %u, enc: %u", T, frm_pcm.size, frm_bit.size)); continue; } /* Parse the bitstream (not really necessary for this case * since we always decode 1 frame, but it's still good * for testing) */ ts.u64 = 0; cnt = PJ_ARRAY_SIZE(frames); CHECK( codec->op->parse(codec, bitstream, frm_bit.size, &ts, &cnt, frames) ); CHECK( (cnt==1 ? PJ_SUCCESS : -1) ); /* Decode or simulate packet loss */ out_frm.buf = (char*)pcmbuf; out_frm.size = sizeof(pcmbuf); if ((pj_rand() % 100) < (int)lost_pct) { /* Simulate loss */ CHECK( codec->op->recover(codec, sizeof(pcmbuf), &out_frm) ); TRACE_((THIS_FILE, "%d.%03d Packet lost", T)); } else { /* Decode */ CHECK( codec->op->decode(codec, &frames[0], sizeof(pcmbuf), &out_frm) ); } /* Write to WAV */ CHECK( pjmedia_port_put_frame(wavout, &out_frm) ); TRACE_((THIS_FILE, "%d.%03d read: %u, enc: %u, dec/write: %u", T, frm_pcm.size, frm_bit.size, out_frm.size)); } /* Close wavs */ pjmedia_port_destroy(wavout); pjmedia_port_destroy(wavin); /* Close codec */ codec->op->close(codec); pjmedia_codec_mgr_dealloc_codec(cm, codec); /* Release pool */ pj_pool_release(pool); return PJ_SUCCESS; }
/* * Destroy stream. */ PJ_DEF(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream) { PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); pjmedia_snd_stream_stop(stream); if (stream->thread) { pj_assert(stream->thread_quit_event); SetEvent(stream->thread_quit_event); pj_thread_join(stream->thread); pj_thread_destroy(stream->thread); stream->thread = NULL; } if (stream->thread_quit_event) { CloseHandle(stream->thread_quit_event); stream->thread_quit_event = NULL; } if (stream->play_strm.lpDsNotify) { IDirectSoundNotify_Release( stream->play_strm.lpDsNotify ); stream->play_strm.lpDsNotify = NULL; } if (stream->play_strm.hEvent) { CloseHandle(stream->play_strm.hEvent); stream->play_strm.hEvent = NULL; } if (stream->play_strm.ds.play.lpDsBuffer) { IDirectSoundBuffer_Release( stream->play_strm.ds.play.lpDsBuffer ); stream->play_strm.ds.play.lpDsBuffer = NULL; } if (stream->play_strm.ds.play.lpDs) { IDirectSound_Release( stream->play_strm.ds.play.lpDs ); stream->play_strm.ds.play.lpDs = NULL; } if (stream->rec_strm.lpDsNotify) { IDirectSoundNotify_Release( stream->rec_strm.lpDsNotify ); stream->rec_strm.lpDsNotify = NULL; } if (stream->rec_strm.hEvent) { CloseHandle(stream->rec_strm.hEvent); stream->rec_strm.hEvent = NULL; } if (stream->rec_strm.ds.capture.lpDsBuffer) { IDirectSoundCaptureBuffer_Release( stream->rec_strm.ds.capture.lpDsBuffer ); stream->rec_strm.ds.capture.lpDsBuffer = NULL; } if (stream->rec_strm.ds.capture.lpDs) { IDirectSoundCapture_Release( stream->rec_strm.ds.capture.lpDs ); stream->rec_strm.ds.capture.lpDs = NULL; } pj_pool_release(stream->pool); return PJ_SUCCESS; }
/* * GET request scenario 2: using on_complete() to get the * complete data. Server does not reply with content-length. * Request timed out, application sets a longer timeout, then * then restart the request. */ int http_client_test2() { pj_str_t url; pj_http_req_callback hcb; pj_http_req_param param; pj_time_val timeout; char urlbuf[80]; pj_bzero(&hcb, sizeof(hcb)); hcb.on_complete = &on_complete; hcb.on_response = &on_response; pj_http_req_param_default(¶m); /* Create pool, timer, and ioqueue */ pool = pj_pool_create(mem, NULL, 8192, 4096, NULL); if (pj_timer_heap_create(pool, 16, &timer_heap)) return -41; if (pj_ioqueue_create(pool, 16, &ioqueue)) return -42; #ifdef USE_LOCAL_SERVER pj_cstr(&url, "http://127.0.0.1:380"); param.timeout.sec = 0; param.timeout.msec = 2000; thread_quit = PJ_FALSE; g_server.action = ACTION_IGNORE; g_server.send_content_length = PJ_FALSE; g_server.data_size = 4173; g_server.buf_size = 1024; sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &g_server.sock); if (sstatus != PJ_SUCCESS) return -41; pj_sockaddr_in_init(&addr, NULL, 0); sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr)); if (sstatus != PJ_SUCCESS) return -43; { pj_sockaddr_in addr; int addr_len = sizeof(addr); sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len); if (sstatus != PJ_SUCCESS) return -44; g_server.port = pj_sockaddr_in_get_port(&addr); pj_ansi_snprintf(urlbuf, sizeof(urlbuf), "http://127.0.0.1:%d", g_server.port); url = pj_str(urlbuf); } sstatus = pj_sock_listen(g_server.sock, 8); if (sstatus != PJ_SUCCESS) return -45; sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server, 0, 0, &g_server.thread); if (sstatus != PJ_SUCCESS) return -47; #else pj_cstr(&url, "http://www.google.com.sg"); param.timeout.sec = 0; param.timeout.msec = 50; #endif pj_http_headers_add_elmt2(¶m.headers, (char*)"Accept", (char*)"image/gif, image/x-xbitmap, image/jpeg, " "image/pjpeg, application/x-ms-application," " application/vnd.ms-xpsdocument, " "application/xaml+xml, " "application/x-ms-xbap, " "application/x-shockwave-flash, " "application/vnd.ms-excel, " "application/vnd.ms-powerpoint, " "application/msword, */*"); pj_http_headers_add_elmt2(¶m.headers, (char*)"Accept-Language", (char*)"en-sg"); pj_http_headers_add_elmt2(¶m.headers, (char*)"User-Agent", (char*)"Mozilla/4.0 (compatible; MSIE 7.0; " "Windows NT 6.0; SLCC1; " ".NET CLR 2.0.50727; " ".NET CLR 3.0.04506)"); if (pj_http_req_create(pool, &url, timer_heap, ioqueue, ¶m, &hcb, &http_req)) return -43; if (pj_http_req_start(http_req)) return -45; while (pj_http_req_is_running(http_req)) { pj_time_val delay = {0, 50}; pj_ioqueue_poll(ioqueue, &delay); pj_timer_heap_poll(timer_heap, NULL); } #ifdef USE_LOCAL_SERVER g_server.action = ACTION_REPLY; #endif timeout.sec = 0; timeout.msec = 10000; pj_http_req_set_timeout(http_req, &timeout); if (pj_http_req_start(http_req)) return -47; while (pj_http_req_is_running(http_req)) { pj_time_val delay = {0, 50}; pj_ioqueue_poll(ioqueue, &delay); pj_timer_heap_poll(timer_heap, NULL); } #ifdef USE_LOCAL_SERVER thread_quit = PJ_TRUE; pj_thread_join(g_server.thread); pj_sock_close(g_server.sock); #endif pj_http_req_destroy(http_req); pj_ioqueue_destroy(ioqueue); pj_timer_heap_destroy(timer_heap); pj_pool_release(pool); return PJ_SUCCESS; }
PJ_DEF(pj_status_t) pj_stun_detect_nat_type2(const pj_sockaddr *server, pj_stun_config *stun_cfg, void *user_data, pj_stun_nat_detect_cb *cb) { pj_pool_t *pool; nat_detect_session *sess; pj_stun_session_cb sess_cb; pj_ioqueue_callback ioqueue_cb; int af, addr_len; char addr[PJ_INET6_ADDRSTRLEN]; pj_status_t status; PJ_ASSERT_RETURN(server && stun_cfg, PJ_EINVAL); PJ_ASSERT_RETURN(stun_cfg->pf && stun_cfg->ioqueue && stun_cfg->timer_heap, PJ_EINVAL); /* * Init NAT detection session. */ pool = pj_pool_create(stun_cfg->pf, "natck%p", PJNATH_POOL_LEN_NATCK, PJNATH_POOL_INC_NATCK, NULL); if (!pool) return PJ_ENOMEM; sess = PJ_POOL_ZALLOC_T(pool, nat_detect_session); sess->pool = pool; sess->user_data = user_data; sess->cb = cb; status = pj_grp_lock_create(pool, NULL, &sess->grp_lock); if (status != PJ_SUCCESS) { /* Group lock not created yet, just destroy pool and return */ pj_pool_release(pool); return status; } pj_grp_lock_add_ref(sess->grp_lock); pj_grp_lock_add_handler(sess->grp_lock, pool, sess, &sess_on_destroy); pj_sockaddr_cp(&sess->server, server); /* * Init timer to self-destroy. */ sess->timer_heap = stun_cfg->timer_heap; sess->timer.cb = &on_sess_timer; sess->timer.user_data = sess; /* * Initialize socket. */ af = server->addr.sa_family; status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &sess->sock); if (status != PJ_SUCCESS) goto on_error; /* * Bind to any. */ addr_len = pj_sockaddr_get_len(server); pj_sockaddr_init(server->addr.sa_family, &sess->local_addr, NULL, 0); status = pj_sock_bind(sess->sock, &sess->local_addr, addr_len); if (status != PJ_SUCCESS) goto on_error; /* * Get local/bound address. */ status = pj_sock_getsockname(sess->sock, &sess->local_addr, &addr_len); if (status != PJ_SUCCESS) goto on_error; /* * Find out which interface is used to send to the server. */ status = get_local_interface(server, &sess->local_addr); if (status != PJ_SUCCESS) goto on_error; PJ_LOG(5,(sess->pool->obj_name, "Local address is %s:%d", pj_sockaddr_print(&sess->local_addr, addr, sizeof(addr), 0), pj_sockaddr_get_port(&sess->local_addr))); PJ_LOG(5,(sess->pool->obj_name, "Server set to %s:%d", pj_sockaddr_print(server, addr, sizeof(addr), 0), pj_sockaddr_get_port(server))); /* * Register socket to ioqueue to receive asynchronous input * notification. */ pj_bzero(&ioqueue_cb, sizeof(ioqueue_cb)); ioqueue_cb.on_read_complete = &on_read_complete; status = pj_ioqueue_register_sock2(sess->pool, stun_cfg->ioqueue, sess->sock, sess->grp_lock, sess, &ioqueue_cb, &sess->key); if (status != PJ_SUCCESS) goto on_error; /* * Create STUN session. */ pj_bzero(&sess_cb, sizeof(sess_cb)); sess_cb.on_request_complete = &on_request_complete; sess_cb.on_send_msg = &on_send_msg; status = pj_stun_session_create(stun_cfg, pool->obj_name, &sess_cb, PJ_FALSE, sess->grp_lock, &sess->stun_sess); if (status != PJ_SUCCESS) goto on_error; pj_stun_session_set_user_data(sess->stun_sess, sess); /* * Kick-off ioqueue reading. */ pj_ioqueue_op_key_init(&sess->read_op, sizeof(sess->read_op)); pj_ioqueue_op_key_init(&sess->write_op, sizeof(sess->write_op)); on_read_complete(sess->key, &sess->read_op, 0); /* * Start TEST_1 */ sess->timer.id = TIMER_TEST; on_sess_timer(stun_cfg->timer_heap, &sess->timer); return PJ_SUCCESS; on_error: sess_destroy(sess); return status; }
/** * Create new session. */ PJ_DEF(pj_status_t) pjmedia_session_create( pjmedia_endpt *endpt, const pjmedia_session_info *si, pjmedia_transport *transports[], void *user_data, pjmedia_session **p_session ) { pj_pool_t *pool; pjmedia_session *session; int i; /* Must be signed */ pj_status_t status; /* Verify arguments. */ PJ_ASSERT_RETURN(endpt && si && p_session, PJ_EINVAL); /* Create pool for the session. */ pool = pjmedia_endpt_create_pool( endpt, "session", PJMEDIA_SESSION_SIZE, PJMEDIA_SESSION_INC); PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); session = PJ_POOL_ZALLOC_T(pool, pjmedia_session); session->pool = pool; session->endpt = endpt; session->stream_cnt = si->stream_cnt; session->user_data = user_data; /* Copy stream info (this simple memcpy may break sometime) */ pj_memcpy(session->stream_info, si->stream_info, si->stream_cnt * sizeof(pjmedia_stream_info)); /* * Now create and start the stream! */ for (i=0; i<(int)si->stream_cnt; ++i) { /* Create the stream */ status = pjmedia_stream_create(endpt, session->pool, &session->stream_info[i], (transports?transports[i]:NULL), session, &session->stream[i]); if (status == PJ_SUCCESS) status = pjmedia_stream_start(session->stream[i]); if (status != PJ_SUCCESS) { for ( --i; i>=0; ++i) { pjmedia_stream_destroy(session->stream[i]); } pj_pool_release(session->pool); return status; } } /* Done. */ *p_session = session; return PJ_SUCCESS; }
/* API: configure the AVI */ PJ_DEF(pj_status_t) pjmedia_avi_dev_alloc( pjmedia_vid_dev_factory *f, pjmedia_avi_dev_param *p, pjmedia_vid_dev_index *p_id) { pjmedia_vid_dev_index id; struct avi_factory *cf = (struct avi_factory*)f; unsigned local_idx; struct avi_dev_info *adi = NULL; pjmedia_format avi_fmt; const pjmedia_video_format_info *vfi; pj_status_t status; PJ_ASSERT_RETURN(f && p && p_id, PJ_EINVAL); if (p_id) *p_id = PJMEDIA_VID_INVALID_DEV; /* Get a free dev */ for (local_idx=0; local_idx<cf->dev_count; ++local_idx) { if (cf->dev_info[local_idx].avi == NULL) { adi = &cf->dev_info[local_idx]; break; } } if (!adi) return PJ_ETOOMANY; /* Convert local ID to global id */ status = pjmedia_vid_dev_get_global_index(&cf->base, local_idx, &id); if (status != PJ_SUCCESS) return status; /* Reset */ if (adi->pool) { pj_pool_release(adi->pool); } pj_bzero(adi, sizeof(*adi)); /* Reinit */ PJ_ASSERT_RETURN(p->path.slen, PJ_EINVAL); adi->pool = pj_pool_create(cf->pf, "avidi%p", 512, 512, NULL); /* Open the AVI */ pj_strdup_with_null(adi->pool, &adi->fpath, &p->path); status = pjmedia_avi_player_create_streams(adi->pool, adi->fpath.ptr, 0, &adi->avi); if (status != PJ_SUCCESS) { goto on_error; } adi->vid = pjmedia_avi_streams_get_stream_by_media(adi->avi, 0, PJMEDIA_TYPE_VIDEO); if (!adi->vid) { status = PJMEDIA_EVID_BADFORMAT; PJ_LOG(4,(THIS_FILE, "Error: cannot find video in AVI %s", adi->fpath.ptr)); goto on_error; } pjmedia_format_copy(&avi_fmt, &adi->vid->info.fmt); vfi = pjmedia_get_video_format_info(NULL, avi_fmt.id); /* Check whether the frame is encoded. */ if (!vfi || vfi->bpp == 0) { /* Yes, prepare codec */ const pjmedia_vid_codec_info *codec_info; pjmedia_vid_codec_param codec_param; pjmedia_video_apply_fmt_param vafp; /* Lookup codec */ status = pjmedia_vid_codec_mgr_get_codec_info2(NULL, avi_fmt.id, &codec_info); if (status != PJ_SUCCESS || !codec_info) goto on_error; status = pjmedia_vid_codec_mgr_get_default_param(NULL, codec_info, &codec_param); if (status != PJ_SUCCESS) goto on_error; /* Open codec */ status = pjmedia_vid_codec_mgr_alloc_codec(NULL, codec_info, &adi->codec); if (status != PJ_SUCCESS) goto on_error; status = pjmedia_vid_codec_init(adi->codec, adi->pool); if (status != PJ_SUCCESS) goto on_error; codec_param.dir = PJMEDIA_DIR_DECODING; codec_param.packing = PJMEDIA_VID_PACKING_WHOLE; status = pjmedia_vid_codec_open(adi->codec, &codec_param); if (status != PJ_SUCCESS) goto on_error; /* Allocate buffer */ avi_fmt.id = codec_info->dec_fmt_id[0]; vfi = pjmedia_get_video_format_info(NULL, avi_fmt.id); pj_bzero(&vafp, sizeof(vafp)); vafp.size = avi_fmt.det.vid.size; status = vfi->apply_fmt(vfi, &vafp); if (status != PJ_SUCCESS) goto on_error; adi->enc_buf = pj_pool_alloc(adi->pool, vafp.framebytes); adi->enc_buf_size = vafp.framebytes; } /* Calculate title */ if (p->title.slen) { pj_strdup_with_null(adi->pool, &adi->title, &p->title); } else { char *start = p->path.ptr + p->path.slen; pj_str_t tmp; while (start >= p->path.ptr) { if (*start == '/' || *start == '\\') break; --start; } tmp.ptr = start + 1; tmp.slen = p->path.ptr + p->path.slen - tmp.ptr; pj_strdup_with_null(adi->pool, &adi->title, &tmp); } /* Init device info */ pj_ansi_strncpy(adi->info.name, adi->title.ptr, sizeof(adi->info.name)-1); pj_ansi_strncpy(adi->info.driver, DRIVER_NAME, sizeof(adi->info.driver)-1); adi->info.dir = PJMEDIA_DIR_CAPTURE; adi->info.has_callback = PJ_FALSE; adi->info.caps = PJMEDIA_VID_DEV_CAP_FORMAT; adi->info.fmt_cnt = 1; pjmedia_format_copy(&adi->info.fmt[0], &avi_fmt); /* Set out vars */ if (p_id) *p_id = id; p->avi_streams = adi->avi; if (p->title.slen == 0) p->title = adi->title; return PJ_SUCCESS; on_error: if (adi->codec) { pjmedia_vid_codec_close(adi->codec); adi->codec = NULL; } if (adi->pool) { pj_pool_release(adi->pool); adi->pool = NULL; } pjmedia_avi_dev_free(id); return status; }
PJ_DEF(pj_status_t) pjmedia_codec_silk_init(pjmedia_endpt *endpt) { pjmedia_codec_mgr *codec_mgr; silk_param *sp; pj_status_t status; if (silk_factory.endpt != NULL) { /* Already initialized. */ return PJ_SUCCESS; } /* Init factory */ pj_bzero(&silk_factory, sizeof(silk_factory)); silk_factory.base.op = &silk_factory_op; silk_factory.base.factory_data = NULL; silk_factory.endpt = endpt; /* Create pool */ silk_factory.pool = pjmedia_endpt_create_pool(endpt, "silk", 4000, 4000); if (!silk_factory.pool) return PJ_ENOMEM; /* Create mutex. */ status = pj_mutex_create_simple(silk_factory.pool, "silk", &silk_factory.mutex); if (status != PJ_SUCCESS) goto on_error; /* Initialize default codec params */ /* From SILK docs: - SILK bitrate tables: +----------------+---------+-----------+ | | fs (Hz) | BR (kbps) | +----------------+---------+-----------+ | Narrowband | 8000 | 6 - 20 | | Mediumband | 12000 | 7 - 25 | | Wideband | 16000 | 8 - 30 | | Super Wideband | 24000 | 12 - 40 | +----------------+---------+-----------+ - The upper limits of the bit rate ranges in this table are recommended values. */ sp = &silk_factory.silk_param[PARAM_NB]; sp->pt = PJMEDIA_RTP_PT_SILK_NB; sp->clock_rate = 8000; sp->max_bitrate = 22000; sp->bitrate = CALC_BITRATE(sp->max_bitrate); sp->ptime = FRAME_LENGTH_MS; sp->complexity = PJMEDIA_CODEC_SILK_DEFAULT_COMPLEXITY; sp->enabled = 1; sp = &silk_factory.silk_param[PARAM_MB]; sp->pt = PJMEDIA_RTP_PT_SILK_MB; sp->clock_rate = 12000; sp->max_bitrate = 28000; sp->bitrate = CALC_BITRATE(sp->max_bitrate); sp->ptime = FRAME_LENGTH_MS; sp->complexity = PJMEDIA_CODEC_SILK_DEFAULT_COMPLEXITY; sp->enabled = 1; sp = &silk_factory.silk_param[PARAM_WB]; sp->pt = PJMEDIA_RTP_PT_SILK_WB; sp->clock_rate = 16000; sp->max_bitrate = 36000; sp->bitrate = CALC_BITRATE(sp->max_bitrate); sp->ptime = FRAME_LENGTH_MS; sp->complexity = PJMEDIA_CODEC_SILK_DEFAULT_COMPLEXITY; sp->enabled = 1; sp = &silk_factory.silk_param[PARAM_SWB]; sp->pt = PJMEDIA_RTP_PT_SILK_SWB; sp->clock_rate = 24000; sp->max_bitrate = 46000; sp->bitrate = CALC_BITRATE(sp->max_bitrate); sp->ptime = FRAME_LENGTH_MS; sp->complexity = PJMEDIA_CODEC_SILK_DEFAULT_COMPLEXITY; sp->enabled = 1; /* Get the codec manager. */ codec_mgr = pjmedia_endpt_get_codec_mgr(endpt); if (!codec_mgr) { return PJ_EINVALIDOP; } /* Register codec factory to endpoint. */ status = pjmedia_codec_mgr_register_factory(codec_mgr, &silk_factory.base); if (status != PJ_SUCCESS) return status; PJ_LOG(4,(THIS_FILE, "SILK codec version %s initialized", SKP_Silk_SDK_get_version())); return PJ_SUCCESS; on_error: if (silk_factory.mutex) { pj_mutex_destroy(silk_factory.mutex); silk_factory.mutex = NULL; } if (silk_factory.pool) { pj_pool_release(silk_factory.pool); silk_factory.pool = NULL; } return status; }
/* Calculate the bandwidth for the specific test configuration. * The test is simple: * - create sockpair_cnt number of producer-consumer socket pair. * - create thread_cnt number of worker threads. * - each producer will send buffer_size bytes data as fast and * as soon as it can. * - each consumer will read buffer_size bytes of data as fast * as it could. * - measure the total bytes received by all consumers during a * period of time. */ static int perform_test(pj_bool_t allow_concur, int sock_type, const char *type_name, unsigned thread_cnt, unsigned sockpair_cnt, pj_size_t buffer_size, pj_size_t *p_bandwidth) { enum { MSEC_DURATION = 5000 }; pj_pool_t *pool; test_item *items; pj_thread_t **thread; pj_ioqueue_t *ioqueue; pj_status_t rc; pj_ioqueue_callback ioqueue_callback; pj_uint32_t total_elapsed_usec, total_received; pj_highprec_t bandwidth; pj_timestamp start, stop; unsigned i; TRACE_((THIS_FILE, " starting test..")); ioqueue_callback.on_read_complete = &on_read_complete; ioqueue_callback.on_write_complete = &on_write_complete; thread_quit_flag = 0; pool = pj_pool_create(mem, NULL, 4096, 4096, NULL); if (!pool) return -10; items = (test_item*) pj_pool_alloc(pool, sockpair_cnt*sizeof(test_item)); thread = (pj_thread_t**) pj_pool_alloc(pool, thread_cnt*sizeof(pj_thread_t*)); TRACE_((THIS_FILE, " creating ioqueue..")); rc = pj_ioqueue_create(pool, sockpair_cnt*2, &ioqueue); if (rc != PJ_SUCCESS) { app_perror("...error: unable to create ioqueue", rc); return -15; } rc = pj_ioqueue_set_default_concurrency(ioqueue, allow_concur); if (rc != PJ_SUCCESS) { app_perror("...error: pj_ioqueue_set_default_concurrency()", rc); return -16; } /* Initialize each producer-consumer pair. */ for (i=0; i<sockpair_cnt; ++i) { pj_ssize_t bytes; items[i].ioqueue = ioqueue; items[i].buffer_size = buffer_size; items[i].outgoing_buffer = (char*) pj_pool_alloc(pool, buffer_size); items[i].incoming_buffer = (char*) pj_pool_alloc(pool, buffer_size); items[i].bytes_recv = items[i].bytes_sent = 0; /* randomize outgoing buffer. */ pj_create_random_string(items[i].outgoing_buffer, buffer_size); /* Create socket pair. */ TRACE_((THIS_FILE, " calling socketpair..")); rc = app_socketpair(pj_AF_INET(), sock_type, 0, &items[i].server_fd, &items[i].client_fd); if (rc != PJ_SUCCESS) { app_perror("...error: unable to create socket pair", rc); return -20; } /* Register server socket to ioqueue. */ TRACE_((THIS_FILE, " register(1)..")); rc = pj_ioqueue_register_sock(pool, ioqueue, items[i].server_fd, &items[i], &ioqueue_callback, &items[i].server_key); if (rc != PJ_SUCCESS) { app_perror("...error: registering server socket to ioqueue", rc); return -60; } /* Register client socket to ioqueue. */ TRACE_((THIS_FILE, " register(2)..")); rc = pj_ioqueue_register_sock(pool, ioqueue, items[i].client_fd, &items[i], &ioqueue_callback, &items[i].client_key); if (rc != PJ_SUCCESS) { app_perror("...error: registering server socket to ioqueue", rc); return -70; } /* Start reading. */ TRACE_((THIS_FILE, " pj_ioqueue_recv..")); bytes = items[i].buffer_size; rc = pj_ioqueue_recv(items[i].server_key, &items[i].recv_op, items[i].incoming_buffer, &bytes, 0); if (rc != PJ_EPENDING) { app_perror("...error: pj_ioqueue_recv", rc); return -73; } /* Start writing. */ TRACE_((THIS_FILE, " pj_ioqueue_write..")); bytes = items[i].buffer_size; rc = pj_ioqueue_send(items[i].client_key, &items[i].send_op, items[i].outgoing_buffer, &bytes, 0); if (rc != PJ_SUCCESS && rc != PJ_EPENDING) { app_perror("...error: pj_ioqueue_write", rc); return -76; } items[i].has_pending_send = (rc==PJ_EPENDING); } /* Create the threads. */ for (i=0; i<thread_cnt; ++i) { struct thread_arg *arg; arg = (struct thread_arg*) pj_pool_zalloc(pool, sizeof(*arg)); arg->id = i; arg->ioqueue = ioqueue; arg->counter = 0; rc = pj_thread_create( pool, NULL, &worker_thread, arg, PJ_THREAD_DEFAULT_STACK_SIZE, PJ_THREAD_SUSPENDED, &thread[i] ); if (rc != PJ_SUCCESS) { app_perror("...error: unable to create thread", rc); return -80; } } /* Mark start time. */ rc = pj_get_timestamp(&start); if (rc != PJ_SUCCESS) return -90; /* Start the thread. */ TRACE_((THIS_FILE, " resuming all threads..")); for (i=0; i<thread_cnt; ++i) { rc = pj_thread_resume(thread[i]); if (rc != 0) return -100; } /* Wait for MSEC_DURATION seconds. * This should be as simple as pj_thread_sleep(MSEC_DURATION) actually, * but unfortunately it doesn't work when system doesn't employ * timeslicing for threads. */ TRACE_((THIS_FILE, " wait for few seconds..")); do { pj_thread_sleep(1); /* Mark end time. */ rc = pj_get_timestamp(&stop); if (thread_quit_flag) { TRACE_((THIS_FILE, " transfer limit reached..")); break; } if (pj_elapsed_usec(&start,&stop)<MSEC_DURATION * 1000) { TRACE_((THIS_FILE, " time limit reached..")); break; } } while (1); /* Terminate all threads. */ TRACE_((THIS_FILE, " terminating all threads..")); thread_quit_flag = 1; for (i=0; i<thread_cnt; ++i) { TRACE_((THIS_FILE, " join thread %d..", i)); pj_thread_join(thread[i]); } /* Close all sockets. */ TRACE_((THIS_FILE, " closing all sockets..")); for (i=0; i<sockpair_cnt; ++i) { pj_ioqueue_unregister(items[i].server_key); pj_ioqueue_unregister(items[i].client_key); } /* Destroy threads */ for (i=0; i<thread_cnt; ++i) { pj_thread_destroy(thread[i]); } /* Destroy ioqueue. */ TRACE_((THIS_FILE, " destroying ioqueue..")); pj_ioqueue_destroy(ioqueue); /* Calculate actual time in usec. */ total_elapsed_usec = pj_elapsed_usec(&start, &stop); /* Calculate total bytes received. */ total_received = 0; for (i=0; i<sockpair_cnt; ++i) { total_received = items[i].bytes_recv; } /* bandwidth = total_received*1000/total_elapsed_usec */ bandwidth = total_received; pj_highprec_mul(bandwidth, 1000); pj_highprec_div(bandwidth, total_elapsed_usec); *p_bandwidth = (pj_uint32_t)bandwidth; PJ_LOG(3,(THIS_FILE, " %.4s %2d %2d %8d KB/s", type_name, thread_cnt, sockpair_cnt, *p_bandwidth)); /* Done. */ pj_pool_release(pool); TRACE_((THIS_FILE, " done..")); return 0; }
static int tcp_perf_test(void) { enum { COUNT=100000 }; pj_pool_t *pool = NULL; pj_ioqueue_t *ioqueue = NULL; pj_sock_t sock1=PJ_INVALID_SOCKET, sock2=PJ_INVALID_SOCKET; pj_activesock_t *asock1 = NULL, *asock2 = NULL; pj_activesock_cb cb; struct tcp_state *state1, *state2; unsigned i; pj_status_t status; pool = pj_pool_create(mem, "tcpperf", 256, 256, NULL); status = app_socketpair(pj_AF_INET(), pj_SOCK_STREAM(), 0, &sock1, &sock2); if (status != PJ_SUCCESS) { status = -100; goto on_return; } status = pj_ioqueue_create(pool, 4, &ioqueue); if (status != PJ_SUCCESS) { status = -110; goto on_return; } pj_bzero(&cb, sizeof(cb)); cb.on_data_read = &tcp_on_data_read; cb.on_data_sent = &tcp_on_data_sent; state1 = PJ_POOL_ZALLOC_T(pool, struct tcp_state); status = pj_activesock_create(pool, sock1, pj_SOCK_STREAM(), NULL, ioqueue, &cb, state1, &asock1); if (status != PJ_SUCCESS) { status = -120; goto on_return; } state2 = PJ_POOL_ZALLOC_T(pool, struct tcp_state); status = pj_activesock_create(pool, sock2, pj_SOCK_STREAM(), NULL, ioqueue, &cb, state2, &asock2); if (status != PJ_SUCCESS) { status = -130; goto on_return; } status = pj_activesock_start_read(asock1, pool, 1000, 0); if (status != PJ_SUCCESS) { status = -140; goto on_return; } /* Send packet as quickly as possible */ for (i=0; i<COUNT && !state1->err && !state2->err; ++i) { struct tcp_pkt *pkt; struct send_key send_key[2], *op_key; pj_ssize_t len; pkt = (struct tcp_pkt*)state2->pkt; pkt->signature = SIGNATURE; pkt->seq = i; pj_memset(pkt->fill, 'a', sizeof(pkt->fill)); op_key = &send_key[i%2]; pj_ioqueue_op_key_init(&op_key->op_key, sizeof(*op_key)); state2->sent = PJ_FALSE; len = sizeof(*pkt); status = pj_activesock_send(asock2, &op_key->op_key, pkt, &len, 0); if (status == PJ_EPENDING) { do { #if PJ_SYMBIAN pj_symbianos_poll(-1, -1); #else pj_ioqueue_poll(ioqueue, NULL); #endif } while (!state2->sent); } else { #if PJ_SYMBIAN /* The Symbian socket always returns PJ_SUCCESS for TCP send, * eventhough the remote end hasn't received the data yet. * If we continue sending, eventually send() will block, * possibly because the send buffer is full. So we need to * poll the ioqueue periodically, to let receiver gets the * data. */ pj_symbianos_poll(-1, 0); #endif if (status != PJ_SUCCESS) { PJ_LOG(1,("", " err: send status=%d", status)); status = -180; break; } else if (status == PJ_SUCCESS) { if (len != sizeof(*pkt)) { PJ_LOG(1,("", " err: shouldn't report partial sent")); status = -190; break; } } } } /* Wait until everything has been sent/received */ if (state1->next_recv_seq < COUNT) { #ifdef PJ_SYMBIAN while (pj_symbianos_poll(-1, 1000) == PJ_TRUE) ; #else pj_time_val delay = {0, 100}; while (pj_ioqueue_poll(ioqueue, &delay) > 0) ; #endif } if (status == PJ_EPENDING) status = PJ_SUCCESS; if (status != 0) goto on_return; if (state1->err) { status = -183; goto on_return; } if (state2->err) { status = -186; goto on_return; } if (state1->next_recv_seq != COUNT) { PJ_LOG(3,("", " err: only %u packets received, expecting %u", state1->next_recv_seq, COUNT)); status = -195; goto on_return; } on_return: if (asock2) pj_activesock_close(asock2); if (asock1) pj_activesock_close(asock1); if (ioqueue) pj_ioqueue_destroy(ioqueue); if (pool) pj_pool_release(pool); return status; }
/******************************************************************* * UDP ping pong test (send packet back and forth between two UDP echo * servers. */ static int udp_ping_pong_test(void) { pj_ioqueue_t *ioqueue = NULL; pj_pool_t *pool = NULL; struct udp_echo_srv *srv1=NULL, *srv2=NULL; pj_bool_t need_send = PJ_TRUE; unsigned data = 0; int count, ret; pj_status_t status; pool = pj_pool_create(mem, "pingpong", 512, 512, NULL); if (!pool) return -10; status = pj_ioqueue_create(pool, 4, &ioqueue); if (status != PJ_SUCCESS) { ret = -20; udp_echo_err("pj_ioqueue_create()", status); goto on_return; } status = udp_echo_srv_create(pool, ioqueue, PJ_TRUE, &srv1); if (status != PJ_SUCCESS) { ret = -30; goto on_return; } status = udp_echo_srv_create(pool, ioqueue, PJ_TRUE, &srv2); if (status != PJ_SUCCESS) { ret = -40; goto on_return; } /* initiate the first send */ for (count=0; count<1000; ++count) { unsigned last_rx1, last_rx2; unsigned i; if (need_send) { pj_str_t loopback; pj_sockaddr_in addr; pj_ssize_t sent; ++data; sent = sizeof(data); loopback = pj_str("127.0.0.1"); pj_sockaddr_in_init(&addr, &loopback, srv2->port); status = pj_activesock_sendto(srv1->asock, &srv1->send_key, &data, &sent, 0, &addr, sizeof(addr)); if (status != PJ_SUCCESS && status != PJ_EPENDING) { ret = -50; udp_echo_err("sendto()", status); goto on_return; } need_send = PJ_FALSE; } last_rx1 = srv1->rx_cnt; last_rx2 = srv2->rx_cnt; for (i=0; i<10 && last_rx1 == srv1->rx_cnt && last_rx2 == srv2->rx_cnt; ++i) { pj_time_val delay = {0, 10}; #ifdef PJ_SYMBIAN pj_symbianos_poll(-1, 100); #else pj_ioqueue_poll(ioqueue, &delay); #endif } if (srv1->rx_err_cnt+srv1->tx_err_cnt != 0 || srv2->rx_err_cnt+srv2->tx_err_cnt != 0) { /* Got error */ ret = -60; goto on_return; } if (last_rx1 == srv1->rx_cnt && last_rx2 == srv2->rx_cnt) { /* Packet lost */ ret = -70; udp_echo_err("packets have been lost", PJ_ETIMEDOUT); goto on_return; } } ret = 0; on_return: if (srv2) udp_echo_srv_destroy(srv2); if (srv1) udp_echo_srv_destroy(srv1); if (ioqueue) pj_ioqueue_destroy(ioqueue); if (pool) pj_pool_release(pool); return ret; }
void SDPTest::tearDown() { delete _session; _session = NULL; pj_pool_release (_testPool); }
static pj_status_t g729_alloc_codec( pjmedia_codec_factory *factory, const pjmedia_codec_info *id, pjmedia_codec **p_codec) { pjmedia_codec *codec = NULL; pj_status_t status; pj_pool_t *pool; PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL); PJ_ASSERT_RETURN(factory==&g729_factory.base, PJ_EINVAL); /* Lock mutex. */ pj_mutex_lock(g729_factory.mutex); /* Allocate new codec if no more is available */ struct g729_private *codec_priv; /* Create pool for codec instance */ pool = pjmedia_endpt_create_pool(g729_factory.endpt, "g729codec", 512, 512); codec = PJ_POOL_ALLOC_T(pool, pjmedia_codec); codec_priv = PJ_POOL_ZALLOC_T(pool, struct g729_private); if (!codec || !codec_priv) { pj_pool_release(pool); pj_mutex_unlock(g729_factory.mutex); return PJ_ENOMEM; } codec_priv->pool = pool; /* Set the payload type */ codec_priv->pt = id->pt; #if !PLC_DISABLED /* Create PLC, always with 10ms ptime */ status = pjmedia_plc_create(pool, 8000, 80, 0, &codec_priv->plc); if (status != PJ_SUCCESS) { pj_pool_release(pool); pj_mutex_unlock(g729_factory.mutex); return status; } #endif /* Create VAD */ status = pjmedia_silence_det_create(g729_factory.pool, 8000, 80, &codec_priv->vad); if (status != PJ_SUCCESS) { pj_mutex_unlock(g729_factory.mutex); return status; } codec->factory = factory; codec->op = &g729_op; codec->codec_data = codec_priv; *p_codec = codec; /* Unlock mutex. */ pj_mutex_unlock(g729_factory.mutex); return PJ_SUCCESS; }
/* API: create stream */ static pj_status_t bb10_factory_create_stream(pjmedia_aud_dev_factory *f, const pjmedia_aud_param *param, pjmedia_aud_rec_cb rec_cb, pjmedia_aud_play_cb play_cb, void *user_data, pjmedia_aud_stream **p_strm) { struct bb10_factory *af = (struct bb10_factory*)f; pj_status_t status; pj_pool_t* pool; struct bb10_stream* stream; pool = pj_pool_create (af->pf, "bb10%p", 1024, 1024, NULL); if (!pool) return PJ_ENOMEM; /* Allocate and initialize comon stream data */ stream = PJ_POOL_ZALLOC_T (pool, struct bb10_stream); stream->base.op = &bb10_stream_op; stream->pool = pool; stream->af = af; stream->user_data = user_data; stream->pb_cb = play_cb; stream->ca_cb = rec_cb; stream->quit = 0; pj_memcpy(&stream->param, param, sizeof(*param)); /* Init playback */ if (param->dir & PJMEDIA_DIR_PLAYBACK) { status = bb10_open_playback (stream, param); if (status != PJ_SUCCESS) { pj_pool_release (pool); return status; } } /* Init capture */ if (param->dir & PJMEDIA_DIR_CAPTURE) { status = bb10_open_capture (stream, param); if (status != PJ_SUCCESS) { if (param->dir & PJMEDIA_DIR_PLAYBACK) { close_play_pcm(stream); } pj_pool_release (pool); return status; } } /* Set the audio routing ONLY if app explicitly asks one */ if ((param->dir & PJMEDIA_DIR_PLAYBACK) && (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE)) { status = bb10_stream_set_cap(&stream->base, PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE, ¶m->output_route); if (status != PJ_SUCCESS) { TRACE_((THIS_FILE, "Error setting output route")); bb10_stream_destroy(&stream->base); return status; } } else { /* Legacy behavior: if none specified, set to speaker */ status = bb10_initialize_playback_ctrl(stream, false); } *p_strm = &stream->base; return PJ_SUCCESS; }
static pj_bool_t turn_on_data_recvfrom(pj_activesock_t *asock, void *data, pj_size_t size, const pj_sockaddr_t *src_addr, int addr_len, pj_status_t status) { test_server *test_srv; pj_pool_t *pool; turn_allocation *alloc; pj_stun_msg *req, *resp = NULL; pj_str_t auth_key = { NULL, 0 }; char client_info[PJ_INET6_ADDRSTRLEN+10]; unsigned i; pj_ssize_t len; if (status != PJ_SUCCESS) return PJ_TRUE; pj_sockaddr_print(src_addr, client_info, sizeof(client_info), 3); test_srv = (test_server*) pj_activesock_get_user_data(asock); pool = pj_pool_create(test_srv->stun_cfg->pf, NULL, 512, 512, NULL); /* Find the client */ for (i=0; i<test_srv->turn_alloc_cnt; i++) { if (pj_sockaddr_cmp(&test_srv->turn_alloc[i].client_addr, src_addr)==0) break; } if (pj_stun_msg_check((pj_uint8_t*)data, size, PJ_STUN_NO_FINGERPRINT_CHECK)!=PJ_SUCCESS) { /* Not STUN message, this probably is a ChannelData */ pj_turn_channel_data cd; const pj_turn_channel_data *pcd = (const pj_turn_channel_data*)data; pj_ssize_t sent; if (i==test_srv->turn_alloc_cnt) { /* Invalid data */ PJ_LOG(1,(THIS_FILE, "TURN Server received strayed data")); goto on_return; } alloc = &test_srv->turn_alloc[i]; cd.ch_number = pj_ntohs(pcd->ch_number); cd.length = pj_ntohs(pcd->length); /* For UDP check the packet length */ if (size < cd.length+sizeof(cd)) { PJ_LOG(1,(THIS_FILE, "TURN Server: ChannelData discarded: UDP size error")); goto on_return; } /* Lookup peer */ for (i=0; i<alloc->perm_cnt; ++i) { if (alloc->chnum[i] == cd.ch_number) break; } if (i==alloc->perm_cnt) { PJ_LOG(1,(THIS_FILE, "TURN Server: ChannelData discarded: invalid channel number")); goto on_return; } /* Relay the data to peer */ sent = cd.length; pj_activesock_sendto(alloc->sock, &alloc->send_key, pcd+1, &sent, 0, &alloc->perm[i], pj_sockaddr_get_len(&alloc->perm[i])); /* Done */ goto on_return; } status = pj_stun_msg_decode(pool, (pj_uint8_t*)data, size, PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET | PJ_STUN_NO_FINGERPRINT_CHECK, &req, NULL, NULL); if (status != PJ_SUCCESS) { char errmsg[PJ_ERR_MSG_SIZE]; pj_strerror(status, errmsg, sizeof(errmsg)); PJ_LOG(1,("", "STUN message decode error from client %s: %s", client_info, errmsg)); goto on_return; } if (i==test_srv->turn_alloc_cnt) { /* New client */ //pj_str_t ip_addr; pj_stun_username_attr *uname; pj_activesock_cb alloc_sock_cb; turn_allocation *alloc; /* Must be Allocate request */ if (req->hdr.type != PJ_STUN_ALLOCATE_REQUEST) { PJ_LOG(1,(THIS_FILE, "Invalid %s %s from client %s", pj_stun_get_method_name(req->hdr.type), pj_stun_get_class_name(req->hdr.type), client_info)); if (PJ_STUN_IS_REQUEST(req->hdr.type)) pj_stun_msg_create_response(pool, req, PJ_STUN_SC_BAD_REQUEST, NULL, &resp); goto send_pkt; } test_srv->turn_stat.rx_allocate_cnt++; /* Skip if we're not responding to Allocate request */ if (!test_srv->turn_respond_allocate) return PJ_TRUE; /* Check if we have too many clients */ if (test_srv->turn_alloc_cnt == MAX_TURN_ALLOC) { pj_stun_msg_create_response(pool, req, PJ_STUN_SC_INSUFFICIENT_CAPACITY, NULL, &resp); goto send_pkt; } /* Get USERNAME attribute */ uname = (pj_stun_username_attr*) pj_stun_msg_find_attr(req, PJ_STUN_ATTR_USERNAME, 0); /* Reject if it doesn't have MESSAGE-INTEGRITY or USERNAME attributes or * the user is incorrect */ if (pj_stun_msg_find_attr(req, PJ_STUN_ATTR_MESSAGE_INTEGRITY, 0) == NULL || uname==NULL || pj_stricmp2(&uname->value, TURN_USERNAME) != 0) { pj_str_t tmp; pj_stun_msg_create_response(pool, req, PJ_STUN_SC_UNAUTHORIZED, NULL, &resp); pj_stun_msg_add_string_attr(pool, resp, PJ_STUN_ATTR_REALM, &test_srv->domain); pj_stun_msg_add_string_attr(pool, resp, PJ_STUN_ATTR_NONCE, pj_cstr(&tmp, TURN_NONCE)); goto send_pkt; } pj_bzero(&alloc_sock_cb, sizeof(alloc_sock_cb)); alloc_sock_cb.on_data_recvfrom = &alloc_on_data_recvfrom; /* Create allocation */ alloc = &test_srv->turn_alloc[test_srv->turn_alloc_cnt]; alloc->perm_cnt = 0; alloc->test_srv = test_srv; pj_memcpy(&alloc->client_addr, src_addr, addr_len); pj_ioqueue_op_key_init(&alloc->send_key, sizeof(alloc->send_key)); alloc->pool = pj_pool_create(test_srv->stun_cfg->pf, "alloc", 512, 512, NULL); /* Create relay socket */ pj_sockaddr_in_init(&alloc->alloc_addr.ipv4, NULL, 0); pj_gethostip(pj_AF_INET(), &alloc->alloc_addr); status = pj_activesock_create_udp(alloc->pool, &alloc->alloc_addr, NULL, test_srv->stun_cfg->ioqueue, &alloc_sock_cb, alloc, &alloc->sock, &alloc->alloc_addr); if (status != PJ_SUCCESS) { pj_pool_release(alloc->pool); pj_stun_msg_create_response(pool, req, PJ_STUN_SC_SERVER_ERROR, NULL, &resp); goto send_pkt; } //pj_sockaddr_set_str_addr(pj_AF_INET(), &alloc->alloc_addr, &ip_addr); pj_activesock_set_user_data(alloc->sock, alloc); status = pj_activesock_start_recvfrom(alloc->sock, alloc->pool, 1500, 0); if (status != PJ_SUCCESS) { pj_activesock_close(alloc->sock); pj_pool_release(alloc->pool); pj_stun_msg_create_response(pool, req, PJ_STUN_SC_SERVER_ERROR, NULL, &resp); goto send_pkt; } /* Create Data indication */ status = pj_stun_msg_create(alloc->pool, PJ_STUN_DATA_INDICATION, PJ_STUN_MAGIC, NULL, &alloc->data_ind); if (status != PJ_SUCCESS) { pj_activesock_close(alloc->sock); pj_pool_release(alloc->pool); pj_stun_msg_create_response(pool, req, PJ_STUN_SC_SERVER_ERROR, NULL, &resp); goto send_pkt; } pj_stun_msg_add_sockaddr_attr(alloc->pool, alloc->data_ind, PJ_STUN_ATTR_XOR_PEER_ADDR, PJ_TRUE, &alloc->alloc_addr, pj_sockaddr_get_len(&alloc->alloc_addr)); pj_stun_msg_add_binary_attr(alloc->pool, alloc->data_ind, PJ_STUN_ATTR_DATA, (pj_uint8_t*)"", 1); /* Create response */ resp = create_success_response(test_srv, alloc, req, pool, 600, &auth_key); if (resp == NULL) { pj_activesock_close(alloc->sock); pj_pool_release(alloc->pool); pj_stun_msg_create_response(pool, req, PJ_STUN_SC_SERVER_ERROR, NULL, &resp); goto send_pkt; } ++test_srv->turn_alloc_cnt; } else { alloc = &test_srv->turn_alloc[i]; if (req->hdr.type == PJ_STUN_ALLOCATE_REQUEST) { test_srv->turn_stat.rx_allocate_cnt++; /* Skip if we're not responding to Allocate request */ if (!test_srv->turn_respond_allocate) return PJ_TRUE; resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key); } else if (req->hdr.type == PJ_STUN_REFRESH_REQUEST) { pj_stun_lifetime_attr *lf_attr; test_srv->turn_stat.rx_refresh_cnt++; /* Skip if we're not responding to Refresh request */ if (!test_srv->turn_respond_refresh) return PJ_TRUE; lf_attr = (pj_stun_lifetime_attr*) pj_stun_msg_find_attr(req, PJ_STUN_ATTR_LIFETIME, 0); if (lf_attr && lf_attr->value != 0) { resp = create_success_response(test_srv, alloc, req, pool, 600, &auth_key); pj_array_erase(test_srv->turn_alloc, sizeof(test_srv->turn_alloc[0]), test_srv->turn_alloc_cnt, i); --test_srv->turn_alloc_cnt; } else resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key); } else if (req->hdr.type == PJ_STUN_CREATE_PERM_REQUEST) { for (i=0; i<req->attr_count; ++i) { if (req->attr[i]->type == PJ_STUN_ATTR_XOR_PEER_ADDR) { pj_stun_xor_peer_addr_attr *pa = (pj_stun_xor_peer_addr_attr*)req->attr[i]; unsigned j; for (j=0; j<alloc->perm_cnt; ++j) { if (pj_sockaddr_cmp(&alloc->perm[j], &pa->sockaddr)==0) break; } if (j==alloc->perm_cnt && alloc->perm_cnt < MAX_TURN_PERM) { char peer_info[PJ_INET6_ADDRSTRLEN]; pj_sockaddr_print(&pa->sockaddr, peer_info, sizeof(peer_info), 3); pj_sockaddr_cp(&alloc->perm[alloc->perm_cnt], &pa->sockaddr); ++alloc->perm_cnt; PJ_LOG(5,("", "Permission %s added to client %s, perm_cnt=%d", peer_info, client_info, alloc->perm_cnt)); } } } resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key); } else if (req->hdr.type == PJ_STUN_SEND_INDICATION) { pj_stun_xor_peer_addr_attr *pa; pj_stun_data_attr *da; test_srv->turn_stat.rx_send_ind_cnt++; pa = (pj_stun_xor_peer_addr_attr*) pj_stun_msg_find_attr(req, PJ_STUN_ATTR_XOR_PEER_ADDR, 0); da = (pj_stun_data_attr*) pj_stun_msg_find_attr(req, PJ_STUN_ATTR_DATA, 0); if (pa && da) { unsigned j; char peer_info[PJ_INET6_ADDRSTRLEN]; pj_ssize_t sent; pj_sockaddr_print(&pa->sockaddr, peer_info, sizeof(peer_info), 3); for (j=0; j<alloc->perm_cnt; ++j) { if (pj_sockaddr_cmp(&alloc->perm[j], &pa->sockaddr)==0) break; } if (j==alloc->perm_cnt) { PJ_LOG(5,("", "SendIndication to %s is rejected (no permission)", peer_info, client_info, alloc->perm_cnt)); } else { PJ_LOG(5,(THIS_FILE, "Relaying %d bytes data from client %s to peer %s, " "perm_cnt=%d", da->length, client_info, peer_info, alloc->perm_cnt)); sent = da->length; pj_activesock_sendto(alloc->sock, &alloc->send_key, da->data, &sent, 0, &pa->sockaddr, pj_sockaddr_get_len(&pa->sockaddr)); } } else { PJ_LOG(1,(THIS_FILE, "Invalid Send Indication from %s", client_info)); } } else if (req->hdr.type == PJ_STUN_CHANNEL_BIND_REQUEST) { pj_stun_xor_peer_addr_attr *pa; pj_stun_channel_number_attr *cna; unsigned j, cn; pa = (pj_stun_xor_peer_addr_attr*) pj_stun_msg_find_attr(req, PJ_STUN_ATTR_XOR_PEER_ADDR, 0); cna = (pj_stun_channel_number_attr*) pj_stun_msg_find_attr(req, PJ_STUN_ATTR_CHANNEL_NUMBER, 0); cn = PJ_STUN_GET_CH_NB(cna->value); resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key); for (j=0; j<alloc->perm_cnt; ++j) { if (pj_sockaddr_cmp(&alloc->perm[j], &pa->sockaddr)==0) break; } if (i==alloc->perm_cnt) { if (alloc->perm_cnt==MAX_TURN_PERM) { pj_stun_msg_create_response(pool, req, PJ_STUN_SC_INSUFFICIENT_CAPACITY, NULL, &resp); goto send_pkt; } pj_sockaddr_cp(&alloc->perm[i], &pa->sockaddr); ++alloc->perm_cnt; } alloc->chnum[i] = cn; resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key); } else if (PJ_STUN_IS_REQUEST(req->hdr.type)) { pj_stun_msg_create_response(pool, req, PJ_STUN_SC_BAD_REQUEST, NULL, &resp); } } send_pkt: if (resp) { status = pj_stun_msg_encode(resp, (pj_uint8_t*)data, MAX_STUN_PKT, 0, &auth_key, &size); if (status != PJ_SUCCESS) goto on_return; len = size; status = pj_activesock_sendto(asock, &test_srv->send_key, data, &len, 0, src_addr, addr_len); } on_return: pj_pool_release(pool); return PJ_TRUE; }
/* * Open stream. */ static pj_status_t open_stream( pjmedia_dir dir, int rec_id, int play_id, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, pjmedia_snd_rec_cb rec_cb, pjmedia_snd_play_cb play_cb, void *user_data, pjmedia_snd_stream **p_snd_strm) { pj_pool_t *pool; pjmedia_snd_stream *strm; pj_status_t status; /* Make sure sound subsystem has been initialized with * pjmedia_snd_init() */ PJ_ASSERT_RETURN( pool_factory != NULL, PJ_EINVALIDOP ); /* Can only support 16bits per sample */ PJ_ASSERT_RETURN(bits_per_sample == BITS_PER_SAMPLE, PJ_EINVAL); /* Create and Initialize stream descriptor */ pool = pj_pool_create(pool_factory, "dsound-dev", 1000, 1000, NULL); PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); strm = pj_pool_zalloc(pool, sizeof(pjmedia_snd_stream)); strm->dir = dir; strm->play_id = play_id; strm->rec_id = rec_id; strm->pool = pool; strm->rec_cb = rec_cb; strm->play_cb = play_cb; strm->user_data = user_data; strm->clock_rate = clock_rate; strm->samples_per_frame = samples_per_frame; strm->bits_per_sample = bits_per_sample; strm->channel_count = channel_count; strm->buffer = pj_pool_alloc(pool, samples_per_frame * BYTES_PER_SAMPLE); if (!strm->buffer) { pj_pool_release(pool); return PJ_ENOMEM; } /* * Create event for stopping the worker thread. */ strm->thread_quit_event = CreateEvent(NULL, FALSE, FALSE, NULL); if (strm->thread_quit_event == NULL) { status = pj_get_os_error(); pj_pool_release(pool); return status; } /* Create player stream */ if (dir & PJMEDIA_DIR_PLAYBACK) { unsigned buffer_count; /* Calculate buffer count, in frame unit */ buffer_count = clock_rate * snd_output_latency / samples_per_frame / 1000; /* There must always be one more buffer than required for the latency */ buffer_count += 1; if (buffer_count < MIN_PACKET_BUFFER_COUNT) buffer_count = MIN_PACKET_BUFFER_COUNT; if (buffer_count > MAX_PACKET_BUFFER_COUNT) buffer_count = MAX_PACKET_BUFFER_COUNT; status = init_player_stream( &strm->play_strm, play_id, clock_rate, channel_count, samples_per_frame, buffer_count ); if (status != PJ_SUCCESS) { pjmedia_snd_stream_close(strm); return status; } } /* Create capture stream */ if (dir & PJMEDIA_DIR_CAPTURE) { unsigned buffer_count; /* Calculate buffer count, in frame unit */ buffer_count = clock_rate * snd_input_latency / samples_per_frame / 1000; if (buffer_count < MIN_PACKET_BUFFER_COUNT) buffer_count = MIN_PACKET_BUFFER_COUNT; if (buffer_count > MAX_PACKET_BUFFER_COUNT) buffer_count = MAX_PACKET_BUFFER_COUNT; status = init_capture_stream( &strm->rec_strm, rec_id, clock_rate, channel_count, samples_per_frame, buffer_count); if (status != PJ_SUCCESS) { pjmedia_snd_stream_close(strm); return status; } } /* Create and start the thread */ status = pj_thread_create(pool, "dsound", &dsound_dev_thread, strm, 0, 0, &strm->thread); if (status != PJ_SUCCESS) { pjmedia_snd_stream_close(strm); return status; } *p_snd_strm = strm; return PJ_SUCCESS; }
static int create_ses_by_remote_sdp(int local_port, char *sdp) { pj_media_session_t *ses = NULL; pjsdp_session_desc *sdp_ses; pj_media_sock_info skinfo; pj_pool_t *pool; char s[4]; const pj_media_stream_info *info[2]; int i, count; pool = pj_pool_create(pf, "sdp", 1024, 0, NULL); if (!pool) { PJ_LOG(1,(THIS_FILE, "Unable to create pool")); return -1; } pj_bzero(&skinfo, sizeof(skinfo)); skinfo.rtp_sock = skinfo.rtcp_sock = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, 0); if (skinfo.rtp_sock == PJ_INVALID_SOCKET) { PJ_LOG(1,(THIS_FILE, "Unable to create socket")); goto on_error; } pj_sockaddr_init2(&skinfo.rtp_addr_name, "0.0.0.0", local_port); if (pj_sock_bind(skinfo.rtp_sock, (struct pj_sockaddr*)&skinfo.rtp_addr_name, sizeof(pj_sockaddr_in)) != 0) { PJ_LOG(1,(THIS_FILE, "Unable to bind socket")); goto on_error; } sdp_ses = pjsdp_parse(sdp, strlen(sdp), pool); if (!sdp_ses) { PJ_LOG(1,(THIS_FILE, "Error parsing SDP")); goto on_error; } ses = pj_media_session_create_from_sdp(mm, sdp_ses, &skinfo); if (!ses) { PJ_LOG(1,(THIS_FILE, "Unable to create session from SDP")); goto on_error; } if (pj_media_session_activate(ses) != 0) { PJ_LOG(1,(THIS_FILE, "Error activating session")); goto on_error; } count = pj_media_session_enum_streams(ses, 2, info); printf("\nDumping streams: \n"); for (i=0; i<count; ++i) { const char *dir; char *local_ip; switch (info[i]->dir) { case PJMEDIA_DIR_NONE: dir = "- NONE -"; break; case PJMEDIA_DIR_ENCODING: dir = "SENDONLY"; break; case PJMEDIA_DIR_DECODING: dir = "RECVONLY"; break; case PJMEDIA_DIR_ENCODING_DECODING: dir = "SENDRECV"; break; default: dir = "?UNKNOWN"; break; } local_ip = pj_sockaddr_get_str_addr(&info[i]->sock_info.rtp_addr_name); printf(" Stream %d: %.*s %s local=%s:%d remote=%.*s:%d\n", i, info[i]->type.slen, info[i]->type.ptr, dir, local_ip, pj_sockaddr_get_port(&info[i]->sock_info.rtp_addr_name), info[i]->rem_addr.slen, info[i]->rem_addr.ptr, info[i]->rem_port); } puts("Press <ENTER> to quit"); fgets(s, sizeof(s), stdin); pj_media_session_destroy(ses); pj_sock_close(skinfo.rtp_sock); pj_pool_release(pool); return 0; on_error: if (ses) pj_media_session_destroy(ses); if (skinfo.rtp_sock != PJ_INVALID_SOCKET) pj_sock_close(skinfo.rtp_sock); if (pool) pj_pool_release(pool); return -1; }
int http_client_test_delete() { pj_str_t url; pj_http_req_callback hcb; pj_http_req_param param; char urlbuf[80]; pj_bzero(&hcb, sizeof(hcb)); hcb.on_complete = &on_complete; hcb.on_response = &on_response; /* Create pool, timer, and ioqueue */ pool = pj_pool_create(mem, NULL, 8192, 4096, NULL); if (pj_timer_heap_create(pool, 16, &timer_heap)) return -61; if (pj_ioqueue_create(pool, 16, &ioqueue)) return -62; #ifdef USE_LOCAL_SERVER thread_quit = PJ_FALSE; g_server.action = ACTION_REPLY; g_server.send_content_length = PJ_TRUE; g_server.data_size = 0; g_server.buf_size = 1024; sstatus = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &g_server.sock); if (sstatus != PJ_SUCCESS) return -41; pj_sockaddr_in_init(&addr, NULL, 0); sstatus = pj_sock_bind(g_server.sock, &addr, sizeof(addr)); if (sstatus != PJ_SUCCESS) return -43; { pj_sockaddr_in addr; int addr_len = sizeof(addr); sstatus = pj_sock_getsockname(g_server.sock, &addr, &addr_len); if (sstatus != PJ_SUCCESS) return -44; g_server.port = pj_sockaddr_in_get_port(&addr); pj_ansi_snprintf(urlbuf, sizeof(urlbuf), "http://127.0.0.1:%d/test/test2.txt", g_server.port); url = pj_str(urlbuf); } sstatus = pj_sock_listen(g_server.sock, 8); if (sstatus != PJ_SUCCESS) return -45; sstatus = pj_thread_create(pool, NULL, &server_thread, &g_server, 0, 0, &g_server.thread); if (sstatus != PJ_SUCCESS) return -47; #else pj_cstr(&url, "http://127.0.0.1:280/test/test2.txt"); #endif pj_http_req_param_default(¶m); pj_strset2(¶m.method, (char*)"DELETE"); if (pj_http_req_create(pool, &url, timer_heap, ioqueue, ¶m, &hcb, &http_req)) return -63; if (pj_http_req_start(http_req)) return -65; while (pj_http_req_is_running(http_req)) { pj_time_val delay = {0, 50}; pj_ioqueue_poll(ioqueue, &delay); pj_timer_heap_poll(timer_heap, NULL); } #ifdef USE_LOCAL_SERVER thread_quit = PJ_TRUE; pj_thread_join(g_server.thread); pj_sock_close(g_server.sock); #endif pj_http_req_destroy(http_req); pj_ioqueue_destroy(ioqueue); pj_timer_heap_destroy(timer_heap); pj_pool_release(pool); return PJ_SUCCESS; }
/* * Destroy DNS resolver instance. */ PJ_DEF(pj_status_t) pj_dns_resolver_destroy( pj_dns_resolver *resolver, pj_bool_t notify) { pj_hash_iterator_t it_buf, *it; PJ_ASSERT_RETURN(resolver, PJ_EINVAL); if (notify) { /* * Notify pending queries if requested. */ it = pj_hash_first(resolver->hquerybyid, &it_buf); while (it) { pj_dns_async_query *q = (pj_dns_async_query *) pj_hash_this(resolver->hquerybyid, it); pj_dns_async_query *cq; if (q->cb) (*q->cb)(q->user_data, PJ_ECANCELLED, NULL); cq = q->child_head.next; while (cq != (pj_dns_async_query*)&q->child_head) { if (cq->cb) (*cq->cb)(cq->user_data, PJ_ECANCELLED, NULL); cq = cq->next; } it = pj_hash_next(resolver->hquerybyid, it); } } /* Destroy cached entries */ it = pj_hash_first(resolver->hrescache, &it_buf); while (it) { struct cached_res *cache; cache = (struct cached_res*) pj_hash_this(resolver->hrescache, it); pj_hash_set(NULL, resolver->hrescache, &cache->key, sizeof(cache->key), 0, NULL); pj_pool_release(cache->pool); it = pj_hash_first(resolver->hrescache, &it_buf); } if (resolver->own_timer && resolver->timer) { pj_timer_heap_destroy(resolver->timer); resolver->timer = NULL; } if (resolver->udp_key != NULL) { pj_ioqueue_unregister(resolver->udp_key); resolver->udp_key = NULL; resolver->udp_sock = PJ_INVALID_SOCKET; } else if (resolver->udp_sock != PJ_INVALID_SOCKET) { pj_sock_close(resolver->udp_sock); resolver->udp_sock = PJ_INVALID_SOCKET; } if (resolver->own_ioqueue && resolver->ioqueue) { pj_ioqueue_destroy(resolver->ioqueue); resolver->ioqueue = NULL; } if (resolver->mutex) { pj_mutex_destroy(resolver->mutex); resolver->mutex = NULL; } if (resolver->pool) { pj_pool_t *pool = resolver->pool; resolver->pool = NULL; pj_pool_release(pool); } return PJ_SUCCESS; }
Jt_Car::~Jt_Car() { pj_pool_release(_pool); }
/* Destroy TCP transport */ static pj_status_t tcp_destroy(pjsip_transport *transport, pj_status_t reason) { struct tcp_transport *tcp = (struct tcp_transport*)transport; if (tcp->close_reason == 0) tcp->close_reason = reason; if (tcp->is_registered) { tcp->is_registered = PJ_FALSE; pjsip_transport_destroy(transport); /* pjsip_transport_destroy will recursively call this function * again. */ return PJ_SUCCESS; } /* Mark transport as closing */ tcp->is_closing = PJ_TRUE; /* Stop keep-alive timer. */ if (tcp->ka_timer.id) { pjsip_endpt_cancel_timer(tcp->base.endpt, &tcp->ka_timer); tcp->ka_timer.id = PJ_FALSE; } /* Cancel all delayed transmits */ while (!pj_list_empty(&tcp->delayed_list)) { struct delayed_tdata *pending_tx; pj_ioqueue_op_key_t *op_key; pending_tx = tcp->delayed_list.next; pj_list_erase(pending_tx); op_key = (pj_ioqueue_op_key_t*)pending_tx->tdata_op_key; on_data_sent(tcp->asock, op_key, -reason); } if (tcp->rdata.tp_info.pool) { pj_pool_release(tcp->rdata.tp_info.pool); tcp->rdata.tp_info.pool = NULL; } if (tcp->asock) { pj_activesock_close(tcp->asock); tcp->asock = NULL; tcp->sock = PJ_INVALID_SOCKET; } else if (tcp->sock != PJ_INVALID_SOCKET) { pj_sock_close(tcp->sock); tcp->sock = PJ_INVALID_SOCKET; } if (tcp->base.lock) { pj_lock_destroy(tcp->base.lock); tcp->base.lock = NULL; } if (tcp->base.ref_cnt) { pj_atomic_destroy(tcp->base.ref_cnt); tcp->base.ref_cnt = NULL; } if (tcp->base.pool) { pj_pool_t *pool; if (reason != PJ_SUCCESS) { char errmsg[PJ_ERR_MSG_SIZE]; pj_strerror(reason, errmsg, sizeof(errmsg)); PJ_LOG(4,(tcp->base.obj_name, "TCP transport destroyed with reason %d: %s", reason, errmsg)); } else { PJ_LOG(4,(tcp->base.obj_name, "TCP transport destroyed normally")); } pool = tcp->base.pool; tcp->base.pool = NULL; pj_pool_release(pool); } return PJ_SUCCESS; }
/***************************************************************************** * main() */ int main(int argc, char *argv[]) { int dev_id = -1; int clock_rate = CLOCK_RATE; int channel_count = NCHANNELS; int samples_per_frame = NSAMPLES; int bits_per_sample = NBITS; pj_caching_pool cp; pjmedia_endpt *med_endpt; pj_pool_t *pool; pjmedia_conf *conf; int i, port_count, file_count; pjmedia_port **file_port; /* Array of file ports */ pjmedia_port *rec_port = NULL; /* Wav writer port */ char tmp[10]; pj_status_t status; /* Must init PJLIB first: */ status = pj_init(); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Get command line options. */ if (get_snd_options(THIS_FILE, argc, argv, &dev_id, &clock_rate, &channel_count, &samples_per_frame, &bits_per_sample)) { usage(); return 1; } /* Must create a pool factory before we can allocate any memory. */ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0); /* * Initialize media endpoint. * This will implicitly initialize PJMEDIA too. */ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Create memory pool to allocate memory */ pool = pj_pool_create( &cp.factory, /* pool factory */ "wav", /* pool name. */ 4000, /* init size */ 4000, /* increment size */ NULL /* callback on error */ ); file_count = argc - pj_optind; port_count = file_count + 1 + RECORDER; /* Create the conference bridge. * With default options (zero), the bridge will create an instance of * sound capture and playback device and connect them to slot zero. */ status = pjmedia_conf_create( pool, /* pool to use */ port_count,/* number of ports */ clock_rate, channel_count, samples_per_frame, bits_per_sample, 0, /* options */ &conf /* result */ ); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to create conference bridge", status); return 1; } #if RECORDER status = pjmedia_wav_writer_port_create( pool, "confrecord.wav", clock_rate, channel_count, samples_per_frame, bits_per_sample, 0, 0, &rec_port); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to create WAV writer", status); return 1; } pjmedia_conf_add_port(conf, pool, rec_port, NULL, NULL); #endif /* Create file ports. */ file_port = pj_pool_alloc(pool, file_count * sizeof(pjmedia_port*)); for (i=0; i<file_count; ++i) { /* Load the WAV file to file port. */ status = pjmedia_wav_player_port_create( pool, /* pool. */ argv[i+pj_optind], /* filename */ 0, /* use default ptime */ 0, /* flags */ 0, /* buf size */ &file_port[i] /* result */ ); if (status != PJ_SUCCESS) { char title[80]; pj_ansi_sprintf(title, "Unable to use %s", argv[i+pj_optind]); app_perror(THIS_FILE, title, status); usage(); return 1; } /* Add the file port to conference bridge */ status = pjmedia_conf_add_port( conf, /* The bridge */ pool, /* pool */ file_port[i], /* port to connect */ NULL, /* Use port's name */ NULL /* ptr for slot # */ ); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to add conference port", status); return 1; } } /* * All ports are set up in the conference bridge. * But at this point, no media will be flowing since no ports are * "connected". User must connect the port manually. */ /* Dump memory usage */ dump_pool_usage(THIS_FILE, &cp); /* Sleep to allow log messages to flush */ pj_thread_sleep(100); /* * UI Menu: */ for (;;) { char tmp1[10]; char tmp2[10]; char *err; int src, dst, level, dur; puts(""); conf_list(conf, 0); puts(""); puts("Menu:"); puts(" s Show ports details"); puts(" c Connect one port to another"); puts(" d Disconnect port connection"); puts(" t Adjust signal level transmitted (tx) to a port"); puts(" r Adjust signal level received (rx) from a port"); puts(" v Display VU meter for a particular port"); puts(" q Quit"); puts(""); printf("Enter selection: "); fflush(stdout); if (fgets(tmp, sizeof(tmp), stdin) == NULL) break; switch (tmp[0]) { case 's': puts(""); conf_list(conf, 1); break; case 'c': puts(""); puts("Connect source port to destination port"); if (!input("Enter source port number", tmp1, sizeof(tmp1)) ) continue; src = strtol(tmp1, &err, 10); if (*err || src < 0 || src >= port_count) { puts("Invalid slot number"); continue; } if (!input("Enter destination port number", tmp2, sizeof(tmp2)) ) continue; dst = strtol(tmp2, &err, 10); if (*err || dst < 0 || dst >= port_count) { puts("Invalid slot number"); continue; } status = pjmedia_conf_connect_port(conf, src, dst, 0); if (status != PJ_SUCCESS) app_perror(THIS_FILE, "Error connecting port", status); break; case 'd': puts(""); puts("Disconnect port connection"); if (!input("Enter source port number", tmp1, sizeof(tmp1)) ) continue; src = strtol(tmp1, &err, 10); if (*err || src < 0 || src >= port_count) { puts("Invalid slot number"); continue; } if (!input("Enter destination port number", tmp2, sizeof(tmp2)) ) continue; dst = strtol(tmp2, &err, 10); if (*err || dst < 0 || dst >= port_count) { puts("Invalid slot number"); continue; } status = pjmedia_conf_disconnect_port(conf, src, dst); if (status != PJ_SUCCESS) app_perror(THIS_FILE, "Error connecting port", status); break; case 't': puts(""); puts("Adjust transmit level of a port"); if (!input("Enter port number", tmp1, sizeof(tmp1)) ) continue; src = strtol(tmp1, &err, 10); if (*err || src < 0 || src >= port_count) { puts("Invalid slot number"); continue; } if (!input("Enter level (-128 to >127, 0 for normal)", tmp2, sizeof(tmp2)) ) continue; level = strtol(tmp2, &err, 10); if (*err || level < -128) { puts("Invalid level"); continue; } status = pjmedia_conf_adjust_tx_level( conf, src, level); if (status != PJ_SUCCESS) app_perror(THIS_FILE, "Error adjusting level", status); break; case 'r': puts(""); puts("Adjust receive level of a port"); if (!input("Enter port number", tmp1, sizeof(tmp1)) ) continue; src = strtol(tmp1, &err, 10); if (*err || src < 0 || src >= port_count) { puts("Invalid slot number"); continue; } if (!input("Enter level (-128 to >127, 0 for normal)", tmp2, sizeof(tmp2)) ) continue; level = strtol(tmp2, &err, 10); if (*err || level < -128) { puts("Invalid level"); continue; } status = pjmedia_conf_adjust_rx_level( conf, src, level); if (status != PJ_SUCCESS) app_perror(THIS_FILE, "Error adjusting level", status); break; case 'v': puts(""); puts("Display VU meter"); if (!input("Enter port number to monitor", tmp1, sizeof(tmp1)) ) continue; src = strtol(tmp1, &err, 10); if (*err || src < 0 || src >= port_count) { puts("Invalid slot number"); continue; } if (!input("Enter r for rx level or t for tx level", tmp2, sizeof(tmp2))) continue; if (tmp2[0] != 'r' && tmp2[0] != 't') { puts("Invalid option"); continue; } if (!input("Duration to monitor (in seconds)", tmp1, sizeof(tmp1)) ) continue; dur = strtol(tmp1, &err, 10); if (*err) { puts("Invalid duration number"); continue; } monitor_level(conf, src, tmp2[0], dur); break; case 'q': goto on_quit; default: printf("Invalid input character '%c'\n", tmp[0]); break; } } on_quit: /* Start deinitialization: */ /* Destroy conference bridge */ status = pjmedia_conf_destroy( conf ); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Destroy file ports */ for (i=0; i<file_count; ++i) { status = pjmedia_port_destroy( file_port[i]); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); } /* Destroy recorder port */ if (rec_port) pjmedia_port_destroy(rec_port); /* Release application pool */ pj_pool_release( pool ); /* Destroy media endpoint. */ pjmedia_endpt_destroy( med_endpt ); /* Destroy pool factory */ pj_caching_pool_destroy( &cp ); /* Shutdown PJLIB */ pj_shutdown(); /* Done. */ return 0; }
/* API: refresh the device list */ static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f) { struct bd_factory *wf = (struct bd_factory*)f; unsigned int i = 0; wchar_t *deviceNamep=NULL; wchar_t captureDevName[BD_IMAD_MAX_DEV_COUNT][BD_IMAD_MAX_DEV_LENGTH_NAME]; unsigned int captureDeviceCount = 0; wchar_t playbackDevName[BD_IMAD_MAX_DEV_COUNT][BD_IMAD_MAX_DEV_LENGTH_NAME]; unsigned int playbackDeviceCount = 0; if(wf->pool != NULL) { pj_pool_release(wf->pool); wf->pool = NULL; } // Enumerate capture sound devices while(bdIMADpj_getDeviceName(BD_IMAD_CAPTURE_DEVICES, &deviceNamep) != BD_PJ_ERROR_IMAD_DEVICE_LIST_EMPTY) { wcscpy(captureDevName[captureDeviceCount], deviceNamep); captureDeviceCount++; } // Enumerate playback sound devices while(bdIMADpj_getDeviceName(BD_IMAD_PLAYBACK_DEVICES, &deviceNamep) != BD_PJ_ERROR_IMAD_DEVICE_LIST_EMPTY) { wcscpy(playbackDevName[playbackDeviceCount], deviceNamep); playbackDeviceCount++; } // Set devices info wf->dev_count = captureDeviceCount + playbackDeviceCount; wf->pool = pj_pool_create(wf->pf, "BD_IMAD_DEVICES", 1000, 1000, NULL); wf->dev_info = (struct bddev_info*)pj_pool_calloc(wf->pool, wf->dev_count, sizeof(struct bddev_info)); // Capture device properties for(i=0;i<captureDeviceCount;i++) { wf->dev_info[i].deviceId = i; wf->dev_info[i].info.caps = PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING | PJMEDIA_AUD_DEV_CAP_EC; wf->dev_info[i].info.default_samples_per_sec = BD_IMAD_DEFAULT_FREQ; strcpy(wf->dev_info[i].info.driver, "BD_IMAD"); wf->dev_info[i].info.ext_fmt_cnt = 0; wf->dev_info[i].info.input_count = BD_IMAD_MAX_CHANNELS; wf->dev_info[i].info.output_count = 0; strcpy(wf->dev_info[i].info.name, BD_IMAD_PJ_WCHARtoCHAR(captureDevName[i])); wf->dev_info[i].info.routes = 0; } // Playback device properties for(i=0;i<playbackDeviceCount;i++) { wf->dev_info[captureDeviceCount+i].deviceId = captureDeviceCount+i; wf->dev_info[captureDeviceCount+i].info.caps = PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING; wf->dev_info[captureDeviceCount+i].info.default_samples_per_sec = BD_IMAD_DEFAULT_FREQ; strcpy(wf->dev_info[captureDeviceCount+i].info.driver, "BD_IMAD"); wf->dev_info[captureDeviceCount+i].info.ext_fmt_cnt = 0; wf->dev_info[captureDeviceCount+i].info.input_count = 0; wf->dev_info[captureDeviceCount+i].info.output_count = BD_IMAD_MAX_CHANNELS; strcpy(wf->dev_info[captureDeviceCount+i].info.name, BD_IMAD_PJ_WCHARtoCHAR(playbackDevName[i])); wf->dev_info[captureDeviceCount+i].info.routes = 0; } PJ_LOG(4, (THIS_FILE, "BDIMAD found %d devices:", wf->dev_count)); for(i=0; i<wf->dev_count; i++) { PJ_LOG(4, (THIS_FILE, " dev_id %d: %s (in=%d, out=%d)", i, wf->dev_info[i].info.name, wf->dev_info[i].info.input_count, wf->dev_info[i].info.output_count)); } return PJ_SUCCESS; }
/* * Perform unregistration test. * * This will create ioqueue and register a server socket. Depending * on the test method, either the callback or the main thread will * unregister and destroy the server socket after some period of time. */ static int perform_unreg_test(pj_ioqueue_t *ioqueue, pj_pool_t *test_pool, const char *title, pj_bool_t other_socket) { enum { WORKER_CNT = 1, MSEC = 500, QUIT_MSEC = 500 }; int i; pj_thread_t *thread[WORKER_CNT]; struct sock_data osd; pj_ioqueue_callback callback; pj_time_val end_time; pj_status_t status; /* Sometimes its important to have other sockets registered to * the ioqueue, because when no sockets are registered, the ioqueue * will return from the poll early. */ if (other_socket) { status = app_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, 56127, &osd.sock); if (status != PJ_SUCCESS) { app_perror("Error creating other socket", status); return -12; } pj_bzero(&callback, sizeof(callback)); status = pj_ioqueue_register_sock(test_pool, ioqueue, osd.sock, NULL, &callback, &osd.key); if (status != PJ_SUCCESS) { app_perror("Error registering other socket", status); return -13; } } else { osd.key = NULL; osd.sock = PJ_INVALID_SOCKET; } /* Init both time duration of testing */ thread_quitting = 0; pj_gettimeofday(&time_to_unregister); time_to_unregister.msec += MSEC; pj_time_val_normalize(&time_to_unregister); end_time = time_to_unregister; end_time.msec += QUIT_MSEC; pj_time_val_normalize(&end_time); /* Create polling thread */ for (i=0; i<WORKER_CNT; ++i) { status = pj_thread_create(test_pool, "unregtest", &worker_thread, ioqueue, 0, 0, &thread[i]); if (status != PJ_SUCCESS) { app_perror("Error creating thread", status); return -20; } } /* Create pair of client/server sockets */ status = app_socketpair(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock_data.sock, &sock_data.csock); if (status != PJ_SUCCESS) { app_perror("app_socketpair error", status); return -30; } /* Initialize test data */ sock_data.pool = pj_pool_create(mem, "sd", 1000, 1000, NULL); sock_data.buffer = (char*) pj_pool_alloc(sock_data.pool, 128); sock_data.bufsize = 128; sock_data.op_key = (pj_ioqueue_op_key_t*) pj_pool_alloc(sock_data.pool, sizeof(*sock_data.op_key)); sock_data.received = 0; sock_data.unregistered = 0; pj_ioqueue_op_key_init(sock_data.op_key, sizeof(*sock_data.op_key)); status = pj_mutex_create_simple(sock_data.pool, "sd", &sock_data.mutex); if (status != PJ_SUCCESS) { app_perror("create_mutex() error", status); return -35; } /* Register socket to ioqueue */ pj_bzero(&callback, sizeof(callback)); callback.on_read_complete = &on_read_complete; status = pj_ioqueue_register_sock(sock_data.pool, ioqueue, sock_data.sock, NULL, &callback, &sock_data.key); if (status != PJ_SUCCESS) { app_perror("pj_ioqueue_register error", status); return -40; } /* Bootstrap the first send/receive */ on_read_complete(sock_data.key, sock_data.op_key, 0); /* Loop until test time ends */ for (;;) { pj_time_val now, timeout; int n; pj_gettimeofday(&now); if (test_method == UNREGISTER_IN_APP && PJ_TIME_VAL_GTE(now, time_to_unregister) && !sock_data.unregistered) { sock_data.unregistered = 1; /* Wait (as much as possible) for callback to complete */ pj_mutex_lock(sock_data.mutex); pj_mutex_unlock(sock_data.mutex); pj_ioqueue_unregister(sock_data.key); } if (PJ_TIME_VAL_GT(now, end_time) && sock_data.unregistered) break; timeout.sec = 0; timeout.msec = 10; n = pj_ioqueue_poll(ioqueue, &timeout); if (n < 0) { app_perror("pj_ioqueue_poll error", -n); pj_thread_sleep(1); } } thread_quitting = 1; for (i=0; i<WORKER_CNT; ++i) { pj_thread_join(thread[i]); pj_thread_destroy(thread[i]); } /* Destroy data */ pj_mutex_destroy(sock_data.mutex); pj_pool_release(sock_data.pool); sock_data.pool = NULL; if (other_socket) { pj_ioqueue_unregister(osd.key); } pj_sock_close(sock_data.csock); PJ_LOG(3,(THIS_FILE, "....%s: done (%d KB/s)", title, sock_data.received * 1000 / MSEC / 1000)); return 0; }
static pj_status_t factory_create_streamBDIMAD(pjmedia_aud_dev_factory *f, const pjmedia_aud_param *param, pjmedia_aud_rec_cb rec_cb, pjmedia_aud_play_cb play_cb, void *user_data, pjmedia_aud_stream **p_aud_strm) { struct bd_factory *wf = (struct bd_factory*)f; pj_pool_t *pool; struct bd_stream *strm; pj_uint8_t silence_char; pj_status_t status; switch (param->ext_fmt.id) { case PJMEDIA_FORMAT_L16: silence_char = '\0'; break; default: return PJMEDIA_EAUD_BADFORMAT; } /* Create and Initialize stream descriptor */ pool = pj_pool_create(wf->pf, "BDIMAD_STREAM", 1000, 1000, NULL); PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); strm = PJ_POOL_ZALLOC_T(pool, struct bd_stream); pj_memcpy(&strm->param, param, sizeof(*param)); strm->pool = pool; strm->rec_cb = rec_cb; strm->play_cb = play_cb; strm->user_data = user_data; strm->fmt_id = (pjmedia_format_id)param->ext_fmt.id; strm->silence_char = silence_char; strm->channel_count = param->channel_count; strm->samples_per_frame = param->samples_per_frame; if (param->dir & PJMEDIA_DIR_CAPTURE_PLAYBACK) { status = init_streams(wf, strm, param); if (status != PJ_SUCCESS) { stream_destroyBDIMAD(&strm->base); return status; } } else { stream_destroyBDIMAD(&strm->base); return PJMEDIA_EAUD_ERR; } strm->rec_buf = (pj_int16_t*)pj_pool_alloc(pool, strm->bytes_per_frame); if (!strm->rec_buf) { pj_pool_release(pool); return PJ_ENOMEM; } strm->rec_buf_count = 0; strm->play_buf = (pj_int16_t*)pj_pool_alloc(pool, strm->bytes_per_frame); if (!strm->play_buf) { pj_pool_release(pool); return PJ_ENOMEM; } strm->play_buf_count = 0; /* Apply the remaining settings */ if(param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING) { stream_set_capBDIMAD(&strm->base, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, ¶m->output_vol); } if(param->flags & PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING) { stream_set_capBDIMAD(&strm->base, PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING, ¶m->input_vol); } if(param->flags & PJMEDIA_AUD_DEV_CAP_EC) { stream_set_capBDIMAD(&strm->base, PJMEDIA_AUD_DEV_CAP_EC, ¶m->ec_enabled); } strm->base.op = &stream_op; *p_aud_strm = &strm->base; return PJ_SUCCESS; }
/* * Create the ZRTP transport. */ PJ_DEF(pj_status_t) pjmedia_transport_zrtp_create(pjmedia_endpt *endpt, const char *name, pjmedia_transport *transport, pjmedia_transport **p_tp, pj_bool_t close_slave) { pj_pool_t *pool; struct tp_zrtp *zrtp; pj_status_t rc; if (name == NULL) name = "tzrtp%p"; /* Create the pool and initialize the adapter structure */ pool = pjmedia_endpt_create_pool(endpt, name, 5*1024, 512); zrtp = PJ_POOL_ZALLOC_T(pool, struct tp_zrtp); zrtp->pool = pool; pj_ansi_strncpy(zrtp->base.name, pool->obj_name, sizeof(zrtp->base.name)); zrtp->base.type = (pjmedia_transport_type) (PJMEDIA_TRANSPORT_TYPE_USER + 2); zrtp->base.op = &tp_zrtp_op; #ifndef DYNAMIC_TIMER if (timer_pool == NULL) { timer_pool = pjmedia_endpt_create_pool(endpt, "zrtp_timer", 256, 256); rc = timer_initialize(); if (rc != PJ_SUCCESS) { pj_pool_release(timer_pool); pj_pool_release(zrtp->pool); return rc; } } #else zrtp->timer_heap = NULL; zrtp->timer_pool = pjmedia_endpt_create_pool(endpt, "zrtp_timer", 256, 256); rc = pj_timer_heap_create(zrtp->timer_pool, 4, &zrtp->timer_heap); if (rc != PJ_SUCCESS) { pj_pool_release(zrtp->timer_pool); pj_pool_release(zrtp->pool); return rc; } #endif /* Create the empty wrapper */ zrtp->zrtpCtx = zrtp_CreateWrapper(); /* Initialize standard values */ zrtp->clientIdString = clientId; /* Set standard name */ zrtp->zrtpSeq = 1; /* TODO: randomize */ rc = pj_mutex_create_simple(zrtp->pool, "zrtp", &zrtp->zrtpMutex); zrtp->zrtpBuffer = pj_pool_zalloc(pool, MAX_ZRTP_SIZE); zrtp->sendBuffer = pj_pool_zalloc(pool, MAX_RTP_BUFFER_LEN); zrtp->sendBufferCtrl = pj_pool_zalloc(pool, MAX_RTCP_BUFFER_LEN); zrtp->slave_tp = transport; zrtp->close_slave = close_slave; zrtp->mitmMode = PJ_FALSE; /* Done */ zrtp->refcount++; *p_tp = &zrtp->base; return PJ_SUCCESS; }
/* * Testing with many handles. * This will just test registering PJ_IOQUEUE_MAX_HANDLES count * of sockets to the ioqueue. */ static int many_handles_test(pj_bool_t allow_concur) { enum { MAX = PJ_IOQUEUE_MAX_HANDLES }; pj_pool_t *pool; pj_ioqueue_t *ioqueue; pj_sock_t *sock; pj_ioqueue_key_t **key; pj_status_t rc; int count, i; /* must be signed */ PJ_LOG(3,(THIS_FILE,"...testing with so many handles")); pool = pj_pool_create(mem, NULL, 4000, 4000, NULL); if (!pool) return PJ_ENOMEM; key = (pj_ioqueue_key_t**) pj_pool_alloc(pool, MAX*sizeof(pj_ioqueue_key_t*)); sock = (pj_sock_t*) pj_pool_alloc(pool, MAX*sizeof(pj_sock_t)); /* Create IOQueue */ rc = pj_ioqueue_create(pool, MAX, &ioqueue); if (rc != PJ_SUCCESS || ioqueue == NULL) { app_perror("...error in pj_ioqueue_create", rc); return -10; } // Set concurrency rc = pj_ioqueue_set_default_concurrency(ioqueue, allow_concur); if (rc != PJ_SUCCESS) { return -11; } /* Register as many sockets. */ for (count=0; count<MAX; ++count) { sock[count] = PJ_INVALID_SOCKET; rc = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock[count]); if (rc != PJ_SUCCESS || sock[count] == PJ_INVALID_SOCKET) { PJ_LOG(3,(THIS_FILE, "....unable to create %d-th socket, rc=%d", count, rc)); break; } key[count] = NULL; rc = pj_ioqueue_register_sock(pool, ioqueue, sock[count], NULL, &test_cb, &key[count]); if (rc != PJ_SUCCESS || key[count] == NULL) { PJ_LOG(3,(THIS_FILE, "....unable to register %d-th socket, rc=%d", count, rc)); return -30; } } /* Test complete. */ /* Now deregister and close all handles. */ /* NOTE for RTEMS: * It seems that the order of close(sock) is pretty important here. * If we close the sockets with the same order as when they were created, * RTEMS doesn't seem to reuse the sockets, thus next socket created * will have descriptor higher than the last socket created. * If we close the sockets in the reverse order, then the descriptor will * get reused. * This used to cause problem with select ioqueue, since the ioqueue * always gives FD_SETSIZE for the first select() argument. This ioqueue * behavior can be changed with setting PJ_SELECT_NEEDS_NFDS macro. */ for (i=count-1; i>=0; --i) { ///for (i=0; i<count; ++i) { rc = pj_ioqueue_unregister(key[i]); if (rc != PJ_SUCCESS) { app_perror("...error in pj_ioqueue_unregister", rc); } } rc = pj_ioqueue_destroy(ioqueue); if (rc != PJ_SUCCESS) { app_perror("...error in pj_ioqueue_destroy", rc); } pj_pool_release(pool); PJ_LOG(3,(THIS_FILE,"....many_handles_test() ok")); return 0; }