📄 pjsip-perf.c
字号:
/* $Id: pjsip-perf.c 1158 2007-04-06 10:25:23Z bennylp $ *//* * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//** * \page page_pjsip_perf_c Samples: SIP Performance Benchmark * * <b>pjsip-perf</b> is a complete program to measure the * performance of PJSIP or other SIP endpoints. It consists of two * parts: * - the server, to respond incoming requests, and * - the client, who actively submits requests and measure the * performance of the server. * * Both server and client part can run simultaneously, to measure the * performance when both endpoints are co-located in a single program. * * The server accepts both INVITE and non-INVITE requests. * The server exports several different types of URL, which would * control how the request would be handled by the server: * - URL with "0" as the user part will be handled statelessly. * It should not be used with INVITE method. * - URL with "1" as the user part will be handled statefully. * If the request is an INVITE request, INVITE transaction will * be created and 200/OK response will be sent, along with a valid * SDP body. However, the SDP is just a static text body, and * is not a proper SDP generated by PJMEDIA. * - URL with "2" as the user part is only meaningful for INVITE * requests, as it would be handled <b>call-statefully</b> by the * server. For this URL, the server also would generate SDP dynamically * and perform a proper SDP negotiation for the incoming call. * Also for every call, server will limit the call duration to * 10 seconds, on which the call will be terminated if the client * doesn't hangup the call. * * * * This file is pjsip-apps/src/samples/pjsip-perf.c * * \includelineno pjsip-perf.c *//* Include all headers. */#include <pjsip.h>#include <pjmedia.h>#include <pjmedia-codec.h>#include <pjsip_ua.h>#include <pjsip_simple.h>#include <pjlib-util.h>#include <pjlib.h>#include <stdio.h>#if defined(PJ_WIN32) && PJ_WIN32!=0# include <windows.h>#endif#define THIS_FILE "pjsip-perf.c"#define DEFAULT_COUNT (PJSIP_MAX_TSX_COUNT/2>10000?10000:PJSIP_MAX_TSX_COUNT/2)#define JOB_WINDOW 1000#define TERMINATE_TSX(x,c)#ifndef CACHING_POOL_SIZE# define CACHING_POOL_SIZE (256*1024*1024)#endif/* Static message body for INVITE, when stateful processing is * invoked (instead of call-stateful, where SDP is generated * dynamically. */static pj_str_t dummy_sdp_str = { "v=0\r\n" "o=- 3360842071 3360842071 IN IP4 192.168.0.68\r\n" "s=pjmedia\r\n" "c=IN IP4 192.168.0.68\r\n" "t=0 0\r\n" "m=audio 4000 RTP/AVP 0 8 3 103 102 101\r\n" "a=rtcp:4001 IN IP4 192.168.0.68\r\n" "a=rtpmap:103 speex/16000\r\n" "a=rtpmap:102 speex/8000\r\n" "a=rtpmap:3 GSM/8000\r\n" "a=rtpmap:0 PCMU/8000\r\n" "a=rtpmap:8 PCMA/8000\r\n" "a=sendrecv\r\n" "a=rtpmap:101 telephone-event/8000\r\n" "a=fmtp:101 0-15\r\n", 0};static pj_str_t mime_application = { "application", 11};static pj_str_t mime_sdp = {"sdp", 3};struct srv_state{ unsigned stateless_cnt; unsigned stateful_cnt; unsigned call_cnt;};struct app{ pj_caching_pool cp; pj_pool_t *pool; pj_bool_t use_tcp; pj_str_t local_addr; int local_port; pjsip_endpoint *sip_endpt; pjmedia_endpt *med_endpt; pj_str_t local_uri; pj_str_t local_contact; unsigned skinfo_cnt; pjmedia_sock_info skinfo[8]; pj_bool_t thread_quit; unsigned thread_count; pj_thread_t *thread[16]; pj_bool_t real_sdp; pjmedia_sdp_session *dummy_sdp; int log_level; struct { pjsip_method method; pj_str_t dst_uri; pj_bool_t stateless; unsigned timeout; unsigned job_count, job_submitted, job_finished, job_window; unsigned stat_max_window; pj_time_val first_request; pj_time_val requests_sent; pj_time_val last_completion; unsigned total_responses; unsigned response_codes[800]; } client; struct { pj_bool_t send_trying; pj_bool_t send_ringing; unsigned delay; struct srv_state prev_state; struct srv_state cur_state; } server;} app;struct call{ pjsip_inv_session *inv; pj_timer_entry ans_timer;};static void app_perror(const char *sender, const char *title, pj_status_t status){ char errmsg[PJ_ERR_MSG_SIZE]; pj_strerror(status, errmsg, sizeof(errmsg)); PJ_LOG(1,(sender, "%s: %s [code=%d]", title, errmsg, status));}/************************************************************************** * STATELESS SERVER */static pj_bool_t mod_stateless_on_rx_request(pjsip_rx_data *rdata);/* Module to handle incoming requests statelessly. */static pjsip_module mod_stateless_server ={ NULL, NULL, /* prev, next. */ { "mod-stateless-server", 20 }, /* Name. */ -1, /* Id */ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */ NULL, /* load() */ NULL, /* start() */ NULL, /* stop() */ NULL, /* unload() */ &mod_stateless_on_rx_request, /* on_rx_request() */ NULL, /* on_rx_response() */ NULL, /* on_tx_request. */ NULL, /* on_tx_response() */ NULL, /* on_tsx_state() */};static pj_bool_t mod_stateless_on_rx_request(pjsip_rx_data *rdata){ const pj_str_t stateless_user = { "0", 1 }; pjsip_uri *uri; pjsip_sip_uri *sip_uri; uri = pjsip_uri_get_uri(rdata->msg_info.msg->line.req.uri); /* Only want to receive SIP scheme */ if (!PJSIP_URI_SCHEME_IS_SIP(uri)) return PJ_FALSE; sip_uri = (pjsip_sip_uri*) uri; /* Check for matching user part */ if (pj_strcmp(&sip_uri->user, &stateless_user)!=0) return PJ_FALSE; /* * Yes, this is for us. */ /* Ignore ACK request */ if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD) return PJ_TRUE; /* * Respond statelessly with 200/OK. */ pjsip_endpt_respond_stateless(app.sip_endpt, rdata, 200, NULL, NULL, NULL); app.server.cur_state.stateless_cnt++; return PJ_TRUE;}/************************************************************************** * STATEFUL SERVER */static pj_bool_t mod_stateful_on_rx_request(pjsip_rx_data *rdata);/* Module to handle incoming requests statefully. */static pjsip_module mod_stateful_server ={ NULL, NULL, /* prev, next. */ { "mod-stateful-server", 19 }, /* Name. */ -1, /* Id */ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */ NULL, /* load() */ NULL, /* start() */ NULL, /* stop() */ NULL, /* unload() */ &mod_stateful_on_rx_request, /* on_rx_request() */ NULL, /* on_rx_response() */ NULL, /* on_tx_request. */ NULL, /* on_tx_response() */ NULL, /* on_tsx_state() */};static pj_bool_t mod_stateful_on_rx_request(pjsip_rx_data *rdata){ const pj_str_t stateful_user = { "1", 1 }; pjsip_uri *uri; pjsip_sip_uri *sip_uri; uri = pjsip_uri_get_uri(rdata->msg_info.msg->line.req.uri); /* Only want to receive SIP scheme */ if (!PJSIP_URI_SCHEME_IS_SIP(uri)) return PJ_FALSE; sip_uri = (pjsip_sip_uri*) uri; /* Check for matching user part */ if (pj_strcmp(&sip_uri->user, &stateful_user)!=0) return PJ_FALSE; /* * Yes, this is for us. * Respond statefully with 200/OK. */ switch (rdata->msg_info.msg->line.req.method.id) { case PJSIP_INVITE_METHOD: { pjsip_msg_body *body; if (dummy_sdp_str.slen == 0) dummy_sdp_str.slen = pj_ansi_strlen(dummy_sdp_str.ptr); body = pjsip_msg_body_create(rdata->tp_info.pool, &mime_application, &mime_sdp, &dummy_sdp_str); pjsip_endpt_respond(app.sip_endpt, &mod_stateful_server, rdata, 200, NULL, NULL, body, NULL); } break; case PJSIP_ACK_METHOD: return PJ_TRUE; default: pjsip_endpt_respond(app.sip_endpt, &mod_stateful_server, rdata, 200, NULL, NULL, NULL, NULL); break; } app.server.cur_state.stateful_cnt++; return PJ_TRUE;}/************************************************************************** * CALL SERVER */static pj_bool_t mod_call_on_rx_request(pjsip_rx_data *rdata);/* Module to handle incoming requests callly. */static pjsip_module mod_call_server ={ NULL, NULL, /* prev, next. */ { "mod-call-server", 15 }, /* Name. */ -1, /* Id */ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */ NULL, /* load() */ NULL, /* start() */ NULL, /* stop() */ NULL, /* unload() */ &mod_call_on_rx_request, /* on_rx_request() */ NULL, /* on_rx_response() */ NULL, /* on_tx_request. */ NULL, /* on_tx_response() */ NULL, /* on_tsx_state() */};static pj_status_t send_response(pjsip_inv_session *inv, pjsip_rx_data *rdata, int code, pj_bool_t *has_initial){ pjsip_tx_data *tdata; pj_status_t status; if (*has_initial) { status = pjsip_inv_answer(inv, code, NULL, NULL, &tdata); } else { status = pjsip_inv_initial_answer(inv, rdata, code, NULL, NULL, &tdata); } if (status != PJ_SUCCESS) { if (*has_initial) { status = pjsip_inv_answer(inv, PJSIP_SC_NOT_ACCEPTABLE, NULL, NULL, &tdata); } else { status = pjsip_inv_initial_answer(inv, rdata, PJSIP_SC_NOT_ACCEPTABLE, NULL, NULL, &tdata); } if (status == PJ_SUCCESS) { *has_initial = PJ_TRUE; pjsip_inv_send_msg(inv, tdata); } else { pjsip_inv_terminate(inv, 500, PJ_FALSE); return -1; } } else { *has_initial = PJ_TRUE; status = pjsip_inv_send_msg(inv, tdata); if (status != PJ_SUCCESS) { pjsip_tx_data_dec_ref(tdata); return status; } } return status;}static void answer_timer_cb(pj_timer_heap_t *h, pj_timer_entry *entry){ struct call *call = entry->user_data; pj_bool_t has_initial = PJ_TRUE; PJ_UNUSED_ARG(h); entry->id = 0; send_response(call->inv, NULL, 200, &has_initial);}static pj_bool_t mod_call_on_rx_request(pjsip_rx_data *rdata){ const pj_str_t call_user = { "2", 1 }; pjsip_uri *uri; pjsip_sip_uri *sip_uri; struct call *call; pjsip_dialog *dlg; pjmedia_sdp_session *sdp; pjsip_tx_data *tdata; pj_bool_t has_initial = PJ_FALSE; pj_status_t status; uri = pjsip_uri_get_uri(rdata->msg_info.msg->line.req.uri); /* Only want to receive SIP scheme */ if (!PJSIP_URI_SCHEME_IS_SIP(uri)) return PJ_FALSE; sip_uri = (pjsip_sip_uri*) uri; /* Only want to handle INVITE requests. */ if (rdata->msg_info.msg->line.req.method.id != PJSIP_INVITE_METHOD) { return PJ_FALSE; } /* Check for matching user part. Incoming requests will be handled * call-statefully if: * - user part is "2", or * - user part is not "0" nor "1" and method is INVITE. */ if (pj_strcmp(&sip_uri->user, &call_user) == 0 || sip_uri->user.slen != 1 || (*sip_uri->user.ptr != '0' && *sip_uri->user.ptr != '1')) { /* Match */ } else { return PJ_FALSE; } /* Verify that we can handle the request. */ if (app.real_sdp) { unsigned options = 0; status = pjsip_inv_verify_request(rdata, &options, NULL, NULL, app.sip_endpt, &tdata); if (status != PJ_SUCCESS) { /* * No we can't handle the incoming INVITE request. */ if (tdata) { pjsip_response_addr res_addr; pjsip_get_response_addr(tdata->pool, rdata, &res_addr); pjsip_endpt_send_response(app.sip_endpt, &res_addr, tdata, NULL, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -