[Pkg-voip-commits] r6620 - in /sip-tester/branches/upstream/current: Makefile call.cpp sipp.hpp
msp at alioth.debian.org
msp at alioth.debian.org
Sun Jan 4 02:02:39 UTC 2009
Author: msp
Date: Sun Jan 4 02:02:39 2009
New Revision: 6620
URL: http://svn.debian.org/wsvn/pkg-voip/?sc=1&rev=6620
Log:
[svn-upgrade] Integrating new upstream version, sip-tester (3.0)
Modified:
sip-tester/branches/upstream/current/Makefile
sip-tester/branches/upstream/current/call.cpp
sip-tester/branches/upstream/current/sipp.hpp
Modified: sip-tester/branches/upstream/current/Makefile
URL: http://svn.debian.org/wsvn/pkg-voip/sip-tester/branches/upstream/current/Makefile?rev=6620&op=diff
==============================================================================
--- sip-tester/branches/upstream/current/Makefile (original)
+++ sip-tester/branches/upstream/current/Makefile Sun Jan 4 02:02:39 2009
@@ -24,8 +24,8 @@
OUTPUT=sipp
# C & C++ object files to be built
-OBJ= xp_parser.o scenario.o screen.o call.o comp.o sipp.o stat.o \
- actions.o variables.o
+OBJ= xp_parser.o message.o scenario.o screen.o call.o comp.o sipp.o stat.o \
+ actions.o variables.o infile.o
# Libraries directories
LIBDIR_linux=
@@ -63,7 +63,7 @@
# C compiler
CC_hpux=aCC
-CC_linux=cc
+CC_linux=gcc
CC_freebsd=cc
CC_tru64=cc
CC_SunOS=gcc
@@ -73,7 +73,7 @@
# C++ compiler mapping
CPP_hpux=aCC
-CPP_linux=gcc
+CPP_linux=g++
CPP_freebsd=g++
CPP_tru64=cxx
CPP_SunOS=g++
@@ -138,15 +138,15 @@
LIBS_linux= -ldl -lpthread -lncurses -lstdc++ -lm -L /usr/local/lib -L /usr/lib -L /usr/lib64
LIBS_hpux= -lcurses -lpthread -L /opt/openssl/lib -L /usr/local/lib
LIBS_tru64= -lcurses -lpthread
-LIBS_freebsd= -lcurses -pthread
+LIBS_freebsd= -lcurses -pthread -L /usr/local/lib
LIBS_SunOS= -lcurses -lpthread -lnsl -lsocket -lstdc++ -lm -ldl -L /usr/local/ssl/lib/
LIBS_Cygwin= -lcurses -lpthread -lstdc++ -L /usr/lib/WpdPack/Lib
LIBS_Darwin= -lcurses
LIBS=$(LIBS_$(SYSTEM)) $(EXTRALIBS)
# Include directories
-INCDIR_linux=-I. -I/opt/openssl/include
-INCDIR_freebsd=-I. -I/opt/openssl/include
+INCDIR_linux=-I. -I/usr/include/openssl
+INCDIR_freebsd=-I. -I/usr/local/include
INCDIR_hpux=-I. -I/usr/local/include -I/opt/openssl/include
INCDIR_tru64=-I. -I/opt/openssl/include
INCDIR_SunOS=-I. -I/usr/local/ssl/include/
@@ -169,7 +169,7 @@
make OSNAME=`uname|sed -e "s/CYGWIN.*/CYGWIN/"` MODELNAME=`uname -m|sed "s/Power Macintosh/ppc/"` OBJ_PCAPPLAY="send_packets.o prepare_pcap.o" PCAPPLAY_LIBS="-lpcap" PCAPPLAY="-DPCAPPLAY" $(OUTPUT)
pcapplay_ossl:
- make OSNAME=`uname|sed -e "s/CYGWIN.*/CYGWIN/"` MODELNAME=`uname -m|sed "s/Power Macintosh/ppc/"` OBJ_TLS="auth.o sslinit.o sslthreadsafe.o milenage.o rijndael.o" TLS_LIBS="-lssl -lcrypto" TLS="-D_USE_OPENSSL -DOPENSSL_NO_KRB5" OBJ_PCAPPLAY="send_packets.o prepare_pcap.o" PCAPPLAY_LIBS="-lpcap -L`if test -f /usr/lib/libpcap.a; then echo /usr; else echo ./ext; fi;`/lib" PCAPPLAY="-DPCAPPLAY -I`if test -f /usr/lib/libpcap.a; then echo /usr; else echo ./ext; fi;`/include" $(OUTPUT)
+ make OSNAME=`uname|sed -e "s/CYGWIN.*/CYGWIN/"` MODELNAME=`uname -m|sed "s/Power Macintosh/ppc/"` OBJ_TLS="auth.o sslinit.o sslthreadsafe.o milenage.o rijndael.o" TLS_LIBS="-lssl -lcrypto" TLS="-D_USE_OPENSSL -DOPENSSL_NO_KRB5" OBJ_PCAPPLAY="send_packets.o prepare_pcap.o" PCAPPLAY_LIBS="-lpcap `if test -f ./ext; then echo -L./ext/lib; fi;`" PCAPPLAY="-DPCAPPLAY `if test -f ./ext; then echo -I./ext/include; fi;`" $(OUTPUT)
pcapplay_hp_li_ia:
@_HPUX_LI_FLAG=-D_HPUX_LI ; export _HPUX_LI_FLAG ; make pcapplay
@@ -190,8 +190,8 @@
debug:
DEBUG_FLAGS="-g -pg" ; export DEBUG_FLAGS ; make all
-debug_tls:
- @DEBUG_FLAGS=-g ; export DEBUG_FLAGS ; make tls
+debug_ossl:
+ @DEBUG_FLAGS=-g ; export DEBUG_FLAGS ; make ossl
debug_pcap_cygwin:
@DEBUG_FLAGS=-g ; export DEBUG_FLAGS ; make pcapplay_ossl_cygwin
Modified: sip-tester/branches/upstream/current/call.cpp
URL: http://svn.debian.org/wsvn/pkg-voip/sip-tester/branches/upstream/current/call.cpp?rev=6620&op=diff
==============================================================================
--- sip-tester/branches/upstream/current/call.cpp (original)
+++ sip-tester/branches/upstream/current/call.cpp Sun Jan 4 02:02:39 2009
@@ -48,19 +48,19 @@
#include "sipp.hpp"
#include "assert.h"
-#define KEYWORD_SIZE 256
-
#ifdef _USE_OPENSSL
extern SSL *ssl_list[];
extern struct pollfd pollfiles[];
extern SSL_CTX *sip_trp_ssl_ctx;
#endif
-extern map<string, int> map_perip_fd;
+extern map<string, struct sipp_socket *> map_perip_fd;
call_map calls;
call_list running_calls;
timewheel paused_calls;
+
+ socket_call_map_map socket_to_calls;
#ifdef PCAPPLAY
/* send_packets pthread wrapper */
@@ -100,7 +100,29 @@
}
}
-call * add_call(char * call_id, bool ipv6)
+struct sipp_socket *call::associate_socket(struct sipp_socket *socket) {
+ if (socket) {
+ this->call_socket = socket;
+ add_call_to_socket(socket, this);
+ }
+ return socket;
+}
+
+struct sipp_socket *call::dissociate_socket() {
+ struct sipp_socket *ret = this->call_socket;
+
+ remove_call_from_socket(this->call_socket, this);
+ this->call_socket = NULL;
+
+ return ret;
+}
+
+call * add_call(char * call_id , bool use_ipv6, int userId)
+{
+ return add_call(call_id, use_ipv6, userId, false /* Is not automatic. */);
+}
+
+call * add_call(char * call_id , bool use_ipv6, int userId, bool isAutomatic)
{
call * new_call;
unsigned int nb;
@@ -119,7 +141,7 @@
}
}
- new_call = new call(call_id, ipv6);
+ new_call = new call(call_id, userId, use_ipv6, isAutomatic);
if(!new_call) {
ERROR("Memory Overflow");
@@ -134,7 +156,12 @@
new_call -> tdm_map_number = nb - 1;
/* Vital counters update */
- next_number++;
+ if (!isAutomatic) {
+ next_number++;
+ } else {
+ /* We do not update the call_id counter, for we create here a call */
+ /* to answer to an out of call message */
+ }
open_calls++;
/* Statistics update */
@@ -145,28 +172,31 @@
open_calls_peak = open_calls;
open_calls_peak_time = clock_tick / 1000;
}
+
return new_call;
}
-#ifdef _USE_OPENSSL
-call * add_call(char * call_id , int P_pollset_indx, bool ipv6)
-{
- call * new_call = add_call(call_id, ipv6);
- new_call -> pollset_index = P_pollset_indx;
+call * add_call(char * call_id , struct sipp_socket *socket) {
+ call *new_call = add_call(call_id, socket->ss_ipv6, 0 /* No User. */, false /* Not Auto. */);
+ new_call->associate_socket(socket);
return new_call;
}
-#endif
-
-
-call * add_call(bool ipv6)
+
+call * add_call(char * call_id , struct sipp_socket *socket, bool isAutomatic) {
+ call *new_call = add_call(call_id, socket->ss_ipv6, 0 /* No User. */, isAutomatic);
+ new_call->associate_socket(socket);
+ return new_call;
+}
+
+call * add_call(int userId, bool ipv6)
{
static char call_id[MAX_HEADER_LEN];
-
+
char * src = call_id_string;
int count = 0;
-
+
if(!next_number) { next_number ++; }
-
+
while (*src && count < MAX_HEADER_LEN-1) {
if (*src == '%') {
++src;
@@ -190,7 +220,7 @@
}
call_id[count] = 0;
- return add_call(call_id, ipv6);
+ return add_call(call_id, ipv6, userId);
}
call * get_call(char * call_id)
@@ -396,6 +426,60 @@
int timewheel::size() {
return count;
+}
+
+/* The caller must delete this list. */
+call_list *get_calls_for_socket(struct sipp_socket *socket) {
+ call_list *l = new call_list;
+
+ socket_call_map_map::iterator map_it = socket_to_calls.find(socket);
+
+ /* No map defined for this socket. */
+ if (map_it == socket_to_calls.end()) {
+ return l;
+ }
+
+ call_map *socket_call_map = (call_map *) map_it->second;
+ call_map::iterator call_it;
+
+ for (call_it = socket_call_map->begin();
+ call_it != socket_call_map->end();
+ call_it++) {
+ l->insert(l->end(), call_it->second);
+ }
+
+ return l;
+}
+
+void add_call_to_socket(struct sipp_socket *socket, call *call) {
+ socket_call_map_map::iterator map_it = socket_to_calls.find(socket);
+ /* No map defined for this socket. */
+ if (map_it == socket_to_calls.end()) {
+ socket_to_calls.insert(socket_map_pair(socket, new call_map));
+ map_it = socket_to_calls.find(socket);
+ assert(map_it != socket_to_calls.end());
+ }
+
+ call_map *socket_call_map = (call_map *) map_it->second;
+ socket_call_map->insert(string_call_pair(call->id, call));
+}
+
+void remove_call_from_socket(struct sipp_socket *socket, call *call) {
+ socket_call_map_map::iterator map_it = socket_to_calls.find(socket);
+ /* We must have a map for this socket. */
+ assert(map_it != socket_to_calls.end());
+
+ call_map *socket_call_map = (call_map *) map_it->second;
+ call_map::iterator call_it = socket_call_map->find(call->id);
+ /* And our call must exist in the map. */
+ assert(call_it != socket_call_map->end());
+ socket_call_map->erase(call_it);
+
+ /* If we have no more calls, we can delete this entry. */
+ if (socket_call_map->begin() == socket_call_map->end()) {
+ delete socket_call_map;
+ socket_to_calls.erase(map_it);
+ }
}
#ifdef PCAPPLAY
@@ -566,10 +650,7 @@
/******************* Call class implementation ****************/
-call::InputFileUsage call::m_usage = call::InputFileSequentialOrder;
-int call::m_counter = 0;
-
-call::call(char * p_id, bool ipv6) : use_ipv6(ipv6)
+call::call(char * p_id, int userId, bool ipv6, bool isAutomatic) : use_ipv6(ipv6)
{
memset(this, 0, sizeof(call));
id = strdup(p_id);
@@ -587,24 +668,16 @@
m_bio = NULL ;
#endif
- pollset_index = 0 ;
- poll_flag_write = false ;
-
call_remote_socket = 0;
// initialising the CallVariable with the Scenario variable
- bool test_var=false;
- int i,j;
- for(i=0; i<SCEN_VARIABLE_SIZE; i++)
+ int i;
+ if (maxVariableUsed >= 0) {
+ M_callVariableTable = new CCallVariable *[maxVariableUsed + 1];
+ }
+ for(i=0; i<=maxVariableUsed; i++)
{
- for (j=0; j<SCEN_MAX_MESSAGES; j++)
- {
- if(scenVariableTable[i][j] != NULL) {
- test_var=true;
- break;
- }
- }
- if (test_var) {
+ if (variableUsed[i]) {
M_callVariableTable[i] = new CCallVariable();
if (M_callVariableTable[i] == NULL) {
ERROR ("call variable allocation failed");
@@ -624,14 +697,19 @@
// by default, last action result is NO_ERROR
last_action_result = call::E_AR_NO_ERROR;
- if (InputFileRandomOrder == m_usage) {
- m_localLineNumber = rand() % numLinesInFile;
- } else {
- m_localLineNumber = m_counter++;
- if (m_counter >= numLinesInFile) {
- m_counter = 0;
- }
-
+ this->userId = userId;
+
+ /* For automatic answer calls to an out of call request, we must not */
+ /* increment the input files line numbers to not disturb */
+ /* the input files read mechanism (otherwise some lines risk */
+ /* to be systematically skipped */
+ if (!isAutomatic) {
+ m_lineNumber = new file_line_map();
+ for (file_map::iterator file_it = inFiles.begin();
+ file_it != inFiles.end();
+ file_it++) {
+ (*m_lineNumber)[file_it->first] = file_it->second->nextLine(userId);
+ }
}
#ifdef PCAPPLAY
@@ -645,6 +723,7 @@
peer_tag = NULL;
recv_timeout = 0;
+ send_timeout = 0;
}
call::~call()
@@ -658,56 +737,22 @@
clock_tick - start_time);
}
-#ifdef _USE_OPENSSL
-
- if ((toolMode == MODE_SERVER) && (multisocket)) {
- if (ssl_list[call_socket] != NULL) {
- if((pollset_index) && (pollfiles[pollset_index].fd == call_socket)) {
- SSL_set_shutdown(ssl_list[call_socket],SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
- SSL_free(ssl_list[call_socket]);
- ssl_list[call_socket] = NULL ;
- pollset_remove(pollset_index);
- shutdown(call_socket, SHUT_RDWR);
- close(call_socket);
- }
- }
- }
-
- if ((toolMode != MODE_SERVER) && (multisocket)) {
- if(pollset_index ) {
- if (ssl_list[call_socket] != NULL) {
- // SSL_shutdown(ssl_list[call_socket]);
- SSL_set_shutdown(ssl_list[call_socket],SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
- SSL_free(ssl_list[call_socket]);
- // BIO_free(m_bio);
- // m_bio = NULL ;
- m_ctx_ssl = NULL ;
- }
- }
- }
-#endif
-
- if (toolMode != MODE_SERVER) {
- // TRACE_MSG((s,"socket close %d at idx = %d\n", socket_close, pollset_index));
- if(pollset_index) {
- if (socket_close) {
- pollset_remove(pollset_index);
- shutdown(call_socket, SHUT_RDWR);
- close(call_socket);
- }
- }
- } else {
- if (call_remote_socket) {
- close(call_remote_socket);
- }
- }
-
- /* Deletion of the call variable */
- for(int i=0; i<SCEN_VARIABLE_SIZE; i++) {
+ sipp_close_socket(dissociate_socket());
+ if (call_remote_socket) {
+ sipp_close_socket(call_remote_socket);
+ }
+
+ /* Deletion of the call variable */
+ for(int i=0; i<=maxVariableUsed; i++) {
if(M_callVariableTable[i] != NULL) {
delete M_callVariableTable[i] ;
M_callVariableTable[i] = NULL;
}
+ }
+ if(M_callVariableTable) { delete M_callVariableTable; }
+ delete m_lineNumber;
+ if (userId) {
+ freeUsers.push_front(userId);
}
if(id) { free(id); }
@@ -723,6 +768,7 @@
free(next_req_url);
}
+
#ifdef _USE_OPENSSL
if(dialog_authentication) {
free(dialog_authentication);
@@ -730,49 +776,50 @@
#endif
call_established= false ;
}
-
+
void call::connect_socket_if_needed()
{
-#ifdef _USE_OPENSSL
- int err;
- SSL *L_ssl_tcp_multiplex=NULL ;
-#endif
+ bool existing;
if(call_socket) return;
if(!multisocket) return;
if(transport == T_UDP) {
struct sockaddr_storage saddr;
- sipp_socklen_t len;
-
- int L_status = 0 ; // no new socket
-
- if(toolMode != MODE_CLIENT) return;
+
+ if(toolMode != MODE_CLIENT)
+ return;
char peripaddr[256];
if (!peripsocket) {
- if ((call_socket = new_socket(use_ipv6, SOCK_DGRAM, &L_status)) == -1) {
- ERROR_NO("Unable to get a UDP socket");
- }
- } else {
- getIpFieldFromInputFile(peripfield, m_localLineNumber, peripaddr);
- map<string, int>::iterator i;
- i = map_perip_fd.find(peripaddr);
- if (i == map_perip_fd.end()) {
- // Socket does not exist
- if ((call_socket = new_socket(use_ipv6, SOCK_DGRAM, &L_status)) == -1) {
- ERROR_NO("Unable to get a UDP socket");
- } else {
- map_perip_fd[peripaddr] = call_socket;
- }
- } else {
- // Socket exists already
- call_socket = i->second;
- }
- }
-
-
- if (L_status) {
+ if ((associate_socket(new_sipp_call_socket(use_ipv6, transport, &existing))) == NULL) {
+ ERROR_NO("Unable to get a UDP socket");
+ }
+ } else {
+ char *tmp = peripaddr;
+ getFieldFromInputFile(ip_file, peripfield, tmp);
+ map<string, struct sipp_socket *>::iterator i;
+ i = map_perip_fd.find(peripaddr);
+ if (i == map_perip_fd.end()) {
+ // Socket does not exist
+ if ((associate_socket(new_sipp_call_socket(use_ipv6, transport, &existing))) == NULL) {
+ ERROR_NO("Unable to get a UDP socket");
+ } else {
+ /* Ensure that it stays persistent, because it is recorded in the map. */
+ call_socket->ss_count++;
+ map_perip_fd[peripaddr] = call_socket;
+ }
+ } else {
+ // Socket exists already
+ associate_socket(i->second);
+ existing = true;
+ i->second->ss_count++;
+ }
+ }
+ if (existing) {
+ return;
+ }
+
memset(&saddr, 0, sizeof(struct sockaddr_storage));
memcpy(&saddr,
@@ -808,56 +855,27 @@
}
}
- if(bind(call_socket,
- (sockaddr *)(void *)&saddr,
- use_ipv6 ? sizeof(struct sockaddr_in6) :
- sizeof(struct sockaddr_in))) {
+ if (sipp_bind_socket(call_socket, &saddr, &call_port)) {
ERROR_NO("Unable to bind UDP socket");
}
+ } else { /* TCP or TLS. */
+ struct sockaddr_storage *L_dest = &remote_sockaddr;
+
+ if ((associate_socket(new_sipp_call_socket(use_ipv6, transport, &existing))) == NULL) {
+ ERROR_NO("Unable to get a TCP socket");
+ }
+
+ if (existing) {
+ return;
}
- if (use_ipv6) {
- len = sizeof(struct sockaddr_in6);
- } else {
- len = sizeof(struct sockaddr_in);
- }
-
- getsockname(call_socket,
- (sockaddr *)(void *)&saddr,
- &len);
-
- if (use_ipv6) {
- call_port =
- ntohs((short)((_RCAST(struct sockaddr_in6 *, &saddr))->sin6_port));
- } else {
- call_port
- = ntohs((short)((_RCAST(struct sockaddr_in *, &saddr))->sin_port));
- }
- /* Asks to receive incoming messages */
- if (L_status) {
- pollset_index = pollset_add(this, call_socket);
- }
-
- } else { /* TCP */
-
- int L_status = 0 ; // no new socket
- struct sockaddr_storage *L_dest = &remote_sockaddr;
-
- if ((call_socket = new_socket(use_ipv6, SOCK_STREAM, &L_status)) == -1) {
- ERROR_NO("Unable to get a TCP socket");
- }
-
- if (L_status) {
- sipp_customize_socket(call_socket);
-
- if (use_remote_sending_addr) {
- L_dest = &remote_sending_sockaddr;
- }
-
- if(connect(call_socket,
- (struct sockaddr *)(void *)L_dest,
- SOCK_ADDR_SIZE(&remote_sockaddr))) {
-
+ sipp_customize_socket(call_socket);
+
+ if (use_remote_sending_addr) {
+ L_dest = &remote_sending_sockaddr;
+ }
+
+ if (sipp_connect_socket(call_socket, L_dest)) {
if (reset_number > 0) {
if(errno == EINVAL){
/* This occurs sometime on HPUX but is not a true INVAL */
@@ -867,48 +885,14 @@
}
start_calls = 1;
} else {
- if(errno == EINVAL){
- /* This occurs sometime on HPUX but is not a true INVAL */
- ERROR("Unable to connect a TCP socket, remote peer error");
- } else {
- ERROR_NO("Unable to connect a TCP socket");
- }
- }
- } else {
-#ifdef _USE_OPENSSL
- if ( transport == T_TLS ) {
- m_ctx_ssl = sip_trp_ssl_ctx ;
-
-
- if (!(L_ssl_tcp_multiplex = SSL_new(m_ctx_ssl))){
- ERROR("Unable to create SSL object : Problem with SSL_new() \n");
- }
-
- // if ( (m_bio = BIO_new_socket(call_socket,BIO_NOCLOSE)) == NULL) {
-
- if ( (m_bio = BIO_new_socket(call_socket,BIO_CLOSE)) == NULL) {
- ERROR("Unable to create BIO object:Problem with BIO_new_socket()\n");
- }
-
-
- // SSL_set_fd(L_ssl_tcp_multiplex, call_socket);
- SSL_set_bio(L_ssl_tcp_multiplex,m_bio,m_bio);
- // SSL_set_bio(L_ssl_tcp_multiplex,bio,bio);
-
- if ( (err = SSL_connect(L_ssl_tcp_multiplex)) < 0 ) {
- ERROR("Error in SSL connection \n");
- }
- ssl_list[call_socket] = L_ssl_tcp_multiplex;
-
-
- }
-#endif
-
-
- /* Asks to receive incoming messages */
- pollset_index = pollset_add(this, call_socket);
- }
- }
+ if(errno == EINVAL){
+ /* This occurs sometime on HPUX but is not a true INVAL */
+ ERROR("Unable to connect a TCP socket, remote peer error");
+ } else {
+ ERROR_NO("Unable to connect a TCP socket");
+ }
+ }
+ }
}
}
@@ -937,23 +921,17 @@
int call::send_raw(char * msg, int index)
{
- void ** state;
- int sock;
+ struct sipp_socket *sock;
int rc;
-#ifdef _USE_OPENSSL
- SSL *ssl;
- // extern SSL *ssl_list[];
-#endif
- if (useMessagef == 1) {
- struct timeval currentTime;
- GET_TIME (¤tTime);
- TRACE_MSG((s, "----------------------------------------------- %s\n"
- "%s message sent:\n\n%s\n",
- CStat::instance()->formatTime(¤tTime),
- TRANSPORT_TO_STRING(transport),
- msg));
- }
-
+
+ if (useShortMessagef == 1) {
+ struct timeval currentTime;
+ GET_TIME (¤tTime);
+ char* cs=get_header_content(msg,"CSeq:");
+ TRACE_SHORTMSG((s, "%s\tS\t%s\tCSeq:%s\t%s\n",
+ CStat::instance()->formatTime(¤tTime),id, cs, get_first_line(msg)));
+ }
+
if((index!=-1) && (lost(index))) {
TRACE_MSG((s, "%s message voluntary lost (while sending).", TRANSPORT_TO_STRING(transport)));
@@ -962,95 +940,54 @@
return 0;
}
- if(call_socket) {
- state = &comp_state;
- sock = call_socket;
-
- if ((use_remote_sending_addr) && (toolMode == MODE_SERVER)) {
- if (!call_remote_socket) {
- struct sockaddr_storage *L_dest = &remote_sending_sockaddr;
-
- if(transport == T_UDP) {
- if((call_remote_socket= socket(use_ipv6 ? AF_INET6 : AF_INET,
- SOCK_DGRAM,
- 0))== -1) {
- ERROR_NO("Unable to get a socket for rsa option");
- }
- if(bind(call_remote_socket,
- (sockaddr *)(void *)L_dest,
- use_ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))) {
- ERROR_NO("Unable to bind UDP socket for rsa option");
- }
- } else {
- if((call_remote_socket= socket(use_ipv6 ? AF_INET6 : AF_INET,
- SOCK_STREAM,
- 0))== -1) {
- ERROR_NO("Unable to get a socket for rsa option");
+ sock = call_socket;
+
+ if ((use_remote_sending_addr) && (toolMode == MODE_SERVER)) {
+ if (!call_remote_socket) {
+ struct sockaddr_storage *L_dest = &remote_sending_sockaddr;
+
+ if((call_remote_socket= new_sipp_socket(use_ipv6, transport)) == NULL) {
+ ERROR_NO("Unable to get a socket for rsa option");
+ }
+
+ sipp_customize_socket(call_remote_socket);
+
+ if(transport != T_UDP) {
+ if (sipp_connect_socket(call_remote_socket, L_dest)) {
+ if(errno == EINVAL){
+ /* This occurs sometime on HPUX but is not a true INVAL */
+ ERROR_P1("Unable to connect a %s socket for rsa option, remote peer error", TRANSPORT_TO_STRING(transport));
+ } else {
+ ERROR_NO("Unable to connect a socket for rsa option");
}
- sipp_customize_socket(call_remote_socket);
-
- if(connect(call_remote_socket,
- (struct sockaddr *)(void *)L_dest,
- SOCK_ADDR_SIZE(&remote_sockaddr))) {
- if(errno == EINVAL){
- /* This occurs sometime on HPUX but is not a true INVAL */
- ERROR_P1("Unable to connect a %s socket for rsa option, remote peer error", TRANSPORT_TO_STRING(transport));
- } else {
- ERROR_NO("Unable to connect a socket for rsa option");
- }
- }
- }
- }
- sock=call_remote_socket ;
- }
-
-#ifdef _USE_OPENSSL
- ssl = ssl_list[sock];
- // ssl = m_ssl;
-#endif
- } else {
- state = &monosocket_comp_state;
- if(transport == T_UDP) {
- sock = main_socket;
- } else {
- sock = tcp_multiplex;
-#ifdef _USE_OPENSSL
- ssl = ssl_tcp_multiplex;
-#endif
- }
- }
-
-#ifdef _USE_OPENSSL
- if ( transport == T_TLS ) {
- rc = send_message_tls(ssl, state, msg);
- } else {
-#endif
- rc = send_message(sock, state, msg);
-#ifdef _USE_OPENSSL
- }
-#endif
-
- if(rc == -1) return -1;
-
- if(rc < -1) {
+ }
+ }
+ }
+ sock=call_remote_socket ;
+ }
+
+ rc = write_socket(sock, msg, strlen(msg), WS_BUFFER);
+ if(rc == -1 && errno == EWOULDBLOCK) {
+ return -1;
+ }
+
+ if(rc < 0) {
CStat::instance()->computeStat(CStat::E_CALL_FAILED);
CStat::instance()->computeStat(CStat::E_FAILED_CANNOT_SEND_MSG);
delete_call(id);
}
-
+
return rc; /* OK */
}
/* This method is used to send messages that are not */
/* part of the XML scenario */
-int call::sendBuffer(char * msg)
-{
- int rc;
-
+void call::sendBuffer(char * msg)
+{
/* call send_raw but with a special scenario index */
- rc=send_raw(msg, -1);
-
- return rc;
+ if (send_raw(msg, -1) < 0) {
+ ERROR_NO("Error sending raw message");
+ }
}
@@ -1132,6 +1069,7 @@
char * src, *dest, *start, *ptr;
/* Are we searching for a short form header? */
bool short_form = false;
+ bool first_time = true;
char src_tmp[MAX_HEADER_LEN + 1];
/* returns empty string in case of error */
@@ -1154,12 +1092,13 @@
dest = last_header;
while(src = strcasestr2(src, src_tmp)) {
- if (content) {
+ if (content || !first_time) {
/* just want the header's content */
src += strlen(name) + 1;
} else {
- src++;
- }
+ src++;
+ }
+ first_time = false;
ptr = strchr(src, '\n');
/* Multiline headers always begin with a tab or a space
@@ -1174,19 +1113,12 @@
// Add "," when several headers are present
if (dest != last_header) {
/* Remove trailing whitespaces, tabs, and CRs */
- *(dest--) = 0;
while ((dest > last_header) &&
- ((*dest == ' ') || (*dest == '\r')|| (*dest == '\t'))) {
- *(dest--) = 0;
+ ((*(dest-1) == ' ') || (*(dest-1) == '\r') || (*(dest-1) == '\n') || (*(dest-1) == '\t'))) {
+ *(--dest) = 0;
}
dest += sprintf(dest, ",");
-
- /* We only want to append the contents of the header, not its name for
- * the second value. */
- if (!content) {
- src += strlen(name);
- }
}
dest += sprintf(dest, "%s", src);
if(ptr) { *ptr = '\n'; }
@@ -1260,6 +1192,78 @@
return start;
}
+char * call::get_first_line(char * message)
+{
+ /* non reentrant. consider accepting char buffer as param */
+ static char last_header[MAX_HEADER_LEN * 10];
+ char * src, *dest;
+
+ /* returns empty string in case of error */
+ memset(last_header, 0, sizeof(last_header));
+
+ if((!message) || (!strlen(message))) {
+ return last_header;
+ }
+
+ src = message;
+ dest = last_header;
+
+ int i=0;
+ while (*src){
+ if((*src=='\n')||(*src=='\r')){
+ break;
+ }
+ else
+ {
+ last_header[i]=*src;
+ }
+ i++;
+ src++;
+ }
+
+ return last_header;
+}
+
+/* Return the last request URI from the To header. On any error returns the
+ * empty string. The caller must free the result. */
+char * call::get_last_request_uri ()
+{
+ char * tmp;
+ char * tmp2;
+ char * last_request_uri;
+ int tmp_len;
+
+ char * last_To = get_last_header("To:");
+ if (!last_To) {
+ return strdup("");
+ }
+
+ tmp = strchr(last_To, '<');
+ if (!tmp) {
+ return strdup("");
+ }
+ tmp++;
+
+ tmp2 = strchr(last_To, '>');
+ if (!tmp2) {
+ return strdup("");
+ }
+
+ tmp_len = strlen(tmp) - strlen(tmp2);
+ if (tmp_len < 0) {
+ return strdup("");
+ }
+
+ if(!(last_request_uri = (char *) malloc(tmp_len+1))) ERROR("Cannot allocate !\n");
+ memset(last_request_uri, 0, sizeof(last_request_uri));
+ if(tmp && (tmp_len > 0)){
+ strncpy(last_request_uri, tmp, tmp_len);
+ }
+ last_request_uri[tmp_len] = '\0';
+ return last_request_uri;
+
+}
+
char * call::send_scene(int index, int *send_status)
{
static char msg_buffer[SIPP_MAX_MSG_SIZE];
@@ -1271,7 +1275,14 @@
/* Socket port must be known before string substitution */
connect_socket_if_needed();
-
+
+ assert(call_socket);
+
+ if (call_socket->ss_congested) {
+ *send_status = -1;
+ return NULL;
+ }
+
if(scenario[index] -> send_scheme) {
char * dest;
dest = createSendingMessage(scenario[index] -> send_scheme, index);
@@ -1294,8 +1305,7 @@
}
if(send_status) {
- *send_status =
- send_raw(msg_buffer, index);
+ *send_status = send_raw(msg_buffer, index);
} else {
send_raw(msg_buffer, index);
}
@@ -1345,7 +1355,7 @@
/* If branch needed, overwrite this default */
if ( scenario[msg_index]->next &&
((test == -1) ||
- (test < SCEN_VARIABLE_SIZE && M_callVariableTable[test] != NULL && M_callVariableTable[test]->isSet()))
+ (test <= maxVariableUsed && M_callVariableTable[test] != NULL && M_callVariableTable[test]->isSet()))
) {
/* Branching possible, check the probability */
int chance = scenario[msg_index]->chance;
@@ -1415,7 +1425,9 @@
msg_index = labelArray[scenario[last_send_index]->on_timeout];
next_retrans = 0;
recv_timeout = 0;
- if (msg_index < scenario_len) return true;
+ if (msg_index < scenario_len) {
+ return true;
+ }
// here if asked to go to the last label delete the call
CStat::instance()->computeStat(CStat::E_CALL_FAILED);
@@ -1470,9 +1482,21 @@
/* Our pause is over. */
paused_until = 0;
return next();
- } else if(scenario[msg_index] -> pause_function) {
+ } else if(scenario[msg_index] -> pause_distribution || scenario[msg_index]->pause_variable) {
unsigned int pause;
- pause = scenario[msg_index] -> pause_function(scenario[msg_index]);
+ if (scenario[msg_index]->pause_distribution) {
+ pause = (int)(scenario[msg_index] -> pause_distribution -> sample());
+ } else {
+ int varId = scenario[msg_index]->pause_variable;
+ if(varId <= maxVariableUsed && M_callVariableTable[varId]) {
+ pause = (int) M_callVariableTable[varId]->getDouble();
+ } else {
+ pause = 0;
+ }
+ }
+ if (pause < 0) {
+ pause = 0;
+ }
if (pause > INT_MAX) {
pause = INT_MAX;
}
@@ -1481,7 +1505,7 @@
/* Increment the number of sessions in pause state */
++scenario[msg_index]->sessions;
return run(); /* In case delay is 0 */
- }
+ }
#ifdef __3PCC__
else if(scenario[msg_index] -> M_type == MSG_TYPE_SENDCMD) {
int send_status;
@@ -1531,26 +1555,47 @@
*/
int incr_cseq = 0;
- if (strncmp(::scenario[msg_index]->send_scheme,"ACK",3) &&
- strncmp(::scenario[msg_index]->send_scheme,"CANCEL",6) &&
- strncmp(::scenario[msg_index]->send_scheme,"SIP/2.0",7)) {
+ if (!scenario[msg_index]->send_scheme->isAck() &&
+ !scenario[msg_index]->send_scheme->isCancel() &&
+ !scenario[msg_index]->send_scheme->isResponse()) {
++cseq;
incr_cseq = 1;
}
- if ((ctrlEW) || (poll_flag_write)) {
- send_status = -1;
- } else {
msg_snd = send_scene(msg_index, &send_status);
- }
-
- if(send_status == -1) { /* Would Block on TCP */
+ if(send_status == -1 && errno == EWOULDBLOCK) {
if (incr_cseq) --cseq;
+ /* Have we set the timeout yet? */
+ if (send_timeout) {
+ /* If we have actually timed out. */
+ if (clock_tick > send_timeout) {
+ WARNING_P2("Call-Id: %s, send timeout on message %d: aborting call",
+ id, msg_index);
+ CStat::instance()->computeStat(CStat::E_CALL_FAILED);
+ CStat::instance()->computeStat(CStat::E_FAILED_TIMEOUT_ON_SEND);
+ if (default_behavior) {
+ return (abortCall());
+ } else {
+ delete_call(id);
+ return false;
+ }
+ }
+ } else if (scenario[msg_index]->timeout) {
+ /* Initialize the send timeout to the per message timeout. */
+ send_timeout = clock_tick + scenario[msg_index]->timeout;
+ } else if (defl_send_timeout) {
+ /* Initialize the send timeout to the global timeout. */
+ send_timeout = clock_tick + defl_send_timeout;
+ }
return true; /* No step, nothing done, retry later */
- } else if(send_status <-1) { /* Send error */
+ } else if(send_status < 0) { /* Send error */
+ /* The timeout will not be sent, so the timeout is no longer needed. */
+ send_timeout = 0;
return false; /* call deleted */
}
-
+ /* We have sent the message, so the timeout is no longer needed. */
+ send_timeout = 0;
+
last_send_index = msg_index;
last_send_msg = (char *) realloc(last_send_msg, strlen(msg_snd) + 1);
strcpy(last_send_msg, msg_snd);
@@ -1628,14 +1673,14 @@
delete_call(id);
return false;
}
- } else if ((scenario[msg_index]->retrans_delay) || (defl_recv_timeout)) {
- if (scenario[msg_index]->retrans_delay)
+ } else if ((scenario[msg_index]->timeout) || (defl_recv_timeout)) {
+ if (scenario[msg_index]->timeout)
// If timeout is specified on message receive, use it
- recv_timeout = getmilliseconds() + scenario[msg_index]->retrans_delay;
+ recv_timeout = getmilliseconds() + scenario[msg_index]->timeout;
else
// Else use the default timeout if specified
recv_timeout = getmilliseconds() + defl_recv_timeout;
- return true;
+ return true;
} else {
/* We are going to wait forever. */
if (!remove_running_call(this)) {
@@ -1649,48 +1694,59 @@
bool call::process_unexpected(char * msg)
{
+ char buffer[MAX_HEADER_LEN];
+ char *desc = buffer;
+
scenario[msg_index] -> nb_unexp++;
-
- if (scenario[msg_index] -> recv_request) {
- if (default_behavior) {
- WARNING_P3("Aborting call on unexpected message for Call-ID '%s': while expecting '%s', received '%s' ",
- id, scenario[msg_index] -> recv_request, msg);
+
+ if (default_behavior) {
+ desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "Aborting ");
} else {
- WARNING_P3("Continuing call on unexpected message for Call-ID '%s': while expecting '%s', received '%s' ",
- id, scenario[msg_index] -> recv_request, msg);
- }
+ desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "Continuing ");
+ }
+ desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "call on unexpected message for Call-Id '%s': ", id);
+
+ if (scenario[msg_index] -> M_type == MSG_TYPE_RECV) {
+ if (scenario[msg_index] -> recv_request) {
+ desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%s' ", scenario[msg_index] -> recv_request);
+ } else {
+ desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%d' ", scenario[msg_index] -> recv_response);
+ }
+ } else if (scenario[msg_index] -> M_type == MSG_TYPE_SEND) {
+ desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while sending ");
+ } else if (scenario[msg_index] -> M_type == MSG_TYPE_PAUSE) {
+ desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while pausing ");
+ } else if (scenario[msg_index] -> M_type == MSG_TYPE_SENDCMD) {
+ desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while sending command ");
+ } else if (scenario[msg_index] -> M_type == MSG_TYPE_RECVCMD) {
+ desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting command ");
} else {
- if (default_behavior) {
- WARNING_P3("Aborting call on unexpected message for Call-ID '%s': while expecting '%d' response, received '%s' ",
- id, scenario[msg_index] -> recv_response, msg);
- } else {
- WARNING_P3("Continuing call on unexpected message for Call-ID '%s': while expecting '%d' response, received '%s' ",
- id, scenario[msg_index] -> recv_response, msg);
- }
- }
-
+ desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while in message type %d ", scenario[msg_index]->M_type);
+ }
+ desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "(index %d)", msg_index);
+
+ WARNING_P2("%s, received '%s'", buffer, msg);
+
TRACE_MSG((s, "-----------------------------------------------\n"
"Unexpected %s message received:\n\n%s\n",
TRANSPORT_TO_STRING(transport),
msg));
-
+
if (default_behavior) {
-#ifdef __3PCC__
- // if twin socket call => reset the other part here
- if (twinSippSocket && (msg_index > 0)) {
- //WARNING_P2("call-ID '%s', internal-cmd: abort_call %s",id, "");
- sendCmdBuffer
- (createSendingMessage((char*)"call-id: [call_id]\ninternal-cmd: abort_call\n", -1));
- }
-#endif /* __3PCC__ */
-
- // usage of last_ keywords => for call aborting
- last_recv_msg = (char *) realloc(last_recv_msg, strlen(msg) + 1);
- strcpy(last_recv_msg, msg);
+ // if twin socket call => reset the other part here
+ if (twinSippSocket && (msg_index > 0)) {
+ //WARNING_P2("call-ID '%s', internal-cmd: abort_call %s",id, "");
+ sendCmdBuffer
+ (createSendingMessage((char*)"call-id: [call_id]\ninternal-cmd: abort_call\n\n", -1));
+ }
+
+ // usage of last_ keywords => for call aborting
+ last_recv_msg = (char *) realloc(last_recv_msg, strlen(msg) + 1);
+ strcpy(last_recv_msg, msg);
CStat::instance()->computeStat(CStat::E_CALL_FAILED);
CStat::instance()->computeStat(CStat::E_FAILED_UNEXPECTED_MSG);
- return (abortCall());
+ return (abortCall());
} else {
// Do not abort call nor send anything in reply if default behavior is disabled
return false;
@@ -1699,7 +1755,6 @@
bool call::abortCall()
{
- int res ;
int is_inv;
char * src_send = NULL ;
@@ -1720,11 +1775,10 @@
// Answer unexpected errors (4XX, 5XX and beyond) with an ACK
// Contributed by F. Tarek Rogers
if((src_recv) && (get_reply_code(src_recv) >= 400)) {
-
- strcpy(L_param, "ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n");
- sprintf(L_param, "%s%s", L_param, "Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n");
- sprintf(L_param, "%s%s", L_param, "From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]\n");
- sprintf(L_param, "%s%s", L_param, "To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n");
+ strcpy(L_param, "ACK [last_Request_URI] SIP/2.0\n");
+ sprintf(L_param, "%s%s", L_param, "[last_Via]\n");
+ sprintf(L_param, "%s%s", L_param, "[last_From]\n");
+ sprintf(L_param, "%s%s", L_param, "[last_To]\n");
sprintf(L_param, "%s%s", L_param, "Call-ID: [call_id]\n");
char * cseq;
cseq = get_header_field_code(src_recv,(char *) "CSeq:");
@@ -1734,9 +1788,9 @@
sprintf(L_param, "%s%s", L_param, "Contact: <sip:sipp@[local_ip]:[local_port];transport=[transport]>\n");
sprintf(L_param, "%s%s", L_param, "Max-Forwards: 70\n");
sprintf(L_param, "%s%s", L_param, "Subject: Performance Test\n");
- sprintf(L_param, "%s%s", L_param, "Content-Length: 0\n");
-
- res = sendBuffer(createSendingMessage((char*)(L_param), -2));
+ sprintf(L_param, "%s%s", L_param, "Content-Length: 0\n\n");
+
+ sendBuffer(createSendingMessage((char*)(L_param), -2));
} else if (src_recv) {
/* Call is not established and the reply is not a 4XX, 5XX */
@@ -1748,45 +1802,48 @@
* and send a BYE afterwards */
ack_is_pending = false;
/* Send an ACK */
- strcpy(L_param, "ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n");
+ strcpy(L_param, "ACK [last_Request_URI] SIP/2.0\n");
sprintf(L_param, "%s%s", L_param, "Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n");
- sprintf(L_param, "%s%s", L_param, "From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]\n");
- sprintf(L_param, "%s%s", L_param, "To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n");
+ sprintf(L_param, "%s%s", L_param, "[last_From]\n");
+ sprintf(L_param, "%s%s", L_param, "[last_To]\n");
sprintf(L_param, "%s%s", L_param, "Call-ID: [call_id]\n");
src_send = last_send_msg ;
cseq = get_header_field_code(src_recv,"CSeq:");
if (cseq != NULL) {
sprintf(L_param, "%s%s ACK\n", L_param, cseq);
}
+ sprintf(L_param, "%s%s", L_param, "Max-Forwards: 70\n");
sprintf(L_param, "%s%s", L_param, "Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n");
- sprintf(L_param, "%s%s", L_param, "Content-Length: 0\n");
- res = sendBuffer(createSendingMessage((char*)(L_param),-1));
+ sprintf(L_param, "%s%s", L_param, "Content-Length: 0\n\n");
+ sendBuffer(createSendingMessage((char*)(L_param),-1));
/* Send the BYE */
cseq = NULL;
- strcpy(L_param, "BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n");
+ strcpy(L_param, "BYE [last_Request_URI] SIP/2.0\n");
sprintf(L_param, "%s%s", L_param, "Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n");
- sprintf(L_param, "%s%s", L_param, "From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]\n");
- sprintf(L_param, "%s%s", L_param, "To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n");
+ sprintf(L_param, "%s%s", L_param, "[last_From]\n");
+ sprintf(L_param, "%s%s", L_param, "[last_To]\n");
sprintf(L_param, "%s%s", L_param, "Call-ID: [call_id]\n");
cseq = compute_cseq(src_recv);
if (cseq != NULL) {
sprintf(L_param, "%s%s BYE\n", L_param, compute_cseq(src_recv));
}
- sprintf(L_param, "%s%s", L_param, "Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n");
- sprintf(L_param, "%s%s", L_param, "Content-Length: 0\n");
- res = sendBuffer(createSendingMessage((char*)(L_param),-1));
+ sprintf(L_param, "%s%s", L_param, "Max-Forwards: 70\n");
+ sprintf(L_param, "%s%s", L_param, "Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n");
+ sprintf(L_param, "%s%s", L_param, "Content-Length: 0\n\n");
+ sendBuffer(createSendingMessage((char*)(L_param),-1));
} else {
/* Send a CANCEL */
- strcpy(L_param, "CANCEL sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n");
- sprintf(L_param, "%s%s", L_param, "Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n");
- sprintf(L_param, "%s%s", L_param, "From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]\n");
- sprintf(L_param, "%s%s", L_param, "To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n");
+ strcpy(L_param, "CANCEL [last_Request_URI] SIP/2.0\n");
+ sprintf(L_param, "%s%s", L_param, "[last_Via]\n");
+ sprintf(L_param, "%s%s", L_param, "[last_From]\n");
+ sprintf(L_param, "%s%s", L_param, "[last_To]\n");
sprintf(L_param, "%s%s", L_param, "Call-ID: [call_id]\n");
- sprintf(L_param, "%sCSeq: 1 CANCEL\n", L_param);
+ sprintf(L_param, "%sCSeq: 1 CANCEL\n", L_param);
+ sprintf(L_param, "%s%s", L_param, "Max-Forwards: 70\n");
sprintf(L_param, "%s%s", L_param, "Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n");
- sprintf(L_param, "%s%s", L_param, "Content-Length: 0\n");
- res = sendBuffer(createSendingMessage((char*)(L_param),-2));
+ sprintf(L_param, "%s%s", L_param, "Content-Length: 0\n\n");
+ sendBuffer(createSendingMessage((char*)(L_param),-2));
}
} else {
/* Call is not established and the reply is not a 4XX, 5XX */
@@ -1795,25 +1852,29 @@
/* any answer. */
/* Do nothing ! */
}
- } else {
- /* Call is established */
+ } else if (last_recv_msg) {
+ /* The call may not be established, if we haven't yet received a message,
+ * because the earlier check depends on the first message being an INVITE
+ * (although it could be something like a message message, therefore we
+ * check that we received a message. */
char * src_recv = last_recv_msg ;
char L_msg_buffer[SIPP_MAX_MSG_SIZE];
L_msg_buffer[0] = '\0';
char * L_param = L_msg_buffer;
- strcpy(L_param, "BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n");
+ strcpy(L_param, "BYE [last_Request_URI] SIP/2.0\n");
sprintf(L_param, "%s%s", L_param, "Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n");
- sprintf(L_param, "%s%s", L_param, "From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]\n");
- sprintf(L_param, "%s%s", L_param, "To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n");
+ sprintf(L_param, "%s%s", L_param, "[last_From:]\n");
+ sprintf(L_param, "%s%s", L_param, "[last_To:]\n");
sprintf(L_param, "%s%s", L_param, "Call-ID: [call_id]\n");
char * cseq;
cseq = compute_cseq(src_recv);
if (cseq != NULL) {
sprintf(L_param, "%s%s BYE\n", L_param, compute_cseq(src_recv));
}
- sprintf(L_param, "%s%s", L_param, "Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n");
- sprintf(L_param, "%s%s", L_param, "Content-Length: 0\n");
- res = sendBuffer(createSendingMessage((char*)(L_param),-1));
+ sprintf(L_param, "%s%s", L_param, "Max-Forwards: 70\n");
+ sprintf(L_param, "%s%s", L_param, "Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n");
+ sprintf(L_param, "%s%s", L_param, "Content-Length: 0\n\n");
+ sendBuffer(createSendingMessage((char*)(L_param),-1));
}
}
@@ -1830,7 +1891,6 @@
}
-#ifdef __3PCC__
int call::sendCmdMessage(int index)
{
char * dest;
@@ -1840,7 +1900,7 @@
/* 3pcc extended mode */
char * peer_dest;
- int * peer_socket;
+ struct sipp_socket **peer_socket;
if(scenario[index] -> M_sendCmdData) {
// WARNING_P1("---PREPARING_TWIN_CMD---%s---", scenario[index] -> M_sendCmdData);
@@ -1854,17 +1914,10 @@
peer_dest = scenario[index]->peer_dest;
if(peer_dest){
peer_socket = get_peer_socket(peer_dest);
- rc = send(* peer_socket,
- dest,
- strlen(dest),
- 0);
-
- }else {
- rc = send(twinSippSocket,
- dest,
- strlen(dest),
- 0);
- }
+ rc = write_socket(*peer_socket, dest, strlen(dest), WS_BUFFER);
+ }else {
+ rc = write_socket(twinSippSocket, dest, strlen(dest), WS_BUFFER);
+ }
if(rc < 0) {
CStat::instance()->computeStat(CStat::E_CALL_FAILED);
CStat::instance()->computeStat(CStat::E_FAILED_CMD_NOT_SENT);
@@ -1878,6 +1931,7 @@
return(-1);
}
+
int call::sendCmdBuffer(char* cmd)
{
char * dest;
@@ -1891,11 +1945,7 @@
strcat(dest, delimitor);
-
- rc = send(twinSippSocket,
- dest,
- strlen(dest),
- 0);
+ rc = write_socket(twinSippSocket, dest, strlen(dest), WS_BUFFER);
if(rc < 0) {
CStat::instance()->computeStat(CStat::E_CALL_FAILED);
CStat::instance()->computeStat(CStat::E_FAILED_CMD_NOT_SENT);
@@ -1906,494 +1956,376 @@
return(0);
}
+char* call::createSendingMessage(SendingMessage *src, int P_index)
+{
+ char * length_marker = NULL;
+ char * auth_marker = NULL;
+ MessageComponent *auth_comp = NULL;
+ bool auth_comp_allocated = false;
+ int len_offset = 0;
+ static char msg_buffer[SIPP_MAX_MSG_SIZE+2];
+ char *dest = msg_buffer;
+ bool supresscrlf = false;
+
+ *dest = '\0';
+
+ for (int i = 0; i < src->numComponents(); i++) {
+ MessageComponent *comp = src->getComponent(i);
+ int left = sizeof(msg_buffer) - (dest - msg_buffer);
+ switch(comp->type) {
+ case E_Message_Literal:
+ if (supresscrlf) {
+ char *ptr = comp->literal;
+ while (isspace(*ptr)) ptr++;
+ dest += snprintf(dest, left, "%s", ptr);
+ supresscrlf = false;
+ } else {
+ dest += snprintf(dest, left, "%s", comp->literal);
+ }
+ break;
+ case E_Message_Remote_IP:
+ dest += snprintf(dest, left, "%s", remote_ip_escaped);
+ break;
+ case E_Message_Remote_Port:
+ dest += snprintf(dest, left, "%d", remote_port + comp->offset);
+ break;
+ case E_Message_Local_IP:
+ dest += snprintf(dest, left, "%s", local_ip_escaped);
+ break;
+ case E_Message_Local_Port:
+ int port;
+ if((transport == T_UDP) && (multisocket) && (toolMode != MODE_SERVER)) {
+ port = call_port;
+ } else {
+ port = local_port;
+ }
+ dest += snprintf(dest, left, "%d", port + comp->offset);
+ break;
+ case E_Message_Transport:
+ dest += snprintf(dest, left, "%s", TRANSPORT_TO_STRING(transport));
+ break;
+ case E_Message_Local_IP_Type:
+ dest += snprintf(dest, left, "%s", (local_ip_is_ipv6 ? "6" : "4"));
+ break;
+ case E_Message_Server_IP: {
+ /* We should do this conversion once per socket creation, rather than
+ * repeating it every single time. */
+ struct sockaddr_storage server_sockaddr;
+
+ sipp_socklen_t len = SOCK_ADDR_SIZE(&server_sockaddr);
+ getsockname(call_socket->ss_fd,
+ (sockaddr *)(void *)&server_sockaddr, &len);
+
+ if (server_sockaddr.ss_family == AF_INET6) {
+ char * temp_dest;
+ temp_dest = (char *) malloc(INET6_ADDRSTRLEN);
+ memset(temp_dest,0,INET6_ADDRSTRLEN);
+ inet_ntop(AF_INET6,
+ &((_RCAST(struct sockaddr_in6 *,&server_sockaddr))->sin6_addr),
+ temp_dest,
+ INET6_ADDRSTRLEN);
+ dest += snprintf(dest, left, "%s",temp_dest);
+ } else {
+ dest += snprintf(dest, left, "%s",
+ inet_ntoa((_RCAST(struct sockaddr_in *,&server_sockaddr))->sin_addr));
+ }
+ }
+ break;
+ case E_Message_Media_IP:
+ dest += snprintf(dest, left, "%s", media_ip_escaped);
+ break;
+ case E_Message_Media_Port:
+ case E_Message_Auto_Media_Port: {
+ int port = media_port + comp->offset;
+ if (comp->type == E_Message_Auto_Media_Port) {
+ port = media_port + (4 * (number - 1)) % 10000 + comp->offset;
+ }
+#ifdef PCAPPLAY
+ char *begin = dest;
+ while (begin > msg_buffer) {
+ if (*begin == '\n') {
+ break;
+ }
+ begin--;
+ }
+ if (begin == msg_buffer) {
+ ERROR("Can not find beginning of a line for the media port!\n");
+ }
+ if (strstr(begin, "audio")) {
+ if (media_ip_is_ipv6) {
+ (_RCAST(struct sockaddr_in6 *, &(play_args_a.from)))->sin6_port = port;
+ } else {
+ (_RCAST(struct sockaddr_in *, &(play_args_a.from)))->sin_port = port;
+ }
+ } else if (strstr(begin, "video")) {
+ if (media_ip_is_ipv6) {
+ (_RCAST(struct sockaddr_in6 *, &(play_args_v.from)))->sin6_port = port;
+ } else {
+ (_RCAST(struct sockaddr_in *, &(play_args_v.from)))->sin_port = port;
+ }
+ } else {
+ ERROR_P1("media_port keyword with no audio or video on the current line (%s)", begin);
+ }
#endif
-
-void call::getHexStringParam(char * dest, char * src, int * len)
-{
- *len=0;
- /* Allows any hex coded string like '0x5B07F6' */
- while (isxdigit(*src)) {
- int val = get_decimal_from_hex(*src);
- src++;
- if (isxdigit(*src)) {
- val = (val << 4) + get_decimal_from_hex(*src);
- src++;
- }
- *dest++ = val & 0xff;
- (*len)++;
- }
-}
-
-char* call::getKeywordParam(char * src, char * param, char * output)
-{
- char *key, *tmp;
- int len;
-
- len = 0;
- key = NULL;
- if(tmp = strstr(src, param)) {
- tmp += strlen(param);
- key = tmp;
- if ((*key == '0') && (*(key+1) == 'x')) {
- key += 2;
- getHexStringParam(output, key, &len);
- key += len * 2;
+ dest += sprintf(dest, "%u", port);
+ break;
+ }
+ case E_Message_Media_IP_Type:
+ dest += snprintf(dest, left, "%s", (media_ip_is_ipv6 ? "6" : "4"));
+ break;
+ case E_Message_Call_Number:
+ dest += snprintf(dest, left, "%u", number);
+ break;
+ case E_Message_Call_ID:
+ dest += snprintf(dest, left, "%s", id);
+ break;
+ case E_Message_CSEQ:
+ dest += snprintf(dest, left, "%u", cseq + comp->offset);
+ break;
+ case E_Message_PID:
+ dest += snprintf(dest, left, "%d", pid);
+ break;
+ case E_Message_Service:
+ dest += snprintf(dest, left, "%s", service);
+ break;
+ case E_Message_Branch:
+ /* Branch is magic cookie + call number + message index in scenario */
+ if(P_index == -2){
+ dest += snprintf(dest, left, "z9hG4bK-%u-%u-%d", pid, number, msg_index-1 + comp->offset);
+ } else {
+ dest += snprintf(dest, left, "z9hG4bK-%u-%u-%d", pid, number, P_index + comp->offset);
+ }
+ break;
+ case E_Message_Index:
+ dest += snprintf(dest, left, "%d", P_index);
+ break;
+ case E_Message_Next_Url:
+ if (next_req_url) {
+ dest += sprintf(dest, "%s", next_req_url);
+ }
+ break;
+ case E_Message_Len:
+ length_marker = dest;
+ dest += snprintf(dest, left, " ");
+ len_offset = comp->offset;
+ break;
+ case E_Message_Authentication:
+ if (auth_marker) {
+ ERROR("Only one [authentication] keyword is currently supported!\n");
+ }
+ auth_marker = dest;
+ dest += snprintf(dest, left, "[authentication place holder]");
+ auth_comp = comp;
+ break;
+ case E_Message_Peer_Tag_Param:
+ if(peer_tag) {
+ dest += snprintf(dest, left, ";tag=%s", peer_tag);
+ }
+ break;
+ case E_Message_Routes:
+ if (dialog_route_set) {
+ dest += sprintf(dest, "Route: %s", dialog_route_set);
+ } else if (*(dest - 1) == '\n') {
+ supresscrlf = true;
+ }
+ break;
+ case E_Message_ClockTick:
+ dest += snprintf(dest, left, "%lu", clock_tick);
+ break;
+ case E_Message_Variable: {
+ int varId = comp->varId;
+ if(varId <= maxVariableUsed) {
+ if(M_callVariableTable[varId] != NULL) {
+ if(M_callVariableTable[varId]->isSet()) {
+ if (M_callVariableTable[varId]->isRegExp()) {
+ dest += sprintf(dest, "%s", M_callVariableTable[varId]->getMatchingValue());
+ } else if (M_callVariableTable[varId]->isDouble()) {
+ dest += sprintf(dest, "%lf", M_callVariableTable[varId]->getDouble());
+ } else if (M_callVariableTable[varId]->isString()) {
+ dest += sprintf(dest, "%s", M_callVariableTable[varId]->getString());
+ } else if (M_callVariableTable[varId]->isBool()) {
+ dest += sprintf(dest, "true");
+ }
+ } else if (M_callVariableTable[varId]->isBool()) {
+ dest += sprintf(dest, "false");
+ }
+ }
+ }
+ break;
+ }
+ case E_Message_Fill: {
+ int varId = comp->varId;
+ int length = 0;
+ if(varId <= maxVariableUsed && M_callVariableTable[varId]) {
+ length = (int) M_callVariableTable[varId]->getDouble();
+ if (length < 0) {
+ length = 0;
+ }
+ }
+ char *filltext = comp->literal;
+ int filllen = strlen(filltext);
+ if (filllen == 0) {
+ ERROR("Internal error: [fill] keyword has zero-length text.");
+ }
+ for (int i = 0, j = 0; i < length; i++, j++) {
+ *dest++ = filltext[j % filllen];
+ }
+ *dest = '\0';
+ break;
+ }
+ case E_Message_Injection: {
+ char *orig_dest = dest;
+ getFieldFromInputFile(comp->comp_param.field_param.filename, comp->comp_param.field_param.field, dest);
+ /* We are injecting an authentication line. */
+ if (char *tmp = strstr(orig_dest, "[authentication")) {
+ if (auth_marker) {
+ ERROR("Only one [authentication] keyword is currently supported!\n");
+ }
+ auth_marker = tmp;
+ auth_comp = (struct MessageComponent *)calloc(1, sizeof(struct MessageComponent));
+ if (!auth_comp) { ERROR("Out of memory!"); }
+ auth_comp_allocated = true;
+
+ tmp = strchr(auth_marker, ']');
+ char c = *tmp;
+ *tmp = '\0';
+ SendingMessage::parseAuthenticationKeyword(auth_comp, auth_marker);
+ *tmp = c;
+ }
+ if (*(dest - 1) == '\n') {
+ supresscrlf = true;
+ }
+ break;
+ }
+ case E_Message_Last_Header: {
+ char * last_header = get_last_header(comp->literal);
+ if(last_header) {
+ dest += sprintf(dest, "%s", last_header);
+ }
+ if (*(dest - 1) == '\n') {
+ supresscrlf = true;
+ }
+ break;
+ }
+ case E_Message_Last_Request_URI: {
+ char * last_request_uri = get_last_request_uri();
+ dest += sprintf(dest, "%s", last_request_uri);
+ free(last_request_uri);
+ break;
+ }
+ case E_Message_TDM_Map:
+ if (!use_tdmmap)
+ ERROR("[tdmmap] keyword without -tdmmap parameter on command line");
+ dest += snprintf(dest, left, "%d.%d.%d/%d",
+ tdm_map_x+(int((tdm_map_number)/((tdm_map_b+1)*(tdm_map_c+1))))%(tdm_map_a+1),
+ tdm_map_h,
+ tdm_map_y+(int((tdm_map_number)/(tdm_map_c+1)))%(tdm_map_b+1),
+ tdm_map_z+(tdm_map_number)%(tdm_map_c+1)
+ );
+ break;
+ }
+ }
+ /* Need the body for length and auth-int calculation */
+ char *body;
+ if (length_marker || auth_marker) {
+ body = strstr(msg_buffer, "\r\n\r\n");
+ }
+
+ /* Fix up the length. */
+ if (length_marker) {
+ if (auth_marker > body) {
+ ERROR("The authentication keyword should appear in the message header, not the body!");
+ }
+
+ if (body && dest - body > 4 && dest - body < 100004) {
+ char tmp = length_marker[5];
+ sprintf(length_marker, "%5u", dest - body - 4 + len_offset);
+ length_marker[5] = tmp;
} else {
- while (*key) {
- if (((key - src) > KEYWORD_SIZE) || (!(key - src))) {
- ERROR_P1("Syntax error parsing '%s' parameter", param);
- } else if (*key == ']' || *key < 33 || *key > 126) {
- strncpy(output, tmp, key-tmp);
- output[key-tmp] = '\0';
- break;
- }
- key++;
- }
- }
- } else {
- output[0] = '\0';
- }
- return key;
-}
-
-char* call::createSendingMessage(char * src, int P_index)
-{
- static char msg_buffer[SIPP_MAX_MSG_SIZE+2];
-
- if(src != NULL) {
- char * dest = msg_buffer;
- char * key;
- char * length_marker = NULL;
- int offset = 0;
- int len_offset = 0;
- char current_line[MAX_HEADER_LEN];
- char * line_mark = NULL;
- char * tsrc;
-
- current_line[0] = '\0';
- while(*src) {
- if (current_line[0] == '\0') {
- line_mark = NULL;
- line_mark = strchr(src, '\n');
- if (line_mark) {
- memcpy(current_line, src, line_mark - src);
- current_line[line_mark-src] = '\0';
- }
- }
- /* This hex encoding could be done in XML parsing, allowing us to skip
- * these conditionals and branches. */
- if ((*src == '\\') && (*(src+1) == 'x')) {
- /* Allows any hex coded char like '\x5B' ([) */
- src += 2;
- if (isxdigit(*src)) {
- int val = get_decimal_from_hex(*src);
- src++;
- if (isxdigit(*src)) {
- val = (val << 4) + get_decimal_from_hex(*src);
- }
- *dest++ = val & 0xff;
- }
- src++;
- } else if(*src == '[') {
- char keyword [KEYWORD_SIZE+1];
- src++;
-
- tsrc=strchr(src, '[');
- key = strchr(src, ']');
- if ((tsrc) && (tsrc<key)){
- memcpy(keyword, src-1, tsrc - src + 1);
- keyword[tsrc - src + 1] = 0;
- src=tsrc+1;
- dest += sprintf(dest, "%s", keyword);
- }
-
- if((!key) || ((key - src) > KEYWORD_SIZE) || (!(key - src))){
- ERROR_P1("Syntax error or invalid [keyword] in scenario while parsing '%s'", current_line);
- }
- memcpy(keyword, src, key - src);
-
- keyword[key - src] = 0;
- src = key + 1;
- // allow +/-n for numeric variables
- if (!strstr(keyword, "authentication") && !strstr(keyword, "map") && ((key = strchr(keyword,'+')) || (key = strchr(keyword,'-'))) && isdigit(*(key+1))) {
- offset = atoi(key);
- *key = 0;
- } else offset = 0;
-
- if(!strcmp(keyword, "remote_ip")) {
- dest += sprintf(dest, "%s", remote_ip_escaped);
- } else if(!strcmp(keyword, "remote_port")) {
- dest += sprintf(dest, "%u", remote_port + offset);
- } else if(!strcmp(keyword, "transport")) {
- dest += sprintf(dest, "%s", TRANSPORT_TO_STRING(transport));
- } else if(!strcmp(keyword, "local_ip")) {
- dest += sprintf(dest, "%s", local_ip_escaped);
- } else if(!strcmp(keyword, "local_ip_type")) {
- dest += sprintf(dest, "%s", (local_ip_is_ipv6 ? "6" : "4"));
- } else if(!strcmp(keyword, "local_port")) {
- if((transport == T_UDP) && (multisocket) && (toolMode != MODE_SERVER)) {
- dest += sprintf(dest, "%u", call_port + offset);
- } else {
- dest += sprintf(dest, "%u", local_port + offset);
- }
- } else if(!strcmp(keyword, "server_ip")) {
- struct sockaddr_storage server_sockaddr;
- sipp_socklen_t len = SOCK_ADDR_SIZE(&server_sockaddr);
- getsockname(call_socket,
- (sockaddr *)(void *)&server_sockaddr,
- &len);
- if (server_sockaddr.ss_family == AF_INET6) {
- char * temp_dest;
- temp_dest = (char *) malloc(INET6_ADDRSTRLEN);
- memset(temp_dest,0,INET6_ADDRSTRLEN);
- inet_ntop(AF_INET6,
- &((_RCAST(struct sockaddr_in6 *,&server_sockaddr))->sin6_addr),
- temp_dest,
- INET6_ADDRSTRLEN);
- dest += sprintf(dest, "%s",temp_dest);
- } else {
- dest += sprintf(dest, "%s",
- inet_ntoa((_RCAST(struct sockaddr_in *,&server_sockaddr))->sin_addr));
- }
- } else if(!strcmp(keyword, "media_ip")) {
- dest += sprintf(dest, "%s", media_ip_escaped);
-#ifdef PCAPPLAY
- } else if (!strcmp(keyword, "auto_media_port")) {
- /* to make media ports begin from true media_port exported from sipp.cpp, as number begins to 1
- * * 4 to allow video (audio+rtcp+video+rtcp)
- * Modulo 10000 to limit the port number
- * -> Max 10000 concurrent RTP sessions for pcap_play
- */
- int port = media_port + (4 * (number - 1)) % 10000 + offset;
- if (strstr(current_line, "m=audio ")) {
- if (media_ip_is_ipv6) {
- (_RCAST(struct sockaddr_in6 *, &(play_args_a.from)))->sin6_port = port;
- } else {
- (_RCAST(struct sockaddr_in *, &(play_args_a.from)))->sin_port = port;
- }
- } else if (strstr(current_line, "m=video ")) {
- if (media_ip_is_ipv6) {
- (_RCAST(struct sockaddr_in6 *, &(play_args_v.from)))->sin6_port = port;
- } else {
- (_RCAST(struct sockaddr_in *, &(play_args_v.from)))->sin_port = port;
- }
- } else {
- ERROR_P1("auto_media_port keyword with no audio or video on the current line (%s)", current_line);
- }
- dest += sprintf(dest, "%u", port);
+ // Other cases: Content-Length is 0
+ sprintf(length_marker, " 0\r\n\r\n");
+ }
+ }
+
+ /*
+ * The authentication substitution must be done outside the above
+ * loop because auth-int will use the body (which must have already
+ * been keyword substituted) to build the md5 hash
+ */
+ if (auth_marker) {
+#ifndef _USE_OPENSSL
+ ERROR("Authentication requires OpenSSL!");
+#else
+ if (!dialog_authentication) {
+ ERROR("Authentication keyword without dialog_authentication!");
+ }
+
+ int auth_marker_len;
+ char * tmp;
+ int authlen;
+
+ auth_marker_len = (strchr(auth_marker, ']') + 1) - auth_marker;
+
+ /* Need the Method name from the CSeq of the Challenge */
+ char method[MAX_HEADER_LEN];
+ tmp = get_last_header("CSeq:") + 5;
+ if(!tmp) {
+ ERROR("Could not extract method from cseq of challenge");
+ }
+ while(isspace(*tmp) || isdigit(*tmp)) tmp++;
+ sscanf(tmp,"%s", method);
+
+ if (!body) {
+ body = "";
+ }
+
+ /* Determine the type of credentials. */
+ char result[MAX_HEADER_LEN];
+ if (dialog_challenge_type == 401) {
+ /* Registrars use Authorization */
+ authlen = sprintf(result, "Authorization: ");
+ } else {
+ /* Proxies use Proxy-Authorization */
+ authlen = sprintf(result, "Proxy-Authorization: ");
+ }
+
+ /* Build the auth credenticals */
+ char uri[MAX_HEADER_LEN];
+ sprintf (uri, "%s:%d", remote_ip, remote_port);
+ if (createAuthHeader(auth_comp->comp_param.auth_param.auth_user, auth_comp->comp_param.auth_param.auth_pass,
+ method, uri, body, dialog_authentication,
+ auth_comp->comp_param.auth_param.aka_OP, auth_comp->comp_param.auth_param.aka_AMF, auth_comp->comp_param.auth_param.aka_K,
+ result + authlen) == 0) {
+ ERROR_P1("%s", result + authlen);
+ }
+ authlen = strlen(result);
+
+ /* Shift the end of the message to its rightful place. */
+ memmove(auth_marker + authlen, auth_marker + auth_marker_len, strlen(auth_marker + auth_marker_len) + 1);
+ /* Copy our result into the hole. */
+ memcpy(auth_marker, result, authlen);
#endif
- } else if(!strcmp(keyword, "media_port")) {
- int port = media_port + offset;
-#ifdef PCAPPLAY
- if (strstr(current_line, "audio")) {
- if (media_ip_is_ipv6) {
- (_RCAST(struct sockaddr_in6 *, &(play_args_a.from)))->sin6_port = port;
- } else {
- (_RCAST(struct sockaddr_in *, &(play_args_a.from)))->sin_port = port;
- }
- } else if (strstr(current_line, "video")) {
- if (media_ip_is_ipv6) {
- (_RCAST(struct sockaddr_in6 *, &(play_args_v.from)))->sin6_port = port;
- } else {
- (_RCAST(struct sockaddr_in *, &(play_args_v.from)))->sin_port = port;
- }
- } else {
- ERROR_P1("media_port keyword with no audio or video on the current line (%s)", current_line);
- }
-#endif
- dest += sprintf(dest, "%u", port);
- } else if(!strcmp(keyword, "media_ip_type")) {
- dest += sprintf(dest, "%s", (media_ip_is_ipv6 ? "6" : "4"));
- } else if(!strcmp(keyword, "call_number")) {
- dest += sprintf(dest, "%u", number);
- } else if(!strcmp(keyword, "call_id")) {
- dest += sprintf(dest, "%s", id);
- } else if(!strcmp(keyword, "cseq")) {
- dest += sprintf(dest, "%u", cseq +offset);
- } else if(!strcmp(keyword, "pid")) {
- dest += sprintf(dest, "%u", pid);
- } else if(!strcmp(keyword, "service")) {
- dest += sprintf(dest, "%s", service);
- } else if(!strncmp(keyword, "field", 5)) {
- char* local_dest = dest;
- getFieldFromInputFile(keyword, m_localLineNumber, dest);
- if (dest == local_dest && ('\r' == *(local_dest-1) || '\n' == *(local_dest-1))) {
- /* If the line begins with a field value and there
- * is nothing to add for this field,
- * Jump to the end of line in scenario. SN
- */
- while((*src) && (*src != '\n')) {
- src++;
- }
- if(*src == '\n') {
- src++;
- }
- }
- } else if(!strcmp(keyword, "peer_tag_param")) {
- if(peer_tag) {
- dest += sprintf(dest, ";tag=%s", peer_tag);
- }
- } else if(strstr(keyword, "tdmmap")) {
- /* keyword to generate c= line for TDM
- * format: g.h.i/j
- * g: varies in interval a, offset x
- * h: fix value
- * i: varies in interval b, offset y
- * j: varies in interval c, offset z
- * Format: tdmmap{1-3}{0}{0-27}{1-24}
- */
- if (!use_tdmmap)
- ERROR("[tdmmap] keyword without -tdmmap parameter on command line");
- dest += sprintf(dest, "%d.%d.%d/%d",
- tdm_map_x+(int((tdm_map_number)/((tdm_map_b+1)*(tdm_map_c+1))))%(tdm_map_a+1),
- tdm_map_h,
- tdm_map_y+(int((tdm_map_number)/(tdm_map_c+1)))%(tdm_map_b+1),
- tdm_map_z+(tdm_map_number)%(tdm_map_c+1)
- );
- } else if(strstr(keyword, "$")) {
- int varId = atoi(keyword+1);
- if(varId < SCEN_VARIABLE_SIZE) {
- if(M_callVariableTable[varId] != NULL) {
- if(M_callVariableTable[varId]->isSet()) {
- dest += sprintf(dest, "%s",
- M_callVariableTable[varId]->
- getMatchingValue());
- // WARNING_P1("VARIABLE --%s--", M_callVariableTable[varId]->getMatchingValue());
- } else {
- dest += sprintf(dest, "%s", "");
- }
- }
- }
- } else if(strstr(keyword, "last_")) {
- char * last_header = get_last_header(keyword+5);
- if(last_header) {
- dest += sprintf(dest, "%s", last_header);
- } else {
- /* Jump to the end of line in scenario if nothing
- * to insert in place of this header. */
- while((*src) && (*src != '\n')) {
- src++;
- }
- if(*src == '\n') {
- src++;
- }
- }
- } else if(strstr(keyword, "routes")) {
- if (dialog_route_set) {
- dest += sprintf(dest, "Route: %s", dialog_route_set);
- } else {
- // Skip to end of line
- while((*src) && (*src != '\n')) src++;
- if (*src == '\n') src++;
- }
-#ifdef _USE_OPENSSL
- } else if(strstr(keyword, "authentication")) {
- /* This keyword is substituted below */
- dest += sprintf(dest, "[%s]", keyword);
-#endif
- } else if(strstr(keyword, "branch")) {
- /* Branch is magic cookie + call number + message index in scenario */
- if(P_index == -2){
- dest += sprintf(dest, "z9hG4bK-%u-%u-%d", pid, number, msg_index-1);
- } else {
- dest += sprintf(dest, "z9hG4bK-%u-%u-%d", pid, number, P_index);
- }
- } else if(strstr(keyword, "msg_index")) {
- /* Message index in scenario */
- dest += sprintf(dest, "%d", P_index);
- } else if(strstr(keyword, "next_url")) {
- if (next_req_url) {
- dest += sprintf(dest, "%s", next_req_url);
- }
- } else if(strstr(keyword, "len")) {
- length_marker = dest;
- dest += sprintf(dest, " ");
- len_offset = offset;
- } else { // scan for the generic parameters - must be last test
- int i = 0;
- while (generic[i]) {
- char *msg1 = *generic[i];
- char *msg2 = *(generic[i] + 1);
- if(!strcmp(keyword, msg1)) {
- dest += sprintf(dest, "%s", msg2);
- break;
- }
- ++i;
- }
- if (!generic[i]) {
- ERROR_P1("Unsupported keyword '%s' in xml scenario file",
- keyword);
- }
- }
- /* This could also be done at XML parsing time. */
- } else if (*src == '\n') {
- *dest++ = '\r';
- *dest++ = *src++;
- current_line[0] = '\0';
- } else {
- *dest++ = *src++;
- }
- }
- *dest = 0;
-
-#ifdef _USE_OPENSSL
- /*
- * The authentication substitution must be done outside the above
- * loop because auth-int will use the body (which must have already
- * been keyword substituted) to build the md5 hash
- */
-
- if(dialog_authentication && (src = strstr(msg_buffer, "[authentication"))) {
- char * auth_marker;
- int auth_marker_len;
-
- char my_auth_user[KEYWORD_SIZE];
- char my_auth_pass[KEYWORD_SIZE];
- char my_aka_OP[KEYWORD_SIZE];
- char my_aka_AMF[KEYWORD_SIZE];
- char my_aka_K[KEYWORD_SIZE];
- char * tmp;
- int authlen;
-
- auth_marker = src;
- auth_marker_len = strchr(src, ']') - src;
- strcpy(my_auth_user, service);
- strcpy(my_auth_pass, auth_password);
- /* Look for optional username and password parameters */
- /* add aka_OP, aka_AMF, aka_K */
- key = getKeywordParam(src, "username=", my_auth_user);
- memset(my_auth_pass,0,KEYWORD_SIZE);
- key = getKeywordParam(src, "password=", my_auth_pass);
- memset(my_aka_OP,0,KEYWORD_SIZE);
- key = getKeywordParam(src, "aka_OP=", my_aka_OP);
- memset(my_aka_AMF,0,KEYWORD_SIZE);
- key = getKeywordParam(src, "aka_AMF=", my_aka_AMF);
- memset(my_aka_K,0,KEYWORD_SIZE);
- key = getKeywordParam(src, "aka_K=", my_aka_K);
- if (my_aka_K[0]==0){
- memcpy(my_aka_K,my_auth_pass,16);
- my_aka_K[16]=0;
- }
-
- /* Need the Method name from the CSeq of the Challenge */
- char method[MAX_HEADER_LEN];
- tmp = get_last_header("CSeq") + 5;
- if(!tmp) {
- ERROR("Could not extract method from cseq of challenge");
- }
- while(isspace(*tmp) || isdigit(*tmp)) tmp++;
- /* This looks like it could have been be a bug, shouldn't it be method instead of &method. */
- sscanf(tmp,"%s", method);
-
- /* Need the body for auth-int calculation */
- char body[SIPP_MAX_MSG_SIZE];
- memset(body, 0, sizeof(body));
- tmp = msg_buffer;
- while(*(tmp+4)) {
- if (*tmp == '\r' && *(tmp + 1) == '\n' &&
- *(tmp + 2) == '\r' && *(tmp + 3) == '\n') {
- sprintf(body, "%s", tmp+4);
- break;
- }
- tmp++;
- }
-
- /* Build the auth credenticals */
- char result[MAX_HEADER_LEN];
- char uri[MAX_HEADER_LEN];
- sprintf (uri, "%s:%d", remote_ip, remote_port);
- if (createAuthHeader(my_auth_user, my_auth_pass, method, uri,
- body, dialog_authentication,
- my_aka_OP,
- my_aka_AMF,
- my_aka_K,
- result) == 0) {
- ERROR_P1("%s", result);
- }
-
- char tmp_buffer[SIPP_MAX_MSG_SIZE];
- dest = strncpy(tmp_buffer, msg_buffer, src - msg_buffer);
- dest += src - msg_buffer;
- key = strchr(src, ']');
- src += key - src + 1;
-
- if (dialog_challenge_type == 401) {
- /* Registrars use Authorization */
- authlen = sprintf(dest, "Authorization: %s", result);
- } else {
- /* Proxies use Proxy-Authorization */
- authlen = sprintf(dest, "Proxy-Authorization: %s", result);
- }
- dest += authlen;
- if (length_marker > auth_marker) {
- length_marker = length_marker - 1 - auth_marker_len + authlen;
- }
- dest += sprintf(dest, "%s", src);
- strcpy(msg_buffer, tmp_buffer);
- dest = msg_buffer + strlen(msg_buffer);
- }
-#endif
-
- // Remove all \r, \n but 1 at the end of a message to send
- int len = strlen(msg_buffer);
- while ( (msg_buffer[len-1] == '\n') &&
- (msg_buffer[len-2] == '\r') &&
- (msg_buffer[len-3] == '\n') &&
- (msg_buffer[len-4] == '\r')) {
- msg_buffer[len-2] = 0;
- len -= 2;
- }
-
- int L_flag_crlf = 0 ; // don't need add crlf
- int L_content_length = 0;
-
- if(P_index < 0 ) {
- L_flag_crlf = 1 ; // Add crlf
- } else {
- message::ContentLengthFlag L_flag_content = scenario[P_index] -> content_length_flag ;
- switch (L_flag_content) {
- case message::ContentLengthValueZero :
- L_flag_crlf = 1;
- break ;
- case message::ContentLengthValueNoZero :
- // the msg contains content-length field and his value is greater than 0
- break ;
- default :
- // the msg does not contain content-length field
- // control the crlf
- L_content_length = xp_get_content_length(msg_buffer) ;
- if( L_content_length == 0) {
- L_flag_crlf = 1;
- } else if (L_content_length == -1 ) {
- // The content_length is not present: its a [len] keyword
- }
- break;
- }
- }
-
- if(L_flag_crlf) {
- // Add crlf
- msg_buffer[len] ='\r';
- msg_buffer[len+1] ='\n';
- msg_buffer[len+2] =0;
- }
-
- if (length_marker) {
- key = strstr(length_marker,"\r\n\r\n");
- if (key && dest - key > 4 && dest - key < 10004) {
- char tmp = length_marker[4];
- sprintf(length_marker, "%4u", dest - key - 4 + len_offset);
- length_marker[4] = tmp;
- } else {
- // Other cases: Content-Length is 0
- sprintf(length_marker, " 0\r\n\r\n");
- }
- }
- } else {
- ERROR("Unsupported 'send' message in scenario");
- }
- return(msg_buffer);
-}
+ }
+
+ if (auth_comp_allocated) {
+ SendingMessage::freeMessageComponent(auth_comp);
+ }
+
+ return msg_buffer;
+}
+
+char* call::createSendingMessage(char *src, int P_index, bool skip_sanity)
+{
+ if (src == NULL) {
+ ERROR("Unsupported 'send' message in scenario");
+ }
+
+ SendingMessage *msgsrc = new SendingMessage(src, skip_sanity);
+ char *msg = createSendingMessage(msgsrc, P_index);
+ delete msgsrc;
+ return msg;
+}
+
#ifdef __3PCC__
@@ -2418,6 +2350,7 @@
continue;
}
/* The received message is different from the expected one */
+ TRACE_MSG((s, "Unexpected control message received (I was expecting a different type of message):\n%s\n", msg));
return rejectCall();
} else {
if(extendedTwinSippMode){ // 3pcc extended mode
@@ -2457,6 +2390,7 @@
}
}
} else {
+ TRACE_MSG((s, "Unexpected control message received (no such message found):\n%s\n", msg));
return rejectCall();
}
msg_index = search_index; //update the state machine
@@ -2705,8 +2639,8 @@
int result;
if ((reply_code) && ((scenario[index] -> recv_response) == reply_code) && \
- (scenario[index]->recv_response_for_cseq_method_list) && \
- (strstr(scenario[index]->recv_response_for_cseq_method_list, responsecseqmethod))) {
+ (index == 0 || ((scenario[index]->recv_response_for_cseq_method_list) && \
+ (strstr(scenario[index]->recv_response_for_cseq_method_list, responsecseqmethod))))) {
return true;
}
@@ -2752,9 +2686,9 @@
paused_calls.remove_paused_call(this);
add_running_call(this);
}
-
- /* Ignore the messages received during a pause if -pause_msg_ign is set */
- if(scenario[msg_index] -> M_type == MSG_TYPE_PAUSE && pause_msg_ign) return(true);
+
+ /* Ignore the messages received during a pause if -pause_msg_ign is set */
+ if(scenario[msg_index] -> M_type == MSG_TYPE_PAUSE && pause_msg_ign) return(true);
/* Authorize nop as a first command, even in server mode */
if((msg_index == 0) && (scenario[msg_index] -> M_type == MSG_TYPE_NOP)) {
@@ -2786,7 +2720,8 @@
if(status == 0) {
scenario[recv_retrans_send_index] -> nb_sent_retrans++;
- } else if(status < -1) {
+ CStat::instance()->computeStat(CStat::E_RETRANSMISSION);
+ } else if(status < 0) {
return false;
}
@@ -2875,7 +2810,7 @@
ERROR_P1("Invalid sip message received '%s'",
msg);
}
-
+
/* Try to find it in the expected non mandatory responses
* until the first mandatory response in the scenario */
for(search_index = msg_index;
@@ -2916,7 +2851,7 @@
if ( (reply_code) &&
(0 == strncmp (responsecseqmethod, "INVITE", strlen(responsecseqmethod)) ) &&
(scenario[search_index+1]->M_type == MSG_TYPE_SEND) &&
- (0 == strncmp(scenario[search_index+1]->send_scheme, "ACK", 3)) ) {
+ (scenario[search_index+1]->send_scheme->isAck()) ) {
sendBuffer(createSendingMessage(scenario[search_index+1] -> send_scheme, (search_index+1)));
return true;
}
@@ -2933,7 +2868,7 @@
}
} else {
// call aborted by automatic response mode if needed
- return (automaticResponseMode(L_case, msg));
+ return automaticResponseMode(L_case, msg);
}
}
@@ -2974,7 +2909,7 @@
}
}
}
-
+
if (request) { // update [cseq] with received CSeq
unsigned long int rcseq = get_cseq_value(msg);
if (rcseq > cseq) cseq = rcseq;
@@ -3066,7 +3001,7 @@
ERROR("Couldn't find 'Proxy-Authenticate' or 'WWW-Authenticate' in 401 or 407!");
}
- dialog_authentication = (char *) calloc(1, strlen(auth) + 2);
+ dialog_authentication = (char *) realloc(dialog_authentication, strlen(auth) + 2);
sprintf(dialog_authentication, "%s", auth);
/* Store the code of the challenge for building the proper header */
@@ -3087,15 +3022,18 @@
if (!(scenario[search_index] -> optional) ||
scenario[search_index]->next &&
((test == -1) ||
- (test < SCEN_VARIABLE_SIZE && M_callVariableTable[test] != NULL && M_callVariableTable[test]->isSet()))
+ (test <= maxVariableUsed && M_callVariableTable[test] != NULL && M_callVariableTable[test]->isSet()))
) {
+ /* If we are paused, then we need to wake up so that we properly go through the state machine. */
+ paused_until = 0;
msg_index = search_index;
return next();
} else {
unsigned int timeout = call_wake(this);
unsigned int candidate;
- if (test < SCEN_VARIABLE_SIZE && M_callVariableTable[test] != NULL && M_callVariableTable[test]->isSet()) {
+ if (scenario[search_index]->next && test <= maxVariableUsed &&
+ M_callVariableTable[test] != NULL && M_callVariableTable[test]->isSet()) {
WARNING_P1("Last message generates an error and will not be used for next sends (for last_ variables):\r\n%s",msg);
}
@@ -3106,7 +3044,7 @@
if(scenario[search_index] -> M_type != MSG_TYPE_RECV) {
break;
}
- candidate = scenario[search_index] -> retrans_delay;
+ candidate = scenario[search_index] -> timeout;
if (candidate == 0) {
if (defl_recv_timeout == 0) {
continue;
@@ -3126,6 +3064,14 @@
return true;
}
+double call::get_rhs(CAction *currentAction) {
+ if (currentAction->getVarInId()) {
+ return M_callVariableTable[currentAction->getVarInId()]->getDouble();
+ } else {
+ return currentAction->getDoubleValue();
+ }
+}
+
call::T_ActionResult call::executeAction(char * msg, int scenarioIndex)
{
CActions* actions;
@@ -3137,7 +3083,7 @@
actions = scenario[scenarioIndex]->M_actions;
// looking for action to do on this message
if(actions != NULL) {
- for(int i=0; i<actions->getUsedAction(); i++) {
+ for(int i=0; i<actions->getActionSize(); i++) {
currentAction = actions->getAction(i);
if(currentAction != NULL) {
if(currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_REGEXP) {
@@ -3206,43 +3152,98 @@
}
} // end if scen variable != null
} else /* end action == E_AT_ASSIGN_FROM_REGEXP */
- if (currentAction->getActionType() == CAction::E_AT_LOG_TO_FILE) {
- char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/);
+ if (currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_VALUE) {
+ M_callVariableTable[currentAction->getVarId()]->setDouble(currentAction->getDoubleValue());
+ } else if (currentAction->getActionType() == CAction::E_AT_VAR_ADD) {
+ double value = M_callVariableTable[currentAction->getVarId()]->getDouble();
+ double operand = get_rhs(currentAction);
+ M_callVariableTable[currentAction->getVarId()]->setDouble(value + operand);
+ } else if (currentAction->getActionType() == CAction::E_AT_VAR_SUBTRACT) {
+ double value = M_callVariableTable[currentAction->getVarId()]->getDouble();
+ double operand = get_rhs(currentAction);
+ M_callVariableTable[currentAction->getVarId()]->setDouble(value - operand);
+ } else if (currentAction->getActionType() == CAction::E_AT_VAR_MULTIPLY) {
+ double value = M_callVariableTable[currentAction->getVarId()]->getDouble();
+ double operand = get_rhs(currentAction);
+ M_callVariableTable[currentAction->getVarId()]->setDouble(value * operand);
+ } else if (currentAction->getActionType() == CAction::E_AT_VAR_DIVIDE) {
+ double value = M_callVariableTable[currentAction->getVarId()]->getDouble();
+ double operand = get_rhs(currentAction);
+ if (operand == 0) {
+ WARNING_P2("Action failure: Can not divide by zero ($%d/$%d)!\n", currentAction->getVarId(), currentAction->getVarInId());
+ } else {
+ M_callVariableTable[currentAction->getVarId()]->setDouble(value / operand);
+ }
+ } else if (currentAction->getActionType() == CAction::E_AT_VAR_TEST) {
+ double value = currentAction->compare(M_callVariableTable);
+ M_callVariableTable[currentAction->getVarId()]->setBool(value);
+ } else if (currentAction->getActionType() == CAction::E_AT_VAR_STRCMP) {
+ char *rhs = M_callVariableTable[currentAction->getVarInId()]->getString();
+ char *lhs = currentAction->getStringValue();
+ int value = strcmp(rhs, lhs);
+ M_callVariableTable[currentAction->getVarId()]->setDouble((double)value);
+ } else if (currentAction->getActionType() == CAction::E_AT_VAR_TO_DOUBLE) {
+ double value;
+
+ if (M_callVariableTable[currentAction->getVarInId()]->toDouble(&value)) {
+ M_callVariableTable[currentAction->getVarId()]->setDouble(value);
+ } else {
+ WARNING_P2("Invalid double conversion from $%d to $%d", currentAction->getVarInId(), currentAction->getVarId());
+ }
+ } else if (currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_SAMPLE) {
+ double value = currentAction->getDistribution()->sample();
+ M_callVariableTable[currentAction->getVarId()]->setDouble(value);
+ } else if (currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_STRING) {
+ char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/, true /* skip sanity check */);
+ char *str = strdup(x);
+ if (!str) {
+ ERROR("Out of memory duplicating string for assignment!");
+ }
+ M_callVariableTable[currentAction->getVarId()]->setString(str);
+ } else if (currentAction->getActionType() == CAction::E_AT_LOG_TO_FILE) {
+ char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/, true /* skip sanity check */);
LOG_MSG((s, "%s\n", x));
- } else /* end action == E_AT_LOG_TO_FILE */
- if (currentAction->getActionType() == CAction::E_AT_EXECUTE_CMD) {
+ } else if (currentAction->getActionType() == CAction::E_AT_EXECUTE_CMD) {
if (currentAction->getCmdLine()) {
- char* x = createSendingMessage(currentAction->getCmdLine(), -2 /* do not add crlf*/);
+ char* x = createSendingMessage(currentAction->getCmdLine(), -2 /* do not add crlf*/, true /* skip sanity check. */);
// TRACE_MSG((s, "Trying to execute [%s]", x));
pid_t l_pid;
switch(l_pid = fork())
{
case -1:
// error when forking !
- ERROR("Forking error");
+ ERROR_NO("Forking error main");
break;
case 0:
- // first child process - execute the command
+ // first child process - execute the command
if((l_pid = fork()) < 0) {
- ERROR("Forking error");
+ ERROR_NO("Forking error child");
} else {
- if( l_pid == 0)
- system(x); // second child runs
- exit(EXIT_OTHER);
+ if( l_pid == 0){
+ int ret;
+ ret = system(x); // second child runs
+ if(ret == -1) {
+ WARNING_P1("system call error for %s",x);
+ }
+ }
+ exit(EXIT_OTHER);
}
break;
default:
// parent process continue
// reap first child immediately
- if(waitpid(l_pid, NULL, 0) != l_pid) {
- ERROR("waitpid error");
+ pid_t ret;
+ while ((ret=waitpid(l_pid, NULL, 0)) != l_pid) {
+ if (ret != -1) {
+ ERROR_P2("waitpid returns %1d for child %1d",ret,l_pid);
+ }
}
break;
}
}
- } else /* end action == E_AT_LOG_TO_FILE */
+ } else /* end action == E_AT_EXECUTE_CMD */
if (currentAction->getActionType() == CAction::E_AT_EXEC_INTCMD) {
switch (currentAction->getIntCmd())
{
@@ -3293,7 +3294,7 @@
ERROR("Can create thread to send RTP packets");
pthread_attr_destroy(&attr);
#endif
- } else {// end action == E_AT_EXECUTE_CMD
+ } else {
ERROR("call::executeAction unknown action");
}
} // end if current action != null
@@ -3362,128 +3363,16 @@
}
}
-void call::dumpFileContents(void)
-{
- WARNING_P3("Line choosing strategy is [%s]. m_counter [%d] numLinesInFile [%d]",
- m_usage == InputFileSequentialOrder ? "SEQUENTIAL" : "RANDOM",
- m_counter, numLinesInFile);
-
- for (int i(0); i < numLinesInFile && fileContents[i][0]; ++i) {
- WARNING_P2("%dth line reads [%s]", i, fileContents[i].c_str());
- }
-}
-
-/* Read MAX_CHAR_BUFFER_SIZE size lines from the
- * "fileName" and populate it in the fileContents
- * vector. The file should not be more than
- * MAX_LINES_IN_FILE lines long and each line
- * should be terminated with a '\n'
- */
-
-void call::readInputFileContents(const char* fileName)
-{
- ifstream *inFile = new ifstream(fileName);
- ifstream &inFileObj = *inFile;
- char line[MAX_CHAR_BUFFER_SIZE];
-
- if (!inFile->good()) {
- ERROR_P1("Unable to open file %s", fileName);
- return ;
- }
-
- numLinesInFile = 0;
- call::m_counter = 0;
- line[0] = '\0';
- inFileObj.getline(line, MAX_CHAR_BUFFER_SIZE);
-
- if (NULL != strstr(line, "RANDOM")) {
- call::m_usage = InputFileRandomOrder;
- } else if (NULL != strstr(line, "SEQUENTIAL")) {
- call::m_usage = InputFileSequentialOrder;
- } else {
- // default
- call::m_usage = InputFileSequentialOrder;
- }
-
- while (!inFileObj.eof()) {
- line[0] = '\0';
- inFileObj.getline(line, MAX_CHAR_BUFFER_SIZE);
- if (line[0]) {
- if ('#' != line[0]) {
- fileContents.push_back(line);
- numLinesInFile++; /* this counts number of valid data lines */
- }
- } else {
- break;
- }
- }
- // call::dumpFileContents();
- delete inFile;
-}
-
-void call::getFieldFromInputFile(const char* keyword, unsigned int lineNum, char*& dest)
-{
- int nthField = atoi(keyword+5 /*strlen("field")*/);
- int origNth = nthField;
-
- if (fileContents.size() > lineNum) {
- const string& line = fileContents[lineNum];
-
- // WARNING_P3("lineNum [%d] nthField [%d] line [%s]",
- // lineNum, nthField, line.c_str());
-
- size_t pos(0), oldpos(0);
- do {
- oldpos = pos;
- size_t localpos = line.find(';', oldpos);
-
- if (localpos != string::npos) {
- pos = localpos + 1;
- } else {
- pos = localpos;
- break;
- }
-
- //string x = line.substr(oldpos, pos - oldpos);
- // WARNING_P3("pos [%d] oldpos [%d] is [%s]", pos, oldpos, x.c_str());
-
- if (nthField) {
- --nthField;
- } else {
- break;
- }
-
- } while (oldpos != string::npos);
-
- if (nthField) {
- WARNING_P1("Field %d not found in the file", origNth);
- // field not found in line
- } else {
- if (string::npos != oldpos) {
- if (string::npos != pos) {
- // should not be decremented for fieldN
- pos -= (oldpos + 1);
- }
-
- string x = line.substr(oldpos, pos);
- if (x.length()) {
- dest += sprintf(dest, "%s", x.c_str());
- }
-
- // WARNING_P2("nthField [%d] is [%s]", origNth, x.c_str());
- }
- }
- } else {
- // WARNING_P1("Field %d definition not found", nthField);
- }
-}
-
-void call::getIpFieldFromInputFile(int fieldNr, int lineNum, char *dest)
-{
- char keyword[10];
- sprintf(keyword, "field%d", fieldNr);
- char *p = dest;
- getFieldFromInputFile(keyword, lineNum, p);
+void call::getFieldFromInputFile(const char *fileName, int field, char*& dest)
+{
+ if (inFiles.find(fileName) == inFiles.end()) {
+ ERROR_P1("Invalid injection file: %s", fileName);
+ }
+ int line = (*m_lineNumber)[fileName];
+ if (line < 0) {
+ return;
+ }
+ dest += inFiles[fileName]->getField(line, field, dest, SIPP_MAX_MSG_SIZE);
}
int call::checkAutomaticResponseMode(char * P_recv) {
@@ -3523,7 +3412,7 @@
scenario[msg_index] -> nb_unexp++;
if (default_behavior) {
WARNING_P1("Aborting call on an unexpected BYE for call: %s", (id==NULL)?"none":id);
- res = sendBuffer(createSendingMessage(
+ sendBuffer(createSendingMessage(
(char*)"SIP/2.0 200 OK\n"
"[last_Via:]\n"
"[last_From:]\n"
@@ -3531,14 +3420,14 @@
"[last_Call-ID:]\n"
"[last_CSeq:]\n"
"Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
- "Content-Length: 0\n"
+ "Content-Length: 0\n\n"
, -1)) ;
#ifdef __3PCC__
// if twin socket call => reset the other part here
if (twinSippSocket && (msg_index > 0)) {
res = sendCmdBuffer
- (createSendingMessage((char*)"call-id: [call_id]\ninternal-cmd: abort_call\n", -1));
+ (createSendingMessage((char*)"call-id: [call_id]\ninternal-cmd: abort_call\n\n", -1));
}
#endif /* __3PCC__ */
CStat::instance()->computeStat(CStat::E_CALL_FAILED);
@@ -3558,7 +3447,7 @@
scenario[msg_index] -> nb_unexp++;
if (default_behavior) {
WARNING_P1("Aborting call on an unexpected CANCEL for call: %s", (id==NULL)?"none":id);
- res = sendBuffer(createSendingMessage(
+ sendBuffer(createSendingMessage(
(char*)"SIP/2.0 200 OK\n"
"[last_Via:]\n"
"[last_From:]\n"
@@ -3566,14 +3455,14 @@
"[last_Call-ID:]\n"
"[last_CSeq:]\n"
"Contact: sip:sipp@[local_ip]:[local_port]\n"
- "Content-Length: 0\n"
+ "Content-Length: 0\n\n"
, -1)) ;
#ifdef __3PCC__
// if twin socket call => reset the other part here
if (twinSippSocket && (msg_index > 0)) {
res = sendCmdBuffer
- (createSendingMessage((char*)"call-id: [call_id]\ninternal-cmd: abort_call\n", -1));
+ (createSendingMessage((char*)"call-id: [call_id]\ninternal-cmd: abort_call\n\n", -1));
}
#endif /* __3PCC__ */
@@ -3593,7 +3482,7 @@
if (default_behavior) {
WARNING_P1("Automatic response mode for an unexpected PING for call: %s", (id==NULL)?"none":id);
count_in_stats = false; // Call must not be counted in statistics
- res = sendBuffer(createSendingMessage(
+ sendBuffer(createSendingMessage(
(char*)"SIP/2.0 200 OK\n"
"[last_Via:]\n"
"[last_Call-ID:]\n"
@@ -3601,7 +3490,7 @@
"[last_From:]\n"
"[last_CSeq:]\n"
"Contact: sip:sipp@[local_ip]:[local_port]\n"
- "Content-Length: 0\n"
+ "Content-Length: 0\n\n"
, -1)) ;
// Note: the call ends here but it is not marked as bad. PING is a
// normal message.
@@ -3609,7 +3498,7 @@
// if twin socket call => reset the other part here
if (twinSippSocket && (msg_index > 0)) {
res = sendCmdBuffer
- (createSendingMessage((char*)"call-id: [call_id]\ninternal-cmd: abort_call\n",-1));
+ (createSendingMessage((char*)"call-id: [call_id]\ninternal-cmd: abort_call\n\n",-1));
}
#endif /* __3PCC__ */
@@ -3635,7 +3524,7 @@
strcpy(last_recv_msg, P_recv);
WARNING_P1("Automatic response mode for an unexpected INFO, UPDATE or NOTIFY for call: %s", (id==NULL)?"none":id);
- res = sendBuffer(createSendingMessage(
+ sendBuffer(createSendingMessage(
(char*)"SIP/2.0 200 OK\n"
"[last_Via:]\n"
"[last_Call-ID:]\n"
@@ -3643,7 +3532,7 @@
"[last_From:]\n"
"[last_CSeq:]\n"
"Contact: sip:sipp@[local_ip]:[local_port]\n"
- "Content-Length: 0\n"
+ "Content-Length: 0\n\n"
, -1)) ;
// restore previous last msg
@@ -3658,6 +3547,41 @@
CStat::instance()->computeStat(CStat::E_AUTO_ANSWERED);
return true;
break;
+
+ case 5: // response for an out of call message
+ old_last_recv_msg = NULL;
+ if (last_recv_msg != NULL) {
+ last_recv_msg_saved = true;
+ old_last_recv_msg = (char *) malloc(strlen(last_recv_msg)+1);
+ strcpy(old_last_recv_msg,last_recv_msg);
+ }
+ // usage of last_ keywords
+ last_recv_msg = (char *) realloc(last_recv_msg, strlen(P_recv) + 1);
+ strcpy(last_recv_msg, P_recv);
+
+ WARNING("Automatic response mode for an out of call message");
+ sendBuffer(createSendingMessage(
+ (char*)"SIP/2.0 200 OK\n"
+ "[last_Via:]\n"
+ "[last_Call-ID:]\n"
+ "[last_To:]\n"
+ "[last_From:]\n"
+ "[last_CSeq:]\n"
+ "Contact: sip:sipp@[local_ip]:[local_port]\n"
+ "Content-Length: 0\n\n"
+ , -1)) ;
+
+ // restore previous last msg
+ if (last_recv_msg_saved == true) {
+ last_recv_msg = (char *) realloc(last_recv_msg, strlen(old_last_recv_msg) + 1);
+ strcpy(last_recv_msg, old_last_recv_msg);
+ if (old_last_recv_msg != NULL) {
+ free(old_last_recv_msg);
+ old_last_recv_msg = NULL;
+ }
+ }
+ CStat::instance()->computeStat(CStat::E_AUTO_ANSWERED);
+ return true;
default:
ERROR_P1("Internal error for automaticResponseMode - mode %d is not implemented!", P_case);
Modified: sip-tester/branches/upstream/current/sipp.hpp
URL: http://svn.debian.org/wsvn/pkg-voip/sip-tester/branches/upstream/current/sipp.hpp?rev=6620&op=diff
==============================================================================
--- sip-tester/branches/upstream/current/sipp.hpp (original)
+++ sip-tester/branches/upstream/current/sipp.hpp Sun Jan 4 02:02:39 2009
@@ -61,6 +61,7 @@
#include "stat.hpp"
#include "actions.hpp"
#include "variables.hpp"
+#include "infile.hpp"
/* Open SSL stuff */
#ifdef _USE_OPENSSL
#include "sslcommon.h"
@@ -92,17 +93,18 @@
/************************** Constants **************************/
-#define SIPP_VERSION 20070516
+#define SIPP_VERSION 20071128
#define T_UDP 0
#define T_TCP 1
+#define T_TLS 2
+
#ifdef _USE_OPENSSL
-#define T_TLS 2
#define DEFAULT_TLS_CERT ((char *)"cacert.pem")
#define DEFAULT_TLS_KEY ((char *)"cakey.pem")
#define DEFAULT_TLS_CRL ((char *)"")
-
-#endif
-#define TRANSPORT_TO_STRING(p) ((p==1) ? "TCP" : ((p==2)? "TLS" :"UDP"))
+#endif
+
+#define TRANSPORT_TO_STRING(p) ((p==T_TCP) ? "TCP" : ((p==T_TLS)? "TLS" :"UDP"))
#define SIPP_MAXFDS 65536
#define SIPP_MAX_MSG_SIZE 65536
@@ -119,6 +121,7 @@
#define DISPLAY_SECONDARY_REPARTITION_SCREEN 6
#define MAX_RECV_LOOPS_PER_CYCLE 1000
+#define MAX_SCHED_LOOPS_PER_CYCLE 1000
#define NB_UPDATE_PER_CYCLE 1
#define MAX_PATH 250
@@ -155,6 +158,7 @@
extern int users _DEFVAL(0);
extern int rate_period_ms _DEFVAL(DEFAULT_RATE_PERIOD_MS);
extern unsigned long defl_recv_timeout _DEFVAL(0);
+extern unsigned long defl_send_timeout _DEFVAL(0);
extern unsigned long global_timeout _DEFVAL(0);
extern int transport _DEFVAL(DEFAULT_TRANSPORT);
extern bool retrans_enabled _DEFVAL(1);
@@ -187,13 +191,15 @@
extern unsigned int timer_resolution _DEFVAL(DEFAULT_TIMER_RESOLUTION);
extern int max_recv_loops _DEFVAL(MAX_RECV_LOOPS_PER_CYCLE);
+extern int max_sched_loops _DEFVAL(MAX_SCHED_LOOPS_PER_CYCLE);
extern char local_ip[40];
extern char local_ip_escaped[42];
extern bool local_ip_is_ipv6;
extern int local_port _DEFVAL(0);
+extern int control_port _DEFVAL(0);
extern int buff_size _DEFVAL(65535);
-extern int tcp_readsize _DEFVAL(4096);
+extern int tcp_readsize _DEFVAL(65535);
#ifdef PCAPPLAY
extern int hasMedia _DEFVAL(0);
#endif
@@ -229,8 +235,6 @@
extern bool backgroundMode _DEFVAL(false);
extern bool signalDump _DEFVAL(false);
-extern bool ctrlEW _DEFVAL(false);
-
extern int currentScreenToDisplay _DEFVAL
(DISPLAY_SCENARIO_SCREEN);
extern int currentRepartitionToDisplay _DEFVAL(1);
@@ -251,8 +255,6 @@
extern bool tdm_map[1024];
#ifdef _USE_OPENSSL
-extern BIO *bio ;
-extern SSL *ssl_tcp_multiplex ;
extern BIO *twinSipp_bio ;
extern SSL *twinSipp_ssl ;
extern char *tls_cert_name _DEFVAL(DEFAULT_TLS_CERT) ;
@@ -262,19 +264,27 @@
#endif
// extern field file management
-typedef std::vector<std::string> IN_FILE_CONTENTS;
-extern IN_FILE_CONTENTS fileContents;
-extern int numLinesInFile _DEFVAL(0);
-
-extern int new_socket(bool P_use_ipv6, int P_type_socket, int * P_status);
+typedef std::map<string, FileContents *> file_map;
+extern file_map inFiles;
+extern char *ip_file _DEFVAL(NULL);
+extern char *default_file _DEFVAL(NULL);
+
+// free user id list
+extern list<int> freeUsers;
+
+//extern int new_socket(bool P_use_ipv6, int P_type_socket, int * P_status);
+extern struct sipp_socket *new_sipp_socket(bool use_ipv6, int transport);
+struct sipp_socket *new_sipp_call_socket(bool use_ipv6, int transport, bool *existing);
+struct sipp_socket *sipp_accept_socket(struct sipp_socket *accept_socket);
+extern int sipp_bind_socket(struct sipp_socket *socket, struct sockaddr_storage *saddr, int *port);
+extern int sipp_connect_socket(struct sipp_socket *socket, struct sockaddr_storage *dest);
+extern void sipp_customize_socket(struct sipp_socket *socket);
extern int delete_socket(int P_socket);
extern int min_socket _DEFVAL(65535);
extern int select_socket _DEFVAL(0);
extern bool socket_close _DEFVAL(true);
extern bool test_socket _DEFVAL(true);
-extern bool socket_open _DEFVAL(true);
extern bool maxSocketPresent _DEFVAL(false);
-extern int *tab_multi_socket;
extern unsigned long getmilliseconds();
extern unsigned long long getmicroseconds();
@@ -329,8 +339,8 @@
/*********************** Global Sockets **********************/
-extern int main_socket _DEFVAL(0);
-extern int tcp_multiplex _DEFVAL(0);
+extern struct sipp_socket *main_socket _DEFVAL(0);
+extern struct sipp_socket *tcp_multiplex _DEFVAL(0);
extern int media_socket _DEFVAL(0);
extern int media_socket_video _DEFVAL(0);
@@ -340,16 +350,15 @@
extern char hostname[80];
extern bool is_ipv6 _DEFVAL(false);
extern int start_calls _DEFVAL(0);
-extern double reset_number _DEFVAL(0);
+extern int reset_number _DEFVAL(0);
extern int reset_close _DEFVAL(1);
extern int reset_sleep _DEFVAL(1000);
extern struct addrinfo * local_addr_storage;
-#ifdef __3PCC__
-extern int twinSippSocket _DEFVAL(0);
-extern int localTwinSippSocket _DEFVAL(0);
-extern struct sockaddr_storage twinSipp_sockaddr;
+extern struct sipp_socket *twinSippSocket _DEFVAL(NULL);
+extern struct sipp_socket *localTwinSippSocket _DEFVAL(NULL);
+extern struct sockaddr_storage twinSipp_sockaddr;
/* 3pcc extended mode */
typedef struct _T_peer_infos {
@@ -357,22 +366,20 @@
int peer_port;
struct sockaddr_storage peer_sockaddr;
char peer_ip[40];
- int peer_socket ;
+ struct sipp_socket *peer_socket ;
} T_peer_infos;
typedef std::map<std::string, char * > peer_addr_map;
extern peer_addr_map peer_addrs;
typedef std::map<std::string, T_peer_infos> peer_map;
extern peer_map peers;
-typedef std::map<int, std::string > peer_socket_map;
+typedef std::map<struct sipp_socket *, std::string > peer_socket_map;
extern peer_socket_map peer_sockets;
-extern int local_sockets[MAX_LOCAL_TWIN_SOCKETS];
+extern struct sipp_socket *local_sockets[MAX_LOCAL_TWIN_SOCKETS];
extern int local_nb _DEFVAL(0);
extern int peers_connected _DEFVAL(0);
-#endif
-
-extern struct sockaddr_storage remote_sockaddr;
-
+
+extern struct sockaddr_storage remote_sockaddr;
extern short use_remote_sending_addr _DEFVAL(0);
extern struct sockaddr_storage remote_sending_sockaddr;
@@ -387,11 +394,13 @@
extern FILE * screenf _DEFVAL(0);
extern FILE * logfile _DEFVAL(0);
extern FILE * messagef _DEFVAL(0);
-extern FILE * timeoutf _DEFVAL(0);
+extern FILE * shortmessagef _DEFVAL(0);
+// extern FILE * timeoutf _DEFVAL(0);
extern bool useMessagef _DEFVAL(0);
+extern bool useShortMessagef _DEFVAL(0);
extern bool useScreenf _DEFVAL(0);
extern bool useLogf _DEFVAL(0);
-extern bool useTimeoutf _DEFVAL(0);
+//extern bool useTimeoutf _DEFVAL(0);
extern bool dumpInFile _DEFVAL(0);
extern bool dumpInRtt _DEFVAL(0);
extern char * scenario_file;
@@ -406,6 +415,15 @@
} \
}
+#define TRACE_SHORTMSG(arg) \
+{ \
+ if(shortmessagef) { \
+ FILE * s = shortmessagef;\
+ fprintf arg; \
+ fflush(shortmessagef); \
+ } \
+}
+
#define LOG_MSG(arg) \
{ \
if(logfile) { \
@@ -415,14 +433,16 @@
} \
}
-#define TRACE_TIMEOUT(arg) \
+// TODO: finish the -trace_timeout option implementation
+
+/* #define TRACE_TIMEOUT(arg) \
{ \
if(timeoutf) { \
FILE * s = timeoutf; \
fprintf arg; \
fflush(timeoutf); \
} \
-}
+} */
/********************* Mini-Parser Routines *******************/
@@ -433,15 +453,65 @@
/********************** Network Interfaces ********************/
-void sipp_customize_socket(int socket);
int send_message(int s, void ** comp_state, char * msg);
#ifdef _USE_OPENSSL
int send_message_tls(SSL *s, void ** comp_state, char * msg);
#endif
-void pollset_remove(int idx);
-void remove_from_pollfiles(int sock);
-int pollset_add(call * p_call, int socket);
+/* Socket Buffer Management. */
+#define NO_COPY 0
+#define DO_COPY 1
+struct socketbuf *alloc_socketbuf(char *buffer, size_t size, int copy);
+void free_socketbuf(struct socketbuf *socketbuf);
+
+/* These buffers lets us read past the end of the message, and then split it if
+ * required. This eliminates the need for reading a message octet by octet and
+ * performing a second read for the content length. */
+struct socketbuf {
+ char *buf;
+ size_t len;
+ size_t offset;
+ struct socketbuf *next;
+};
+
+/* This is an abstraction of a socket, which provides buffers for input and
+ * output. */
+struct sipp_socket {
+ int ss_count; /* How many users are there of this socket? */
+
+ int ss_transport; /* T_TCP, T_UDP, or T_TLS. */
+ bool ss_ipv6;
+ bool ss_control; /* Is this a control socket? */
+ bool ss_call_socket; /* Is this a call socket? */
+
+ int ss_fd; /* The underlying file descriptor for this socket. */
+ void *ss_comp_state; /* The compression state. */
+#ifdef _USE_OPENSSL
+ SSL *ss_ssl; /* The underlying SSL descriptor for this socket. */
+ BIO *ss_bio; /* The underlying BIO descriptor for this socket. */
+#endif
+ struct sockaddr_storage ss_remote_sockaddr; /* Who we are talking to. */
+
+
+ int ss_pollidx; /* The index of this socket in our poll structures. */
+ bool ss_congested; /* Is this socket congested? */
+ bool ss_invalid; /* Has this socket been closed remotely? */
+
+ struct socketbuf *ss_in; /* Buffered input. */
+ size_t ss_msglen; /* Is there a complete SIP message waiting, and if so how big? */
+ struct socketbuf *ss_out; /* Buffered output. */
+};
+
+/* Write data to a socket. */
+int write_socket(struct sipp_socket *socket, char *buffer, ssize_t len, int flags);
+/* Mark a socket as "bad". */
+void sipp_socket_invalidate(struct sipp_socket *socket);
+/* Actually free the socket. */
+void sipp_close_socket(struct sipp_socket *socket);
+
+#define WS_EAGAIN 1 /* Return EAGAIN if there is no room for writing the message. */
+#define WS_BUFFER 2 /* Buffer the message if there is no room for writing the message. */
+
#if defined (__hpux) || defined (__alpha) && !defined (__FreeBSD__)
#define sipp_socklen_t int
@@ -467,15 +537,16 @@
int reset_connections() ;
int close_calls();
+int close_calls(struct sipp_socket *);
int close_connections();
int open_connections();
void timeout_alarm(int);
/* extended 3PCC mode */
-int * get_peer_socket(char *);
-bool is_a_peer_socket(int);
-bool is_a_local_socket(int);
-void connect_to_peer (char *, int *, sockaddr_storage *, char *, int *);
+struct sipp_socket **get_peer_socket(char *);
+bool is_a_peer_socket(struct sipp_socket *);
+bool is_a_local_socket(struct sipp_socket *);
+void connect_to_peer (char *, int , sockaddr_storage *, char *, struct sipp_socket **);
void connect_to_all_peers ();
void connect_local_twin_socket(char *);
void close_peer_sockets();
More information about the Pkg-voip-commits
mailing list