static BOOL OnInitStack (void) { pjsua_config cfg; pjsua_logging_config log_cfg; pjsua_media_config media_cfg; pjsua_transport_config udp_cfg; pjsua_transport_config rtp_cfg; pjsua_transport_id transport_id; pjsua_transport_info transport_info; pj_str_t tmp; pj_status_t status; /* Create pjsua */ status = pjsua_create(); if (status != PJ_SUCCESS) { OnError (TEXT ("Error creating pjsua"), status); return FALSE; } /* Create global pool for application */ g_pool = pjsua_pool_create ("pjsua", 4000, 4000); /* Init configs */ pjsua_config_default (&cfg); pjsua_media_config_default (&media_cfg); pjsua_transport_config_default (&udp_cfg); udp_cfg.port = SIP_PORT; pjsua_transport_config_default (&rtp_cfg); rtp_cfg.port = 40000; pjsua_logging_config_default (&log_cfg); log_cfg.level = 5; log_cfg.log_filename = pj_str ("\\pjsua.txt"); log_cfg.msg_logging = 1; log_cfg.decor = pj_log_get_decor() | PJ_LOG_HAS_CR; /* Setup media */ media_cfg.clock_rate = 8000; media_cfg.ec_options = PJMEDIA_ECHO_SIMPLE; media_cfg.ec_tail_len = 256; // use default quality setting //media_cfg.quality = 1; media_cfg.ptime = 20; media_cfg.enable_ice = USE_ICE; /* Initialize application callbacks */ cfg.cb.on_call_state = &on_call_state; cfg.cb.on_call_media_state = &on_call_media_state; cfg.cb.on_incoming_call = &on_incoming_call; cfg.cb.on_reg_state = &on_reg_state; cfg.cb.on_buddy_state = &on_buddy_state; cfg.cb.on_pager = &on_pager; cfg.cb.on_typing = &on_typing; cfg.cb.on_nat_detect = &nat_detect_cb; if (SIP_PROXY) { cfg.outbound_proxy_cnt = 1; cfg.outbound_proxy[0] = pj_str (SIP_PROXY); } if (NAMESERVER) { cfg.nameserver_count = 1; cfg.nameserver[0] = pj_str (NAMESERVER); } if (NAMESERVER && STUN_DOMAIN) { cfg.stun_domain = pj_str (STUN_DOMAIN); } else if (STUN_SERVER) { cfg.stun_host = pj_str (STUN_SERVER); } /* Initialize pjsua */ status = pjsua_init (&cfg, &log_cfg, &media_cfg); if (status != PJ_SUCCESS) { OnError (TEXT ("Initialization error"), status); return FALSE; } /* Set codec priority */ pjsua_codec_set_priority (pj_cstr (&tmp, "pcmu"), 240); pjsua_codec_set_priority (pj_cstr (&tmp, "pcma"), 230); pjsua_codec_set_priority (pj_cstr (&tmp, "speex/8000"), 190); pjsua_codec_set_priority (pj_cstr (&tmp, "ilbc"), 189); pjsua_codec_set_priority (pj_cstr (&tmp, "speex/16000"), 180); pjsua_codec_set_priority (pj_cstr (&tmp, "speex/32000"), 0); pjsua_codec_set_priority (pj_cstr (&tmp, "gsm"), 100); /* Add UDP transport and the corresponding PJSUA account */ status = pjsua_transport_create (PJSIP_TRANSPORT_UDP, &udp_cfg, &transport_id); if (status != PJ_SUCCESS) { OnError (TEXT ("Error starting SIP transport"), status); return FALSE; } pjsua_transport_get_info (transport_id, &transport_info); g_local_uri.ptr = (char*) pj_pool_alloc (g_pool, 128); g_local_uri.slen = pj_ansi_sprintf (g_local_uri.ptr, "<sip:%.*s:%d>", (int) transport_info.local_name.host.slen, transport_info.local_name.host.ptr, transport_info.local_name.port); /* Add local account */ pjsua_acc_add_local (transport_id, PJ_TRUE, &g_current_acc); pjsua_acc_set_online_status (g_current_acc, PJ_TRUE); /* Add account */ if (HAS_SIP_ACCOUNT) { pjsua_acc_config cfg; pjsua_acc_config_default (&cfg); cfg.id = pj_str ("sip:" SIP_USER "@" SIP_DOMAIN); cfg.reg_uri = pj_str ("sip:" SIP_DOMAIN); cfg.cred_count = 1; cfg.cred_info[0].realm = pj_str (SIP_REALM); cfg.cred_info[0].scheme = pj_str ("digest"); cfg.cred_info[0].username = pj_str (SIP_USER); cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD; cfg.cred_info[0].data = pj_str (SIP_PASSWD); status = pjsua_acc_add (&cfg, PJ_TRUE, &g_current_acc); if (status != PJ_SUCCESS) { pjsua_destroy(); return PJ_FALSE; } } /* Add buddy */ if (SIP_DST_URI) { pjsua_buddy_config bcfg; pjsua_buddy_config_default (&bcfg); bcfg.uri = pj_str (SIP_DST_URI); bcfg.subscribe = PJ_FALSE; pjsua_buddy_add (&bcfg, NULL); } /* Start pjsua */ status = pjsua_start(); if (status != PJ_SUCCESS) { OnError (TEXT ("Error starting pjsua"), status); return FALSE; } return TRUE; }
static char* print_binary(const pj_uint8_t *data, unsigned data_len) { static char buf[1500]; unsigned length = sizeof(buf); char *p = buf; unsigned i; for (i=0; i<data_len;) { unsigned j; pj_ansi_snprintf(p, 1500-(p-buf), "%04d-%04d ", i, (i+20 < data_len) ? i+20 : data_len); p += 12; for (j=0; j<20 && i<data_len && p<(buf+length-10); ++j, ++i) { pj_ansi_sprintf(p, "%02x ", (*data) & 0xFF); p += 3; data++; } pj_ansi_sprintf(p, "\n"); p++; } return buf; }
/* Allocate memory from the pool */ PJ_DEF(void*) pj_pool_alloc_imp( const char *file, int line, pj_pool_t *pool, pj_size_t sz) { struct pj_pool_mem *mem; PJ_UNUSED_ARG(file); PJ_UNUSED_ARG(line); mem = malloc(sz + sizeof(struct pj_pool_mem)); if (!mem) { if (pool->cb) (*pool->cb)(pool, sz); return NULL; } mem->next = pool->first_mem; pool->first_mem = mem; #ifdef TRACE_ { char msg[120]; pj_ansi_sprintf(msg, "Mem %X (%d+%d bytes) allocated by %s:%d\r\n", mem, sz, sizeof(struct pj_pool_mem), file, line); TRACE_(msg); } #endif return ((char*)mem) + sizeof(struct pj_pool_mem); }
static const char *good_number(char *buf, pj_int32_t val) { if (val < 1000) { pj_ansi_sprintf(buf, "%d", val); } else if (val < 1000000) { pj_ansi_sprintf(buf, "%d.%dK", val / 1000, (val % 1000) / 100); } else { pj_ansi_sprintf(buf, "%d.%02dM", val / 1000000, (val % 1000000) / 10000); } return buf; }
int tsx_basic_test(struct tsx_test_param *param) { int status; pj_ansi_sprintf(TARGET_URI, "sip:[email protected]:%d;transport=%s", param->port, param->tp_type); pj_ansi_sprintf(FROM_URI, "sip:[email protected]:%d;transport=%s", param->port, param->tp_type); status = tsx_layer_test(); if (status != 0) return status; status = double_terminate(); if (status != 0) return status; return 0; }
static void close_report(void) { pj_ssize_t len; if (fd_report) { len = pj_ansi_sprintf(buf, "</TABLE>\n</BODY>\n</HTML>\n"); pj_file_write(fd_report, buf, &len); pj_file_close(fd_report); } }
void report_sval(const char *name, const char* value, const char *valname, const char *desc) { pj_ssize_t len; len = pj_ansi_sprintf(buf, " <TR><TD><TT>%s</TT></TD>\n" " <TD align=\"right\"><B>%s %s</B></TD>\n" " <TD>%s</TD>\n" " </TR>\n", name, value, valname, desc); pj_file_write(fd_report, buf, &len); }
static int print_binary(char *buffer, unsigned length, const pj_uint8_t *data, unsigned data_len) { unsigned i; if (length < data_len * 2 + 8) return -1; pj_ansi_sprintf(buffer, ", data="); buffer += 7; for (i=0; i<data_len; ++i) { pj_ansi_sprintf(buffer, "%02x", (*data) & 0xFF); buffer += 2; data++; } pj_ansi_sprintf(buffer, "\n"); buffer++; return data_len * 2 + 8; }
pj_status_t gui_start(gui_menu *menu) { while (!console_quit) { unsigned i; char input[10], *p; gui_menu *choice; puts("M E N U :"); puts("---------"); for (i=0; i<menu->submenu_cnt; ++i) { char menu_id[4]; pj_ansi_sprintf(menu_id, "%u", i); print_menu("", menu_id, menu->submenus[i]); } puts(""); printf("Enter the menu number: "); if (!fgets(input, sizeof(input), stdin)) break; p = input; choice = menu; while (*p && *p!='\r' && *p!='\n') { unsigned d = (*p - '0'); if (d < 0 || d >= choice->submenu_cnt) { puts("Invalid selection"); choice = NULL; break; } choice = choice->submenus[d]; ++p; } if (choice && *p!='\r' && *p!='\n') { puts("Invalid characters entered"); continue; } if (choice && choice->handler) (*choice->handler)(); } return PJ_SUCCESS; }
/* Check if command already added to command hash */ static pj_bool_t cmd_name_exists(pj_cli_t *cli, pj_cli_cmd_spec *group, pj_str_t *cmd) { pj_str_t cmd_val; char cmd_ptr[64]; cmd_val.ptr = &cmd_ptr[0]; cmd_val.slen = 0; if (group) { char cmd_str[16]; pj_ansi_sprintf(&cmd_str[0], "%d", group->id); pj_strcat2(&cmd_val, &cmd_str[0]); } pj_strcat(&cmd_val, cmd); return (pj_hash_get(cli->cmd_name_hash, cmd_val.ptr, cmd_val.slen, NULL) != 0); }
/* Get the command from the command hash */ static pj_cli_cmd_spec *get_cmd_name(const pj_cli_t *cli, const pj_cli_cmd_spec *group, const pj_str_t *cmd) { pj_str_t cmd_val; char cmd_ptr[MAX_CMD_HASH_NAME_LENGTH]; cmd_val.ptr = cmd_ptr; cmd_val.slen = 0; if (group) { char cmd_str[MAX_CMD_ID_LENGTH]; pj_ansi_sprintf(cmd_str, "%d", group->id); pj_strcat2(&cmd_val, cmd_str); } pj_strcat(&cmd_val, cmd); return (pj_cli_cmd_spec *)pj_hash_get(cli->cmd_name_hash, cmd_val.ptr, (unsigned)cmd_val.slen, NULL); }
static void print_menu(const char *indent, char *menu_id, gui_menu *menu) { char child_indent[16]; unsigned i; pj_ansi_snprintf(child_indent, sizeof(child_indent), "%s ", indent); printf("%s%s: %s\n", indent, menu_id, menu->title); for (i=0; i<menu->submenu_cnt; ++i) { char child_id[10]; pj_ansi_sprintf(child_id, "%s%u", menu_id, i); if (!menu->submenus[i]) puts(""); else print_menu(child_indent, child_id, menu->submenus[i]); } }
/* Add command to the command hash */ static void add_cmd_name(pj_cli_t *cli, pj_cli_cmd_spec *group, pj_cli_cmd_spec *cmd, pj_str_t *cmd_name) { pj_str_t cmd_val; pj_str_t add_cmd; char cmd_ptr[MAX_CMD_HASH_NAME_LENGTH]; cmd_val.ptr = cmd_ptr; cmd_val.slen = 0; if (group) { char cmd_str[MAX_CMD_ID_LENGTH]; pj_ansi_sprintf(cmd_str, "%d", group->id); pj_strcat2(&cmd_val, cmd_str); } pj_strcat(&cmd_val, cmd_name); pj_strdup(cli->pool, &add_cmd, &cmd_val); pj_hash_set(cli->pool, cli->cmd_name_hash, cmd_val.ptr, (unsigned)cmd_val.slen, 0, cmd); }
static void on_send_data(pj_http_req *hreq, void **data, pj_size_t *size) { char *sdata; pj_size_t sendsz = 8397; PJ_UNUSED_ARG(hreq); if (send_size + sendsz > total_size) { sendsz = total_size - send_size; } send_size += sendsz; sdata = (char*)pj_pool_alloc(pool, sendsz); pj_create_random_string(sdata, sendsz); pj_ansi_sprintf(sdata, "\nSegment #%d\n", ++counter); *data = sdata; *size = sendsz; PJ_LOG(5, (THIS_FILE, "\nSending data progress: %d out of %d bytes", send_size, total_size)); }
/* Set default config. */ static void default_config(struct app_config *cfg) { char tmp[80]; unsigned i; pjsua_config_default(&cfg->cfg); pj_ansi_sprintf(tmp, "Sipek on PJSUA v%s/%s", pj_get_version(), PJ_OS_NAME); pj_strdup2_with_null(app_config.pool, &cfg->cfg.user_agent, tmp); pjsua_logging_config_default(&cfg->log_cfg); pjsua_media_config_default(&cfg->media_cfg); pjsua_transport_config_default(&cfg->udp_cfg); cfg->udp_cfg.port = 5060; pjsua_transport_config_default(&cfg->rtp_cfg); cfg->rtp_cfg.port = 4000; cfg->duration = NO_LIMIT; cfg->wav_id = PJSUA_INVALID_ID; cfg->rec_id = PJSUA_INVALID_ID; cfg->wav_port = PJSUA_INVALID_ID; cfg->rec_port = PJSUA_INVALID_ID; cfg->mic_level = cfg->speaker_level = 1.0; cfg->capture_dev = PJSUA_INVALID_ID; cfg->playback_dev = PJSUA_INVALID_ID; cfg->capture_lat = PJMEDIA_SND_DEFAULT_REC_LATENCY; cfg->playback_lat = PJMEDIA_SND_DEFAULT_PLAY_LATENCY; cfg->ringback_slot = PJSUA_INVALID_ID; cfg->ring_slot = PJSUA_INVALID_ID; for (i=0; i<PJ_ARRAY_SIZE(cfg->acc_cfg); ++i) pjsua_acc_config_default(&cfg->acc_cfg[i]); for (i=0; i<PJ_ARRAY_SIZE(cfg->buddy_cfg); ++i) pjsua_buddy_config_default(&cfg->buddy_cfg[i]); cfg->log_cfg.log_filename = pj_str("pjsip.log"); }
/* * List the ports in conference bridge */ static void conf_list(pjmedia_conf *conf, int detail) { enum { MAX_PORTS = 32 }; unsigned i, count; pjmedia_conf_port_info info[MAX_PORTS]; printf("Conference ports:\n"); count = PJ_ARRAY_SIZE(info); pjmedia_conf_get_ports_info(conf, &count, info); for (i=0; i<count; ++i) { char txlist[4*MAX_PORTS]; unsigned j; pjmedia_conf_port_info *port_info = &info[i]; txlist[0] = '\0'; for (j=0; j<port_info->listener_cnt; ++j) { char s[10]; pj_ansi_sprintf(s, "#%d ", port_info->listener_slots[j]); pj_ansi_strcat(txlist, s); } if (txlist[0] == '\0') { txlist[0] = '-'; txlist[1] = '\0'; } if (!detail) { printf("Port #%02d %-25.*s transmitting to: %s\n", port_info->slot, (int)port_info->name.slen, port_info->name.ptr, txlist); } else { unsigned tx_level, rx_level; pjmedia_conf_get_signal_level(conf, port_info->slot, &tx_level, &rx_level); printf("Port #%02d:\n" " Name : %.*s\n" " Sampling rate : %d Hz\n" " Samples per frame : %d\n" " Frame time : %d ms\n" " Signal level adjustment : tx=%d, rx=%d\n" " Current signal level : tx=%u, rx=%u\n" " Transmitting to ports : %s\n\n", port_info->slot, (int)port_info->name.slen, port_info->name.ptr, port_info->clock_rate, port_info->samples_per_frame, port_info->samples_per_frame*1000/port_info->clock_rate, port_info->tx_adj_level, port_info->rx_adj_level, tx_level, rx_level, txlist); } } puts(""); }
static pj_bool_t on_rx_request( pjsip_rx_data *rdata ) { pj_sockaddr hostaddr; char temp[80], hostip[PJ_INET6_ADDRSTRLEN]; pj_str_t local_uri; pjsip_dialog *dlg; pjsip_rdata_sdp_info *sdp_info; pjmedia_sdp_session *answer = NULL; pjsip_tx_data *tdata = NULL; call_t *call = NULL; unsigned i; pj_status_t status; PJ_LOG(3,(THIS_FILE, "RX %.*s from %s", (int)rdata->msg_info.msg->line.req.method.name.slen, rdata->msg_info.msg->line.req.method.name.ptr, rdata->pkt_info.src_name)); if (rdata->msg_info.msg->line.req.method.id == PJSIP_REGISTER_METHOD) { /* Let me be a registrar! */ pjsip_hdr hdr_list, *h; pjsip_msg *msg; int expires = -1; pj_list_init(&hdr_list); msg = rdata->msg_info.msg; h = (pjsip_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_EXPIRES, NULL); if (h) { expires = ((pjsip_expires_hdr*)h)->ivalue; pj_list_push_back(&hdr_list, pjsip_hdr_clone(rdata->tp_info.pool, h)); PJ_LOG(3,(THIS_FILE, " Expires=%d", expires)); } if (expires != 0) { h = (pjsip_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_CONTACT, NULL); if (h) pj_list_push_back(&hdr_list, pjsip_hdr_clone(rdata->tp_info.pool, h)); } pjsip_endpt_respond(app.sip_endpt, &mod_sipecho, rdata, 200, NULL, &hdr_list, NULL, NULL); return PJ_TRUE; } if (rdata->msg_info.msg->line.req.method.id != PJSIP_INVITE_METHOD) { if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) { pj_str_t reason = pj_str("Go away"); pjsip_endpt_respond_stateless( app.sip_endpt, rdata, 400, &reason, NULL, NULL); } return PJ_TRUE; } sdp_info = pjsip_rdata_get_sdp_info(rdata); if (!sdp_info || !sdp_info->sdp) { pj_str_t reason = pj_str("Require valid offer"); pjsip_endpt_respond_stateless( app.sip_endpt, rdata, 400, &reason, NULL, NULL); } for (i=0; i<MAX_CALLS; ++i) { if (app.call[i].inv == NULL) { call = &app.call[i]; break; } } if (i==MAX_CALLS) { pj_str_t reason = pj_str("We're full"); pjsip_endpt_respond_stateless( app.sip_endpt, rdata, PJSIP_SC_BUSY_HERE, &reason, NULL, NULL); return PJ_TRUE; } /* Generate Contact URI */ status = pj_gethostip(AF, &hostaddr); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to retrieve local host IP", status); return PJ_TRUE; } pj_sockaddr_print(&hostaddr, hostip, sizeof(hostip), 2); pj_ansi_sprintf(temp, "<sip:sipecho@%s:%d>", hostip, SIP_PORT); local_uri = pj_str(temp); status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata, &local_uri, &dlg); if (status == PJ_SUCCESS) answer = create_answer(call-app.call, dlg->pool, sdp_info->sdp); if (status == PJ_SUCCESS) status = pjsip_inv_create_uas( dlg, rdata, answer, 0, &call->inv); if (status == PJ_SUCCESS) status = pjsip_inv_initial_answer(call->inv, rdata, 100, NULL, NULL, &tdata); if (status == PJ_SUCCESS) status = pjsip_inv_send_msg(call->inv, tdata); if (status == PJ_SUCCESS) status = pjsip_inv_answer(call->inv, 180, NULL, NULL, &tdata); if (status == PJ_SUCCESS) status = pjsip_inv_send_msg(call->inv, tdata); if (status == PJ_SUCCESS) status = pjsip_inv_answer(call->inv, 200, NULL, NULL, &tdata); if (status == PJ_SUCCESS) status = pjsip_inv_send_msg(call->inv, tdata); if (status != PJ_SUCCESS) { pjsip_endpt_respond_stateless( app.sip_endpt, rdata, 500, NULL, NULL, NULL); destroy_call(call); } else { call->inv->mod_data[mod_sipecho.id] = call; } return PJ_TRUE; }
static int server_thread(void *p) { struct server_t *srv = (struct server_t*)p; char *pkt = (char*)pj_pool_alloc(pool, srv->buf_size); pj_sock_t newsock = PJ_INVALID_SOCKET; while (!thread_quit) { pj_ssize_t pkt_len; int rc; pj_fd_set_t rset; pj_time_val timeout = {0, 500}; while (!thread_quit) { PJ_FD_ZERO(&rset); PJ_FD_SET(srv->sock, &rset); rc = pj_sock_select((int)srv->sock+1, &rset, NULL, NULL, &timeout); if (rc != 1) { continue; } rc = pj_sock_accept(srv->sock, &newsock, NULL, NULL); if (rc == PJ_SUCCESS) { break; } } if (thread_quit) break; while (!thread_quit) { PJ_FD_ZERO(&rset); PJ_FD_SET(newsock, &rset); rc = pj_sock_select((int)newsock+1, &rset, NULL, NULL, &timeout); if (rc != 1) { PJ_LOG(3,("http test", "client timeout")); continue; } pkt_len = srv->buf_size; rc = pj_sock_recv(newsock, pkt, &pkt_len, 0); if (rc == PJ_SUCCESS) { break; } } if (thread_quit) break; /* Simulate network RTT */ pj_thread_sleep(50); if (srv->action == ACTION_IGNORE) { continue; } else if (srv->action == ACTION_REPLY) { pj_size_t send_size = 0; unsigned ctr = 0; pj_ansi_sprintf(pkt, "HTTP/1.0 200 OK\r\n"); if (srv->send_content_length) { pj_ansi_sprintf(pkt + pj_ansi_strlen(pkt), "Content-Length: %d\r\n", srv->data_size); } pj_ansi_sprintf(pkt + pj_ansi_strlen(pkt), "\r\n"); pkt_len = pj_ansi_strlen(pkt); rc = pj_sock_send(newsock, pkt, &pkt_len, 0); if (rc != PJ_SUCCESS) { pj_sock_close(newsock); continue; } while (send_size < srv->data_size) { pkt_len = srv->data_size - send_size; if (pkt_len > (signed)srv->buf_size) pkt_len = srv->buf_size; send_size += pkt_len; pj_create_random_string(pkt, pkt_len); pj_ansi_sprintf(pkt, "\nPacket: %d", ++ctr); pkt[pj_ansi_strlen(pkt)] = '\n'; rc = pj_sock_send(newsock, pkt, &pkt_len, 0); if (rc != PJ_SUCCESS) break; } pj_sock_close(newsock); } } return 0; }
int uri_test(void) { enum { COUNT = 1, DETECT=0, PARSE=1, PRINT=2 }; struct { unsigned parse; unsigned print; unsigned cmp; } run[COUNT]; unsigned i, max; pj_ssize_t avg_len; char desc[200]; pj_status_t status; status = simple_uri_test(); if (status != PJ_SUCCESS) return status; #if INCLUDE_BENCHMARKS for (i=0; i<COUNT; ++i) { PJ_LOG(3,(THIS_FILE, " benchmarking (%d of %d)...", i+1, COUNT)); status = uri_benchmark(&run[i].parse, &run[i].print, &run[i].cmp); if (status != PJ_SUCCESS) return status; } /* Calculate average URI length */ for (i=0, avg_len=0; i<PJ_ARRAY_SIZE(uri_test_array); ++i) { avg_len += uri_test_array[i].len; } avg_len /= PJ_ARRAY_SIZE(uri_test_array); /* * Print maximum parse/sec */ for (i=0, max=0; i<COUNT; ++i) if (run[i].parse > max) max = run[i].parse; PJ_LOG(3,("", " Maximum URI parse/sec=%u", max)); pj_ansi_sprintf(desc, "Number of SIP/TEL URIs that can be <B>parsed</B> with " "<tt>pjsip_parse_uri()</tt> per second " "(tested with %d URI set, with average length of " "%d chars)", (int)PJ_ARRAY_SIZE(uri_test_array), (int)avg_len); report_ival("uri-parse-per-sec", max, "URI/sec", desc); /* URI parsing bandwidth */ report_ival("uri-parse-bandwidth-mb", (int)avg_len*max/1000000, "MB/sec", "URI parsing bandwidth in megabytes (number of megabytes " "worth of URI that can be parsed per second)"); /* Print maximum print/sec */ for (i=0, max=0; i<COUNT; ++i) if (run[i].print > max) max = run[i].print; PJ_LOG(3,("", " Maximum URI print/sec=%u", max)); pj_ansi_sprintf(desc, "Number of SIP/TEL URIs that can be <B>printed</B> with " "<tt>pjsip_uri_print()</tt> per second " "(tested with %d URI set, with average length of " "%d chars)", (int)PJ_ARRAY_SIZE(uri_test_array), (int)avg_len); report_ival("uri-print-per-sec", max, "URI/sec", desc); /* Print maximum detect/sec */ for (i=0, max=0; i<COUNT; ++i) if (run[i].cmp > max) max = run[i].cmp; PJ_LOG(3,("", " Maximum URI comparison/sec=%u", max)); pj_ansi_sprintf(desc, "Number of SIP/TEL URIs that can be <B>compared</B> with " "<tt>pjsip_uri_cmp()</tt> per second " "(tested with %d URI set, with average length of " "%d chars)", (int)PJ_ARRAY_SIZE(uri_test_array), (int)avg_len); report_ival("uri-cmp-per-sec", max, "URI/sec", desc); #endif /* INCLUDE_BENCHMARKS */ return PJ_SUCCESS; }
static int uas_tsx_bench(unsigned working_set, pj_timestamp *p_elapsed) { unsigned i; pjsip_tx_data *request; pjsip_via_hdr *via; pjsip_rx_data rdata; pj_sockaddr_in remote; pjsip_transaction **tsx; pj_timestamp t1, t2, elapsed; char branch_buf[80] = PJSIP_RFC3261_BRANCH_ID "0000000000"; pj_status_t status; /* Create the request first. */ pj_str_t str_target = pj_str("sip:[email protected]"); pj_str_t str_from = pj_str("\"Local User\" <sip:[email protected]>"); pj_str_t str_to = pj_str("\"Remote User\" <sip:[email protected]>"); pj_str_t str_contact = str_from; status = pjsip_endpt_create_request(endpt, &pjsip_invite_method, &str_target, &str_from, &str_to, &str_contact, NULL, -1, NULL, &request); if (status != PJ_SUCCESS) { app_perror(" error: unable to create request", status); return status; } /* Create Via */ via = pjsip_via_hdr_create(request->pool); via->sent_by.host = pj_str("192.168.0.7"); via->sent_by.port = 5061; via->transport = pj_str("udp"); via->rport_param = 1; via->recvd_param = pj_str("192.168.0.7"); pjsip_msg_insert_first_hdr(request->msg, (pjsip_hdr*)via); /* Create "dummy" rdata from the tdata */ pj_bzero(&rdata, sizeof(pjsip_rx_data)); rdata.tp_info.pool = request->pool; rdata.msg_info.msg = request->msg; rdata.msg_info.from = (pjsip_from_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_FROM, NULL); rdata.msg_info.to = (pjsip_to_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_TO, NULL); rdata.msg_info.cseq = (pjsip_cseq_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_CSEQ, NULL); rdata.msg_info.cid = (pjsip_cid_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_FROM, NULL); rdata.msg_info.via = via; pj_sockaddr_in_init(&remote, 0, 0); status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM, &remote, sizeof(pj_sockaddr_in), NULL, &rdata.tp_info.transport); if (status != PJ_SUCCESS) { app_perror(" error: unable to get loop transport", status); return status; } /* Create transaction array */ tsx = (pjsip_transaction**) pj_pool_zalloc(request->pool, working_set * sizeof(pj_pool_t*)); pj_bzero(&mod_tsx_user, sizeof(mod_tsx_user)); mod_tsx_user.id = -1; /* Benchmark */ elapsed.u64 = 0; pj_get_timestamp(&t1); for (i=0; i<working_set; ++i) { via->branch_param.ptr = branch_buf; via->branch_param.slen = PJSIP_RFC3261_BRANCH_LEN + pj_ansi_sprintf(branch_buf+PJSIP_RFC3261_BRANCH_LEN, "-%d", i); status = pjsip_tsx_create_uas(&mod_tsx_user, &rdata, &tsx[i]); if (status != PJ_SUCCESS) goto on_error; } pj_get_timestamp(&t2); pj_sub_timestamp(&t2, &t1); pj_add_timestamp(&elapsed, &t2); p_elapsed->u64 = elapsed.u64; status = PJ_SUCCESS; on_error: for (i=0; i<working_set; ++i) { if (tsx[i]) { pjsip_tsx_terminate(tsx[i], 601); tsx[i] = NULL; } } pjsip_tx_data_dec_ref(request); flush_events(2000); return status; }
/* * PUT request scenario 1: sending the whole data at once */ int http_client_test_put1() { pj_str_t url; pj_http_req_callback hcb; pj_http_req_param param; char *data; int length = 3875; char urlbuf[80]; pj_bzero(&hcb, sizeof(hcb)); hcb.on_complete = &on_complete; hcb.on_data_read = &on_data_read; 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 -51; if (pj_ioqueue_create(pool, 16, &ioqueue)) return -52; #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 = 4096; 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/test.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/test.txt"); #endif pj_http_req_param_default(¶m); pj_strset2(¶m.method, (char*)"PUT"); data = (char*)pj_pool_alloc(pool, length); pj_create_random_string(data, length); pj_ansi_sprintf(data, "PUT test\n"); param.reqdata.data = data; param.reqdata.size = length; if (pj_http_req_create(pool, &url, timer_heap, ioqueue, ¶m, &hcb, &http_req)) return -53; if (pj_http_req_start(http_req)) return -55; 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; }
/* * main() * * If called with argument, treat argument as SIP URL to be called. * Otherwise wait for incoming calls. */ int main(int argc, char *argv[]) { pj_pool_t *pool = NULL; pj_status_t status; unsigned i; /* Must init PJLIB first: */ status = pj_init(); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); pj_log_set_level(5); /* Then init PJLIB-UTIL: */ status = pjlib_util_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); /* Create global endpoint: */ { const pj_str_t *hostname; const char *endpt_name; /* Endpoint MUST be assigned a globally unique name. * The name will be used as the hostname in Warning header. */ /* For this implementation, we'll use hostname for simplicity */ hostname = pj_gethostname(); endpt_name = hostname->ptr; /* Create the endpoint: */ status = pjsip_endpt_create(&cp.factory, endpt_name, &g_endpt); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); } /* * Add UDP transport, with hard-coded port * Alternatively, application can use pjsip_udp_transport_attach() to * start UDP transport, if it already has an UDP socket (e.g. after it * resolves the address with STUN). */ { pj_sockaddr addr; pj_sockaddr_init(AF, &addr, NULL, (pj_uint16_t)SIP_PORT); if (AF == pj_AF_INET()) { status = pjsip_udp_transport_start( g_endpt, &addr.ipv4, NULL, 1, NULL); } else if (AF == pj_AF_INET6()) { status = pjsip_udp_transport_start6(g_endpt, &addr.ipv6, NULL, 1, NULL); } else { status = PJ_EAFNOTSUP; } if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to start UDP transport", status); return 1; } } /* * Init transaction layer. * This will create/initialize transaction hash tables etc. */ status = pjsip_tsx_layer_init_module(g_endpt); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* * Initialize UA layer module. * This will create/initialize dialog hash tables etc. */ status = pjsip_ua_init_module( g_endpt, NULL ); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* * Init invite session module. * The invite session module initialization takes additional argument, * i.e. a structure containing callbacks to be called on specific * occurence of events. * * The on_state_changed and on_new_session callbacks are mandatory. * Application must supply the callback function. * * We use on_media_update() callback in this application to start * media transmission. */ { pjsip_inv_callback inv_cb; /* Init the callback for INVITE session: */ pj_bzero(&inv_cb, sizeof(inv_cb)); inv_cb.on_state_changed = &call_on_state_changed; inv_cb.on_new_session = &call_on_forked; inv_cb.on_media_update = &call_on_media_update; /* Initialize invite session module: */ status = pjsip_inv_usage_init(g_endpt, &inv_cb); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); } /* Initialize 100rel support */ status = pjsip_100rel_init_module(g_endpt); PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); /* * Register our module to receive incoming requests. */ status = pjsip_endpt_register_module( g_endpt, &mod_simpleua); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* * Register message logger module. */ status = pjsip_endpt_register_module( g_endpt, &msg_logger); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* * Initialize media endpoint. * This will implicitly initialize PJMEDIA too. */ #if PJ_HAS_THREADS status = pjmedia_endpt_create(&cp.factory, NULL, 1, &g_med_endpt); #else status = pjmedia_endpt_create(&cp.factory, pjsip_endpt_get_ioqueue(g_endpt), 0, &g_med_endpt); #endif PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* * Add PCMA/PCMU codec to the media endpoint. */ #if defined(PJMEDIA_HAS_G711_CODEC) && PJMEDIA_HAS_G711_CODEC!=0 status = pjmedia_codec_g711_init(g_med_endpt); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); #endif #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) /* Init video subsystem */ pool = pjmedia_endpt_create_pool(g_med_endpt, "Video subsystem", 512, 512); status = pjmedia_video_format_mgr_create(pool, 64, 0, NULL); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); status = pjmedia_converter_mgr_create(pool, NULL); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); status = pjmedia_vid_codec_mgr_create(pool, NULL); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); status = pjmedia_vid_dev_subsys_init(&cp.factory); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); # if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC!=0 /* Init ffmpeg video codecs */ status = pjmedia_codec_ffmpeg_vid_init(NULL, &cp.factory); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); # endif /* PJMEDIA_HAS_FFMPEG_VID_CODEC */ #endif /* PJMEDIA_HAS_VIDEO */ /* * Create media transport used to send/receive RTP/RTCP socket. * One media transport is needed for each call. Application may * opt to re-use the same media transport for subsequent calls. */ for (i = 0; i < PJ_ARRAY_SIZE(g_med_transport); ++i) { status = pjmedia_transport_udp_create3(g_med_endpt, AF, NULL, NULL, RTP_PORT + i*2, 0, &g_med_transport[i]); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to create media transport", status); return 1; } /* * Get socket info (address, port) of the media transport. We will * need this info to create SDP (i.e. the address and port info in * the SDP). */ pjmedia_transport_info_init(&g_med_tpinfo[i]); pjmedia_transport_get_info(g_med_transport[i], &g_med_tpinfo[i]); pj_memcpy(&g_sock_info[i], &g_med_tpinfo[i].sock_info, sizeof(pjmedia_sock_info)); } /* * If URL is specified, then make call immediately. */ if (argc > 1) { pj_sockaddr hostaddr; char hostip[PJ_INET6_ADDRSTRLEN+2]; char temp[80]; pj_str_t dst_uri = pj_str(argv[1]); pj_str_t local_uri; pjsip_dialog *dlg; pjmedia_sdp_session *local_sdp; pjsip_tx_data *tdata; if (pj_gethostip(AF, &hostaddr) != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to retrieve local host IP", status); return 1; } pj_sockaddr_print(&hostaddr, hostip, sizeof(hostip), 2); pj_ansi_sprintf(temp, "<sip:simpleuac@%s:%d>", hostip, SIP_PORT); local_uri = pj_str(temp); /* Create UAC dialog */ status = pjsip_dlg_create_uac( pjsip_ua_instance(), &local_uri, /* local URI */ &local_uri, /* local Contact */ &dst_uri, /* remote URI */ &dst_uri, /* remote target */ &dlg); /* dialog */ if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to create UAC dialog", status); return 1; } /* If we expect the outgoing INVITE to be challenged, then we should * put the credentials in the dialog here, with something like this: * { pjsip_cred_info cred[1]; cred[0].realm = pj_str("sip.server.realm"); cred[0].scheme = pj_str("digest"); cred[0].username = pj_str("theuser"); cred[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD; cred[0].data = pj_str("thepassword"); pjsip_auth_clt_set_credentials( &dlg->auth_sess, 1, cred); } * */ /* Get the SDP body to be put in the outgoing INVITE, by asking * media endpoint to create one for us. */ status = pjmedia_endpt_create_sdp( g_med_endpt, /* the media endpt */ dlg->pool, /* pool. */ MAX_MEDIA_CNT, /* # of streams */ g_sock_info, /* RTP sock info */ &local_sdp); /* the SDP result */ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Create the INVITE session, and pass the SDP returned earlier * as the session's initial capability. */ status = pjsip_inv_create_uac( dlg, local_sdp, 0, &g_inv); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* If we want the initial INVITE to travel to specific SIP proxies, * then we should put the initial dialog's route set here. The final * route set will be updated once a dialog has been established. * To set the dialog's initial route set, we do it with something * like this: * { pjsip_route_hdr route_set; pjsip_route_hdr *route; const pj_str_t hname = { "Route", 5 }; char *uri = "sip:proxy.server;lr"; pj_list_init(&route_set); route = pjsip_parse_hdr( dlg->pool, &hname, uri, strlen(uri), NULL); PJ_ASSERT_RETURN(route != NULL, 1); pj_list_push_back(&route_set, route); pjsip_dlg_set_route_set(dlg, &route_set); } * * Note that Route URI SHOULD have an ";lr" parameter! */ /* Create initial INVITE request. * This INVITE request will contain a perfectly good request and * an SDP body as well. */ status = pjsip_inv_invite(g_inv, &tdata); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); /* Send initial INVITE request. * From now on, the invite session's state will be reported to us * via the invite session callbacks. */ status = pjsip_inv_send_msg(g_inv, tdata); PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); } else { /* No URL to make call to */ PJ_LOG(3,(THIS_FILE, "Ready to accept incoming calls...")); } /* Loop until one call is completed */ for (;!g_complete;) { pj_time_val timeout = {0, 10}; pjsip_endpt_handle_events(g_endpt, &timeout); } /* On exit, dump current memory usage: */ dump_pool_usage(THIS_FILE, &cp); /* Destroy audio ports. Destroy the audio port first * before the stream since the audio port has threads * that get/put frames to the stream. */ if (g_snd_port) pjmedia_snd_port_destroy(g_snd_port); #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) /* Destroy video ports */ if (g_vid_capturer) pjmedia_vid_port_destroy(g_vid_capturer); if (g_vid_renderer) pjmedia_vid_port_destroy(g_vid_renderer); #endif /* Destroy streams */ if (g_med_stream) pjmedia_stream_destroy(g_med_stream); #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) if (g_med_vstream) pjmedia_vid_stream_destroy(g_med_vstream); /* Deinit ffmpeg codec */ # if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC!=0 pjmedia_codec_ffmpeg_vid_deinit(); # endif #endif /* Destroy media transports */ for (i = 0; i < MAX_MEDIA_CNT; ++i) { if (g_med_transport[i]) pjmedia_transport_close(g_med_transport[i]); } /* Deinit pjmedia endpoint */ if (g_med_endpt) pjmedia_endpt_destroy(g_med_endpt); /* Deinit pjsip endpoint */ if (g_endpt) pjsip_endpt_destroy(g_endpt); /* Release pool */ if (pool) pj_pool_release(pool); return 0; }
/* * Callback when incoming requests outside any transactions and any * dialogs are received. We're only interested to hande incoming INVITE * request, and we'll reject any other requests with 500 response. */ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ) { pj_sockaddr hostaddr; char temp[80], hostip[PJ_INET6_ADDRSTRLEN]; pj_str_t local_uri; pjsip_dialog *dlg; pjmedia_sdp_session *local_sdp; pjsip_tx_data *tdata; unsigned options = 0; pj_status_t status; /* * Respond (statelessly) any non-INVITE requests with 500 */ if (rdata->msg_info.msg->line.req.method.id != PJSIP_INVITE_METHOD) { if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) { pj_str_t reason = pj_str("Simple UA unable to handle " "this request"); pjsip_endpt_respond_stateless( g_endpt, rdata, 500, &reason, NULL, NULL); } return PJ_TRUE; } /* * Reject INVITE if we already have an INVITE session in progress. */ if (g_inv) { pj_str_t reason = pj_str("Another call is in progress"); pjsip_endpt_respond_stateless( g_endpt, rdata, 500, &reason, NULL, NULL); return PJ_TRUE; } /* Verify that we can handle the request. */ status = pjsip_inv_verify_request(rdata, &options, NULL, NULL, g_endpt, NULL); if (status != PJ_SUCCESS) { pj_str_t reason = pj_str("Sorry Simple UA can not handle this INVITE"); pjsip_endpt_respond_stateless( g_endpt, rdata, 500, &reason, NULL, NULL); return PJ_TRUE; } /* * Generate Contact URI */ if (pj_gethostip(AF, &hostaddr) != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to retrieve local host IP", status); return PJ_TRUE; } pj_sockaddr_print(&hostaddr, hostip, sizeof(hostip), 2); pj_ansi_sprintf(temp, "<sip:simpleuas@%s:%d>", hostip, SIP_PORT); local_uri = pj_str(temp); /* * Create UAS dialog. */ status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata, &local_uri, /* contact */ &dlg); if (status != PJ_SUCCESS) { pjsip_endpt_respond_stateless(g_endpt, rdata, 500, NULL, NULL, NULL); return PJ_TRUE; } /* * Get media capability from media endpoint: */ status = pjmedia_endpt_create_sdp( g_med_endpt, rdata->tp_info.pool, MAX_MEDIA_CNT, g_sock_info, &local_sdp); PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE); /* * Create invite session, and pass both the UAS dialog and the SDP * capability to the session. */ status = pjsip_inv_create_uas( dlg, rdata, local_sdp, 0, &g_inv); PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE); /* * Initially send 180 response. * * The very first response to an INVITE must be created with * pjsip_inv_initial_answer(). Subsequent responses to the same * transaction MUST use pjsip_inv_answer(). */ status = pjsip_inv_initial_answer(g_inv, rdata, 180, NULL, NULL, &tdata); PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE); /* Send the 180 response. */ status = pjsip_inv_send_msg(g_inv, tdata); PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE); /* * Now create 200 response. */ status = pjsip_inv_answer( g_inv, 200, NULL, /* st_code and st_text */ NULL, /* SDP already specified */ &tdata); PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE); /* * Send the 200 response. */ status = pjsip_inv_send_msg(g_inv, tdata); PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE); /* Done. * When the call is disconnected, it will be reported via the callback. */ return PJ_TRUE; }
/* * Initialize and start SRTP session with the given parameters. */ PJ_DEF(pj_status_t) pjmedia_transport_srtp_start( pjmedia_transport *tp, const pjmedia_srtp_crypto *tx, const pjmedia_srtp_crypto *rx) { transport_srtp *srtp = (transport_srtp*) tp; srtp_policy_t tx_; srtp_policy_t rx_; err_status_t err; int cr_tx_idx = 0; int au_tx_idx = 0; int cr_rx_idx = 0; int au_rx_idx = 0; pj_status_t status = PJ_SUCCESS; PJ_ASSERT_RETURN(tp && tx && rx, PJ_EINVAL); pj_lock_acquire(srtp->mutex); if (srtp->session_inited) { pjmedia_transport_srtp_stop(tp); } /* Get encryption and authentication method */ cr_tx_idx = au_tx_idx = get_crypto_idx(&tx->name); if (tx->flags & PJMEDIA_SRTP_NO_ENCRYPTION) cr_tx_idx = 0; if (tx->flags & PJMEDIA_SRTP_NO_AUTHENTICATION) au_tx_idx = 0; cr_rx_idx = au_rx_idx = get_crypto_idx(&rx->name); if (rx->flags & PJMEDIA_SRTP_NO_ENCRYPTION) cr_rx_idx = 0; if (rx->flags & PJMEDIA_SRTP_NO_AUTHENTICATION) au_rx_idx = 0; /* Check whether the crypto-suite requested is supported */ if (cr_tx_idx == -1 || cr_rx_idx == -1 || au_tx_idx == -1 || au_rx_idx == -1) { status = PJMEDIA_SRTP_ENOTSUPCRYPTO; goto on_return; } /* If all options points to 'NULL' method, just bypass SRTP */ if (cr_tx_idx == 0 && cr_rx_idx == 0 && au_tx_idx == 0 && au_rx_idx == 0) { srtp->bypass_srtp = PJ_TRUE; goto on_return; } /* Check key length */ if (tx->key.slen != (pj_ssize_t)crypto_suites[cr_tx_idx].cipher_key_len || rx->key.slen != (pj_ssize_t)crypto_suites[cr_rx_idx].cipher_key_len) { status = PJMEDIA_SRTP_EINKEYLEN; goto on_return; } /* Init transmit direction */ pj_bzero(&tx_, sizeof(srtp_policy_t)); pj_memmove(srtp->tx_key, tx->key.ptr, tx->key.slen); if (cr_tx_idx && au_tx_idx) tx_.rtp.sec_serv = sec_serv_conf_and_auth; else if (cr_tx_idx) tx_.rtp.sec_serv = sec_serv_conf; else if (au_tx_idx) tx_.rtp.sec_serv = sec_serv_auth; else tx_.rtp.sec_serv = sec_serv_none; tx_.key = (uint8_t*)srtp->tx_key; tx_.ssrc.type = ssrc_any_outbound; tx_.ssrc.value = 0; tx_.rtp.cipher_type = crypto_suites[cr_tx_idx].cipher_type; tx_.rtp.cipher_key_len = crypto_suites[cr_tx_idx].cipher_key_len; tx_.rtp.auth_type = crypto_suites[au_tx_idx].auth_type; tx_.rtp.auth_key_len = crypto_suites[au_tx_idx].auth_key_len; tx_.rtp.auth_tag_len = crypto_suites[au_tx_idx].srtp_auth_tag_len; tx_.rtcp = tx_.rtp; tx_.rtcp.auth_tag_len = crypto_suites[au_tx_idx].srtcp_auth_tag_len; tx_.next = NULL; err = srtp_create(&srtp->srtp_tx_ctx, &tx_); if (err != err_status_ok) { status = PJMEDIA_ERRNO_FROM_LIBSRTP(err); goto on_return; } srtp->tx_policy = *tx; pj_strset(&srtp->tx_policy.key, srtp->tx_key, tx->key.slen); srtp->tx_policy.name=pj_str(crypto_suites[get_crypto_idx(&tx->name)].name); /* Init receive direction */ pj_bzero(&rx_, sizeof(srtp_policy_t)); pj_memmove(srtp->rx_key, rx->key.ptr, rx->key.slen); if (cr_rx_idx && au_rx_idx) rx_.rtp.sec_serv = sec_serv_conf_and_auth; else if (cr_rx_idx) rx_.rtp.sec_serv = sec_serv_conf; else if (au_rx_idx) rx_.rtp.sec_serv = sec_serv_auth; else rx_.rtp.sec_serv = sec_serv_none; rx_.key = (uint8_t*)srtp->rx_key; rx_.ssrc.type = ssrc_any_inbound; rx_.ssrc.value = 0; rx_.rtp.sec_serv = crypto_suites[cr_rx_idx].service; rx_.rtp.cipher_type = crypto_suites[cr_rx_idx].cipher_type; rx_.rtp.cipher_key_len = crypto_suites[cr_rx_idx].cipher_key_len; rx_.rtp.auth_type = crypto_suites[au_rx_idx].auth_type; rx_.rtp.auth_key_len = crypto_suites[au_rx_idx].auth_key_len; rx_.rtp.auth_tag_len = crypto_suites[au_rx_idx].srtp_auth_tag_len; rx_.rtcp = rx_.rtp; rx_.rtcp.auth_tag_len = crypto_suites[au_rx_idx].srtcp_auth_tag_len; rx_.next = NULL; err = srtp_create(&srtp->srtp_rx_ctx, &rx_); if (err != err_status_ok) { srtp_dealloc(srtp->srtp_tx_ctx); status = PJMEDIA_ERRNO_FROM_LIBSRTP(err); goto on_return; } srtp->rx_policy = *rx; pj_strset(&srtp->rx_policy.key, srtp->rx_key, rx->key.slen); srtp->rx_policy.name=pj_str(crypto_suites[get_crypto_idx(&rx->name)].name); /* Declare SRTP session initialized */ srtp->session_inited = PJ_TRUE; /* Logging stuffs */ #if PJ_LOG_MAX_LEVEL >= 5 { char b64[PJ_BASE256_TO_BASE64_LEN(MAX_KEY_LEN)]; int b64_len; /* TX crypto and key */ b64_len = sizeof(b64); status = pj_base64_encode((pj_uint8_t*)tx->key.ptr, tx->key.slen, b64, &b64_len); if (status != PJ_SUCCESS) b64_len = pj_ansi_sprintf(b64, "--key too long--"); else b64[b64_len] = '\0'; PJ_LOG(5, (srtp->pool->obj_name, "TX: %s key=%s", srtp->tx_policy.name.ptr, b64)); if (srtp->tx_policy.flags) { PJ_LOG(5,(srtp->pool->obj_name, "TX: disable%s%s", (cr_tx_idx?"":" enc"), (au_tx_idx?"":" auth"))); } /* RX crypto and key */ b64_len = sizeof(b64); status = pj_base64_encode((pj_uint8_t*)rx->key.ptr, rx->key.slen, b64, &b64_len); if (status != PJ_SUCCESS) b64_len = pj_ansi_sprintf(b64, "--key too long--"); else b64[b64_len] = '\0'; PJ_LOG(5, (srtp->pool->obj_name, "RX: %s key=%s", srtp->rx_policy.name.ptr, b64)); if (srtp->rx_policy.flags) { PJ_LOG(5,(srtp->pool->obj_name,"RX: disable%s%s", (cr_rx_idx?"":" enc"), (au_rx_idx?"":" auth"))); } } #endif on_return: pj_lock_release(srtp->mutex); return status; }
/* * Parse fmtp for specified format/payload type. */ static void parse_fmtp( pj_pool_t *pool, const pjmedia_sdp_media *m, unsigned pt, pjmedia_codec_fmtp *fmtp) { const pjmedia_sdp_attr *attr; pjmedia_sdp_fmtp sdp_fmtp; char *p, *p_end, fmt_buf[8]; pj_str_t fmt; pj_assert(m && fmtp); pj_bzero(fmtp, sizeof(pjmedia_codec_fmtp)); /* Get "fmtp" attribute for the format */ pj_ansi_sprintf(fmt_buf, "%d", pt); fmt = pj_str(fmt_buf); attr = pjmedia_sdp_media_find_attr2(m, "fmtp", &fmt); if (attr == NULL) return; /* Parse "fmtp" attribute */ if (pjmedia_sdp_attr_get_fmtp(attr, &sdp_fmtp) != PJ_SUCCESS) return; /* Prepare parsing */ p = sdp_fmtp.fmt_param.ptr; p_end = p + sdp_fmtp.fmt_param.slen; /* Parse */ while (p < p_end) { char *token, *start, *end; /* Skip whitespaces */ while (p < p_end && (*p == ' ' || *p == '\t')) ++p; if (p == p_end) break; /* Get token */ start = p; while (p < p_end && *p != ';' && *p != '=') ++p; end = p - 1; /* Right trim */ while (end >= start && (*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n' )) --end; /* Forward a char after trimming */ ++end; /* Store token */ if (end > start) { token = (char*)pj_pool_alloc(pool, end - start); pj_ansi_strncpy(token, start, end - start); if (*p == '=') /* Got param name */ pj_strset(&fmtp->param[fmtp->cnt].name, token, end - start); else /* Got param value */ pj_strset(&fmtp->param[fmtp->cnt++].val, token, end - start); } else if (*p != '=') { ++fmtp->cnt; } /* Next */ ++p; } }
int tsx_bench(void) { enum { WORKING_SET=10000, REPEAT = 4 }; unsigned i, speed; pj_timestamp usec[REPEAT], min, freq; char desc[250]; int status; status = pj_get_timestamp_freq(&freq); if (status != PJ_SUCCESS) return status; /* * Benchmark UAC */ PJ_LOG(3,(THIS_FILE, " benchmarking UAC transaction creation:")); for (i=0; i<REPEAT; ++i) { PJ_LOG(3,(THIS_FILE, " test %d of %d..", i+1, REPEAT)); status = uac_tsx_bench(WORKING_SET, &usec[i]); if (status != PJ_SUCCESS) return status; } min.u64 = PJ_UINT64(0xFFFFFFFFFFFFFFF); for (i=0; i<REPEAT; ++i) { if (usec[i].u64 < min.u64) min.u64 = usec[i].u64; } /* Report time */ pj_ansi_sprintf(desc, "Time to create %d UAC transactions, in miliseconds", WORKING_SET); report_ival("create-uac-time", (unsigned)(min.u64 * 1000 / freq.u64), "msec", desc); /* Write speed */ speed = (unsigned)(freq.u64 * WORKING_SET / min.u64); PJ_LOG(3,(THIS_FILE, " UAC created at %d tsx/sec", speed)); pj_ansi_sprintf(desc, "Number of UAC transactions that potentially can be created per second " "with <tt>pjsip_tsx_create_uac()</tt>, based on the time " "to create %d simultaneous transactions above.", WORKING_SET); report_ival("create-uac-tsx-per-sec", speed, "tsx/sec", desc); /* * Benchmark UAS */ PJ_LOG(3,(THIS_FILE, " benchmarking UAS transaction creation:")); for (i=0; i<REPEAT; ++i) { PJ_LOG(3,(THIS_FILE, " test %d of %d..", i+1, REPEAT)); status = uas_tsx_bench(WORKING_SET, &usec[i]); if (status != PJ_SUCCESS) return status; } min.u64 = PJ_UINT64(0xFFFFFFFFFFFFFFF); for (i=0; i<REPEAT; ++i) { if (usec[i].u64 < min.u64) min.u64 = usec[i].u64; } /* Report time */ pj_ansi_sprintf(desc, "Time to create %d UAS transactions, in miliseconds", WORKING_SET); report_ival("create-uas-time", (unsigned)(min.u64 * 1000 / freq.u64), "msec", desc); /* Write speed */ speed = (unsigned)(freq.u64 * WORKING_SET / min.u64); PJ_LOG(3,(THIS_FILE, " UAS created at %d tsx/sec", speed)); pj_ansi_sprintf(desc, "Number of UAS transactions that potentially can be created per second " "with <tt>pjsip_tsx_create_uas()</tt>, based on the time " "to create %d simultaneous transactions above.", WORKING_SET); report_ival("create-uas-tsx-per-sec", speed, "tsx/sec", desc); return PJ_SUCCESS; }
static pj_status_t init_report(void) { char tmp[80]; pj_time_val timestamp; pj_parsed_time date_time; pj_ssize_t len; pj_status_t status; pj_ansi_sprintf(tmp, "pjsip-static-bench-%s-%s.htm", PJ_OS_NAME, PJ_CC_NAME); status = pj_file_open(NULL, tmp, PJ_O_WRONLY, &fd_report); if (status != PJ_SUCCESS) return status; /* Title */ len = pj_ansi_sprintf(buf, "<HTML>\n" " <HEAD>\n" " <TITLE>PJSIP %s (%s) - Static Benchmark</TITLE>\n" " </HEAD>\n" "<BODY>\n" "\n", PJ_VERSION, (PJ_DEBUG ? "Debug" : "Release")); pj_file_write(fd_report, buf, &len); /* Title */ len = pj_ansi_sprintf(buf, "<H1>PJSIP %s (%s) - Static Benchmark</H1>\n", PJ_VERSION, (PJ_DEBUG ? "Debug" : "Release")); pj_file_write(fd_report, buf, &len); len = pj_ansi_sprintf(buf, "<P>Below is the benchmark result generated " "by <b>test-pjsip</b> program. The program " "is single-threaded only.</P>\n"); pj_file_write(fd_report, buf, &len); /* Write table heading */ len = pj_ansi_sprintf(buf, "<TABLE border=\"1\" cellpadding=\"4\">\n" " <TR><TD bgColor=\"aqua\" align=\"center\">Variable</TD>\n" " <TD bgColor=\"aqua\" align=\"center\">Value</TD>\n" " <TD bgColor=\"aqua\" align=\"center\">Description</TD>\n" " </TR>\n"); pj_file_write(fd_report, buf, &len); /* Write version */ report_sval("version", PJ_VERSION, "", "PJLIB/PJSIP version"); /* Debug or release */ report_sval("build-type", (PJ_DEBUG ? "Debug" : "Release"), "", "Build type"); /* Write timestamp */ pj_gettimeofday(×tamp); report_ival("timestamp", timestamp.sec, "", "System timestamp of the test"); /* Write time of day */ pj_time_decode(×tamp, &date_time); len = pj_ansi_sprintf(tmp, "%04d-%02d-%02d %02d:%02d:%02d", date_time.year, date_time.mon+1, date_time.day, date_time.hour, date_time.min, date_time.sec); report_sval("date-time", tmp, "", "Date/time of the test"); /* Write System */ report_sval("system", system_name, "", "System description"); /* Write OS type */ report_sval("os-family", PJ_OS_NAME, "", "Operating system family"); /* Write CC name */ len = pj_ansi_sprintf(tmp, "%s-%d.%d.%d", PJ_CC_NAME, PJ_CC_VER_1, PJ_CC_VER_2, PJ_CC_VER_2); report_sval("cc-name", tmp, "", "Compiler name and version"); return PJ_SUCCESS; }
/* main() * * If called with argument, treat argument as SIP URL to be called. * Otherwise wait for incoming calls. */ int main(int argc, char *argv[]) { if (init_stack()) goto on_error; /* If URL is specified, then make call immediately. */ if (argc > 1) { pj_sockaddr hostaddr; char hostip[PJ_INET6_ADDRSTRLEN+2]; char temp[80]; call_t *call; pj_str_t dst_uri = pj_str(argv[1]); pj_str_t local_uri; pjsip_dialog *dlg; pj_status_t status; pjsip_tx_data *tdata; if (pj_gethostip(AF, &hostaddr) != PJ_SUCCESS) { PJ_LOG(1,(THIS_FILE, "Unable to retrieve local host IP")); goto on_error; } pj_sockaddr_print(&hostaddr, hostip, sizeof(hostip), 2); pj_ansi_sprintf(temp, "<sip:sipecho@%s:%d>", hostip, SIP_PORT); local_uri = pj_str(temp); call = &app.call[0]; status = pjsip_dlg_create_uac( pjsip_ua_instance(), &local_uri, /* local URI */ &local_uri, /* local Contact */ &dst_uri, /* remote URI */ &dst_uri, /* remote target */ &dlg); /* dialog */ if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to create UAC dialog", status); return 1; } status = pjsip_inv_create_uac( dlg, NULL, 0, &call->inv); if (status != PJ_SUCCESS) goto on_error; call->inv->mod_data[mod_sipecho.id] = call; status = pjsip_inv_invite(call->inv, &tdata); if (status != PJ_SUCCESS) goto on_error; status = pjsip_inv_send_msg(call->inv, tdata); if (status != PJ_SUCCESS) goto on_error; puts("Press ENTER to quit..."); } else { puts("Ready for incoming calls. Press ENTER to quit..."); } for (;;) { char s[10]; printf("\nMenu:\n" " h Hangup all calls\n" " l %s message logging\n" " q Quit\n", (app.enable_msg_logging? "Disable" : "Enable")); if (fgets(s, sizeof(s), stdin) == NULL) continue; if (s[0]=='q') break; switch (s[0]) { case 'l': app.enable_msg_logging = !app.enable_msg_logging; break; case 'h': hangup_all(); break; } } destroy_stack(); puts("Bye bye.."); return 0; on_error: puts("An error has occurred. run a debugger.."); return 1; }
/***************************************************************************** * 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; }
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 (%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 (%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 (%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 (%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; }