summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pjlib/include/pj/string.h13
-rw-r--r--pjlib/src/pj/pool_caching.c2
-rw-r--r--pjsip-apps/build/Makefile20
-rw-r--r--pjsip-apps/build/pjsip_apps.dsw33
-rw-r--r--pjsip-apps/build/pjsip_perf.dsp114
-rw-r--r--pjsip-apps/build/sample_debug.dsp3
-rw-r--r--pjsip-apps/src/pjsip-perf/handler_call.c417
-rw-r--r--pjsip-apps/src/pjsip-perf/handler_options.c154
-rw-r--r--pjsip-apps/src/pjsip-perf/main.c880
-rw-r--r--pjsip-apps/src/pjsip-perf/pjsip_perf.h178
-rw-r--r--pjsip-apps/src/samples/pjsip-perf.c129
-rw-r--r--pjsip/include/pjsip/sip_config.h10
-rw-r--r--pjsip/src/pjsip/sip_endpoint.c24
13 files changed, 138 insertions, 1839 deletions
diff --git a/pjlib/include/pj/string.h b/pjlib/include/pj/string.h
index 5c2cc251..7c513e7c 100644
--- a/pjlib/include/pj/string.h
+++ b/pjlib/include/pj/string.h
@@ -543,6 +543,19 @@ PJ_DECL(int) pj_utoa(unsigned long val, char *buf);
*/
PJ_DECL(int) pj_utoa_pad( unsigned long val, char *buf, int min_dig, int pad);
+
+/**
+ * Fill the memory location with zero.
+ *
+ * @param dst The destination buffer.
+ * @param size The number of bytes.
+ */
+PJ_INLINE(void) pj_bzero(void *dst, pj_size_t size)
+{
+ bzero(dst, size);
+}
+
+
/**
* Fill the memory location with value.
*
diff --git a/pjlib/src/pj/pool_caching.c b/pjlib/src/pj/pool_caching.c
index 4f9904e8..1c9f3e2f 100644
--- a/pjlib/src/pj/pool_caching.c
+++ b/pjlib/src/pj/pool_caching.c
@@ -198,6 +198,8 @@ static void cpool_release_pool( pj_pool_factory *pf, pj_pool_t *pool)
pj_pool_get_used_size(pool)*100/pool_capacity));
pj_pool_reset(pool);
+ pool_capacity = pj_pool_get_capacity(pool);
+
/*
* Otherwise put the pool in our recycle list.
*/
diff --git a/pjsip-apps/build/Makefile b/pjsip-apps/build/Makefile
index 16c916e2..e2fe85a3 100644
--- a/pjsip-apps/build/Makefile
+++ b/pjsip-apps/build/Makefile
@@ -43,25 +43,12 @@ export PJSUA_LDFLAGS += $(_LDFLAGS)
export PJSUA_EXE:=../bin/pjsua-$(TARGET_NAME)$(HOST_EXE)
-
-###############################################################################
-# Defines for building PJSIP-PERF
-#
-export PJSIPPERF_SRCDIR = ../src/pjsip-perf
-export PJSIPPERF_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
- handler_call.o handler_options.o main.o
-export PJSIPPERF_CFLAGS += $(_CFLAGS)
-export PJSIPPERF_LDFLAGS += $(_LDFLAGS)
-export PJSIPPERF_EXE:=../bin/pjsip-perf-$(TARGET_NAME)$(HOST_EXE)
-
-
-
export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT
###############################################################################
# Main entry
#
#
-TARGETS := pjsua pjsip-perf samples
+TARGETS := pjsua samples
.PHONY: $(TARGETS)
@@ -78,9 +65,6 @@ distclean: realclean
pjsua:
$(MAKE) -f $(RULES_MAK) APP=PJSUA app=pjsua $(PJSUA_EXE)
-pjsip-perf:
- $(MAKE) -f $(RULES_MAK) APP=PJSIPPERF app=pjsip-perf $(PJSUA_EXE)
-
samples:
$(MAKE) -f Samples.mak
@@ -90,11 +74,9 @@ samples:
clean depend realclean:
$(MAKE) -f $(RULES_MAK) APP=PJSUA app=pjsua $@
- $(MAKE) -f $(RULES_MAK) APP=PJSIPPERF app=pjsip-perf $@
$(MAKE) -f Samples.mak $@
@if test "$@" = "depend"; then \
echo '$(PJSUA_EXE): $(PJSIP_LIB) $(PJSIP_UA_LIB) $(PJSIP_SIMPLE) $(PJSUA_LIB_LIB) $(PJLIB_LIB) $(PJLIB_UTIL_LIB) $(PJMEDIA_LIB) $(PJMEDIA_CODEC_LIB) Makefile' >> .pjsua-$(TARGET_NAME).depend; \
- echo '$(PJSIPPERF_EXE): $(PJSIP_LIB) $(PJSIP_UA_LIB) $(PJSIP_SIMPLE) $(PJSUA_LIB_LIB) $(PJLIB_LIB) $(PJLIB_UTIL_LIB) $(PJMEDIA_LIB) $(PJMEDIA_CODEC_LIB)' >> .pjsip-perf-$(TARGET_NAME).depend; \
fi
diff --git a/pjsip-apps/build/pjsip_apps.dsw b/pjsip-apps/build/pjsip_apps.dsw
index 240e30a5..72cf939e 100644
--- a/pjsip-apps/build/pjsip_apps.dsw
+++ b/pjsip-apps/build/pjsip_apps.dsw
@@ -63,39 +63,6 @@ Package=<4>
###############################################################################
-Project: "pjsip_perf"=".\pjsip_perf.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name pjlib
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name pjlib_util
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name pjsip_core
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name pjsip_simple
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name pjsip_ua
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name pjsua_lib
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name pjmedia
- End Project Dependency
-}}}
-
-###############################################################################
-
Project: "pjsip_simple"="..\..\pjsip\build\pjsip_simple.dsp" - Package Owner=<4>
Package=<5>
diff --git a/pjsip-apps/build/pjsip_perf.dsp b/pjsip-apps/build/pjsip_perf.dsp
deleted file mode 100644
index c6402062..00000000
--- a/pjsip-apps/build/pjsip_perf.dsp
+++ /dev/null
@@ -1,114 +0,0 @@
-# Microsoft Developer Studio Project File - Name="pjsip_perf" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=pjsip_perf - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "pjsip_perf.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "pjsip_perf.mak" CFG="pjsip_perf - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "pjsip_perf - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "pjsip_perf - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "pjsip_perf - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir ".\output\pjsip-perf-i386-win32-vc6-release"
-# PROP BASE Intermediate_Dir ".\output\pjsip-perf-i386-win32-vc6-release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir ".\output\pjsip-perf-i386-win32-vc6-release"
-# PROP Intermediate_Dir ".\output\pjsip-perf-i386-win32-vc6-release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W4 /GX /O2 /I "../../pjsip/include" /I "../../pjmedia/include" /I "../../pjlib-util/include" /I "../../pjlib/include" /D "NDEBUG" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ole32.lib user32.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\pjsip-perf-i386-win32-vc6.exe"
-
-!ELSEIF "$(CFG)" == "pjsip_perf - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir ".\output\pjsip-perf-i386-win32-vc6-debug"
-# PROP BASE Intermediate_Dir ".\output\pjsip-perf-i386-win32-vc6-debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir ".\output\pjsip-perf-i386-win32-vc6-debug"
-# PROP Intermediate_Dir ".\output\pjsip-perf-i386-win32-vc6-debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../../pjsip/include" /I "../../pjmedia/include" /I "../../pjlib-util/include" /I "../../pjlib/include" /D "_DEBUG" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ole32.lib user32.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /debug /machine:I386 /out:"..\bin\pjsip-perf-i386-win32-vc6d.exe"
-
-!ENDIF
-
-# Begin Target
-
-# Name "pjsip_perf - Win32 Release"
-# Name "pjsip_perf - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE="..\src\pjsip-perf\handler_call.c"
-# End Source File
-# Begin Source File
-
-SOURCE="..\src\pjsip-perf\handler_options.c"
-# End Source File
-# Begin Source File
-
-SOURCE="..\src\pjsip-perf\main.c"
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE="..\src\pjsip-perf\pjsip_perf.h"
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/pjsip-apps/build/sample_debug.dsp b/pjsip-apps/build/sample_debug.dsp
index a6af92cb..1cf451c4 100644
--- a/pjsip-apps/build/sample_debug.dsp
+++ b/pjsip-apps/build/sample_debug.dsp
@@ -42,7 +42,8 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../pjsip/include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../../pjmedia/include" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "../../pjsip/include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../../pjmedia/include" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
diff --git a/pjsip-apps/src/pjsip-perf/handler_call.c b/pjsip-apps/src/pjsip-perf/handler_call.c
deleted file mode 100644
index bc7ae339..00000000
--- a/pjsip-apps/src/pjsip-perf/handler_call.c
+++ /dev/null
@@ -1,417 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2006 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
- */
-#include "pjsip_perf.h"
-
-/*
- * This file handles call generation and incoming calls.
- */
-#define THIS_FILE "handler_call.c"
-
-/*
- * Dummy SDP.
- */
-static pjmedia_sdp_session *local_sdp;
-
-
-#define TIMER_ID 1234
-
-/* Call data, to be attached to invite session. */
-struct call_data
-{
- pjsip_inv_session *inv;
- pj_bool_t confirmed;
- pj_timer_entry bye_timer;
- void *test_data;
- void (*completion_cb)(void*,pj_bool_t);
-};
-
-
-/****************************************************************************
- *
- * INCOMING CALL HANDLER
- *
- ****************************************************************************
- */
-
-
-static pj_bool_t mod_call_on_rx_request(pjsip_rx_data *rdata);
-
-/* The module instance. */
-static pjsip_module mod_call =
-{
- NULL, NULL, /* prev, next. */
- { "mod-perf-call", 13 }, /* 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() */
-};
-
-
-
-/*
- * Handle incoming requests.
- * Because this module is registered to the INVITE module too, this
- * callback may be called for requests inside a dialog.
- */
-static pj_bool_t mod_call_on_rx_request(pjsip_rx_data *rdata)
-{
- pjsip_msg *msg = rdata->msg_info.msg;
- pjsip_dialog *dlg;
- pjsip_inv_session *inv;
- pjsip_tx_data *response;
- struct call_data *call_data;
- unsigned options;
- pj_status_t status;
-
-
- /* Don't want to handle anything but INVITE */
- if (msg->line.req.method.id != PJSIP_INVITE_METHOD)
- return PJ_FALSE;
-
- /* Don't want to handle request that's already associated with
- * existing dialog or transaction.
- */
- if (pjsip_rdata_get_dlg(rdata) || pjsip_rdata_get_tsx(rdata))
- return PJ_FALSE;
-
-
- /* Verify that we can handle the request. */
- options = 0;
- status = pjsip_inv_verify_request(rdata, &options, NULL, NULL,
- settings.endpt, &response);
- if (status != PJ_SUCCESS) {
-
- /*
- * No we can't handle the incoming INVITE request.
- */
-
- if (response) {
- pjsip_response_addr res_addr;
-
- pjsip_get_response_addr(response->pool, rdata, &res_addr);
- pjsip_endpt_send_response(settings.endpt, &res_addr, response,
- NULL, NULL);
-
- } else {
-
- /* Respond with 500 (Internal Server Error) */
- pjsip_endpt_respond_stateless(settings.endpt, rdata, 500, NULL,
- NULL, NULL);
- }
-
- return PJ_TRUE;
- }
-
- /*
- * Yes we can handle the incoming INVITE request.
- */
-
- /* Create dialog. */
- status = pjsip_dlg_create_uas(pjsip_ua_instance(), rdata, NULL, &dlg);
- if (status != PJ_SUCCESS) {
- pjsip_dlg_respond(dlg, rdata, 500, NULL, NULL, NULL);
- return PJ_TRUE;
- }
-
- /* Create invite session: */
- status = pjsip_inv_create_uas( dlg, rdata, local_sdp, 0, &inv);
- if (status != PJ_SUCCESS) {
-
- pjsip_dlg_respond(dlg, rdata, 500, NULL, NULL, NULL);
-
- // TODO: Need to delete dialog
- return PJ_TRUE;
- }
-
- /* Create and associate call data. */
- call_data = pj_pool_zalloc(inv->pool, sizeof(struct call_data));
- call_data->inv = inv;
- call_data->bye_timer.user_data = call_data;
- inv->mod_data[mod_call.id] = call_data;
-
- /* Answer with 200 straight away. */
- status = pjsip_inv_initial_answer(inv, rdata, 200,
- NULL, NULL, &response);
- if (status != PJ_SUCCESS) {
-
- app_perror(THIS_FILE, "Unable to create 200 response", status);
-
- pjsip_dlg_respond(dlg, rdata, 500, NULL, NULL, NULL);
-
- // TODO: Need to delete dialog
-
- } else {
- status = pjsip_inv_send_msg(inv, response);
- if (status != PJ_SUCCESS)
- app_perror(THIS_FILE, "Unable to send 100 response", status);
- }
-
-
- return PJ_TRUE;
-}
-
-
-/****************************************************************************
- *
- * OUTGOING CALL GENERATOR
- *
- ****************************************************************************
- */
-
-/**
- * Make outgoing call.
- */
-pj_status_t call_spawn_test( const pj_str_t *target,
- const pj_str_t *from,
- const pj_str_t *to,
- unsigned cred_cnt,
- const pjsip_cred_info cred[],
- const pjsip_route_hdr *route_set,
- void *test_data,
- void (*completion_cb)(void*,pj_bool_t))
-{
- pjsip_dialog *dlg;
- pjsip_inv_session *inv;
- pjsip_tx_data *tdata;
- struct call_data *call_data;
- pj_status_t status;
-
- /* Create outgoing dialog: */
- status = pjsip_dlg_create_uac( pjsip_ua_instance(),
- from, NULL,
- to, target,
- &dlg);
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Dialog creation failed", status);
- return status;
- }
-
- /* Create the INVITE session: */
- status = pjsip_inv_create_uac( dlg, local_sdp, 0, &inv);
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Invite session creation failed", status);
- goto on_error;
- }
-
-
- /* Set dialog Route-Set: */
- if (route_set)
- pjsip_dlg_set_route_set(dlg, route_set);
-
-
- /* Set credentials: */
- pjsip_auth_clt_set_credentials( &dlg->auth_sess, cred_cnt, cred);
-
-
- /* Create initial INVITE: */
- status = pjsip_inv_invite(inv, &tdata);
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Unable to create initial INVITE request",
- status);
- goto on_error;
- }
-
-
- /* Create and associate our call data */
- call_data = pj_pool_zalloc(inv->pool, sizeof(struct call_data));
- call_data->inv = inv;
- call_data->test_data = test_data;
- call_data->bye_timer.user_data = call_data;
- call_data->completion_cb = completion_cb;
-
- inv->mod_data[mod_call.id] = call_data;
-
-
- /* Send initial INVITE: */
- status = pjsip_inv_send_msg(inv, tdata);
- if (status != PJ_SUCCESS) {
- app_perror( THIS_FILE, "Unable to send initial INVITE request",
- status);
- goto on_error;
- }
-
-
- return PJ_SUCCESS;
-
-
-on_error:
- PJ_TODO(DESTROY_DIALOG_ON_FAIL);
- return status;
-}
-
-
-/* Timer callback to send BYE. */
-static void bye_callback( pj_timer_heap_t *ht, pj_timer_entry *e)
-{
- struct call_data *call_data = e->user_data;
- pjsip_tx_data *tdata;
- pj_status_t status;
-
- PJ_UNUSED_ARG(ht);
- PJ_UNUSED_ARG(e);
-
- e->id = 0;
-
- status = pjsip_inv_end_session(call_data->inv, PJSIP_SC_REQUEST_TIMEOUT,
- NULL, &tdata);
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Unable to create BYE", status);
- return;
- }
-
- status = pjsip_inv_send_msg(call_data->inv, tdata);
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Unable to send BYE", status);
- return;
- }
-
-}
-
-/*
- * This callback receives notification from invite session when the
- * session state has changed.
- */
-static void call_on_state_changed( pjsip_inv_session *inv, pjsip_event *e)
-{
- struct call_data *call_data;
-
- PJ_UNUSED_ARG(e);
-
- call_data = inv->mod_data[mod_call.id];
- if (call_data == NULL)
- return;
-
- /* Once call has been confirmed, schedule timer to terminate the call. */
- if (inv->state == PJSIP_INV_STATE_CONFIRMED) {
-
- pj_time_val interval;
-
- call_data->confirmed = PJ_TRUE;
-
- /* For UAC, schedule time to send BYE.
- * For UAS, schedule time to disconnect INVITE, just in case BYE
- * is not received.
- */
- if (inv->role == PJSIP_ROLE_UAC)
- interval.sec = settings.duration, interval.msec = 0;
- else
- interval.sec = settings.duration+5, interval.msec = 0;
-
- call_data->bye_timer.id = TIMER_ID;
- call_data->bye_timer.cb = &bye_callback;
- pjsip_endpt_schedule_timer(settings.endpt, &call_data->bye_timer,
- &interval);
-
- }
- /* If call has been terminated, cancel our timer, if any.
- * And call tester's callback.
- */
- else if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
-
- /* Cancel timer, if any. */
- if (call_data->bye_timer.id == TIMER_ID) {
- call_data->bye_timer.id = 0;
- pjsip_endpt_cancel_timer(settings.endpt, &call_data->bye_timer);
- }
-
- /* Detach call data from the invite session. */
- inv->mod_data[mod_call.id] = NULL;
-
- /* Call tester callback. */
- if (call_data->completion_cb) {
- (*call_data->completion_cb)(call_data->test_data,
- call_data->confirmed);
- }
- }
-}
-
-
-/*
- * This callback is called by invite session framework when UAC session
- * has forked.
- */
-static void call_on_forked( pjsip_inv_session *inv, pjsip_event *e)
-{
- PJ_UNUSED_ARG(inv);
- PJ_UNUSED_ARG(e);
-
- PJ_TODO(HANDLE_FORKED_DIALOG);
-}
-
-
-
-/****************************************************************************
- *
- * INITIALIZATION
- *
- ****************************************************************************
- */
-
-pj_status_t call_handler_init(void)
-{
- pjsip_inv_callback inv_cb;
- pjmedia_sock_info skinfo;
- pj_status_t status;
-
- /* Register incoming call handler. */
- status = pjsip_endpt_register_module(settings.endpt, &mod_call);
- if (status != PJ_SUCCESS) {
- app_perror( THIS_FILE, "Unable to register call handler",
- status);
- return status;
- }
-
- /* Invite session callback: */
- pj_memset(&inv_cb, 0, sizeof(inv_cb));
- inv_cb.on_state_changed = &call_on_state_changed;
- inv_cb.on_new_session = &call_on_forked;
-
- /* Initialize invite session module: */
- status = pjsip_inv_usage_init(settings.endpt, &inv_cb);
- if (status != PJ_SUCCESS) {
- app_perror( THIS_FILE, "Unable to initialize INVITE session module",
- status);
- return status;
- }
-
- /* Create dummy SDP. */
- pj_memset(&skinfo, 0, sizeof(skinfo));
- pj_sockaddr_in_init(&skinfo.rtp_addr_name, pj_gethostname(), 4000);
- pj_sockaddr_in_init(&skinfo.rtcp_addr_name, pj_gethostname(), 4001);
-
- status = pjmedia_endpt_create_sdp( settings.med_endpt, settings.pool,
- 1, &skinfo, &local_sdp);
- if (status != PJ_SUCCESS) {
- app_perror( THIS_FILE, "Unable to generate local SDP",
- status);
- return status;
- }
-
- return PJ_SUCCESS;
-}
-
-
diff --git a/pjsip-apps/src/pjsip-perf/handler_options.c b/pjsip-apps/src/pjsip-perf/handler_options.c
deleted file mode 100644
index bd14a724..00000000
--- a/pjsip-apps/src/pjsip-perf/handler_options.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2006 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
- */
-#include "pjsip_perf.h"
-
-
-/*
- * This file handles OPTIONS generator and incoming OPTIONS requests.
- */
-#define THIS_FILE "handler_options.c"
-
-
-/****************************************************************************
- *
- * INCOMING OPTIONS HANDLER
- *
- ****************************************************************************
- */
-
-
-static pj_bool_t mod_options_on_rx_request(pjsip_rx_data *rdata);
-
-
-/* The module instance. */
-static pjsip_module mod_perf_options =
-{
- NULL, NULL, /* prev, next. */
- { "mod-perf-options", 16 }, /* Name. */
- -1, /* Id */
- PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
- NULL, /* load() */
- NULL, /* start() */
- NULL, /* stop() */
- NULL, /* unload() */
- &mod_options_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_options_on_rx_request(pjsip_rx_data *rdata)
-{
- pjsip_msg *msg = rdata->msg_info.msg;
-
- if (msg->line.req.method.id == PJSIP_OPTIONS_METHOD) {
-
- if (settings.stateless) {
- pjsip_endpt_respond_stateless( settings.endpt, rdata, 200, NULL,
- NULL, NULL);
- } else {
-
- pjsip_endpt_respond( settings.endpt, NULL, rdata, 200, NULL,
- NULL, NULL, NULL);
- }
-
- return PJ_TRUE;
- }
-
- return PJ_FALSE;
-}
-
-
-/****************************************************************************
- *
- * OUTGOING OPTIONS GENERATOR.
- *
- ****************************************************************************
- */
-
-struct callback_data
-{
- void *test_data;
- void (*completion_cb)(void*,pj_bool_t);
-};
-
-static void options_callback(void *token, const pjsip_event *e)
-{
- struct callback_data *cb_data = token;
-
- if (e->type == PJSIP_EVENT_TSX_STATE) {
- (*cb_data->completion_cb)(cb_data->test_data,
- e->body.tsx_state.tsx->status_code/100==2);
- }
-}
-
-pj_status_t options_spawn_test(const pj_str_t *target,
- const pj_str_t *from,
- const pj_str_t *to,
- unsigned cred_cnt,
- const pjsip_cred_info cred[],
- const pjsip_route_hdr *route_set,
- void *test_data,
- void (*completion_cb)(void*,pj_bool_t))
-{
- pj_status_t status;
- struct callback_data *cb_data;
- pjsip_tx_data *tdata;
-
- PJ_LOG(5,(THIS_FILE,"Sending OPTIONS request.."));
-
- PJ_UNUSED_ARG(route_set);
- PJ_UNUSED_ARG(cred_cnt);
- PJ_UNUSED_ARG(cred);
-
- status = pjsip_endpt_create_request( settings.endpt,
- &pjsip_options_method,
- target,
- from,
- to,
- NULL, NULL, -1, NULL,
- &tdata);
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Unable to create request", status);
- return status;
- }
-
- cb_data = pj_pool_alloc(tdata->pool, sizeof(struct callback_data));
- cb_data->test_data = test_data;
- cb_data->completion_cb = completion_cb;
-
- status = pjsip_endpt_send_request( settings.endpt, tdata, -1,
- cb_data, &options_callback);
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Unable to send request", status);
- return status;
- }
-
- return PJ_SUCCESS;
-}
-
-
-pj_status_t options_handler_init(void)
-{
- return pjsip_endpt_register_module(settings.endpt, &mod_perf_options);
-}
-
-
diff --git a/pjsip-apps/src/pjsip-perf/main.c b/pjsip-apps/src/pjsip-perf/main.c
deleted file mode 100644
index da590248..00000000
--- a/pjsip-apps/src/pjsip-perf/main.c
+++ /dev/null
@@ -1,880 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2006 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
- */
-#include "pjsip_perf.h"
-#include <stdlib.h> /* atoi */
-
-#define THIS_FILE "main.c"
-
-pjsip_perf_settings settings;
-
-/* Show error message. */
-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(3,(sender, "%s: %s [code=%d]", title, errmsg, status));
-}
-
-
-/* Init default settings. */
-static void init_settings(void)
-{
- pj_status_t status;
-
- settings.stateless = 0;
- settings.start_rate = 10;
- settings.max_capacity = 64;
- settings.duration = 0;
- settings.thread_cnt = 1;
- settings.local_port = 5060;
- settings.log_level = 3;
- settings.app_log_level = 3;
-
- pjsip_method_set(&settings.method, PJSIP_OPTIONS_METHOD);
-
- pj_init();
-
- /* Create caching pool. */
- pj_caching_pool_init(&settings.cp, &pj_pool_factory_default_policy,
- 4 * 1024 * 1024);
-
- /* Create application pool. */
- settings.pool = pj_pool_create(&settings.cp.factory, "pjsip-perf", 1024,
- 1024, NULL);
-
- /* Create endpoint. */
- status = pjsip_endpt_create(&settings.cp.factory, NULL, &settings.endpt);
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Unable to create endpoint", status);
- return;
- }
-
-}
-
-/* Poll function. */
-static int PJ_THREAD_FUNC poll_pjsip(void *arg)
-{
- pj_status_t last_err = 0;
-
- PJ_UNUSED_ARG(arg);
-
- do {
- pj_time_val timeout = { 0, 10 };
- pj_status_t status;
-
- status = pjsip_endpt_handle_events (settings.endpt, &timeout);
- if (status != last_err) {
- last_err = status;
- app_perror(THIS_FILE, "handle_events() returned error", status);
- }
- } while (!settings.quit_flag);
-
- return 0;
-}
-
-/*****************************************************************************
- * This is a simple module to count and log messages
- */
-static void on_rx_msg(pjsip_rx_data *rdata)
-{
- PJ_LOG(5,(THIS_FILE, "RX %d bytes %s from %s:%d:\n"
- "%s\n"
- "--end msg--",
- rdata->msg_info.len,
- pjsip_rx_data_get_info(rdata),
- rdata->pkt_info.src_name,
- rdata->pkt_info.src_port,
- rdata->msg_info.msg_buf));
-}
-
-static void on_tx_msg(pjsip_tx_data *tdata)
-{
- PJ_LOG(5,(THIS_FILE, "TX %d bytes %s to %s:%d:\n"
- "%s\n"
- "--end msg--",
- (tdata->buf.cur - tdata->buf.start),
- pjsip_tx_data_get_info(tdata),
- tdata->tp_info.dst_name,
- tdata->tp_info.dst_port,
- tdata->buf.start));
-}
-
-static pj_bool_t mod_counter_on_rx_request(pjsip_rx_data *rdata)
-{
- settings.rx_req++;
- on_rx_msg(rdata);
- return PJ_FALSE;
-}
-
-static pj_bool_t mod_counter_on_rx_response(pjsip_rx_data *rdata)
-{
- settings.rx_res++;
- on_rx_msg(rdata);
- return PJ_FALSE;
-}
-
-static pj_status_t mod_counter_on_tx_request(pjsip_tx_data *tdata)
-{
- settings.tx_req++;
- on_tx_msg(tdata);
- return PJ_SUCCESS;
-}
-
-static pj_status_t mod_counter_on_tx_response(pjsip_tx_data *tdata)
-{
- settings.tx_res++;
- on_tx_msg(tdata);
- return PJ_SUCCESS;
-}
-
-static pjsip_module mod_counter =
-{
- NULL, NULL, /* prev, next. */
- { "mod-counter", 11 }, /* Name. */
- -1, /* Id */
- PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority */
- NULL, /* load() */
- NULL, /* start() */
- NULL, /* stop() */
- NULL, /* unload() */
- &mod_counter_on_rx_request, /* on_rx_request() */
- &mod_counter_on_rx_response, /* on_rx_response() */
- &mod_counter_on_tx_request, /* on_tx_request. */
- &mod_counter_on_tx_response, /* on_tx_response() */
- NULL, /* on_tsx_state() */
-
-};
-
-
-/*****************************************************************************
- * Console application custom logging:
- */
-
-
-static FILE *log_file;
-static void app_log_writer(int level, const char *buffer, int len)
-{
- /* Write to both stdout and file. */
- if (level <= settings.app_log_level)
- pj_log_write(level, buffer, len);
-
- if (log_file) {
- fwrite(buffer, len, 1, log_file);
- fflush(log_file);
- }
-}
-
-
-static pj_status_t app_logging_init(void)
-{
- /* Redirect log function to ours */
-
- pj_log_set_log_func( &app_log_writer );
-
- /* If output log file is desired, create the file: */
-
- if (settings.log_file) {
- log_file = fopen(settings.log_file, "wt");
- if (log_file == NULL) {
- PJ_LOG(1,(THIS_FILE, "Unable to open log file %s",
- settings.log_file));
- return -1;
- }
- }
-
- return PJ_SUCCESS;
-}
-
-
-void app_logging_shutdown(void)
-{
- /* Close logging file, if any: */
- if (log_file) {
- fclose(log_file);
- log_file = NULL;
- }
-}
-
-
-/* Initialize */
-static pj_status_t initialize(void)
-{
- pj_sockaddr_in addr;
- int i;
- pj_status_t status;
-
- /* Init logging */
- if (app_logging_init() != PJ_SUCCESS)
- return -1;
-
- /* Create UDP transport. */
- pj_memset(&addr, 0, sizeof(addr));
- addr.sin_family = PJ_AF_INET;
- addr.sin_port = pj_htons((pj_uint16_t)settings.local_port);
- status = pjsip_udp_transport_start(settings.endpt, &addr, NULL,
- settings.thread_cnt, NULL);
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Unable to start UDP transport", status);
- return status;
- }
-
-
- /* Initialize transaction layer: */
- status = pjsip_tsx_layer_init_module(settings.endpt);
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Transaction layer initialization error",
- status);
- return status;
- }
-
- /* Initialize UA layer module: */
- pjsip_ua_init_module( settings.endpt, NULL );
-
- /* Init core SIMPLE module : */
- pjsip_evsub_init_module(settings.endpt);
-
- /* Init presence module: */
- pjsip_pres_init_module( settings.endpt, pjsip_evsub_instance());
-
- /* Init xfer/REFER module */
- pjsip_xfer_init_module( settings.endpt );
-
- /* Init multimedia endpoint. */
- status = pjmedia_endpt_create(&settings.cp.factory,
- pjsip_endpt_get_ioqueue(settings.endpt), 0,
- &settings.med_endpt);
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Unable to create media endpoint",
- status);
- return status;
- }
-
- /* Init OPTIONS test handler */
- status = options_handler_init();
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Unable to create OPTIONS handler", status);
- return status;
- }
-
- /* Init call test handler */
- status = call_handler_init();
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Unable to initialize call handler", status);
- return status;
- }
-
-
- /* Register message counter module. */
- status = pjsip_endpt_register_module(settings.endpt, &mod_counter);
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Unable to register module", status);
- return status;
- }
-
- /* Start worker thread. */
- for (i=0; i<settings.thread_cnt; ++i) {
- status = pj_thread_create(settings.pool, "pjsip-perf", &poll_pjsip,
- NULL, 0, 0, &settings.thread[i]);
- if (status != PJ_SUCCESS) {
- app_perror(THIS_FILE, "Unable to create thread", status);
- return status;
- }
- }
-
- pj_log_set_level(settings.log_level);
- return PJ_SUCCESS;
-}
-
-
-/* Shutdown */
-static void shutdown(void)
-{
- int i;
-
- /* Signal and wait worker thread to quit. */
- settings.quit_flag = 1;
-
- for (i=0; i<settings.thread_cnt; ++i) {
- pj_thread_join(settings.thread[i]);
- pj_thread_destroy(settings.thread[i]);
- }
-
- pjsip_endpt_destroy(settings.endpt);
- pj_caching_pool_destroy(&settings.cp);
-}
-
-
-/* Verify that valid SIP url is given. */
-pj_status_t verify_sip_url(const char *c_url)
-{
- pjsip_uri *p;
- pj_pool_t *pool;
- char *url;
- int len = (c_url ? pj_ansi_strlen(c_url) : 0);
-
- if (!len) return -1;
-
- pool = pj_pool_create(&settings.cp.factory, "check%p", 1024, 0, NULL);
- if (!pool) return -1;
-
- url = pj_pool_alloc(pool, len+1);
- pj_ansi_strcpy(url, c_url);
-
- p = pjsip_parse_uri(pool, url, len, 0);
- if (!p || pj_stricmp2(pjsip_uri_get_scheme(p), "sip") != 0)
- p = NULL;
-
- pj_pool_release(pool);
- return p ? 0 : -1;
-}
-
-
-
-/* Usage */
-static void usage(void)
-{
- puts("Usage:");
- puts(" pjsip-perf [options] [target]");
- puts("where");
- puts(" target Optional default target URL");
- puts("");
- puts("General options:");
- puts(" --help Display this help screen");
- puts(" --version Display version info");
- puts("");
- puts("Logging options:");
- puts(" --log-level=N Set log verbosity (default=3)");
- puts(" --app-log-level=N Set screen log verbosity (default=3)");
- puts(" --log-file=FILE Save log to FILE");
- puts("");
- puts("SIP options:");
- puts(" --local-port=N SIP local port");
- puts(" --stateless Handle incoming request statelessly if possible");
- puts(" --thread-cnt=N Number of worker threads (default=1)");
- puts("");
- puts("Rate control:");
- puts(" --start-rate=N Start rate in tasks per seconds (default=1)");
- puts("");
- puts("Capacity control:");
- puts(" --max-capacity=N Maximum outstanding sessions (default=64)");
- puts("");
- puts("Duration control:");
- puts(" --duration=secs Sessions duration (default=0)");
- puts("");
-}
-
-
-/* Read options. */
-static pj_status_t parse_options(int argc, char *argv[])
-{
- enum {
- OPT_HELP,
- OPT_VERSION,
- OPT_LOG_LEVEL,
- OPT_APP_LOG_LEVEL,
- OPT_LOG_FILE,
- OPT_LOCAL_PORT,
- OPT_STATELESS,
- OPT_THREAD_CNT,
- OPT_START_RATE,
- OPT_MAX_CAPACITY,
- OPT_DURATION
- };
- struct pj_getopt_option long_opts[] = {
- { "help", 0, 0, OPT_HELP},
- { "version", 0, 0, OPT_VERSION},
- { "log-level", 1, 0, OPT_LOG_LEVEL},
- { "app-log-level", 1, 0, OPT_APP_LOG_LEVEL},
- { "log-file", 1, 0, OPT_LOG_FILE},
- { "local-port", 1, 0, OPT_LOCAL_PORT},
- { "stateless", 0, 0, OPT_STATELESS},
- { "thread-cnt", 1, 0, OPT_THREAD_CNT},
- { "start-rate", 1, 0, OPT_START_RATE},
- { "max-capacity", 1, 0, OPT_MAX_CAPACITY},
- { "duration", 1, 0, OPT_DURATION},
- { NULL, 0, 0, 0}
- };
- int c, option_index;
-
- pj_optind = 0;
- while ((c=pj_getopt_long(argc, argv, "", long_opts, &option_index)) != -1) {
- switch (c) {
-
- case OPT_HELP:
- usage();
- return PJ_EINVAL;
-
- case OPT_VERSION:
- pj_dump_config();
- return PJ_EINVAL;
-
- case OPT_LOG_LEVEL:
- settings.log_level = atoi(pj_optarg);
- break;
-
- case OPT_APP_LOG_LEVEL:
- settings.app_log_level = atoi(pj_optarg);
- break;
-
- case OPT_LOG_FILE:
- settings.log_file = pj_optarg;
- break;
-
- case OPT_LOCAL_PORT:
- settings.local_port = atoi(pj_optarg);
- if (settings.local_port < 1 || settings.local_port > 65535) {
- PJ_LOG(1,(THIS_FILE,"Invalid --local-port %s", pj_optarg));
- return PJ_EINVAL;
- }
- break;
-
- case OPT_STATELESS:
- settings.stateless = 1;
- break;
-
- case OPT_THREAD_CNT:
- settings.thread_cnt = atoi(pj_optarg);
- if (settings.thread_cnt < 1 ||
- settings.thread_cnt > PJ_ARRAY_SIZE(settings.thread))
- {
- PJ_LOG(1,(THIS_FILE,"Invalid --thread-cnt %s", pj_optarg));
- return PJ_EINVAL;
- }
- break;
-
- case OPT_START_RATE:
- settings.start_rate = atoi(pj_optarg);
- if (settings.start_rate < 1 || settings.start_rate > 1000000) {
- PJ_LOG(1,(THIS_FILE,"Invalid --start-rate %s", pj_optarg));
- return PJ_EINVAL;
- }
- break;
-
- case OPT_MAX_CAPACITY:
- settings.max_capacity = atoi(pj_optarg);
- if (settings.max_capacity < 1 || settings.max_capacity > 65000) {
- PJ_LOG(1,(THIS_FILE,
- "Invalid --max-capacity %s (range=1-65000)",
- pj_optarg));
- return PJ_EINVAL;
- }
- break;
-
- case OPT_DURATION:
- settings.duration = atoi(pj_optarg);
- if (settings.duration < 0 || settings.duration > 1000000) {
- PJ_LOG(1,(THIS_FILE,"Invalid --duration %s", pj_optarg));
- return PJ_EINVAL;
- }
- break;
-
- }
- }
-
- if (pj_optind != argc) {
- if (verify_sip_url(argv[pj_optind]) != PJ_SUCCESS) {
- PJ_LOG(3,(THIS_FILE, "Invalid SIP URL %s", argv[pj_optind]));
- return PJ_EINVAL;
- }
-
- settings.target = pj_str(argv[pj_optind]);
- ++pj_optind;
- }
-
- if (pj_optind != argc) {
- printf("Error: unknown options %s\n", argv[pj_optind]);
- return PJ_EINVAL;
- }
-
- return PJ_SUCCESS;
-}
-
-
-static void spawn_batch( pj_timer_heap_t *timer_heap,
- struct pj_timer_entry *entry );
-
-/* Completion callback. */
-static void completion_cb(void *token, pj_bool_t success)
-{
- batch *batch = token;
-
- if (success)
- batch->success++;
- else
- batch->failed++;
-
- if (batch->success+batch->failed == batch->rate) {
- pj_time_val elapsed, sess_elapsed;
- unsigned msec;
-
- pj_gettimeofday(&batch->end_time);
- elapsed = sess_elapsed = batch->end_time;
-
- /* Batch time. */
- PJ_TIME_VAL_SUB(elapsed, batch->start_time);
- msec = PJ_TIME_VAL_MSEC(elapsed);
- if (msec == 0) msec = 1;
-
- /* Session time */
- PJ_TIME_VAL_SUB(sess_elapsed, settings.session->start_time);
-
- /* Spawn time */
- PJ_TIME_VAL_SUB(batch->spawned_time, batch->start_time);
-
- if (batch->failed) {
- PJ_LOG(2,(THIS_FILE,
- "%02d:%02d:%02d: %d tasks in %d.%ds (%d tasks/sec), "
- "spawn=time=%d.%d, FAILED=%d",
- (sess_elapsed.sec / 3600),
- (sess_elapsed.sec % 3600) / 60,
- (sess_elapsed.sec % 60),
- batch->rate,
- elapsed.sec, elapsed.msec,
- batch->rate * 1000 / msec,
- batch->spawned_time.sec,
- batch->spawned_time.msec,
- batch->failed));
- } else {
- PJ_LOG(3,(THIS_FILE,
- "%02d:%02d:%02d: %d tasks in %d.%ds (%d tasks/sec), "
- "spawn=time=%d.%d",
- (sess_elapsed.sec / 3600),
- (sess_elapsed.sec % 3600) / 60,
- (sess_elapsed.sec % 60),
- batch->rate,
- elapsed.sec, elapsed.msec,
- batch->rate * 1000 / msec,
- batch->spawned_time.sec,
- batch->spawned_time.msec));
- }
-
- if (!settings.session->stopping) {
- pj_time_val interval;
-
- if (msec >= 1000)
- interval.sec = interval.msec = 0;
- else
- interval.sec = 0, interval.msec = 1000-msec;
-
- settings.timer.cb = &spawn_batch;
- pjsip_endpt_schedule_timer( settings.endpt, &settings.timer, &interval);
- } else {
- PJ_LOG(3,(THIS_FILE, "%.*s test session completed",
- (int)settings.session->method.name.slen,
- settings.session->method.name.ptr));
- pj_pool_release(settings.session->pool);
- settings.session = NULL;
- }
- }
-}
-
-/* Spawn new batch. */
-static void spawn_batch( pj_timer_heap_t *timer_heap,
- struct pj_timer_entry *entry )
-{
- session *sess = settings.session;
- batch *batch;
- pj_status_t status = PJ_SUCCESS;
- pjsip_cred_info cred_info[1];
- pj_time_val elapsed;
-
- unsigned i;
-
- PJ_UNUSED_ARG(timer_heap);
- PJ_UNUSED_ARG(entry);
-
- if (!pj_list_empty(&sess->free_list)) {
- batch = sess->free_list.next;
- pj_list_erase(batch);
- } else {
- batch = pj_pool_alloc(sess->pool, sizeof(struct batch));
- }
-
- pj_gettimeofday(&batch->start_time);
- batch->rate = settings.cur_rate;
- batch->started = 0;
- batch->success = 0;
- batch->failed = 0;
- pj_gettimeofday(&batch->start_time);
- batch->spawned_time = batch->start_time;
-
- pj_list_push_back(&sess->active_list, batch);
-
- for (i=0; i<batch->rate; ++i) {
- pj_str_t from = { "sip:user@127.0.0.1", 18};
-
- if (sess->method.id == PJSIP_OPTIONS_METHOD) {
- status = options_spawn_test(&settings.target, &from,
- &settings.target,
- 0, cred_info, NULL, batch,
- &completion_cb);
- } else if (sess->method.id == PJSIP_INVITE_METHOD) {
- status = call_spawn_test( &settings.target, &from,
- &settings.target,
- 0, cred_info, NULL, batch,
- &completion_cb);
- }
- if (status != PJ_SUCCESS)
- break;
-
- batch->started++;
-
- elapsed.sec = elapsed.msec = 0;
- pjsip_endpt_handle_events(settings.endpt, &elapsed);
- }
-
- pj_gettimeofday(&batch->spawned_time);
-
- ///
-#if 0
- elapsed = batch->spawned_time;
- PJ_TIME_VAL_SUB(elapsed, batch->start_time);
- PJ_LOG(2,(THIS_FILE, "%d requests sent in %d ms", batch->started,
- PJ_TIME_VAL_MSEC(elapsed)));
-#endif
-
- sess->total_created += batch->started;
-
- batch = sess->active_list.next;
- sess->outstanding = 0;
- while (batch != &sess->active_list) {
- sess->outstanding += (batch->started - batch->success - batch->failed);
-
- if (batch->started == batch->success + batch->failed) {
- struct batch *next = batch->next;
- pj_list_erase(batch);
- pj_list_push_back(&sess->free_list, batch);
- batch = next;
- } else {
- batch = batch->next;
- }
- }
-}
-
-
-/* Start new session */
-static void start_session(pj_bool_t auto_repeat)
-{
- pj_time_val interval = { 0, 0 };
- pj_pool_t *pool;
- session *sess;
-
- pool = pjsip_endpt_create_pool(settings.endpt, "session", 4000, 4000);
- if (!pool) {
- app_perror(THIS_FILE, "Unable to create pool", PJ_ENOMEM);
- return;
- }
-
- sess = pj_pool_zalloc(pool, sizeof(session));
- sess->pool = pool;
- sess->stopping = auto_repeat ? 0 : 1;
- sess->method = settings.method;
-
- pj_list_init(&sess->active_list);
- pj_list_init(&sess->free_list);
- pj_gettimeofday(&sess->start_time);
-
- settings.session = sess;
-
- settings.timer.cb = &spawn_batch;
- pjsip_endpt_schedule_timer( settings.endpt, &settings.timer, &interval);
-}
-
-
-/* Dump state */
-static void dump(pj_bool_t detail)
-{
- pjsip_endpt_dump(settings.endpt, detail);
- pjsip_tsx_layer_dump(detail);
- pjsip_ua_dump(detail);
-}
-
-
-/* help screen */
-static void help_screen(void)
-{
- puts ("+============================================================================+");
- printf("| Current mode: %-10s Current rate: %-5d Call Capacity: %-7d |\n",
- settings.method.name.ptr, settings.cur_rate, settings.max_capacity);
- printf("| Call Duration: %-7d |\n",
- settings.duration);
-
- printf("| Total tx requests: %-7u rx requests: %-7u |\n",
- settings.tx_req, settings.rx_req);
- printf("| tx responses: %-7u rx responses: %-7u |\n",
- settings.tx_res, settings.rx_res);
- puts ("+--------------------------------------+-------------------------------------+");
- puts ("| Test Settings | Misc Commands: |");
- puts ("| | |");
- puts ("| m Change mode | |");
- puts ("| + - Increment/decrement rate by 10 | d Dump status |");
- puts ("| * / Increment/decrement rate by 100 | dd Dump detailed (e.g. tables) |");
- puts ("+--------------------------------------+-------------------------------------+");
- puts ("| Test Commands |");
- puts ("| |");
- puts ("| s Start single test batch c Clear counters |");
- puts ("| sc Start continuous test x Stop continuous tests |");
- puts ("+----------------------------------------------------------------------------+");
- puts ("| q: Quit |");
- puts ("+============================================================================+");
- puts ("");
-
-}
-
-/*
- * Input simple string
- */
-static pj_bool_t simple_input(const char *title, char *buf, pj_size_t len)
-{
- char *p;
-
- printf("%s (empty to cancel): ", title); fflush(stdout);
- fgets(buf, len, stdin);
-
- /* Remove trailing newlines. */
- for (p=buf; ; ++p) {
- if (*p=='\r' || *p=='\n') *p='\0';
- else if (!*p) break;
- }
-
- if (!*buf)
- return PJ_FALSE;
-
- return PJ_TRUE;
-}
-
-/* Main input loop */
-static void test_main(void)
-{
- char menuin[10];
- char input[80];
-
- settings.cur_rate = settings.start_rate;
-
- help_screen();
-
- for (;;) {
- printf(">>>> "); fflush(stdout);
-
- fgets(menuin, sizeof(menuin), stdin);
-
- switch (menuin[0]) {
- case 's':
- if (settings.session != NULL) {
- PJ_LOG(3,(THIS_FILE,"Error: another session is in progress"));
- } else if (settings.target.slen == 0) {
- PJ_LOG(3,(THIS_FILE,"Error: target URL is not configured"));
- } else {
- start_session(menuin[1]=='c');
- }
- break;
-
- case 'x':
- if (settings.session) {
- settings.session->stopping = 1;
- puts("Stopping sessions...");
- } else {
- PJ_LOG(3,(THIS_FILE,"Error: no sessions"));
- }
- break;
-
- case 'c':
- /* Clear counters */
- settings.rx_req = settings.rx_res = settings.tx_req =
- settings.tx_res = 0;
- puts("Counters cleared");
- break;
-
- case 'm':
- if (!simple_input("Change method [OPTIONS,INVITE]", input, sizeof(input)))
- continue;
-
- if (pj_ansi_stricmp(input, "OPTIONS")==0)
- pjsip_method_set(&settings.method, PJSIP_OPTIONS_METHOD);
- else if (pj_ansi_stricmp(input, "INVITE")==0)
- pjsip_method_set(&settings.method, PJSIP_INVITE_METHOD);
- else {
- puts("Error: invalid method");
- }
- break;
-
- case 'd':
- dump(menuin[1]=='d');
- break;
-
- case '+':
- settings.cur_rate += 10;
- PJ_LOG(3,(THIS_FILE, "Rate is now %d", settings.cur_rate));
- break;
-
- case '-':
- if (settings.cur_rate > 10) {
- settings.cur_rate -= 10;
- PJ_LOG(3,(THIS_FILE, "Rate is now %d", settings.cur_rate));
- }
- break;
-
- case '*':
- settings.cur_rate += 100;
- PJ_LOG(3,(THIS_FILE, "Rate is now %d", settings.cur_rate));
- break;
-
- case '/':
- if (settings.cur_rate > 100) {
- settings.cur_rate -= 100;
- PJ_LOG(3,(THIS_FILE, "Rate is now %d", settings.cur_rate));
- }
- break;
-
- case 'q':
- return;
-
- default:
- help_screen();
- break;
-
- }
- }
-}
-
-
-/* main() */
-int main(int argc, char *argv[])
-{
- pj_status_t status;
-
- init_settings();
-
- status = parse_options(argc, argv);
- if (status != PJ_SUCCESS)
- return 1;
-
- status = initialize();
- if (status != PJ_SUCCESS)
- return 1;
-
-
- test_main();
-
- shutdown();
-
- return 0;
-}
-
diff --git a/pjsip-apps/src/pjsip-perf/pjsip_perf.h b/pjsip-apps/src/pjsip-perf/pjsip_perf.h
deleted file mode 100644
index 6c5372e3..00000000
--- a/pjsip-apps/src/pjsip-perf/pjsip_perf.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2006 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
- */
-#ifndef __PJSIP_PERF_H__
-#define __PJSIP_PERF_H__
-
-#include <pjsua-lib/pjsua.h>
-
-
-PJ_BEGIN_DECL
-
-
-typedef struct batch batch;
-typedef struct session session;
-
-/**
- * A test batch.
- */
-struct batch
-{
- PJ_DECL_LIST_MEMBER(struct batch);
-
- unsigned rate; /**< How many tasks to perform */
-
- unsigned started; /**< # of tasks started. */
- unsigned success; /**< # of tasks completed successfully. */
- unsigned failed; /**< # of failed tasks. */
-
- pj_time_val start_time; /**< Start time of the tests. */
- pj_time_val spawned_time; /**< Time when all tasks has been started. */
- pj_time_val end_time; /**< Time when all tasks has completed. */
-};
-
-/**
- * Test session.
- */
-struct session
-{
- pj_pool_t *pool;
- pj_time_val start_time;
- pj_bool_t stopping;
- pjsip_method method;
- struct batch active_list;
- struct batch free_list;
-
- unsigned outstanding;
- unsigned total_created;
-};
-
-
-/**
- * Request parameter.
- */
-struct request_param
-{
- pj_str_t dst;
- pj_str_t src;
- pjsip_cred_info cred;
-};
-
-
-typedef struct request_param request_param;
-
-
-void app_perror(const char *sender, const char *title, pj_status_t status);
-
-/* OPTIONS test */
-pj_status_t options_handler_init(void);
-pj_status_t options_spawn_test(const pj_str_t *target,
- const pj_str_t *from,
- const pj_str_t *to,
- unsigned cred_cnt,
- const pjsip_cred_info cred[],
- const pjsip_route_hdr *route_set,
- void *test_data,
- void (*completion_cb)(void*,pj_bool_t));
-
-/* CALL test */
-pj_status_t call_handler_init(void);
-pj_status_t call_spawn_test( const pj_str_t *target,
- const pj_str_t *from,
- const pj_str_t *to,
- unsigned cred_cnt,
- const pjsip_cred_info cred[],
- const pjsip_route_hdr *route_set,
- void *test_data,
- void (*completion_cb)(void*,pj_bool_t));
-
-
-
-/**
- * Global settings
- */
-struct pjsip_perf_settings
-{
- /* Global */
- pj_caching_pool cp;
- pj_pool_t *pool;
- pjsip_endpoint *endpt;
- pj_mutex_t *mutex;
-
- /* Misc: */
- int log_level;
- int app_log_level;
- char *log_file;
-
- /* Network: */
- int local_port;
-
- /* Threads. */
- pj_bool_t quit_flag;
- int thread_cnt;
- pj_thread_t *thread[16];
-
- /* Outgoing request method: */
- pjsip_method method;
-
- /* Default target: */
- pj_str_t target;
-
- /* Media: */
- pjmedia_endpt *med_endpt;
- pjmedia_conf *mconf;
-
- /* Handling incoming requests: */
- pj_bool_t stateless;
-
- /* Rate control. */
- pj_uint32_t start_rate;
- pj_uint32_t cur_rate;
-
- /* Capacity control. */
- pj_uint32_t max_capacity;
-
- /* Duration control: */
- pj_uint32_t duration;
-
- /* Test control: */
- session *session;
- pj_timer_entry timer;
-
- /* Counters: */
- pj_uint32_t tx_req;
- pj_uint32_t tx_res;
- pj_uint32_t rx_req;
- pj_uint32_t rx_res;
-};
-
-
-typedef struct pjsip_perf_settings pjsip_perf_settings;
-
-extern pjsip_perf_settings settings;
-
-
-
-PJ_END_DECL
-
-
-#endif /* __PJSIP_PERF_H__ */
-
-
-
-
diff --git a/pjsip-apps/src/samples/pjsip-perf.c b/pjsip-apps/src/samples/pjsip-perf.c
index dbc6fb21..7f41668c 100644
--- a/pjsip-apps/src/samples/pjsip-perf.c
+++ b/pjsip-apps/src/samples/pjsip-perf.c
@@ -66,9 +66,19 @@
#include <pjlib.h>
#include <stdio.h>
-#define THIS_FILE "pjsip-perf.c"
-#define DEFAULT_COUNT (PJSIP_MAX_TSX_COUNT/2>10000?10000:PJSIP_MAX_TSX_COUNT/2)
-#define JOB_WINDOW DEFAULT_COUNT
+#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 DEFAULT_COUNT
+#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
@@ -138,6 +148,7 @@ struct app
job_submitted,
job_finished,
job_window;
+ unsigned stat_max_window;
pj_time_val first_request;
pj_time_val last_completion;
unsigned total_responses;
@@ -587,7 +598,8 @@ static pj_status_t create_app(void)
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
/* Must create a pool factory before we can allocate any memory. */
- pj_caching_pool_init(&app.cp, &pj_pool_factory_default_policy, 0);
+ pj_caching_pool_init(&app.cp, &pj_pool_factory_default_policy,
+ CACHING_POOL_SIZE);
/* Create application pool for misc. */
app.pool = pj_pool_create(&app.cp.factory, "app", 1000, 1000, NULL);
@@ -632,7 +644,7 @@ static pj_status_t init_sip()
pjsip_tpfactory *tpfactory;
transport_type = "tcp";
- pj_sockaddr_in_init(&local_addr, 0, app.local_port);
+ pj_sockaddr_in_init(&local_addr, 0, (pj_uint16_t)app.local_port);
status = pjsip_tcp_transport_start(app.sip_endpt, &local_addr,
app.thread_count, &tpfactory);
if (status == PJ_SUCCESS) {
@@ -975,6 +987,7 @@ static void usage(void)
" --thread-count=N Set number of worker threads (default=1)\n"
" --stateless, -s Set client to operate in stateless mode\n"
" (default: stateful)\n"
+ " --window=COUNT, -w Set maximum outstanding job in client (default: %d)\n"
" --real-sdp Generate real SDP from pjmedia, and also perform\n"
" proper SDP negotiation (default: dummy)\n"
" --timeout=SEC, -t Set client timeout (default=60 sec)\n"
@@ -985,7 +998,7 @@ static void usage(void)
" - sip:0@server-addr To handle requests statelessly (non-INVITE only)\n"
" - sip:1@server-addr To handle requests statefully (INVITE and non-INVITE)\n"
" - sip:2@server-addr To handle INVITE call (INVITE only)\n",
- DEFAULT_COUNT);
+ DEFAULT_COUNT, JOB_WINDOW);
}
@@ -1010,6 +1023,7 @@ static pj_status_t init_options(int argc, char *argv[])
{ "real-sdp", 0, 0, OPT_REAL_SDP },
{ "verbose", 0, 0, 'v' },
{ "use-tcp", 0, 0, 'T' },
+ { "window", 1, 0, 'w' },
{ NULL, 0, 0, 0 },
};
int c;
@@ -1026,7 +1040,7 @@ static pj_status_t init_options(int argc, char *argv[])
/* Parse options */
pj_optind = 0;
- while((c=pj_getopt_long(argc,argv, "p:c:m:t:hsv",
+ while((c=pj_getopt_long(argc,argv, "p:c:m:t:w:hsv",
long_options, &option_index))!=-1)
{
switch (c) {
@@ -1090,6 +1104,14 @@ static pj_status_t init_options(int argc, char *argv[])
}
break;
+ case 'w':
+ app.client.job_window = my_atoi(pj_optarg);
+ if (app.client.job_window <= 0) {
+ PJ_LOG(3,(THIS_FILE, "Invalid --window %s", pj_optarg));
+ return -1;
+ }
+ break;
+
case 'T':
app.use_tcp = PJ_TRUE;
break;
@@ -1183,7 +1205,7 @@ static void tsx_completion_cb(void *token, pjsip_event *event)
report_completion(tsx->status_code);
tsx->mod_data[mod_test.id] = (void*)1;
- pjsip_tsx_terminate(tsx, tsx->status_code);
+ TERMINATE_TSX(tsx, tsx->status_code);
}
}
@@ -1219,6 +1241,7 @@ static pj_status_t submit_job(void)
/* Client worker thread */
static int client_thread(void *arg)
{
+ unsigned last_timeout_check = 0;
pj_time_val end_time, now;
PJ_UNUSED_ARG(arg);
@@ -1239,15 +1262,23 @@ static int client_thread(void *arg)
int outstanding;
pj_status_t status;
+ /* Calculate current outstanding job */
+ outstanding = app.client.job_submitted - app.client.job_finished;
+
+ /* Update stats on max outstanding jobs */
+ if (outstanding > (int)app.client.stat_max_window)
+ app.client.stat_max_window = outstanding;
+
/* Wait if there are more pending jobs than allowed in the
* window.
*/
- outstanding = app.client.job_submitted - app.client.job_finished;
- while (outstanding >= (int)app.client.job_window) {
+ for (i=0; outstanding > (int)app.client.job_window && i<100; ++i) {
pjsip_endpt_handle_events(app.sip_endpt, &timeout);
outstanding = app.client.job_submitted - app.client.job_finished;
}
+
+ /* Submit one job */
if (app.client.method.id == PJSIP_INVITE_METHOD) {
status = make_call(&app.client.dst_uri);
} else if (app.client.stateless) {
@@ -1258,11 +1289,15 @@ static int client_thread(void *arg)
++app.client.job_submitted;
- for (i=0; i<2; ++i) {
- unsigned cnt=0;
- pjsip_endpt_handle_events2(app.sip_endpt, &timeout, &cnt);
- if (cnt==0)
+ /* Handle event */
+ pjsip_endpt_handle_events2(app.sip_endpt, &timeout, NULL);
+
+ /* Check for time out */
+ if (app.client.job_submitted - last_timeout_check >= 2000) {
+ pj_gettimeofday(&now);
+ if (PJ_TIME_VAL_GTE(now, end_time))
break;
+ last_timeout_check = app.client.job_submitted;
}
}
@@ -1271,11 +1306,8 @@ static int client_thread(void *arg)
pj_time_val timeout = { 0, 0 };
unsigned i;
- for (i=0; i<2; ++i) {
- unsigned cnt=0;
- pjsip_endpt_handle_events2(app.sip_endpt, &timeout, &cnt);
- if (cnt==0)
- break;
+ for (i=0; i<2000; ++i) {
+ pjsip_endpt_handle_events2(app.sip_endpt, &timeout, NULL);
}
pj_gettimeofday(&now);
@@ -1352,7 +1384,7 @@ static int server_thread(void *arg)
good_number(str_stateful, app.server.cur_state.stateful_cnt);
good_number(str_call, app.server.cur_state.call_cnt);
- printf("Total(rate): stateless:%s (%d/s), statefull:%s (%d/s), call:%s (%d/s)\r",
+ printf("Total(rate): stateless:%s (%d/s), statefull:%s (%d/s), call:%s (%d/s) \r",
str_stateless, stateless*1000/msec,
str_stateful, stateful*1000/msec,
str_call, call*1000/msec);
@@ -1366,8 +1398,20 @@ static int server_thread(void *arg)
return 0;
}
+static void write_report(const char *msg)
+{
+ puts(msg);
+
+#if defined(PJ_WIN32) && PJ_WIN32!=0
+ OutputDebugString(msg);
+ OutputDebugString("\n");
+#endif
+}
+
+
int main(int argc, char *argv[])
{
+ static char report[1024];
if (create_app() != 0)
return 1;
@@ -1458,24 +1502,33 @@ int main(int argc, char *argv[])
if (msec == 0) msec = 1;
- printf("Total %d %s sent, %d responses received in %d msec:\n"
- " - 2xx responses: %7d (rate=%d/sec)\n"
- " - 3xx responses: %7d (rate=%d/sec)\n"
- " - 4xx responses: %7d (rate=%d/sec)\n"
- " - 5xx responses: %7d (rate=%d/sec)\n"
- " - 6xx responses: %7d (rate=%d/sec)\n"
- " - 7xx responses: %7d (rate=%d/sec)\n"
- " ----------------\n"
- " TOTAL responses: %7d (rate=%d/sec)\n",
- app.client.job_submitted, test_type,
- app.client.total_responses, msec,
- app.client.status_class[2], app.client.status_class[2]*1000/msec,
- app.client.status_class[3], app.client.status_class[3]*1000/msec,
- app.client.status_class[4], app.client.status_class[4]*1000/msec,
- app.client.status_class[5], app.client.status_class[5]*1000/msec,
- app.client.status_class[6], app.client.status_class[6]*1000/msec,
- app.client.status_class[7], app.client.status_class[7]*1000/msec,
- app.client.total_responses, app.client.total_responses*1000/msec);
+ pj_ansi_snprintf(
+ report, sizeof(report),
+ "Total %d %s sent, %d responses received in %d ms:\n"
+ " - 2xx responses: %7d (rate=%d/sec)\n"
+ " - 3xx responses: %7d (rate=%d/sec)\n"
+ " - 4xx responses: %7d (rate=%d/sec)\n"
+ " - 5xx responses: %7d (rate=%d/sec)\n"
+ " - 6xx responses: %7d (rate=%d/sec)\n"
+ " - 7xx responses: %7d (rate=%d/sec)\n"
+ " ----------------\n"
+ " TOTAL responses: %7d (rate=%d/sec)\n",
+ app.client.job_submitted, test_type,
+ app.client.total_responses, msec,
+ app.client.status_class[2], app.client.status_class[2]*1000/msec,
+ app.client.status_class[3], app.client.status_class[3]*1000/msec,
+ app.client.status_class[4], app.client.status_class[4]*1000/msec,
+ app.client.status_class[5], app.client.status_class[5]*1000/msec,
+ app.client.status_class[6], app.client.status_class[6]*1000/msec,
+ app.client.status_class[7], app.client.status_class[7]*1000/msec,
+ app.client.total_responses, app.client.total_responses*1000/msec);
+
+ write_report(report);
+
+ pj_ansi_sprintf(report, "Maximum outstanding job: %d",
+ app.client.stat_max_window);
+ write_report(report);
+
} else {
/* Server mode */
diff --git a/pjsip/include/pjsip/sip_config.h b/pjsip/include/pjsip/sip_config.h
index 608550ce..535f6697 100644
--- a/pjsip/include/pjsip/sip_config.h
+++ b/pjsip/include/pjsip/sip_config.h
@@ -120,6 +120,16 @@
#endif
+/**
+ * Allow SIP modules removal or insertions during operation?
+ * If yes, then locking will be employed when endpoint need to
+ * access module.
+ */
+#ifndef PJSIP_SAFE_MODULE
+# define PJSIP_SAFE_MODULE 1
+#endif
+
+
/* Endpoint. */
#define PJSIP_MAX_TIMER_COUNT (2*PJSIP_MAX_TSX_COUNT + 2*PJSIP_MAX_DIALOG_COUNT)
diff --git a/pjsip/src/pjsip/sip_endpoint.c b/pjsip/src/pjsip/sip_endpoint.c
index ba8967a9..940fdf16 100644
--- a/pjsip/src/pjsip/sip_endpoint.c
+++ b/pjsip/src/pjsip/sip_endpoint.c
@@ -88,6 +88,15 @@ struct pjsip_endpoint
};
+#if defined(PJSIP_SAFE_MODULE) && PJSIP_SAFE_MODULE!=0
+# define LOCK_MODULE_ACCESS(ept) pj_rwmutex_lock_read(ept->mod_mutex)
+# define UNLOCK_MODULE_ACCESS(ept) pj_rwmutex_unlock_read(ept->mod_mutex)
+#else
+# define LOCK_MODULE_ACCESS(endpt)
+# define UNLOCK_MODULE_ACCESS(endpt)
+#endif
+
+
/*
* Prototypes.
@@ -581,9 +590,14 @@ PJ_DEF(void) pjsip_endpt_release_pool( pjsip_endpoint *endpt, pj_pool_t *pool )
{
PJ_LOG(6, (THIS_FILE, "Releasing pool %s", pj_pool_getobjname(pool)));
- pj_mutex_lock(endpt->mutex);
+ /* Don't need to acquire mutex since pool factory is thread safe
+ pj_mutex_lock(endpt->mutex);
+ */
pj_pool_release( pool );
+
+ /*
pj_mutex_unlock(endpt->mutex);
+ */
}
@@ -776,7 +790,7 @@ static void endpt_on_rx_msg( pjsip_endpoint *endpt,
/* Distribute to modules, starting from modules with highest priority */
- pj_rwmutex_lock_read(endpt->mod_mutex);
+ LOCK_MODULE_ACCESS(endpt);
if (msg->type == PJSIP_REQUEST_MSG) {
pjsip_module *mod;
@@ -823,7 +837,7 @@ static void endpt_on_rx_msg( pjsip_endpoint *endpt,
}
}
- pj_rwmutex_unlock_read(endpt->mod_mutex);
+ UNLOCK_MODULE_ACCESS(endpt);
/* Must clear mod_data before returning rdata to transport, since
* rdata may be reused.
@@ -842,7 +856,7 @@ static pj_status_t endpt_on_tx_msg( pjsip_endpoint *endpt,
pjsip_module *mod;
/* Distribute to modules, starting from modules with LOWEST priority */
- pj_rwmutex_lock_read(endpt->mod_mutex);
+ LOCK_MODULE_ACCESS(endpt);
mod = endpt->module_list.prev;
if (tdata->msg->type == PJSIP_REQUEST_MSG) {
@@ -864,7 +878,7 @@ static pj_status_t endpt_on_tx_msg( pjsip_endpoint *endpt,
}
}
- pj_rwmutex_unlock_read(endpt->mod_mutex);
+ UNLOCK_MODULE_ACCESS(endpt);
return status;
}