[Pkg-voip-commits] r6622 - 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:47:02 UTC 2009
Author: msp
Date: Sun Jan 4 02:47:02 2009
New Revision: 6622
URL: http://svn.debian.org/wsvn/pkg-voip/?sc=1&rev=6622
Log:
[svn-upgrade] Integrating new upstream version, sip-tester (3.1)
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=6622&op=diff
==============================================================================
--- sip-tester/branches/upstream/current/Makefile (original)
+++ sip-tester/branches/upstream/current/Makefile Sun Jan 4 02:47:02 2009
@@ -19,13 +19,15 @@
#
-include local.mk
+SVN_VERSION=$(shell if test -d .svn ; then svnversion . | sed -e 's/^/svn/;' ; else echo unknown ; fi)
+VERINFO=-DSVN_VERSION="\"$(SVN_VERSION)\""
# Output binary to be built
OUTPUT=sipp
# C & C++ object files to be built
OBJ= xp_parser.o message.o scenario.o screen.o call.o comp.o sipp.o stat.o \
- actions.o variables.o infile.o
+ actions.o variables.o infile.o deadcall.o task.o socketowner.o listener.o
# Libraries directories
LIBDIR_linux=
@@ -99,20 +101,20 @@
CFLAGS_linux=-D__LINUX -pthread
CFLAGS_freebsd=-D__LINUX -pthread
CFLAGS_tru64=-D__OSF1 -pthread
-CFLAGS_SunOS=-g -D__SUNOS
+CFLAGS_SunOS=${DEBUG_FLAGS} -D__SUNOS
CFLAGS_Cygwin=-D__CYGWIN -Dsocklen_t=int
CFLAGS_Darwin=-D__DARWIN
-CFLAGS=$(CFLAGS_$(SYSTEM)) -D__3PCC__ $(TLS) $(PCAPPLAY) $(EXTRACFLAGS)
+CFLAGS=$(CFLAGS_$(SYSTEM)) $(VERINFO) $(TLS) $(PCAPPLAY) $(EXTRACFLAGS)
#C++ Compiler Flags
-CPPFLAGS_hpux=-AA -mt -D__HPUX +W829
+CPPFLAGS_hpux=-AA -mt -D__HPUX -D_INCLUDE_LONGLONG -DNOMACROS +W829
CPPFLAGS_linux=-D__LINUX -pthread
CPPFLAGS_freebsd=-D__LINUX -pthread
CPPFLAGS_tru64=-D__OSF1 -pthread
-CPPFLAGS_SunOS=-g -D__SUNOS
+CPPFLAGS_SunOS=${DEBUG_FLAGS} -D__SUNOS
CPPFLAGS_Cygwin=-D__CYGWIN -Dsocklen_t=int
CPPFLAGS_Darwin=-D__DARWIN
-CPPFLAGS=$(CPPFLAGS_$(SYSTEM)) -D__3PCC__ $(TLS) $(PCAPPLAY) $(EXTRACPPFLAGS)
+CPPFLAGS=$(CPPFLAGS_$(SYSTEM)) $(VERINFO) $(TLS) $(PCAPPLAY) $(EXTRACPPFLAGS)
#Linker mapping
CCLINK_hpux=aCC
@@ -129,7 +131,7 @@
LFLAGS_linux=
LFLAGS_freebsd=
LFLAGS_tru64=
-LFLAGS_SunOS=
+LFLAGS_SunOS=-mt ${DEBUG_FLAGS}
LFLAGS_Cygwin=
LFLAGS_Darwin=
LFLAGS=$(LFLAGS_$(SYSTEM)) $(EXTRALFLAGS)
@@ -139,7 +141,7 @@
LIBS_hpux= -lcurses -lpthread -L /opt/openssl/lib -L /usr/local/lib
LIBS_tru64= -lcurses -lpthread
LIBS_freebsd= -lcurses -pthread -L /usr/local/lib
-LIBS_SunOS= -lcurses -lpthread -lnsl -lsocket -lstdc++ -lm -ldl -L /usr/local/ssl/lib/
+LIBS_SunOS= -lcurses -lpthread -lnsl -lsocket -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic -lm -ldl -L /usr/local/ssl/lib/
LIBS_Cygwin= -lcurses -lpthread -lstdc++ -L /usr/lib/WpdPack/Lib
LIBS_Darwin= -lcurses
LIBS=$(LIBS_$(SYSTEM)) $(EXTRALIBS)
@@ -222,4 +224,3 @@
.c.o:
$(CC) $(CFLAGS) $(MFLAGS) $(DEBUG_FLAGS) $(_HPUX_LI_FLAG) $(INCDIR) -c -o $*.o $<
-
Modified: sip-tester/branches/upstream/current/call.cpp
URL: http://svn.debian.org/wsvn/pkg-voip/sip-tester/branches/upstream/current/call.cpp?rev=6622&op=diff
==============================================================================
--- sip-tester/branches/upstream/current/call.cpp (original)
+++ sip-tester/branches/upstream/current/call.cpp Sun Jan 4 02:47:02 2009
@@ -46,6 +46,7 @@
#include "send_packets.h"
#endif
#include "sipp.hpp"
+#include "deadcall.hpp"
#include "assert.h"
#ifdef _USE_OPENSSL
@@ -56,26 +57,15 @@
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 */
void *send_wrapper(void *);
#endif
/************** Call map and management routines **************/
-call_map * get_calls()
-{
- return & calls;
-}
-
static unsigned int next_number = 1;
-unsigned int get_tdm_map_number(unsigned int number) {
+unsigned int get_tdm_map_number() {
unsigned int nb = 0;
unsigned int i=0;
unsigned int interval=0;
@@ -100,95 +90,197 @@
}
}
-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;
-
- if(!next_number) { next_number ++; }
-
- if (use_tdmmap) {
- nb = get_tdm_map_number(next_number);
- if (nb != 0) {
- /* Mark the entry in the list as busy */
- tdm_map[nb - 1] = true;
+/* When should this call wake up? */
+unsigned int call::wake() {
+ unsigned int wake = 0;
+
+ if (zombie) {
+ return wake;
+ }
+
+ if (paused_until) {
+ wake = paused_until;
+ }
+
+ if (next_retrans && (!wake || (next_retrans < wake))) {
+ wake = next_retrans;
+ }
+
+ if (recv_timeout && (!wake || (recv_timeout < wake))) {
+ wake = recv_timeout;
+ }
+
+ return wake;
+}
+
+#ifdef PCAPPLAY
+/******* Media information management *************************/
+/*
+ * Look for "c=IN IP4 " pattern in the message and extract the following value
+ * which should be IP address
+ */
+uint32_t get_remote_ip_media(char *msg)
+{
+ char pattern[] = "c=IN IP4 ";
+ char *begin, *end;
+ char ip[32];
+ begin = strstr(msg, pattern);
+ if (!begin) {
+ /* Can't find what we're looking at -> return no address */
+ return INADDR_NONE;
+ }
+ begin += sizeof("c=IN IP4 ") - 1;
+ end = strstr(begin, "\r\n");
+ if (!end)
+ return INADDR_NONE;
+ memset(ip, 0, 32);
+ strncpy(ip, begin, end - begin);
+ return inet_addr(ip);
+}
+
+/*
+ * Look for "c=IN IP6 " pattern in the message and extract the following value
+ * which should be IPv6 address
+ */
+uint8_t get_remote_ipv6_media(char *msg, struct in6_addr addr)
+{
+ char pattern[] = "c=IN IP6 ";
+ char *begin, *end;
+ char ip[128];
+
+ memset(&addr, 0, sizeof(addr));
+ memset(ip, 0, 128);
+
+ begin = strstr(msg, pattern);
+ if (!begin) {
+ /* Can't find what we're looking at -> return no address */
+ return 0;
+ }
+ begin += sizeof("c=IN IP6 ") - 1;
+ end = strstr(begin, "\r\n");
+ if (!end)
+ return 0;
+ strncpy(ip, begin, end - begin);
+ if (!inet_pton(AF_INET6, ip, &addr)) {
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Look for "m=audio " or "m=video " pattern in the message and extract the
+ * following value which should be port number
+ */
+#define PAT_AUDIO 1
+#define PAT_VIDEO 2
+uint16_t get_remote_port_media(char *msg, int pattype)
+{
+ char *pattern;
+ char *begin, *end;
+ char number[6];
+
+ if (pattype == PAT_AUDIO) {
+ pattern = "m=audio ";
+ } else if (pattype == PAT_VIDEO) {
+ pattern = "m=video ";
} else {
- /* Can't create the new call */
- WARNING("Can't create new outgoing call: all tdm_map circuits busy");
- return NULL;
- }
- }
-
- new_call = new call(call_id, userId, use_ipv6, isAutomatic);
-
- if(!new_call) {
- ERROR("Memory Overflow");
- }
-
- /* All calls must exist in the map. */
- calls[std::string(call_id)] = new_call;
- /* All calls start off in the running state. */
- add_running_call(new_call);
-
- new_call -> number = next_number;
- new_call -> tdm_map_number = nb - 1;
-
- /* Vital counters update */
- 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 */
- calls_since_last_rate_change++;
- total_calls ++;
-
- if(open_calls > open_calls_peak) {
- open_calls_peak = open_calls;
- open_calls_peak_time = clock_tick / 1000;
- }
-
- return new_call;
-}
-
-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;
-}
-
-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)
+ ERROR("Internal error: Undefined media pattern %d\n", 3);
+ }
+
+ begin = strstr(msg, pattern);
+ if (!begin) {
+ /* m=audio not found */
+ return 0;
+ }
+ begin += strlen(pattern) - 1;
+ end = strstr(begin, "\r\n");
+ if (!end)
+ ERROR("get_remote_port_media: no CRLF found");
+ memset(number, 0, sizeof(number));
+ strncpy(number, begin, sizeof(number) - 1);
+ return atoi(number);
+}
+
+/*
+ * IPv{4,6} compliant
+ */
+void call::get_remote_media_addr(char *msg) {
+ uint16_t video_port, audio_port;
+ if (media_ip_is_ipv6) {
+ struct in6_addr ip_media;
+ if (get_remote_ipv6_media(msg, ip_media)) {
+ audio_port = get_remote_port_media(msg, PAT_AUDIO);
+ if (audio_port) {
+ /* We have audio in the SDP: set the to_audio addr */
+ (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_flowinfo = 0;
+ (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_scope_id = 0;
+ (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_family = AF_INET6;
+ (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_port = audio_port;
+ (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_addr = ip_media;
+ }
+ video_port = get_remote_port_media(msg, PAT_VIDEO);
+ if (video_port) {
+ /* We have video in the SDP: set the to_video addr */
+ (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_flowinfo = 0;
+ (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_scope_id = 0;
+ (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_family = AF_INET6;
+ (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_port = video_port;
+ (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_addr = ip_media;
+ }
+ hasMediaInformation = 1;
+ }
+ }
+ else {
+ uint32_t ip_media;
+ ip_media = get_remote_ip_media(msg);
+ if (ip_media != INADDR_NONE) {
+ audio_port = get_remote_port_media(msg, PAT_AUDIO);
+ if (audio_port) {
+ /* We have audio in the SDP: set the to_audio addr */
+ (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_family = AF_INET;
+ (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_port = audio_port;
+ (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_addr.s_addr = ip_media;
+ }
+ video_port = get_remote_port_media(msg, PAT_VIDEO);
+ if (video_port) {
+ /* We have video in the SDP: set the to_video addr */
+ (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_family = AF_INET;
+ (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_port = video_port;
+ (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_addr.s_addr = ip_media;
+ }
+ hasMediaInformation = 1;
+ }
+ }
+}
+
+#endif
+
+/******* Very simple hash for retransmission detection *******/
+
+unsigned long hash(char * msg) {
+ unsigned long hash = 0;
+ int c;
+
+ while (c = *msg++)
+ hash = c + (hash << 6) + (hash << 16) - hash;
+
+ return hash;
+}
+
+/******************* Call class implementation ****************/
+call::call(char *p_id, bool use_ipv6, int userId, struct sockaddr_storage *dest) : listener(p_id, true) {
+ init(main_scenario, NULL, dest, p_id, userId, use_ipv6, false);
+}
+
+call::call(char *p_id, struct sipp_socket *socket, struct sockaddr_storage *dest) : listener(p_id, true) {
+ init(main_scenario, socket, dest, p_id, 0 /* No User. */, socket->ss_ipv6, false /* Not Auto. */);
+}
+
+call::call(scenario * call_scenario, struct sipp_socket *socket, struct sockaddr_storage *dest, char * p_id, int userId, bool ipv6, bool isAutomatic) : listener(p_id, true) {
+ init(call_scenario, socket, dest, p_id, userId, ipv6, isAutomatic);
+}
+
+call *call::add_call(int userId, bool ipv6, struct sockaddr_storage *dest)
{
static char call_id[MAX_HEADER_LEN];
@@ -220,472 +312,112 @@
}
call_id[count] = 0;
- return add_call(call_id, ipv6, userId);
-}
-
-call * get_call(char * call_id)
-{
-
- call * call_ptr;
-
- call_map::iterator call_it ;
- call_it = calls.find(call_map::key_type(call_id));
- call_ptr = (call_it != calls.end()) ? call_it->second : NULL ;
-
- return call_ptr;
-}
-
-void delete_call(char * call_id)
-{
- call * call_ptr;
- call_map::iterator call_it ;
- call_it = calls.find(call_map::key_type(call_id));
- call_ptr = (call_it != calls.end()) ? call_it->second : NULL ;
-
- if(call_ptr) {
- if (use_tdmmap)
- tdm_map[call_ptr->tdm_map_number] = false;
- calls.erase(call_it);
-
- if (call_ptr->running) {
- remove_running_call(call_ptr);
- } else {
- paused_calls.remove_paused_call(call_ptr);
- }
-
- delete call_ptr;
- open_calls--;
- } else {
- if (start_calls == 0) {
- ERROR("Call not found");
- }
- }
-}
-
-void delete_calls(void)
-{
- call * call_ptr;
-
- call_map::iterator call_it ;
- call_it = calls.begin();
- while (call_it != calls.end()) {
- call_ptr = (call_it != calls.end()) ? call_it->second : NULL ;
- WARNING_P1("Aborting call with Call-Id '%s'", call_ptr->id);
- call_ptr->abortCall();
- call_it = calls.begin();
- }
-
-}
-
-/* Routines for running calls. */
-
-/* Get the overall list of running calls. */
-call_list * get_running_calls()
-{
- return & running_calls;
-}
-
-/* Put this call in the run queue. */
-void add_running_call(call *call) {
- call->runit = running_calls.insert(running_calls.end(), call);
- call->running = true;
-}
-
-/* Remove this call from the run queue. */
-bool remove_running_call(call *call) {
- if (!call->running) {
- return false;
- }
- running_calls.erase(call->runit);
- call->running = false;
- return true;
-}
-
-/* When should this call wake up? */
-unsigned int call_wake(call *call) {
- unsigned int wake = 0;
-
- if (call->paused_until) {
- wake = call->paused_until;
- }
-
- if (call->next_retrans && (!wake || (call->next_retrans < wake))) {
- wake = call->next_retrans;
- }
-
- if (call->recv_timeout && (!wake || (call->recv_timeout < wake))) {
- wake = call->recv_timeout;
- }
-
- return wake;
-}
-
-call_list *timewheel::call2list(call *call) {
- unsigned int wake = call_wake(call);
- unsigned int wake_sigbits = wake;
- unsigned int base_sigbits = wheel_base;
-
- if (wake == 0) {
- return &forever_list;
- }
-
- wake_sigbits /= LEVEL_ONE_SLOTS;
- base_sigbits /= LEVEL_ONE_SLOTS;
- if (wake_sigbits == base_sigbits) {
- return &wheel_one[wake % LEVEL_ONE_SLOTS];
- }
- wake_sigbits /= LEVEL_TWO_SLOTS;
- base_sigbits /= LEVEL_TWO_SLOTS;
- if (wake_sigbits == base_sigbits) {
- return &wheel_two[(wake / LEVEL_ONE_SLOTS) % LEVEL_TWO_SLOTS];
- }
- assert(wake_sigbits < LEVEL_THREE_SLOTS);
- return &wheel_three[wake_sigbits];
-}
-
-int expire_paused_calls() {
- return paused_calls.expire_paused_calls();
-}
-int paused_calls_count() {
- return paused_calls.size();
-}
-void remove_paused_call(call *call) {
- assert(!call->running);
- paused_calls.remove_paused_call(call);
-}
-
-/* Iterate through our sorted set of paused calls, removing those that
- * should no longer be paused, and adding them to the run queue. */
-int timewheel::expire_paused_calls() {
- int found = 0;
-
- while (wheel_base < clock_tick) {
- int slot1 = wheel_base % LEVEL_ONE_SLOTS;
-
- /* Migrate calls from slot2 when we hit 0. */
- if (slot1 == 0) {
- int slot2 = (wheel_base / LEVEL_ONE_SLOTS) % LEVEL_TWO_SLOTS;
-
- /* If slot2 is also zero, we must migrate calls from slot3 into slot2. */
- if (slot2 == 0) {
- int slot3 = ((wheel_base / LEVEL_ONE_SLOTS) / LEVEL_TWO_SLOTS);
- assert(slot3 < LEVEL_THREE_SLOTS);
-
- for (call_list::iterator l3it = wheel_three[slot3].begin();
- l3it != wheel_three[slot3].end();
- l3it++) {
- /* Migrate this call to wheel two. */
- add_paused_call(*l3it, false);
- }
-
- wheel_three[slot3].clear();
- }
-
- for (call_list::iterator l2it = wheel_two[slot2].begin();
- l2it != wheel_two[slot2].end();
- l2it++) {
- /* Migrate this call to wheel one. */
- add_paused_call(*l2it, false);
- }
-
- wheel_two[slot2].clear();
- }
-
- found += wheel_one[slot1].size();
- for(call_list::iterator it = wheel_one[slot1].begin();
- it != wheel_one[slot1].end(); it++) {
- add_running_call(*it);
- count--;
- }
- wheel_one[slot1].clear();
-
- wheel_base++;
- }
-
- return found;
-}
-
-void timewheel::add_paused_call(call *call, bool increment) {
- call_list *list = call2list(call);
- call->pauseit = list->insert(list->end(), call);
- if (increment) {
- count++;
- }
-}
-
-void timewheel::remove_paused_call(call *call) {
- call_list *list = call2list(call);
- list->erase(call->pauseit);
- count--;
-}
-
-timewheel::timewheel() {
- count = 0;
- wheel_base = clock_tick;
-}
-
-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
-/******* Media information management *************************/
-/*
- * Look for "c=IN IP4 " pattern in the message and extract the following value
- * which should be IP address
- */
-uint32_t get_remote_ip_media(char *msg)
-{
- char pattern[] = "c=IN IP4 ";
- char *begin, *end;
- char ip[32];
- begin = strstr(msg, pattern);
- if (!begin) {
- /* Can't find what we're looking at -> return no address */
- return INADDR_NONE;
- }
- begin += sizeof("c=IN IP4 ") - 1;
- end = strstr(begin, "\r\n");
- if (!end)
- return INADDR_NONE;
- memset(ip, 0, 32);
- strncpy(ip, begin, end - begin);
- return inet_addr(ip);
-}
-
-/*
- * Look for "c=IN IP6 " pattern in the message and extract the following value
- * which should be IPv6 address
- */
-uint8_t get_remote_ipv6_media(char *msg, struct in6_addr addr)
-{
- char pattern[] = "c=IN IP6 ";
- char *begin, *end;
- char ip[128];
-
- memset(&addr, 0, sizeof(addr));
- memset(ip, 0, 128);
-
- begin = strstr(msg, pattern);
- if (!begin) {
- /* Can't find what we're looking at -> return no address */
- return 0;
- }
- begin += sizeof("c=IN IP6 ") - 1;
- end = strstr(begin, "\r\n");
- if (!end)
- return 0;
- strncpy(ip, begin, end - begin);
- if (!inet_pton(AF_INET6, ip, &addr)) {
- return 0;
- }
- return 1;
-}
-
-/*
- * Look for "m=audio " pattern in the message and extract the following value
- * which should be port number
- */
-uint16_t get_remote_audio_port_media(char *msg)
-{
- char pattern[] = "m=audio ";
- char *begin, *end;
- char number[6];
- begin = strstr(msg, pattern);
- if (!begin) {
- /* m=audio not found */
- return 0;
- }
- begin += sizeof("m=audio ") - 1;
- end = strstr(begin, "\r\n");
- if (!end)
- ERROR("get_remote_audio_port_media: no CRLF found");
- memset(number, 0, sizeof(number));
- strncpy(number, begin, sizeof(number) - 1);
- return atoi(number);
-}
-
-/*
- * Look for "m=video " pattern in the message and extract the following value
- * which should be port number
- */
-uint16_t get_remote_video_port_media(char *msg)
-{
- char pattern[] = "m=video ";
- char *begin, *end;
- char number[5];
- begin = strstr(msg, pattern);
- if (!begin) {
- /* m=video not found */
- return 0;
- }
- begin += sizeof("m=video ") - 1;
- end = strstr(begin, "\r\n");
- if (!end)
- ERROR("get_remote_video_port_media: no CRLF found");
- memset(number, 0, 5);
- strncpy(number, begin, end - begin);
- return atoi(number);
-}
-
-/*
- * IPv{4,6} compliant
- */
-void call::get_remote_media_addr(char *msg) {
- uint16_t video_port, audio_port;
- if (media_ip_is_ipv6) {
- struct in6_addr ip_media;
- if (get_remote_ipv6_media(msg, ip_media)) {
- audio_port = get_remote_audio_port_media(msg);
- if (audio_port) {
- /* We have audio in the SDP: set the to_audio addr */
- (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_flowinfo = 0;
- (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_scope_id = 0;
- (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_family = AF_INET6;
- (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_port = audio_port;
- (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_addr = ip_media;
- }
- video_port = get_remote_video_port_media(msg);
- if (video_port) {
- /* We have video in the SDP: set the to_video addr */
- (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_flowinfo = 0;
- (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_scope_id = 0;
- (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_family = AF_INET6;
- (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_port = video_port;
- (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_addr = ip_media;
- }
- hasMediaInformation = 1;
- }
- }
- else {
- uint32_t ip_media;
- ip_media = get_remote_ip_media(msg);
- if (ip_media != INADDR_NONE) {
- audio_port = get_remote_audio_port_media(msg);
- if (audio_port) {
- /* We have audio in the SDP: set the to_audio addr */
- (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_family = AF_INET;
- (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_port = audio_port;
- (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_addr.s_addr = ip_media;
- }
- video_port = get_remote_video_port_media(msg);
- if (video_port) {
- /* We have video in the SDP: set the to_video addr */
- (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_family = AF_INET;
- (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_port = video_port;
- (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_addr.s_addr = ip_media;
- }
- hasMediaInformation = 1;
- }
- }
-}
-
-#endif
-
-/******* Very simple hash for retransmission detection *******/
-
-unsigned long hash(char * msg) {
- unsigned long hash = 0;
- int c;
-
- while (c = *msg++)
- hash = c + (hash << 6) + (hash << 16) - hash;
-
- return hash;
-}
-
-/******************* Call class implementation ****************/
-
-call::call(char * p_id, int userId, bool ipv6, bool isAutomatic) : use_ipv6(ipv6)
-{
- memset(this, 0, sizeof(call));
- id = strdup(p_id);
+ return new call(main_scenario, NULL, dest, call_id, userId, ipv6, false /* Not Auto. */);
+}
+
+
+void call::init(scenario * call_scenario, struct sipp_socket *socket, struct sockaddr_storage *dest, char * p_id, int userId, bool ipv6, bool isAutomatic)
+{
+ this->call_scenario = call_scenario;
+ zombie = false;
+ msg_index = 0;
+ last_send_index = 0;
+ last_send_msg = NULL;
+
+ last_recv_hash = 0;
+ last_recv_index = -1;
+ last_recv_msg = NULL;
+
+ recv_retrans_hash = 0;
+ recv_retrans_recv_index = -1;
+ recv_retrans_send_index = -1;
+
+ dialog_route_set = NULL;
+ next_req_url = NULL;
+
+ cseq = 0;
+
+ next_retrans = 0;
+ nb_retrans = 0;
+ nb_last_delay = 0;
+
+ paused_until = 0;
+
+ call_port = 0;
+ comp_state = NULL;
+
start_time = clock_tick;
call_established=false ;
- count_in_stats=true ;
ack_is_pending=false ;
last_recv_msg = NULL;
cseq = base_cseq;
nb_last_delay = 0;
- tdm_map_number = 0;
+ use_ipv6 = ipv6;
+ queued_msg = NULL;
#ifdef _USE_OPENSSL
+ dialog_authentication = NULL;
+ dialog_challenge_type = 0;
+
m_ctx_ssl = NULL ;
m_bio = NULL ;
#endif
- call_remote_socket = 0;
+#ifdef PCAPPLAY
+ hasMediaInformation = 0;
+#endif
+
+ call_remote_socket = NULL;
+ if (socket) {
+ associate_socket(socket);
+ socket->ss_count++;
+ } else {
+ call_socket = NULL;
+ }
+ if (dest) {
+ memcpy(&call_peer, dest, SOCK_ADDR_SIZE(dest));
+ } else {
+ memset(&call_peer, 0, sizeof(call_peer));
+ }
// initialising the CallVariable with the Scenario variable
int i;
- if (maxVariableUsed >= 0) {
- M_callVariableTable = new CCallVariable *[maxVariableUsed + 1];
- }
- for(i=0; i<=maxVariableUsed; i++)
- {
- if (variableUsed[i]) {
- M_callVariableTable[i] = new CCallVariable();
- if (M_callVariableTable[i] == NULL) {
- ERROR ("call variable allocation failed");
- }
- } else {
- M_callVariableTable[i] = NULL;
- }
- }
+ VariableTable *userVars = NULL;
+ bool putUserVars = false;
+ if (userId) {
+ int_vt_map::iterator it = userVarMap.find(userId);
+ if (it != userVarMap.end()) {
+ userVars = it->second;
+ }
+ } else {
+ userVars = new VariableTable(userVariables);
+ /* Creating this table creates a reference to it, but if it is really used,
+ * then the refcount will be increased. */
+ putUserVars = true;
+ }
+ if (call_scenario->allocVars->size > 0) {
+ if (userVars) {
+ M_callVariableTable = new VariableTable(userVars, call_scenario->allocVars->size);
+ } else {
+ M_callVariableTable = new VariableTable(userVars, call_scenario->allocVars->size);
+ }
+ } else if (userVars->size > 0) {
+ M_callVariableTable = userVars->getTable();
+ } else if (globalVariables->size > 0) {
+ M_callVariableTable = globalVariables->getTable();
+ } else {
+ M_callVariableTable = NULL;
+ }
+ if (putUserVars) {
+ userVars->putTable();
+ }
+
+ if (call_scenario->maxTxnUsed > 0) {
+ txnID = (char **)malloc(sizeof(char *) * call_scenario->maxTxnUsed);
+ memset(txnID, 0, sizeof(char *) * call_scenario->maxTxnUsed);
+ } else {
+ txnID = NULL;
+ }
// If not updated by a message we use the start time
// information to compute rtd information
@@ -710,6 +442,8 @@
file_it++) {
(*m_lineNumber)[file_it->first] = file_it->second->nextLine(userId);
}
+ } else {
+ m_lineNumber = NULL;
}
#ifdef PCAPPLAY
@@ -724,38 +458,67 @@
peer_tag = NULL;
recv_timeout = 0;
send_timeout = 0;
+ timewait = false;
+
+ if (!isAutomatic) {
+ /* Not advancing the number is safe, because for automatic calls we do not
+ * assign the identifier, the only other place it is used is for the auto
+ * media port. */
+ number = next_number++;
+
+ if (use_tdmmap) {
+ tdm_map_number = get_tdm_map_number();
+ if (tdm_map_number == 0) {
+ /* Can't create the new call */
+ WARNING("Can't create new outgoing call: all tdm_map circuits busy");
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_OUTBOUND_CONGESTION);
+ this->zombie = true;
+ return;
+ }
+ /* Mark the entry in the list as busy */
+ tdm_map[tdm_map_number - 1] = true;
+ } else {
+ tdm_map_number = 0;
+ }
+ }
+
+ setRunning();
}
call::~call()
{
- deleted += 1;
+ computeStat(CStat::E_ADD_CALL_DURATION, clock_tick - start_time);
if(comp_state) { comp_free(&comp_state); }
- if(count_in_stats) {
- CStat::instance()->computeStat(CStat::E_ADD_CALL_DURATION,
- clock_tick - start_time);
- }
-
- 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(M_callVariableTable) {
+ M_callVariableTable->putTable();
+ }
+ if (m_lineNumber) {
+ delete m_lineNumber;
+ }
if (userId) {
- freeUsers.push_front(userId);
- }
-
- if(id) { free(id); }
+ if (call_scenario->stats->GetStat(CStat::CPT_C_CurrentCall) >= open_calls_allowed) {
+ retiredUsers.push_front(userId);
+ } else {
+ freeUsers.push_front(userId);
+ }
+ }
+
+ if (txnID) {
+ for (int i = 0; i < call_scenario->maxTxnUsed; i++) {
+ free(txnID[i]);
+ }
+ free(txnID);
+ }
+
if(last_recv_msg) { free(last_recv_msg); }
if(last_send_msg) { free(last_send_msg); }
if(peer_tag) { free(peer_tag); }
@@ -774,21 +537,55 @@
free(dialog_authentication);
}
#endif
- call_established= false ;
-}
-
-void call::connect_socket_if_needed()
+
+ if (use_tdmmap) {
+ tdm_map[tdm_map_number] = false;
+ }
+}
+
+void call::computeStat (CStat::E_Action P_action) {
+ call_scenario->stats->computeStat(P_action);
+}
+
+void call::computeStat (CStat::E_Action P_action, unsigned long P_value) {
+ call_scenario->stats->computeStat(P_action, P_value);
+}
+
+void call::computeStat (CStat::E_Action P_action, unsigned long P_value, int which) {
+ call_scenario->stats->computeStat(P_action, P_value, which);
+}
+
+/* Dump call info to error log. */
+void call::dump() {
+ char s[MAX_HEADER_LEN];
+ sprintf(s, "%s: State %d", id, msg_index);
+ if (next_retrans) {
+ sprintf(s, "%s (next retrans %ld)", s, next_retrans);
+ }
+ if (paused_until) {
+ sprintf(s, "%s (paused until %ld)", s, paused_until);
+ }
+ if (recv_timeout) {
+ sprintf(s, "%s (recv timeout %ld)", s, recv_timeout);
+ }
+ if (send_timeout) {
+ sprintf(s, "%s (send timeout %ld)", s, send_timeout);
+ }
+ WARNING("%s", s);
+}
+
+bool call::connect_socket_if_needed()
{
bool existing;
- if(call_socket) return;
- if(!multisocket) return;
+ if(call_socket) return true;
+ if(!multisocket) return true;
if(transport == T_UDP) {
struct sockaddr_storage saddr;
if(toolMode != MODE_CLIENT)
- return;
+ return true;
char peripaddr[256];
if (!peripsocket) {
@@ -797,7 +594,7 @@
}
} else {
char *tmp = peripaddr;
- getFieldFromInputFile(ip_file, peripfield, tmp);
+ getFieldFromInputFile(ip_file, peripfield, NULL, tmp);
map<string, struct sipp_socket *>::iterator i;
i = map_perip_fd.find(peripaddr);
if (i == map_perip_fd.end()) {
@@ -817,7 +614,7 @@
}
}
if (existing) {
- return;
+ return true;
}
memset(&saddr, 0, sizeof(struct sockaddr_storage));
@@ -866,7 +663,7 @@
}
if (existing) {
- return;
+ return true;
}
sipp_customize_socket(call_socket);
@@ -876,14 +673,26 @@
}
if (sipp_connect_socket(call_socket, L_dest)) {
- if (reset_number > 0) {
+ if (reconnect_allowed()) {
if(errno == EINVAL){
/* This occurs sometime on HPUX but is not a true INVAL */
WARNING("Unable to connect a TCP socket, remote peer error");
} else {
WARNING("Unable to connect a TCP socket");
}
- start_calls = 1;
+ /* This connection failed. We must be in multisocket mode, because
+ * otherwise we would already have a call_socket. This call can not
+ * succeed, but does not affect any of our other calls. We do decrement
+ * the reconnection counter however. */
+ if (reset_number != -1) {
+ reset_number--;
+ }
+
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_TCP_CONNECT);
+ delete this;
+
+ return false;
} else {
if(errno == EINVAL){
/* This occurs sometime on HPUX but is not a true INVAL */
@@ -894,17 +703,18 @@
}
}
}
-}
-
-bool lost(int index)
+ return true;
+}
+
+bool call::lost(int index)
{
static int inited = 0;
double percent = global_lost;
if(!lose_packets) return false;
- if (scenario[index]->lost >= 0) {
- percent = scenario[index]->lost;
+ if (call_scenario->messages[index]->lost >= 0) {
+ percent = call_scenario->messages[index]->lost;
}
if (percent == 0) {
@@ -928,15 +738,15 @@
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)));
+ TRACE_SHORTMSG("%s\tS\t%s\tCSeq:%s\t%s\n",
+ CStat::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)));
+ TRACE_MSG("%s message voluntary lost (while sending).", TRANSPORT_TO_STRING(transport));
if(comp_state) { comp_free(&comp_state); }
- scenario[index] -> nb_lost++;
+ call_scenario->messages[index] -> nb_lost++;
return 0;
}
@@ -956,7 +766,7 @@
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));
+ ERROR("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");
}
@@ -966,15 +776,15 @@
sock=call_remote_socket ;
}
- rc = write_socket(sock, msg, strlen(msg), WS_BUFFER);
+ rc = write_socket(sock, msg, strlen(msg), WS_BUFFER, &call_peer);
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);
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_CANNOT_SEND_MSG);
+ delete this;
}
return rc; /* OK */
@@ -986,7 +796,11 @@
{
/* call send_raw but with a special scenario index */
if (send_raw(msg, -1) < 0) {
- ERROR_NO("Error sending raw message");
+ if (sendbuffer_warn) {
+ ERROR_NO("Error sending raw message");
+ } else {
+ WARNING_NO("Error sending raw message");
+ }
}
}
@@ -1044,7 +858,7 @@
/* Ideally this check should be moved to the XML parser so that it is not
* along a critical path. We could also handle lowercasing there. */
if (len > MAX_HEADER_LEN) {
- ERROR_P2("call::get_last_header: Header to parse bigger than %d (%zu)", MAX_HEADER_LEN, strlen(name));
+ ERROR("call::get_last_header: Header to parse bigger than %d (%zu)", MAX_HEADER_LEN, strlen(name));
}
if (name[len - 1] == ':') {
@@ -1081,7 +895,7 @@
/* for safety's sake */
if (NULL == name || NULL == strrchr(name, ':')) {
- WARNING_P1("Can not searching for header (no colon): %s", name ? name : "(null)");
+ WARNING("Can not searching for header (no colon): %s", name ? name : "(null)");
return last_header;
}
@@ -1274,7 +1088,10 @@
char *L_ptr2 ;
/* Socket port must be known before string substitution */
- connect_socket_if_needed();
+ if (!connect_socket_if_needed()) {
+ *send_status = -2;
+ return NULL;
+ }
assert(call_socket);
@@ -1283,34 +1100,32 @@
return NULL;
}
- if(scenario[index] -> send_scheme) {
- char * dest;
- dest = createSendingMessage(scenario[index] -> send_scheme, index);
- strcpy(msg_buffer, dest);
-
- if (dest) {
- L_ptr1=msg_name ;
- L_ptr2=msg_buffer ;
- while ((*L_ptr2 != ' ') && (*L_ptr2 != '\n') && (*L_ptr2 != '\t')) {
- *L_ptr1 = *L_ptr2;
- L_ptr1 ++;
- L_ptr2 ++;
- }
- *L_ptr1 = '\0' ;
- }
-
- if (strcmp(msg_name,"ACK") == 0) {
- call_established = true ;
- ack_is_pending = false ;
- }
-
- if(send_status) {
- *send_status = send_raw(msg_buffer, index);
- } else {
- send_raw(msg_buffer, index);
- }
+ assert(call_scenario->messages[index]->send_scheme);
+
+ char * dest;
+ dest = createSendingMessage(call_scenario->messages[index] -> send_scheme, index);
+ strcpy(msg_buffer, dest);
+
+ if (dest) {
+ L_ptr1=msg_name ;
+ L_ptr2=msg_buffer ;
+ while ((*L_ptr2 != ' ') && (*L_ptr2 != '\n') && (*L_ptr2 != '\t')) {
+ *L_ptr1 = *L_ptr2;
+ L_ptr1 ++;
+ L_ptr2 ++;
+ }
+ *L_ptr1 = '\0' ;
+ }
+
+ if (strcmp(msg_name,"ACK") == 0) {
+ call_established = true ;
+ ack_is_pending = false ;
+ }
+
+ if(send_status) {
+ *send_status = send_raw(msg_buffer, index);
} else {
- ERROR("Unsupported 'send' message in scenario");
+ send_raw(msg_buffer, index);
}
return msg_buffer;
@@ -1318,75 +1133,108 @@
void call::do_bookkeeping(int index) {
/* If this message increments a counter, do it now. */
- if(int counter = scenario[index] -> counter) {
- CStat::instance()->computeStat(CStat::E_ADD_GENERIC_COUNTER, 1, counter - 1);
+ if(int counter = call_scenario->messages[index] -> counter) {
+ computeStat(CStat::E_ADD_GENERIC_COUNTER, 1, counter - 1);
}
/* If this message can be used to compute RTD, do it now */
- if(int rtd = scenario[index] -> start_rtd) {
+ if(int rtd = call_scenario->messages[index] -> start_rtd) {
start_time_rtd[rtd - 1] = getmicroseconds();
}
- if(int rtd = scenario[index] -> stop_rtd) {
+ if(int rtd = call_scenario->messages[index] -> stop_rtd) {
if (!rtd_done[rtd - 1]) {
unsigned long long start = start_time_rtd[rtd - 1];
unsigned long long end = getmicroseconds();
if(dumpInRtt) {
- CStat::instance()->computeRtt(start, end, rtd);
- }
-
- CStat::instance()->computeStat(CStat::E_ADD_RESPONSE_TIME_DURATION,
+ call_scenario->stats->computeRtt(start, end, rtd);
+ }
+
+ computeStat(CStat::E_ADD_RESPONSE_TIME_DURATION,
(end - start) / 1000, rtd - 1);
- if (!scenario[index] -> repeat_rtd) {
+ if (!call_scenario->messages[index] -> repeat_rtd) {
rtd_done[rtd - 1] = true;
}
}
}
}
+void call::tcpClose() {
+ terminate(CStat::E_FAILED_TCP_CLOSED);
+}
+
+bool call::terminate(CStat::E_Action reason) {
+ char reason_str[100];
+
+ stopListening();
+
+ // Call end -> was it successful?
+ if(call::last_action_result != call::E_AR_NO_ERROR) {
+ switch(call::last_action_result) {
+ case call::E_AR_REGEXP_DOESNT_MATCH:
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_REGEXP_DOESNT_MATCH);
+ if (deadcall_wait) {
+ sprintf(reason_str, "regexp match failure at index %d", msg_index);
+ new deadcall(id, reason_str);
+ }
+ break;
+ case call::E_AR_HDR_NOT_FOUND:
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_REGEXP_HDR_NOT_FOUND);
+ if (deadcall_wait) {
+ sprintf(reason_str, "regexp header not found at index %d", msg_index);
+ new deadcall(id, reason_str);
+ }
+ break;
+ case call::E_AR_NO_ERROR:
+ case call::E_AR_STOP_CALL:
+ /* Do nothing. */
+ break;
+ }
+ } else {
+ if (reason == CStat::E_CALL_SUCCESSFULLY_ENDED || timewait) {
+ computeStat(CStat::E_CALL_SUCCESSFULLY_ENDED);
+ if (deadcall_wait) {
+ new deadcall(id, "successful");
+ }
+ } else {
+ computeStat(CStat::E_CALL_FAILED);
+ if (reason != CStat::E_NO_ACTION) {
+ computeStat(reason);
+ }
+ if (deadcall_wait) {
+ sprintf(reason_str, "failed at index %d", msg_index);
+ new deadcall(id, reason_str);
+ }
+ }
+ }
+ delete this;
+}
+
bool call::next()
{
- int test = scenario[msg_index]->test;
+ int test = call_scenario->messages[msg_index]->test;
/* What is the next message index? */
/* Default without branching: use the next message */
int new_msg_index = msg_index+1;
/* If branch needed, overwrite this default */
- if ( scenario[msg_index]->next &&
- ((test == -1) ||
- (test <= maxVariableUsed && M_callVariableTable[test] != NULL && M_callVariableTable[test]->isSet()))
+ if ( (call_scenario->messages[msg_index]->next >= 0) &&
+ ((test == -1) || M_callVariableTable->getVar(test)->isSet())
) {
/* Branching possible, check the probability */
- int chance = scenario[msg_index]->chance;
+ int chance = call_scenario->messages[msg_index]->chance;
if ((chance <= 0) || (rand() > chance )) {
/* Branch == overwrite with the 'next' attribute value */
- new_msg_index = labelArray[scenario[msg_index]->next];
+ new_msg_index = call_scenario->messages[msg_index]->next;
}
}
msg_index=new_msg_index;
recv_timeout = 0;
- if(msg_index >= scenario_len) {
- // Call end -> was it successful?
- if(call::last_action_result != call::E_AR_NO_ERROR) {
- switch(call::last_action_result) {
- case call::E_AR_REGEXP_DOESNT_MATCH:
- CStat::instance()->computeStat(CStat::E_CALL_FAILED);
- CStat::instance()->computeStat(CStat::E_FAILED_REGEXP_DOESNT_MATCH);
- break;
- case call::E_AR_HDR_NOT_FOUND:
- CStat::instance()->computeStat(CStat::E_CALL_FAILED);
- CStat::instance()->computeStat(CStat::E_FAILED_REGEXP_HDR_NOT_FOUND);
- break;
- case call::E_AR_NO_ERROR:
- case call::E_AR_STOP_CALL:
- /* Do nothing. */
- break;
- }
- } else {
- CStat::instance()->computeStat(CStat::E_CALL_SUCCESSFULLY_ENDED);
- }
- delete_call(id);
+ if(msg_index >= call_scenario->length) {
+ terminate(CStat::E_CALL_SUCCESSFULLY_ENDED);
return false;
}
@@ -1400,12 +1248,19 @@
assert(running);
+ if (zombie) {
+ delete this;
+ return false;
+ }
+
clock_tick = getmilliseconds();
- if(msg_index >= scenario_len) {
- ERROR_P3("Scenario overrun for call %s (%p) (index = %d)\n",
+ if(msg_index >= call_scenario->length) {
+ ERROR("Scenario overrun for call %s (%p) (index = %d)\n",
id, this, msg_index);
}
+
+ message *curmsg = call_scenario->messages[msg_index];
/* Manages retransmissions or delete if max retrans reached */
if(next_retrans && (next_retrans < clock_tick)) {
@@ -1418,38 +1273,38 @@
if((nb_retrans > (bInviteTransaction ? max_invite_retrans : max_non_invite_retrans)) ||
(nb_retrans > max_udp_retrans)) {
- scenario[last_send_index] -> nb_timeout ++;
- if (scenario[last_send_index]->on_timeout) { // action on timeout
- WARNING_P3("Call-Id: %s, timeout on max UDP retrans for message %d, jumping to label %d ",
- id, msg_index, scenario[last_send_index]->on_timeout);
- msg_index = labelArray[scenario[last_send_index]->on_timeout];
+ call_scenario->messages[last_send_index] -> nb_timeout ++;
+ if (call_scenario->messages[last_send_index]->on_timeout >= 0) { // action on timeout
+ WARNING("Call-Id: %s, timeout on max UDP retrans for message %d, jumping to label %d ",
+ id, msg_index, call_scenario->messages[last_send_index]->on_timeout);
+ msg_index = call_scenario->messages[last_send_index]->on_timeout;
next_retrans = 0;
recv_timeout = 0;
- if (msg_index < scenario_len) {
+ if (msg_index < call_scenario->length) {
return true;
}
// here if asked to go to the last label delete the call
- CStat::instance()->computeStat(CStat::E_CALL_FAILED);
- CStat::instance()->computeStat(CStat::E_FAILED_MAX_UDP_RETRANS);
- if (default_behavior) {
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_MAX_UDP_RETRANS);
+ if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
// Abort the call by sending proper SIP message
return(abortCall());
} else {
// Just delete existing call
- delete_call(id);
+ delete this;
return false;
}
}
- CStat::instance()->computeStat(CStat::E_CALL_FAILED);
- CStat::instance()->computeStat(CStat::E_FAILED_MAX_UDP_RETRANS);
- if (default_behavior) {
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_MAX_UDP_RETRANS);
+ if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
// Abort the call by sending proper SIP message
- WARNING_P1("Aborting call on UDP retransmission timeout for Call-ID '%s'", id);
+ WARNING("Aborting call on UDP retransmission timeout for Call-ID '%s'", id);
return(abortCall());
} else {
// Just delete existing call
- delete_call(id);
+ delete this;
return false;
}
} else {
@@ -1464,8 +1319,8 @@
if(send_raw(last_send_msg, last_send_index) < -1) {
return false;
}
- scenario[last_send_index] -> nb_sent_retrans++;
- CStat::instance()->computeStat(CStat::E_RETRANSMISSION);
+ call_scenario->messages[last_send_index] -> nb_sent_retrans++;
+ computeStat(CStat::E_RETRANSMISSION);
next_retrans = clock_tick + nb_last_delay;
}
}
@@ -1473,26 +1328,19 @@
if(paused_until) {
/* Process a pending pause instruction until delay expiration */
if(paused_until > clock_tick) {
- if (!remove_running_call(this)) {
- ERROR("Tried to remove a running call that wasn't running!\n");
- }
- paused_calls.add_paused_call(this, true);
+ setPaused();
return true;
}
/* Our pause is over. */
paused_until = 0;
return next();
- } else if(scenario[msg_index] -> pause_distribution || scenario[msg_index]->pause_variable) {
+ } else if(curmsg -> pause_distribution || curmsg->pause_variable != -1) {
unsigned int pause;
- if (scenario[msg_index]->pause_distribution) {
- pause = (int)(scenario[msg_index] -> pause_distribution -> sample());
+ if (curmsg->pause_distribution) {
+ pause = (int)(curmsg -> 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;
- }
+ int varId = curmsg->pause_variable;
+ pause = (int) M_callVariableTable->getVar(varId)->getDouble();
}
if (pause < 0) {
pause = 0;
@@ -1502,12 +1350,18 @@
}
paused_until = clock_tick + pause;
+ /* This state is used as the last message of a scenario, just for handling
+ * final retransmissions. If the connection closes, we do not mark it is
+ * failed. */
+ this->timewait = curmsg->timewait;
+
/* Increment the number of sessions in pause state */
- ++scenario[msg_index]->sessions;
+ curmsg->sessions++;
+ do_bookkeeping(msg_index);
+ actionResult = executeAction(NULL, msg_index);
return run(); /* In case delay is 0 */
}
-#ifdef __3PCC__
- else if(scenario[msg_index] -> M_type == MSG_TYPE_SENDCMD) {
+ else if(curmsg -> M_type == MSG_TYPE_SENDCMD) {
int send_status;
if(next_retrans) {
@@ -1519,18 +1373,20 @@
if(send_status != 0) { /* Send error */
return false; /* call deleted */
}
- scenario[msg_index] -> M_nbCmdSent++;
+ curmsg -> M_nbCmdSent++;
next_retrans = 0;
- return(next());
- }
-#endif
- else if(scenario[msg_index] -> M_type == MSG_TYPE_NOP) {
+
do_bookkeeping(msg_index);
actionResult = executeAction(NULL, msg_index);
return(next());
}
-
- else if(scenario[msg_index] -> send_scheme) {
+ else if(curmsg -> M_type == MSG_TYPE_NOP) {
+ do_bookkeeping(msg_index);
+ actionResult = executeAction(NULL, msg_index);
+ return(next());
+ }
+
+ else if(curmsg -> send_scheme) {
char * msg_snd;
int send_status;
@@ -1538,10 +1394,7 @@
* retransmission enabled is acknowledged */
if(next_retrans) {
- if (!remove_running_call(this)) {
- ERROR("Tried to remove a running call that wasn't running!\n");
- }
- paused_calls.add_paused_call(this, true);
+ setPaused();
return true;
}
@@ -1555,9 +1408,9 @@
*/
int incr_cseq = 0;
- if (!scenario[msg_index]->send_scheme->isAck() &&
- !scenario[msg_index]->send_scheme->isCancel() &&
- !scenario[msg_index]->send_scheme->isResponse()) {
+ if (!curmsg->send_scheme->isAck() &&
+ !curmsg->send_scheme->isCancel() &&
+ !curmsg->send_scheme->isResponse()) {
++cseq;
incr_cseq = 1;
}
@@ -1569,20 +1422,20 @@
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",
+ WARNING("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) {
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_TIMEOUT_ON_SEND);
+ if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
return (abortCall());
} else {
- delete_call(id);
+ delete this;
return false;
}
}
- } else if (scenario[msg_index]->timeout) {
+ } else if (curmsg->timeout) {
/* Initialize the send timeout to the per message timeout. */
- send_timeout = clock_tick + scenario[msg_index]->timeout;
+ send_timeout = clock_tick + curmsg->timeout;
} else if (defl_send_timeout) {
/* Initialize the send timeout to the global timeout. */
send_timeout = clock_tick + defl_send_timeout;
@@ -1591,7 +1444,8 @@
} 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 */
+ /* The call was already deleted by connect_socket_if_needed or send_raw. */
+ return false;
}
/* We have sent the message, so the timeout is no longer needed. */
send_timeout = 0;
@@ -1600,96 +1454,203 @@
last_send_msg = (char *) realloc(last_send_msg, strlen(msg_snd) + 1);
strcpy(last_send_msg, msg_snd);
- if(last_recv_hash) {
+ if (curmsg->start_txn) {
+ txnID[curmsg->start_txn - 1] = (char *)realloc(txnID[curmsg->start_txn - 1], MAX_HEADER_LEN);
+ extract_transaction(txnID[curmsg->start_txn - 1], last_send_msg);
+ }
+
+ if(last_recv_index >= 0) {
/* We are sending just after msg reception. There is a great
* chance that we will be asked to retransmit this message */
recv_retrans_hash = last_recv_hash;
recv_retrans_recv_index = last_recv_index;
recv_retrans_send_index = msg_index;
-
+
/* Prevent from detecting the cause relation between send and recv
* in the next valid send */
last_recv_hash = 0;
}
/* Update retransmission information */
- if(scenario[msg_index] -> retrans_delay) {
+ if(curmsg -> retrans_delay) {
if((transport == T_UDP) && (retrans_enabled)) {
- next_retrans = clock_tick + scenario[msg_index] -> retrans_delay;
+ next_retrans = clock_tick + curmsg -> retrans_delay;
nb_retrans = 0;
- nb_last_delay = scenario[msg_index]->retrans_delay;
+ nb_last_delay = curmsg->retrans_delay;
}
} else {
next_retrans = 0;
}
-
-#ifdef PCAPPLAY
+
actionResult = executeAction(msg_snd, msg_index);
-#endif
-
+
/* Update scenario statistics */
- scenario[msg_index] -> nb_sent++;
+ curmsg -> nb_sent++;
return next();
- } else if (scenario[msg_index]->M_type == MSG_TYPE_RECV
-#ifdef __3PCC__
- || scenario[msg_index]->M_type == MSG_TYPE_RECVCMD
-#endif
+ } else if (curmsg->M_type == MSG_TYPE_RECV
+ || curmsg->M_type == MSG_TYPE_RECVCMD
) {
- if (recv_timeout) {
+ if (queued_msg) {
+ char *msg = queued_msg;
+ queued_msg = NULL;
+ bool ret = process_incoming(msg);
+ free(msg);
+ return ret;
+ } else if (recv_timeout) {
if(recv_timeout > clock_tick || recv_timeout > getmilliseconds()) {
- if (!remove_running_call(this)) {
- ERROR("Tried to remove a running call that wasn't running!\n");
- }
- paused_calls.add_paused_call(this, true);
+ setPaused();
return true;
}
recv_timeout = 0;
- ++scenario[msg_index]->nb_timeout;
- if (scenario[msg_index]->on_timeout == 0) {
+ curmsg->nb_timeout++;
+ if (curmsg->on_timeout < 0) {
// if you set a timeout but not a label, the call is aborted
- WARNING_P2("Call-Id: %s, receive timeout on message %d without label to jump to (ontimeout attribute): aborting call",
+ WARNING("Call-Id: %s, receive timeout on message %d without label to jump to (ontimeout attribute): aborting call",
id, msg_index);
- CStat::instance()->computeStat(CStat::E_CALL_FAILED);
- CStat::instance()->computeStat(CStat::E_FAILED_TIMEOUT_ON_RECV);
- if (default_behavior) {
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_TIMEOUT_ON_RECV);
+ if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
return (abortCall());
} else {
- delete_call(id);
+ delete this;
return false;
}
}
- WARNING_P3("Call-Id: %s, receive timeout on message %d, jumping to label %d",
- id, msg_index, scenario[msg_index]->on_timeout);
- msg_index = labelArray[scenario[msg_index]->on_timeout];
+ WARNING("Call-Id: %s, receive timeout on message %d, jumping to label %d",
+ id, msg_index, curmsg->on_timeout);
+ msg_index = curmsg->on_timeout;
recv_timeout = 0;
- if (msg_index < scenario_len) return true;
+ if (msg_index < call_scenario->length) return true;
// special case - the label points to the end - finish the call
- CStat::instance()->computeStat(CStat::E_CALL_FAILED);
- CStat::instance()->computeStat(CStat::E_FAILED_TIMEOUT_ON_RECV);
- if (default_behavior) {
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_TIMEOUT_ON_RECV);
+ if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
return (abortCall());
} else {
- delete_call(id);
+ delete this;
return false;
}
- } else if ((scenario[msg_index]->timeout) || (defl_recv_timeout)) {
- if (scenario[msg_index]->timeout)
+ } else if (curmsg->timeout || defl_recv_timeout) {
+ if (curmsg->timeout)
// If timeout is specified on message receive, use it
- recv_timeout = getmilliseconds() + scenario[msg_index]->timeout;
+ recv_timeout = getmilliseconds() + curmsg->timeout;
else
// Else use the default timeout if specified
recv_timeout = getmilliseconds() + defl_recv_timeout;
return true;
} else {
/* We are going to wait forever. */
- if (!remove_running_call(this)) {
- ERROR("Tried to remove a running call that wasn't running!\n");
- }
- paused_calls.add_paused_call(this, true);
+ setPaused();
}
}
return true;
+}
+
+char *default_message_names[] = {
+ "3pcc_abort",
+ "ack",
+ "ack2",
+ "bye",
+ "cancel",
+ "200",
+};
+char *default_message_strings[] = {
+ /* 3pcc_abort */
+ "call-id: [call_id]\ninternal-cmd: abort_call\n\n",
+ /* ack */
+ "ACK [last_Request_URI] SIP/2.0\n"
+ "[last_Via]\n"
+ "[last_From]\n"
+ "[last_To]\n"
+ "Call-ID: [call_id]\n"
+ "CSeq: [last_cseq_number] ACK\n"
+ "Contact: <sip:sipp@[local_ip]:[local_port];transport=[transport]>\n"
+ "Max-Forwards: 70\n"
+ "Subject: Performance Test\n"
+ "Content-Length: 0\n\n",
+ /* ack2, the only difference is Via, I don't quite know why. */
+ "ACK [last_Request_URI] SIP/2.0\n"
+ "Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
+ "[last_From]\n"
+ "[last_To]\n"
+ "Call-ID: [call_id]\n"
+ "CSeq: [last_cseq_number] ACK\n"
+ "Contact: <sip:sipp@[local_ip]:[local_port];transport=[transport]>\n"
+ "Max-Forwards: 70\n"
+ "Subject: Performance Test\n"
+ "Content-Length: 0\n\n",
+ /* bye */
+ "BYE [last_Request_URI] SIP/2.0\n"
+ "Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
+ "[last_From]\n"
+ "[last_To]\n"
+ "Call-ID: [call_id]\n"
+ "CSeq: [last_cseq_number+1] BYE\n"
+ "Max-Forwards: 70\n"
+ "Contact: <sip:sipp@[local_ip]:[local_port];transport=[transport]>\n"
+ "Content-Length: 0\n\n",
+ /* cancel */
+ "CANCEL [last_Request_URI] SIP/2.0\n"
+ "[last_Via]\n"
+ "[last_From]\n"
+ "[last_To]\n"
+ "Call-ID: [call_id]\n"
+ "CSeq: [last_cseq_number] CANCEL\n"
+ "Max-Forwards: 70\n"
+ "Contact: <sip:sipp@[local_ip]:[local_port];transport=[transport]>\n"
+ "Content-Length: 0\n\n",
+ /* 200 */
+ "SIP/2.0 200 OK\n"
+ "[last_Via:]\n"
+ "[last_From:]\n"
+ "[last_To:]\n"
+ "[last_Call-ID:]\n"
+ "[last_CSeq:]\n"
+ "Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
+ "Content-Length: 0\n\n"
+};
+
+SendingMessage **default_messages;
+
+void init_default_messages() {
+ int messages = sizeof(default_message_strings)/sizeof(default_message_strings[0]);
+ default_messages = new SendingMessage* [messages];
+ for (int i = 0; i < messages; i++) {
+ default_messages[i] = new SendingMessage(main_scenario, default_message_strings[i]);
+ }
+}
+
+void free_default_messages() {
+ int messages = sizeof(default_message_strings)/sizeof(default_message_strings[0]);
+ if (!default_messages) {
+ return;
+ }
+ for (int i = 0; i < messages; i++) {
+ delete default_messages[i];
+ }
+ delete [] default_messages;
+}
+
+SendingMessage *get_default_message(const char *which) {
+ int messages = sizeof(default_message_names)/sizeof(default_message_names[0]);
+ for (int i = 0; i < messages; i++) {
+ if (!strcmp(which, default_message_names[i])) {
+ return default_messages[i];
+ }
+ }
+ ERROR("Internal Error: Unknown default message: %s!", which);
+}
+
+void set_default_message(const char *which, char *msg) {
+ int messages = sizeof(default_message_names)/sizeof(default_message_names[0]);
+ for (int i = 0; i < messages; i++) {
+ if (!strcmp(which, default_message_names[i])) {
+ default_message_strings[i] = msg;
+ return;
+ }
+ }
+ ERROR("Internal Error: Unknown default message: %s!", which);
}
bool call::process_unexpected(char * msg)
@@ -1697,60 +1658,70 @@
char buffer[MAX_HEADER_LEN];
char *desc = buffer;
- scenario[msg_index] -> nb_unexp++;
-
- if (default_behavior) {
+ message *curmsg = call_scenario->messages[msg_index];
+
+ curmsg->nb_unexp++;
+
+ if (default_behaviors & DEFAULT_BEHAVIOR_ABORTUNEXP) {
desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "Aborting ");
} else {
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);
+ if (curmsg -> M_type == MSG_TYPE_RECV) {
+ if (curmsg -> recv_request) {
+ desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%s' ", curmsg -> 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 expecting '%d' ", curmsg -> recv_response);
+ }
+ } else if (curmsg -> 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) {
+ } else if (curmsg -> 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) {
+ } else if (curmsg -> 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) {
+ } else if (curmsg -> M_type == MSG_TYPE_RECVCMD) {
desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting command ");
} else {
- 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), "while in message type %d ", curmsg->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"
+ WARNING("%s, received '%s'", buffer, msg);
+
+ TRACE_MSG("-----------------------------------------------\n"
"Unexpected %s message received:\n\n%s\n",
TRANSPORT_TO_STRING(transport),
- msg));
-
- if (default_behavior) {
+ msg);
+
+ if (default_behaviors & DEFAULT_BEHAVIOR_ABORTUNEXP) {
// 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));
+ sendCmdBuffer(createSendingMessage(get_default_message("3pcc_abort"), -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());
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_UNEXPECTED_MSG);
+ if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
+ return (abortCall());
+ } else {
+ delete this;
+ return false;
+ }
} else {
// Do not abort call nor send anything in reply if default behavior is disabled
return false;
}
+}
+
+void call::abort() {
+ WARNING("Aborted call with Call-ID '%s'", id);
+ abortCall();
}
bool call::abortCall()
@@ -1775,23 +1746,7 @@
// 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 [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:");
- if (cseq != NULL) {
- sprintf(L_param, "%s%s ACK\n", L_param, cseq);
- }
- 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\n");
-
- sendBuffer(createSendingMessage((char*)(L_param), -2));
-
+ sendBuffer(createSendingMessage(get_default_message("ack"), -2));
} else if (src_recv) {
/* Call is not established and the reply is not a 4XX, 5XX */
/* And we already received a message. */
@@ -1802,48 +1757,13 @@
* and send a BYE afterwards */
ack_is_pending = false;
/* Send an ACK */
- 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, "[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\n");
- sendBuffer(createSendingMessage((char*)(L_param),-1));
-
+ sendBuffer(createSendingMessage(get_default_message("ack"), -1));
+
/* Send the BYE */
- cseq = NULL;
- 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, "[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, "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));
+ sendBuffer(createSendingMessage(get_default_message("bye"), -1));
} else {
/* Send a CANCEL */
- 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, "%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),-2));
+ sendBuffer(createSendingMessage(get_default_message("cancel"), -1));
}
} else {
/* Call is not established and the reply is not a 4XX, 5XX */
@@ -1861,32 +1781,27 @@
char L_msg_buffer[SIPP_MAX_MSG_SIZE];
L_msg_buffer[0] = '\0';
char * L_param = L_msg_buffer;
- 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, "[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, "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));
- }
- }
-
- delete_call(id);
+ sendBuffer(createSendingMessage(get_default_message("bye"), -1));
+ }
+ }
+
+ stopListening();
+ deadcall *deadcall_ptr = NULL;
+ if (deadcall_wait) {
+ char reason[100];
+ sprintf(reason, "aborted at index %d", msg_index);
+ deadcall_ptr = new deadcall(id, reason);
+ }
+ delete this;
+
return false;
}
bool call::rejectCall()
{
- CStat::instance()->computeStat(CStat::E_CALL_FAILED);
- CStat::instance()->computeStat(CStat::E_FAILED_CALL_REJECTED);
- delete_call(id);
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_CALL_REJECTED);
+ delete this;
return false;
}
@@ -1902,26 +1817,28 @@
char * peer_dest;
struct sipp_socket **peer_socket;
- if(scenario[index] -> M_sendCmdData) {
- // WARNING_P1("---PREPARING_TWIN_CMD---%s---", scenario[index] -> M_sendCmdData);
- dest = createSendingMessage(scenario[index] -> M_sendCmdData, -1);
+ message *curmsg = call_scenario->messages[index];
+
+ if(curmsg -> M_sendCmdData) {
+ // WARNING("---PREPARING_TWIN_CMD---%s---", scenario[index] -> M_sendCmdData);
+ dest = createSendingMessage(curmsg -> M_sendCmdData, -1);
strcat(dest, delimitor);
- //WARNING_P1("---SEND_TWIN_CMD---%s---", dest);
+ //WARNING("---SEND_TWIN_CMD---%s---", dest);
int rc;
/* 3pcc extended mode */
- peer_dest = scenario[index]->peer_dest;
- if(peer_dest){
+ peer_dest = curmsg->peer_dest;
+ if(peer_dest){
peer_socket = get_peer_socket(peer_dest);
- rc = write_socket(*peer_socket, dest, strlen(dest), WS_BUFFER);
+ rc = write_socket(*peer_socket, dest, strlen(dest), WS_BUFFER, &call_peer);
}else {
- rc = write_socket(twinSippSocket, dest, strlen(dest), WS_BUFFER);
+ rc = write_socket(twinSippSocket, dest, strlen(dest), WS_BUFFER, &call_peer);
}
if(rc < 0) {
- CStat::instance()->computeStat(CStat::E_CALL_FAILED);
- CStat::instance()->computeStat(CStat::E_FAILED_CMD_NOT_SENT);
- delete_call(id);
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_CMD_NOT_SENT);
+ delete this;
return(-1);
}
@@ -1945,25 +1862,30 @@
strcat(dest, delimitor);
- rc = write_socket(twinSippSocket, dest, strlen(dest), WS_BUFFER);
+ rc = write_socket(twinSippSocket, dest, strlen(dest), WS_BUFFER, &twinSippSocket->ss_remote_sockaddr);
if(rc < 0) {
- CStat::instance()->computeStat(CStat::E_CALL_FAILED);
- CStat::instance()->computeStat(CStat::E_FAILED_CMD_NOT_SENT);
- delete_call(id);
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_CMD_NOT_SENT);
+ delete this;
return(-1);
}
return(0);
}
-char* call::createSendingMessage(SendingMessage *src, int P_index)
+
+char* call::createSendingMessage(SendingMessage *src, int P_index) {
+ static char msg_buffer[SIPP_MAX_MSG_SIZE+2];
+ return createSendingMessage(src, P_index, msg_buffer, sizeof(msg_buffer));
+}
+
+char* call::createSendingMessage(SendingMessage *src, int P_index, char *msg_buffer, int buf_len)
{
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;
@@ -1971,7 +1893,7 @@
for (int i = 0; i < src->numComponents(); i++) {
MessageComponent *comp = src->getComponent(i);
- int left = sizeof(msg_buffer) - (dest - msg_buffer);
+ int left = buf_len - (dest - msg_buffer);
switch(comp->type) {
case E_Message_Literal:
if (supresscrlf) {
@@ -1985,6 +1907,9 @@
break;
case E_Message_Remote_IP:
dest += snprintf(dest, left, "%s", remote_ip_escaped);
+ break;
+ case E_Message_Remote_Host:
+ dest += snprintf(dest, left, "%s", remote_host);
break;
case E_Message_Remote_Port:
dest += snprintf(dest, left, "%d", remote_port + comp->offset);
@@ -2064,7 +1989,7 @@
(_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);
+ ERROR("media_port keyword with no audio or video on the current line (%s)", begin);
}
#endif
dest += sprintf(dest, "%u", port);
@@ -2132,35 +2057,40 @@
case E_Message_ClockTick:
dest += snprintf(dest, left, "%lu", clock_tick);
break;
+ case E_Message_Timestamp:
+ struct timeval currentTime;
+ gettimeofday(¤tTime, NULL);
+ dest += snprintf(dest, left, "%s", CStat::formatTime(¤tTime));
+ break;
+ case E_Message_Users:
+ dest += snprintf(dest, left, "%d", users);
+ break;
+ case E_Message_UserID:
+ dest += snprintf(dest, left, "%d", userId);
+ 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");
- }
+ CCallVariable *var = M_callVariableTable->getVar(varId);
+ if(var->isSet()) {
+ if (var->isRegExp()) {
+ dest += sprintf(dest, "%s", var->getMatchingValue());
+ } else if (var->isDouble()) {
+ dest += sprintf(dest, "%lf", var->getDouble());
+ } else if (var->isString()) {
+ dest += sprintf(dest, "%s", var->getString());
+ } else if (var->isBool()) {
+ dest += sprintf(dest, "true");
}
+ } else if (var->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;
- }
+ int length = (int) M_callVariableTable->getVar(varId)->getDouble();
+ if (length < 0) {
+ length = 0;
}
char *filltext = comp->literal;
int filllen = strlen(filltext);
@@ -2175,7 +2105,7 @@
}
case E_Message_Injection: {
char *orig_dest = dest;
- getFieldFromInputFile(comp->comp_param.field_param.filename, comp->comp_param.field_param.field, dest);
+ getFieldFromInputFile(comp->comp_param.field_param.filename, comp->comp_param.field_param.field, comp->comp_param.field_param.line, dest);
/* We are injecting an authentication line. */
if (char *tmp = strstr(orig_dest, "[authentication")) {
if (auth_marker) {
@@ -2189,7 +2119,7 @@
tmp = strchr(auth_marker, ']');
char c = *tmp;
*tmp = '\0';
- SendingMessage::parseAuthenticationKeyword(auth_comp, auth_marker);
+ SendingMessage::parseAuthenticationKeyword(call_scenario, auth_comp, auth_marker);
*tmp = c;
}
if (*(dest - 1) == '\n') {
@@ -2207,11 +2137,29 @@
}
break;
}
+ case E_Message_Last_Message:
+ if(last_recv_msg && strlen(last_recv_msg)) {
+ dest += sprintf(dest, "%s", last_recv_msg);
+ }
+ 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;
+ break;
+ }
+ case E_Message_Last_CSeq_Number: {
+ int last_cseq = 0;
+
+ char *last_header = get_last_header("CSeq:");
+ if(last_header) {
+ last_header += 5;
+ /* Extract the integer value of the field */
+ while(isspace(*last_header)) last_header++;
+ sscanf(last_header,"%d", &last_cseq);
+ }
+ dest += sprintf(dest, "%d", last_cseq + comp->offset);
+ break;
}
case E_Message_TDM_Map:
if (!use_tdmmap)
@@ -2268,10 +2216,11 @@
/* Need the Method name from the CSeq of the Challenge */
char method[MAX_HEADER_LEN];
- tmp = get_last_header("CSeq:") + 5;
+ tmp = get_last_header("CSeq:");
if(!tmp) {
ERROR("Could not extract method from cseq of challenge");
}
+ tmp += 5;
while(isspace(*tmp) || isdigit(*tmp)) tmp++;
sscanf(tmp,"%s", method);
@@ -2292,11 +2241,22 @@
/* 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);
+ /* These cause this function to not be reentrant. */
+ static char my_auth_user[MAX_HEADER_LEN + 2];
+ static char my_auth_pass[MAX_HEADER_LEN + 2];
+ static char my_aka_OP[MAX_HEADER_LEN + 2];
+ static char my_aka_AMF[MAX_HEADER_LEN + 2];
+ static char my_aka_K[MAX_HEADER_LEN + 2];
+
+ createSendingMessage(auth_comp->comp_param.auth_param.auth_user, -2, my_auth_user, sizeof(my_auth_user));
+ createSendingMessage(auth_comp->comp_param.auth_param.auth_pass, -2, my_auth_pass, sizeof(my_auth_pass));
+ createSendingMessage(auth_comp->comp_param.auth_param.aka_K, -2, my_aka_K, sizeof(my_aka_K));
+ createSendingMessage(auth_comp->comp_param.auth_param.aka_AMF, -2, my_aka_AMF, sizeof(my_aka_AMF));
+ createSendingMessage(auth_comp->comp_param.auth_param.aka_OP, -2, my_aka_OP, sizeof(my_aka_OP));
+
+ if (createAuthHeader(my_auth_user, my_auth_pass, method, uri, body, dialog_authentication,
+ my_aka_OP, my_aka_AMF, my_aka_K, result + authlen) == 0) {
+ ERROR("%s", result + authlen);
}
authlen = strlen(result);
@@ -2314,64 +2274,47 @@
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__
bool call::process_twinSippCom(char * msg)
{
int search_index;
bool found = false;
T_ActionResult actionResult;
- if (!running) {
- paused_calls.remove_paused_call(this);
- add_running_call(this);
- }
+ setRunning();
if (checkInternalCmd(msg) == false) {
for(search_index = msg_index;
- search_index < scenario_len;
+ search_index < call_scenario->length;
search_index++) {
- if(scenario[search_index] -> M_type != MSG_TYPE_RECVCMD) {
- if(scenario[search_index] -> optional) {
- 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();
+ if(call_scenario->messages[search_index] -> M_type != MSG_TYPE_RECVCMD) {
+ if(call_scenario->messages[search_index] -> optional) {
+ continue;
+ }
+ /* The received message is different from the expected one */
+ TRACE_MSG("Unexpected control message received (I was expecting a different type of message):\n%s\n", msg);
+ return rejectCall();
} else {
- if(extendedTwinSippMode){ // 3pcc extended mode
+ if(extendedTwinSippMode){ // 3pcc extended mode
if(check_peer_src(msg, search_index)){
- found = true;
- break;
+ found = true;
+ break;
} else{
- WARNING_P1("Unexpected sender for the received peer message \n%s\n", msg);
+ WARNING("Unexpected sender for the received peer message \n%s\n", msg);
return rejectCall();
- }
- }
- else {
- found = true;
- break;
- }
- }
- }
-
+ }
+ }
+ else {
+ found = true;
+ break;
+ }
+ }
+ }
+
if (found) {
- scenario[search_index]->M_nbCmdRecv ++;
-
+ call_scenario->messages[search_index]->M_nbCmdRecv ++;
+ do_bookkeeping(search_index);
+
// variable treatment
// Remove \r, \n at the end of a received command
// (necessary for transport, to be removed for usage)
@@ -2380,7 +2323,7 @@
msg[strlen(msg)-2] = 0;
}
actionResult = executeAction(msg, search_index);
-
+
if(actionResult != call::E_AR_NO_ERROR) {
// Store last action result if it is an error
// and go on with the scenario
@@ -2390,12 +2333,11 @@
}
}
} else {
- TRACE_MSG((s, "Unexpected control message received (no such message found):\n%s\n", msg));
+ TRACE_MSG("Unexpected control message received (no such message found):\n%s\n", msg);
return rejectCall();
}
msg_index = search_index; //update the state machine
return(next());
-
} else {
return (false);
}
@@ -2426,7 +2368,7 @@
if (strcmp(L_ptr1, "abort_call") == 0) {
*L_ptr2 = L_backup;
abortCall();
- CStat::instance()->computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_CALL_FAILED);
return (true);
}
@@ -2454,7 +2396,7 @@
if(!*L_ptr2) { return (false); }
L_backup = *L_ptr2;
*L_ptr2 = 0;
- if (strcmp(L_ptr1, scenario[search_index] -> peer_src) == 0) {
+ if (strcmp(L_ptr1, call_scenario->messages[search_index] -> peer_src) == 0) {
*L_ptr2 = L_backup;
return(true);
}
@@ -2462,7 +2404,6 @@
*L_ptr2 = L_backup;
return (false);
}
-#endif
void call::extract_cseq_method (char* method, char* msg)
@@ -2485,6 +2426,28 @@
method[nbytes] = '\0';
}
}
+}
+
+void call::extract_transaction (char* txn, char* msg)
+{
+ char *otxn = txn;
+ char *via = get_header_content(msg, "via:");
+ if (!via) {
+ txn[0] = '\0';
+ return;
+ }
+
+ char *branch = strstr(via, ";branch=");
+ if (!branch) {
+ txn[0] = '\0';
+ return;
+ }
+
+ branch += strlen(";branch=");
+ while (*branch && *branch != ';' && *branch != ',' && !isspace(*branch)) {
+ *txn++ = *branch++;
+ }
+ *txn = '\0';
}
void call::formatNextReqUrl (char* next_req_url)
@@ -2634,39 +2597,50 @@
}
}
-bool call::matches_scenario(unsigned int index, int reply_code, char * request, char * responsecseqmethod)
-{
+bool call::matches_scenario(unsigned int index, int reply_code, char * request, char * responsecseqmethod, char *txn)
+{
int result;
-
- if ((reply_code) && ((scenario[index] -> recv_response) == reply_code) && \
- (index == 0 || ((scenario[index]->recv_response_for_cseq_method_list) && \
- (strstr(scenario[index]->recv_response_for_cseq_method_list, responsecseqmethod))))) {
- return true;
- }
-
- if ((scenario[index] -> recv_request) && \
- (!strcmp(scenario[index] -> recv_request, request))) {
- return true;
- }
-
- if ((scenario[index] -> recv_request) && (scenario[index] -> regexp_match)) {
-
- if (scenario[index] -> regexp_compile == NULL) {
- regex_t *re = new regex_t;
- if (regcomp(re, scenario[index] -> recv_request, REG_EXTENDED|REG_NOSUB)) {
- // regexp is not well formed
- scenario[index] -> regexp_match = 0;
- free(re);
- return false;
- }
- scenario[index] -> regexp_compile = re;
- }
-
- result = regexec(scenario[index] -> regexp_compile, request, (size_t)0, NULL, 0);
- if (!result) return true;
+ message *curmsg = call_scenario->messages[index];
+
+ if ((curmsg -> recv_request)) {
+ if (curmsg->regexp_match) {
+ if (curmsg -> regexp_compile == NULL) {
+ regex_t *re = new regex_t;
+ if (regcomp(re, curmsg -> recv_request, REG_EXTENDED|REG_NOSUB)) {
+ ERROR("Invalid regular expression for index %d: %s", curmsg->recv_request);
+ }
+ curmsg -> regexp_compile = re;
+ }
+ return !regexec(curmsg -> regexp_compile, request, (size_t)0, NULL, 0);
+ } else {
+ return !strcmp(curmsg -> recv_request, request);
+ }
+ } else if (curmsg->recv_response && (curmsg->recv_response == reply_code)) {
+ /* This is a potential candidate, we need to match transactions. */
+ if (curmsg->response_txn) {
+ if (txnID[curmsg->response_txn - 1] && !strcmp(txnID[curmsg->response_txn - 1], txn)) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (index == 0) {
+ /* Always true for the first message. */
+ return true;
+ } else if (curmsg->recv_response_for_cseq_method_list &&
+ strstr(curmsg->recv_response_for_cseq_method_list, responsecseqmethod)) {
+ /* If we do not have a transaction defined, we just check the CSEQ method. */
+ return true;
+ } else {
+ return false;
+ }
}
return false;
+}
+
+void call::queue_up(char *msg) {
+ free(queued_msg);
+ queued_msg = strdup(msg);
}
bool call::process_incoming(char * msg)
@@ -2674,53 +2648,51 @@
int reply_code;
static char request[65];
char responsecseqmethod[65];
+ char txn[MAX_HEADER_LEN];
unsigned long cookie;
char * ptr;
int search_index;
bool found = false;
T_ActionResult actionResult;
- int L_case = 0 ;
-
- if (!running) {
- paused_calls.remove_paused_call(this);
- add_running_call(this);
- }
+ setRunning();
/* 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);
+ if(call_scenario->messages[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)) {
- actionResult = executeAction(NULL, msg_index);
- return next();
+ if((msg_index == 0) && (call_scenario->messages[msg_index] -> M_type == MSG_TYPE_NOP)) {
+ queue_up (msg);
+ paused_until = 0;
+ return run();
}
responsecseqmethod[0] = '\0';
+ txn[0] = '\0';
if((transport == T_UDP) && (retrans_enabled)) {
/* Detects retransmissions from peer and retransmit the
* message which was sent just after this one was received */
cookie = hash(msg);
- if(recv_retrans_hash == cookie) {
+ if((recv_retrans_recv_index >= 0) && (recv_retrans_hash == cookie)) {
int status;
if(lost(recv_retrans_recv_index)) {
- TRACE_MSG((s, "%s message (retrans) lost (recv).",
- TRANSPORT_TO_STRING(transport)));
+ TRACE_MSG("%s message (retrans) lost (recv).",
+ TRANSPORT_TO_STRING(transport));
if(comp_state) { comp_free(&comp_state); }
- scenario[recv_retrans_recv_index] -> nb_lost++;
+ call_scenario->messages[recv_retrans_recv_index] -> nb_lost++;
return true;
}
- scenario[recv_retrans_recv_index] -> nb_recv_retrans++;
+ call_scenario->messages[recv_retrans_recv_index] -> nb_recv_retrans++;
send_scene(recv_retrans_send_index, &status);
if(status == 0) {
- scenario[recv_retrans_send_index] -> nb_sent_retrans++;
- CStat::instance()->computeStat(CStat::E_RETRANSMISSION);
+ call_scenario->messages[recv_retrans_send_index] -> nb_sent_retrans++;
+ computeStat(CStat::E_RETRANSMISSION);
} else if(status < 0) {
return false;
}
@@ -2728,7 +2700,7 @@
return true;
}
- if(last_recv_hash == cookie) {
+ if((last_recv_index >= 0) && (last_recv_hash == cookie)) {
/* This one has already been received, but not processed
* yet => (has not triggered something yet) so we can discard.
*
@@ -2742,7 +2714,7 @@
* This case can also appear in case of message duplication by
* the network. This should not be considered as an unexpected.
*/
- scenario[last_recv_index]->nb_recv_retrans++;
+ call_scenario->messages[last_recv_index]->nb_recv_retrans++;
return true;
}
}
@@ -2782,6 +2754,7 @@
request[0]=0;
// extract the cseq method from the response
extract_cseq_method (responsecseqmethod, msg);
+ extract_transaction (txn, msg);
} else if(ptr = strchr(msg, ' ')) {
if((ptr - msg) < 64) {
memcpy(request, msg, ptr - msg);
@@ -2803,21 +2776,21 @@
reply_code = 0;
} else {
- ERROR_P1("SIP method too long in received message '%s'",
+ ERROR("SIP method too long in received message '%s'",
msg);
}
} else {
- ERROR_P1("Invalid sip message received '%s'",
+ ERROR("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;
- search_index < scenario_len;
+ search_index < call_scenario->length;
search_index++) {
- if(!matches_scenario(search_index, reply_code, request, responsecseqmethod)) {
- if(scenario[search_index] -> optional) {
+ if(!matches_scenario(search_index, reply_code, request, responsecseqmethod, txn)) {
+ if(call_scenario->messages[search_index] -> optional) {
continue;
}
/* The received message is different for the expected one */
@@ -2838,23 +2811,44 @@
for(search_index = msg_index - 1;
search_index >= 0;
search_index--) {
- if (scenario[search_index]->optional == OPTIONAL_FALSE) contig = false;
- if(matches_scenario(search_index, reply_code, request, responsecseqmethod)) {
- if (contig || scenario[search_index]->optional == OPTIONAL_GLOBAL) {
+ if (call_scenario->messages[search_index]->optional == OPTIONAL_FALSE) contig = false;
+ if(matches_scenario(search_index, reply_code, request, responsecseqmethod, txn)) {
+ if (contig || call_scenario->messages[search_index]->optional == OPTIONAL_GLOBAL) {
found = true;
break;
} else {
- /*
- * we received a non mandatory msg for an old transaction (this could be due to a retransmit.
- * If this response is for an INVITE transaction, retransmit the ACK to quench retransmits.
- */
- if ( (reply_code) &&
- (0 == strncmp (responsecseqmethod, "INVITE", strlen(responsecseqmethod)) ) &&
- (scenario[search_index+1]->M_type == MSG_TYPE_SEND) &&
- (scenario[search_index+1]->send_scheme->isAck()) ) {
- sendBuffer(createSendingMessage(scenario[search_index+1] -> send_scheme, (search_index+1)));
- return true;
- }
+ if (int checkTxn = call_scenario->messages[search_index]->response_txn) {
+ /* This is a reply to an old transaction. */
+ if (!strcmp(txnID[checkTxn - 1], txn)) {
+ /* This reply is provisional, so it should have no effect if we recieve it out-of-order. */
+ if (reply_code >= 100 && reply_code <= 199) {
+ TRACE_MSG("-----------------------------------------------\n"
+ "Ignoring provisional %s message for transaction %s:\n\n%s\n",
+ TRANSPORT_TO_STRING(transport), call_scenario->txnRevMap[checkTxn - 1], msg);
+ return true;
+ } else if (call_scenario->messages[search_index + 1]->M_type == MSG_TYPE_SEND && call_scenario->messages[search_index + 1]->send_scheme->isAck()) {
+ /* This is the message before an ACK, so verify that this is an invite transaction. */
+ if (!strcmp(responsecseqmethod, "INVITE")) {
+ sendBuffer(createSendingMessage(call_scenario->messages[search_index+1] -> send_scheme, (search_index+1)));
+ return true;
+ }
+ }
+ /* This is a non-provisional message for the transaction, and
+ * we have already gotten our allowable response. */
+ }
+ } else {
+ /*
+ * we received a non mandatory msg for an old transaction (this could be due to a retransmit.
+ * If this response is for an INVITE transaction, retransmit the ACK to quench retransmits.
+ */
+ if ( (reply_code) &&
+ (0 == strncmp (responsecseqmethod, "INVITE", strlen(responsecseqmethod)) ) &&
+ (call_scenario->messages[search_index+1]->M_type == MSG_TYPE_SEND) &&
+ (call_scenario->messages[search_index+1]->send_scheme->isAck()) ) {
+ sendBuffer(createSendingMessage(call_scenario->messages[search_index+1] -> send_scheme, (search_index+1)));
+ return true;
+ }
+ }
}
}
}
@@ -2862,17 +2856,43 @@
/* If it is still not found, process an unexpected message */
if(!found) {
- if ((L_case = checkAutomaticResponseMode(request)) == 0) {
- if (!process_unexpected(msg)) {
- return false; // Call aborted by unexpected message handling
+ if (call_scenario->unexpected_jump >= 0) {
+ bool recursive = false;
+ if (call_scenario->retaddr >= 0) {
+ if (M_callVariableTable->getVar(call_scenario->retaddr)->getDouble() != 0) {
+ /* We are already in a jump! */
+ recursive = true;
+ } else {
+ M_callVariableTable->getVar(call_scenario->retaddr)->setDouble(msg_index);
+ }
+ }
+ if (!recursive) {
+ if (call_scenario->pausedaddr >= 0) {
+ M_callVariableTable->getVar(call_scenario->pausedaddr)->setDouble(paused_until);
+ }
+ msg_index = call_scenario->unexpected_jump;
+ queue_up(msg);
+ paused_until = 0;
+ return run();
+ } else {
+ if (!process_unexpected(msg)) {
+ return false; // Call aborted by unexpected message handling
+ }
}
} else {
- // call aborted by automatic response mode if needed
- return automaticResponseMode(L_case, msg);
- }
- }
-
- int test = (!found) ? -1 : scenario[search_index]->test;
+ T_AutoMode L_case;
+ if ((L_case = checkAutomaticResponseMode(request)) == 0) {
+ if (!process_unexpected(msg)) {
+ return false; // Call aborted by unexpected message handling
+ }
+ } else {
+ // call aborted by automatic response mode if needed
+ return automaticResponseMode(L_case, msg);
+ }
+ }
+ }
+
+ int test = (!found) ? -1 : call_scenario->messages[search_index]->test;
/* test==0: No branching"
* test==-1 branching without testing"
* test>0 branching with testing
@@ -2880,10 +2900,10 @@
/* Simulate loss of messages */
if(lost(search_index)) {
- TRACE_MSG((s, "%s message lost (recv).",
- TRANSPORT_TO_STRING(transport)));
+ TRACE_MSG("%s message lost (recv).",
+ TRANSPORT_TO_STRING(transport));
if(comp_state) { comp_free(&comp_state); }
- scenario[search_index] -> nb_lost++;
+ call_scenario->messages[search_index] -> nb_lost++;
return true;
}
@@ -2892,12 +2912,12 @@
do_bookkeeping(search_index);
/* Increment the recv counter */
- scenario[search_index] -> nb_recv++;
+ call_scenario->messages[search_index] -> nb_recv++;
// Action treatment
if (found) {
- //WARNING_P1("---EXECUTE_ACTION_ON_MSG---%s---", msg);
-
+ //WARNING("---EXECUTE_ACTION_ON_MSG---%s---", msg);
+
actionResult = executeAction(msg, search_index);
if(actionResult != call::E_AR_NO_ERROR) {
@@ -2953,7 +2973,7 @@
}
/* store the route set only once. TODO: does not support target refreshes!! */
- if (scenario[search_index] -> bShouldRecordRoutes &&
+ if (call_scenario->messages[search_index] -> bShouldRecordRoutes &&
NULL == dialog_route_set ) {
next_req_url = (char*) calloc(1, MAX_HEADER_LEN);
@@ -2962,7 +2982,7 @@
memset(rr, 0, sizeof(rr));
strcpy(rr, get_header_content(msg, (char*)"Record-Route:"));
- // WARNING_P1("rr [%s]", rr);
+ // WARNING("rr [%s]", rr);
char ch[MAX_HEADER_LEN];
strcpy(ch, get_header_content(msg, (char*)"Contact:"));
@@ -2982,12 +3002,12 @@
{
computeRouteSetAndRemoteTargetUri (rr, ch, true);
}
- // WARNING_P1("next_req_url is [%s]", next_req_url);
+ // WARNING("next_req_url is [%s]", next_req_url);
}
#ifdef _USE_OPENSSL
/* store the authentication info */
- if ((scenario[search_index] -> bShouldAuthenticate) &&
+ if ((call_scenario->messages[search_index] -> bShouldAuthenticate) &&
(reply_code == 401 || reply_code == 407)) {
/* is a challenge */
@@ -3008,6 +3028,11 @@
dialog_challenge_type = reply_code;
}
#endif
+
+ /* If we are not advancing state, we should quite before we change this stuff. */
+ if (!call_scenario->messages[search_index]->advance_state) {
+ return true;
+ }
/* Store last received message information for all messages so that we can
* correctly identify retransmissions, and use its body for inclusion
@@ -3019,32 +3044,30 @@
/* If this was a mandatory message, or if there is an explicit next label set
* we must update our state machine. */
- if (!(scenario[search_index] -> optional) ||
- scenario[search_index]->next &&
- ((test == -1) ||
- (test <= maxVariableUsed && M_callVariableTable[test] != NULL && M_callVariableTable[test]->isSet()))
+ if (!(call_scenario->messages[search_index] -> optional) ||
+ call_scenario->messages[search_index]->next &&
+ ((test == -1) || (M_callVariableTable->getVar(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 timeout = wake();
unsigned int candidate;
- 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);
+ if (call_scenario->messages[search_index]->next && M_callVariableTable->getVar(test)->isSet()) {
+ WARNING("Last message generates an error and will not be used for next sends (for last_ variables):\r\n%s",msg);
}
/* We are just waiting for a message to be received, if any of the
* potential messages have a timeout we set it as our timeout. We
* start from the next message and go until any non-receives. */
- for(search_index++; search_index < scenario_len; search_index++) {
- if(scenario[search_index] -> M_type != MSG_TYPE_RECV) {
- break;
- }
- candidate = scenario[search_index] -> timeout;
+ for(search_index++; search_index < call_scenario->length; search_index++) {
+ if(call_scenario->messages[search_index] -> M_type != MSG_TYPE_RECV) {
+ break;
+ }
+ candidate = call_scenario->messages[search_index] -> timeout;
if (candidate == 0) {
if (defl_recv_timeout == 0) {
continue;
@@ -3056,17 +3079,14 @@
}
}
- if (!remove_running_call(this)) {
- ERROR("Tried to remove a running call that wasn't running!\n");
- }
- paused_calls.add_paused_call(this, true);
+ setPaused();
}
return true;
}
double call::get_rhs(CAction *currentAction) {
if (currentAction->getVarInId()) {
- return M_callVariableTable[currentAction->getVarInId()]->getDouble();
+ return M_callVariableTable->getVar(currentAction->getVarInId())->getDouble();
} else {
return currentAction->getDoubleValue();
}
@@ -3076,138 +3096,179 @@
{
CActions* actions;
CAction* currentAction;
- CVariable* scenVariable;
- char msgPart[MAX_SUB_MESSAGE_LENGTH];
- int currentId;
-
- actions = scenario[scenarioIndex]->M_actions;
+
+ actions = call_scenario->messages[scenarioIndex]->M_actions;
// looking for action to do on this message
if(actions != NULL) {
for(int i=0; i<actions->getActionSize(); i++) {
currentAction = actions->getAction(i);
if(currentAction != NULL) {
if(currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_REGEXP) {
- currentId = currentAction->getVarId();
- scenVariable = scenVariableTable[currentId][scenarioIndex];
- if(scenVariable != NULL) {
- if(currentAction->getLookingPlace() == CAction::E_LP_HDR) {
- extractSubMessage
- (msg,
- currentAction->getLookingChar(),
- msgPart,
- currentAction->getCaseIndep(),
- currentAction->getOccurence(),
- currentAction->getHeadersOnly());
-
- if(strlen(msgPart) > 0) {
-
- scenVariable->executeRegExp(msgPart,
- M_callVariableTable,
- currentId,
- currentAction->getNbSubVarId(),
- currentAction->getSubVarId());
-
- if( (!(M_callVariableTable[currentId]->isSet()))
- && (currentAction->getCheckIt() == true) ) {
- // the message doesn't match and the checkit
- // action say it MUST match
- // Allow easier regexp debugging
- WARNING_P2("Failed regexp match: looking "
- "in '%s', with regexp '%s'",
- msgPart,
- scenVariable->
- getRegularExpression());
- // --> Call will be marked as failed
- return(call::E_AR_REGEXP_DOESNT_MATCH);
- }
- } else {// sub part of message not found
- if( currentAction->getCheckIt() == true ) {
- // the sub message is not found and the
- // checking action say it MUST match
- // --> Call will be marked as failed but
- // will go on
- WARNING_P2("Failed regexp match: header %s not found in message %s\n", currentAction->getLookingChar(), msg);
- return(call::E_AR_HDR_NOT_FOUND);
- }
- }
- } else {// we must look in the entire message
- // WARNING_P1("LOOKING IN MSG -%s-", msg);
- scenVariable->executeRegExp(msg,
- M_callVariableTable,
- currentId,
- currentAction->getNbSubVarId(),
- currentAction->getSubVarId());
- if((!(M_callVariableTable[currentId]->isSet()))
- && (currentAction->getCheckIt() == true) ) {
- // the message doesn't match and the checkit
- // action say it MUST match
- // Allow easier regexp debugging
- WARNING_P2("Failed regexp match: looking in '%s'"
- ", with regexp '%s'",
- msg,
- scenVariable->getRegularExpression());
- // --> rejecting the call
- return(call::E_AR_REGEXP_DOESNT_MATCH);
- }
- }
- } // end if scen variable != null
+ char msgPart[MAX_SUB_MESSAGE_LENGTH];
+
+ /* Where to look. */
+ char *haystack;
+
+ if(currentAction->getLookingPlace() == CAction::E_LP_HDR) {
+ extractSubMessage (msg,
+ currentAction->getLookingChar(),
+ msgPart,
+ currentAction->getCaseIndep(),
+ currentAction->getOccurence(),
+ currentAction->getHeadersOnly());
+ if(currentAction->getCheckIt() == true && (strlen(msgPart) < 0)) {
+ // the sub message is not found and the checking action say it
+ // MUST match --> Call will be marked as failed but will go on
+ WARNING("Failed regexp match: header %s not found in message %s\n", currentAction->getLookingChar(), msg);
+ return(call::E_AR_HDR_NOT_FOUND);
+ }
+ haystack = msgPart;
+ } else {
+ haystack = msg;
+ }
+ currentAction->executeRegExp(haystack, M_callVariableTable);
+
+ if( (!(M_callVariableTable->getVar(currentAction->getVarId())->isSet())) && (currentAction->getCheckIt() == true) ) {
+ // the message doesn't match and the checkit action say it MUST match
+ // Allow easier regexp debugging
+ WARNING("Failed regexp match: looking in '%s', with regexp '%s'",
+ haystack, currentAction->getRegularExpression());
+ return(call::E_AR_REGEXP_DOESNT_MATCH);
+ }
} else /* end action == E_AT_ASSIGN_FROM_REGEXP */
if (currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_VALUE) {
- M_callVariableTable[currentAction->getVarId()]->setDouble(currentAction->getDoubleValue());
+ double operand = get_rhs(currentAction);
+ M_callVariableTable->getVar(currentAction->getVarId())->setDouble(operand);
+ } else if (currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_INDEX) {
+ M_callVariableTable->getVar(currentAction->getVarId())->setDouble(msg_index);
+ } else if (currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_GETTIMEOFDAY) {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ M_callVariableTable->getVar(currentAction->getVarId())->setDouble((double)tv.tv_sec);
+ M_callVariableTable->getVar(currentAction->getSubVarId(0))->setDouble((double)tv.tv_usec);
+ } else if (currentAction->getActionType() == CAction::E_AT_LOOKUP) {
+ /* Create strings from the sending messages. */
+ char *file = strdup(createSendingMessage(currentAction->getMessage(0), -2));
+ char *key = strdup(createSendingMessage(currentAction->getMessage(1), -2));
+ double value = -1;
+
+ str_int_map::iterator index_it = infIndex[file]->find(key);
+ if (index_it != infIndex[file]->end()) {
+ value = index_it->second;
+ }
+ M_callVariableTable->getVar(currentAction->getVarId())->setDouble(value);
+ free(file);
+ free(key);
+#ifdef _USE_OPENSSL
+ } else if (currentAction->getActionType() == CAction::E_AT_VERIFY_AUTH) {
+ bool result;
+ char *lf;
+ char *end;
+
+ lf = strchr(msg, '\n');
+ end = strchr(msg, ' ');
+
+ if (!lf || !end) {
+ result = false;
+ } else if (lf < end) {
+ result = false;
+ } else {
+ char *auth = get_header(msg, "Authorization:", true);
+ char *method = (char *)malloc(end - msg + 1);
+ strncpy(method, msg, end - msg);
+ method[end - msg] = '\0';
+
+ /* Generate the username to verify it against. */
+ char *tmp = createSendingMessage(currentAction->getMessage(0), -2 /* do not add crlf*/);
+ char *username = strdup(tmp);
+ /* Generate the password to verify it against. */
+ tmp= createSendingMessage(currentAction->getMessage(1), -2 /* do not add crlf*/);
+ char *password = strdup(tmp);
+
+ result = verifyAuthHeader(username, password, method, auth);
+
+ free(username);
+ free(password);
+ }
+
+ M_callVariableTable->getVar(currentAction->getVarId())->setBool(result);
+#endif
+ } else if (currentAction->getActionType() == CAction::E_AT_JUMP) {
+ double operand = get_rhs(currentAction);
+ msg_index = (int)operand - 1;
+ } else if (currentAction->getActionType() == CAction::E_AT_PAUSE_RESTORE) {
+ double operand = get_rhs(currentAction);
+ paused_until = (int)operand;
} else if (currentAction->getActionType() == CAction::E_AT_VAR_ADD) {
- double value = M_callVariableTable[currentAction->getVarId()]->getDouble();
+ double value = M_callVariableTable->getVar(currentAction->getVarId())->getDouble();
double operand = get_rhs(currentAction);
- M_callVariableTable[currentAction->getVarId()]->setDouble(value + operand);
+ M_callVariableTable->getVar(currentAction->getVarId())->setDouble(value + operand);
} else if (currentAction->getActionType() == CAction::E_AT_VAR_SUBTRACT) {
- double value = M_callVariableTable[currentAction->getVarId()]->getDouble();
+ double value = M_callVariableTable->getVar(currentAction->getVarId())->getDouble();
double operand = get_rhs(currentAction);
- M_callVariableTable[currentAction->getVarId()]->setDouble(value - operand);
+ M_callVariableTable->getVar(currentAction->getVarId())->setDouble(value - operand);
} else if (currentAction->getActionType() == CAction::E_AT_VAR_MULTIPLY) {
- double value = M_callVariableTable[currentAction->getVarId()]->getDouble();
+ double value = M_callVariableTable->getVar(currentAction->getVarId())->getDouble();
double operand = get_rhs(currentAction);
- M_callVariableTable[currentAction->getVarId()]->setDouble(value * operand);
+ M_callVariableTable->getVar(currentAction->getVarId())->setDouble(value * operand);
} else if (currentAction->getActionType() == CAction::E_AT_VAR_DIVIDE) {
- double value = M_callVariableTable[currentAction->getVarId()]->getDouble();
+ double value = M_callVariableTable->getVar(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());
+ WARNING("Action failure: Can not divide by zero ($%d/$%d)!\n", currentAction->getVarId(), currentAction->getVarInId());
} else {
- M_callVariableTable[currentAction->getVarId()]->setDouble(value / operand);
+ M_callVariableTable->getVar(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);
+ M_callVariableTable->getVar(currentAction->getVarId())->setBool(value);
} else if (currentAction->getActionType() == CAction::E_AT_VAR_STRCMP) {
- char *rhs = M_callVariableTable[currentAction->getVarInId()]->getString();
+ char *rhs = M_callVariableTable->getVar(currentAction->getVarInId())->getString();
char *lhs = currentAction->getStringValue();
int value = strcmp(rhs, lhs);
- M_callVariableTable[currentAction->getVarId()]->setDouble((double)value);
+ M_callVariableTable->getVar(currentAction->getVarId())->setDouble((double)value);
+ } else if (currentAction->getActionType() == CAction::E_AT_VAR_TRIM) {
+ CCallVariable *var = M_callVariableTable->getVar(currentAction->getVarId());
+ char *in = var->getString();
+ char *p = in;
+ while (isspace(*p)) {
+ p++;
+ }
+ char *q = strdup(p);
+ var->setString(q);
+ int l = strlen(q);
+ for (int i = l - 1; i >= 0 & isspace(q[i]); i--) {
+ q[i] = '\0';
+ }
} 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);
+ if (M_callVariableTable->getVar(currentAction->getVarInId())->toDouble(&value)) {
+ M_callVariableTable->getVar(currentAction->getVarId())->setDouble(value);
} else {
- WARNING_P2("Invalid double conversion from $%d to $%d", currentAction->getVarInId(), currentAction->getVarId());
+ WARNING("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);
+ M_callVariableTable->getVar(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* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/);
char *str = strdup(x);
if (!str) {
ERROR("Out of memory duplicating string for assignment!");
}
- M_callVariableTable[currentAction->getVarId()]->setString(str);
+ M_callVariableTable->getVar(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));
+ char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/);
+ LOG_MSG("%s\n", x);
+ } else if (currentAction->getActionType() == CAction::E_AT_LOG_WARNING) {
+ char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/);
+ WARNING("%s", x);
} else if (currentAction->getActionType() == CAction::E_AT_EXECUTE_CMD) {
if (currentAction->getCmdLine()) {
- char* x = createSendingMessage(currentAction->getCmdLine(), -2 /* do not add crlf*/, true /* skip sanity check. */);
- // TRACE_MSG((s, "Trying to execute [%s]", x));
+ char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/);
+ // TRACE_MSG("Trying to execute [%s]", x);
pid_t l_pid;
switch(l_pid = fork())
{
@@ -3225,7 +3286,7 @@
int ret;
ret = system(x); // second child runs
if(ret == -1) {
- WARNING_P1("system call error for %s",x);
+ WARNING("system call error for %s",x);
}
}
exit(EXIT_OTHER);
@@ -3237,7 +3298,7 @@
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);
+ ERROR("waitpid returns %1d for child %1d",ret,l_pid);
}
}
break;
@@ -3363,39 +3424,54 @@
}
}
-void call::getFieldFromInputFile(const char *fileName, int field, char*& dest)
+void call::getFieldFromInputFile(const char *fileName, int field, SendingMessage *lineMsg, char*& dest)
{
if (inFiles.find(fileName) == inFiles.end()) {
- ERROR_P1("Invalid injection file: %s", fileName);
+ ERROR("Invalid injection file: %s", fileName);
}
int line = (*m_lineNumber)[fileName];
+ if (lineMsg) {
+ char lineBuffer[20];
+ char *endptr;
+ createSendingMessage(lineMsg, -2, lineBuffer, sizeof(lineBuffer));
+ line = (int) strtod(lineBuffer, &endptr);
+ if (*endptr != 0) {
+ ERROR("Invalid line number generated: '%s'", lineBuffer);
+ }
+ if (line > inFiles[fileName]->numLines()) {
+ line = -1;
+ }
+ }
if (line < 0) {
return;
}
dest += inFiles[fileName]->getField(line, field, dest, SIPP_MAX_MSG_SIZE);
}
-int call::checkAutomaticResponseMode(char * P_recv) {
-
- int L_res = 0 ;
+call::T_AutoMode call::checkAutomaticResponseMode(char * P_recv) {
+
+ int L_res = E_AM_DEFAULT ;
if (strcmp(P_recv, "BYE")==0) {
- L_res = 1 ;
+ return E_AM_UNEXP_BYE;
} else if (strcmp(P_recv, "CANCEL") == 0) {
- L_res = 2 ;
+ return E_AM_UNEXP_CANCEL;
} else if (strcmp(P_recv, "PING") == 0) {
- L_res = 3 ;
+ return E_AM_PING;
} else if (((strcmp(P_recv, "INFO") == 0) || (strcmp(P_recv, "NOTIFY") == 0) || (strcmp(P_recv, "UPDATE") == 0))
&& (auto_answer == true)){
- L_res = 4 ;
- }
-
- return (L_res) ;
-
-}
-
-
-bool call::automaticResponseMode(int P_case, char * P_recv)
+ return E_AM_AA;
+ } else {
+ return E_AM_DEFAULT;
+ }
+}
+
+void call::setLastMsg(const char *msg) {
+ last_recv_msg = (char *) realloc(last_recv_msg, strlen(msg) + 1);
+ strcpy(last_recv_msg, msg);
+}
+
+bool call::automaticResponseMode(T_AutoMode P_case, char * P_recv)
{
int res ;
@@ -3403,113 +3479,81 @@
bool last_recv_msg_saved = false;
switch (P_case) {
- case 1: // response for an unexpected BYE
+ case E_AM_UNEXP_BYE: // response for an unexpected BYE
// usage of last_ keywords
last_recv_msg = (char *) realloc(last_recv_msg, strlen(P_recv) + 1);
strcpy(last_recv_msg, P_recv);
// The BYE is unexpected, count it
- scenario[msg_index] -> nb_unexp++;
- if (default_behavior) {
- WARNING_P1("Aborting call on an unexpected BYE for call: %s", (id==NULL)?"none":id);
- sendBuffer(createSendingMessage(
- (char*)"SIP/2.0 200 OK\n"
- "[last_Via:]\n"
- "[last_From:]\n"
- "[last_To:]\n"
- "[last_Call-ID:]\n"
- "[last_CSeq:]\n"
- "Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
- "Content-Length: 0\n\n"
- , -1)) ;
-
-#ifdef __3PCC__
+ call_scenario->messages[msg_index] -> nb_unexp++;
+ if (default_behaviors & DEFAULT_BEHAVIOR_ABORTUNEXP) {
+ WARNING("Aborting call on an unexpected BYE for call: %s", (id==NULL)?"none":id);
+ if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
+ sendBuffer(createSendingMessage(get_default_message("200"), -1));
+ }
+
+ // if twin socket call => reset the other part here
+ if (twinSippSocket && (msg_index > 0)) {
+ res = sendCmdBuffer(createSendingMessage(get_default_message("3pcc_abort"), -1));
+ }
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_UNEXPECTED_MSG);
+ delete this;
+ } else {
+ WARNING("Continuing call on an unexpected BYE for call: %s", (id==NULL)?"none":id);
+ }
+ break ;
+
+ case E_AM_UNEXP_CANCEL: // response for an unexpected cancel
+ // usage of last_ keywords
+ last_recv_msg = (char *) realloc(last_recv_msg, strlen(P_recv) + 1);
+ strcpy(last_recv_msg, P_recv);
+
+ // The CANCEL is unexpected, count it
+ call_scenario->messages[msg_index] -> nb_unexp++;
+ if (default_behaviors & DEFAULT_BEHAVIOR_ABORTUNEXP) {
+ WARNING("Aborting call on an unexpected CANCEL for call: %s", (id==NULL)?"none":id);
+ if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
+ sendBuffer(createSendingMessage(get_default_message("200"), -1));
+ }
+
// 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\n", -1));
- }
-#endif /* __3PCC__ */
- CStat::instance()->computeStat(CStat::E_CALL_FAILED);
- CStat::instance()->computeStat(CStat::E_FAILED_UNEXPECTED_MSG);
- delete_call(id);
+ (createSendingMessage(get_default_message("3pcc_abort"), -1));
+ }
+
+ computeStat(CStat::E_CALL_FAILED);
+ computeStat(CStat::E_FAILED_UNEXPECTED_MSG);
+ delete this;
} else {
- WARNING_P1("Continuing call on an unexpected BYE for call: %s", (id==NULL)?"none":id);
- }
- break ;
-
- case 2: // response for an unexpected cancel
- // usage of last_ keywords
- last_recv_msg = (char *) realloc(last_recv_msg, strlen(P_recv) + 1);
- strcpy(last_recv_msg, P_recv);
-
- // The CANCEL is unexpected, count it
- scenario[msg_index] -> nb_unexp++;
- if (default_behavior) {
- WARNING_P1("Aborting call on an unexpected CANCEL for call: %s", (id==NULL)?"none":id);
- sendBuffer(createSendingMessage(
- (char*)"SIP/2.0 200 OK\n"
- "[last_Via:]\n"
- "[last_From:]\n"
- "[last_To:]\n"
- "[last_Call-ID:]\n"
- "[last_CSeq:]\n"
- "Contact: sip:sipp@[local_ip]:[local_port]\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\n", -1));
- }
-#endif /* __3PCC__ */
-
- CStat::instance()->computeStat(CStat::E_CALL_FAILED);
- CStat::instance()->computeStat(CStat::E_FAILED_UNEXPECTED_MSG);
- delete_call(id);
- } else {
- WARNING_P1("Continuing call on unexpected CANCEL for call: %s", (id==NULL)?"none":id);
+ WARNING("Continuing call on unexpected CANCEL for call: %s", (id==NULL)?"none":id);
}
break ;
- case 3: // response for a random ping
+ case E_AM_PING: // response for a random ping
// usage of last_ keywords
last_recv_msg = (char *) realloc(last_recv_msg, strlen(P_recv) + 1);
strcpy(last_recv_msg, P_recv);
- 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
- 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)) ;
+ if (default_behaviors & DEFAULT_BEHAVIOR_PINGREPLY) {
+ WARNING("Automatic response mode for an unexpected PING for call: %s", (id==NULL)?"none":id);
+ sendBuffer(createSendingMessage(get_default_message("200"), -1));
// Note: the call ends here but it is not marked as bad. PING is a
// normal message.
-#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\n",-1));
- }
-#endif /* __3PCC__ */
+ res = sendCmdBuffer(createSendingMessage(get_default_message("3pcc_abort"), -1));
+ }
- CStat::instance()->computeStat(CStat::E_AUTO_ANSWERED);
- delete_call(id);
+ CStat::globalStat(CStat::E_AUTO_ANSWERED);
+ delete this;
} else {
- WARNING_P1("Do not answer on an unexpected PING for call: %s", (id==NULL)?"none":id);
+ WARNING("Do not answer on an unexpected PING for call: %s", (id==NULL)?"none":id);
}
break ;
- case 4: // response for a random INFO, UPDATE or NOTIFY
+ case E_AM_AA: // response for a random INFO, UPDATE or NOTIFY
// store previous last msg if msg is INFO, UPDATE or NOTIFY
// restore last_recv_msg to previous one
// after sending ok
@@ -3523,17 +3567,8 @@
last_recv_msg = (char *) realloc(last_recv_msg, strlen(P_recv) + 1);
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);
- 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)) ;
+ WARNING("Automatic response mode for an unexpected INFO, UPDATE or NOTIFY for call: %s", (id==NULL)?"none":id);
+ sendBuffer(createSendingMessage(get_default_message("200"), -1));
// restore previous last msg
if (last_recv_msg_saved == true) {
@@ -3544,52 +3579,16 @@
old_last_recv_msg = NULL;
}
}
- CStat::instance()->computeStat(CStat::E_AUTO_ANSWERED);
+ CStat::globalStat(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);
+ ERROR("Internal error for automaticResponseMode - mode %d is not implemented!", P_case);
break ;
}
return false;
-
}
#ifdef PCAPPLAY
Modified: sip-tester/branches/upstream/current/sipp.hpp
URL: http://svn.debian.org/wsvn/pkg-voip/sip-tester/branches/upstream/current/sipp.hpp?rev=6622&op=diff
==============================================================================
--- sip-tester/branches/upstream/current/sipp.hpp (original)
+++ sip-tester/branches/upstream/current/sipp.hpp Sun Jan 4 02:47:02 2009
@@ -45,7 +45,13 @@
#include <vector>
#include <string>
#include <map>
+#include <set>
#include <math.h>
+#ifndef __SUNOS
+#include <curses.h>
+#else
+#include <stdarg.h>
+#endif
#if defined(__HPUX) || defined(__SUNOS)
#include <alloca.h>
@@ -56,6 +62,9 @@
#include "xp_parser.h"
#include "scenario.hpp"
#include "screen.hpp"
+#include "task.hpp"
+#include "listener.hpp"
+#include "socketowner.hpp"
#include "call.hpp"
#include "comp.h"
#include "stat.hpp"
@@ -93,7 +102,16 @@
/************************** Constants **************************/
-#define SIPP_VERSION 20071128
+#ifdef SVN_VERSION
+# ifdef LOCAL_VERSION_EXTRA
+# define SIPP_VERSION SVN_VERSION LOCAL_VERSION_EXTRA
+# else
+# define SIPP_VERSION SVN_VERSION
+# endif
+#else
+# define SIPP_VERSION "unknown"
+#endif
+
#define T_UDP 0
#define T_TCP 1
#define T_TLS 2
@@ -133,13 +151,12 @@
/******************** Default parameters ***********************/
#define DEFAULT_RATE 10.0
+#define DEFAULT_RATE_SCALE 1.0
#define DEFAULT_RATE_PERIOD_MS 1000
#define DEFAULT_TRANSPORT T_UDP
#define DEFAULT_PORT 5060
#define DEFAULT_MEDIA_PORT 6000
-#ifdef __3PCC__
#define DEFAULT_3PCC_PORT 6060
-#endif
#define DEFAULT_SERVICE ((char *)"service")
#define DEFAULT_AUTH_PASSWORD ((char *)"password")
#define DEFAULT_REPORT_FREQ 1000
@@ -148,14 +165,24 @@
#define DEFAULT_FREQ_DUMP_RTT 200
#define DEFAULT_MAX_MULTI_SOCKET 50000
#define DEFAULT_CTRL_SOCKET_PORT 8888
+#define DEFAULT_DEADCALL_WAIT 33000
+
+#define DEFAULT_BEHAVIOR_NONE 0
+#define DEFAULT_BEHAVIOR_BYE 1
+#define DEFAULT_BEHAVIOR_ABORTUNEXP 2
+#define DEFAULT_BEHAVIOR_PINGREPLY 4
+
+#define DEFAULT_BEHAVIOR_ALL (DEFAULT_BEHAVIOR_BYE | DEFAULT_BEHAVIOR_ABORTUNEXP | DEFAULT_BEHAVIOR_PINGREPLY)
/************ User controls and command line options ***********/
extern int duration _DEFVAL(0);
extern double rate _DEFVAL(DEFAULT_RATE);
+extern double rate_scale _DEFVAL(DEFAULT_RATE_SCALE);
extern int rate_increase _DEFVAL(0);
extern int rate_max _DEFVAL(0);
-extern int users _DEFVAL(0);
+extern bool rate_quit _DEFVAL(true);
+extern int users _DEFVAL(-1);
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);
@@ -165,7 +192,8 @@
extern int max_udp_retrans _DEFVAL(UDP_MAX_RETRANS);
extern int max_invite_retrans _DEFVAL(UDP_MAX_RETRANS_INVITE_TRANSACTION);
extern int max_non_invite_retrans _DEFVAL(UDP_MAX_RETRANS_NON_INVITE_TRANSACTION);
-extern bool default_behavior _DEFVAL(1);
+extern unsigned long default_behaviors _DEFVAL(DEFAULT_BEHAVIOR_ALL);
+extern unsigned long deadcall_wait _DEFVAL(DEFAULT_DEADCALL_WAIT);
extern bool pause_msg_ign _DEFVAL(0);
extern int auto_answer _DEFVAL(0);
extern int multisocket _DEFVAL(0);
@@ -179,6 +207,7 @@
extern unsigned long report_freq _DEFVAL(DEFAULT_REPORT_FREQ);
extern unsigned long report_freq_dumpLog _DEFVAL
(DEFAULT_REPORT_FREQ_DUMP_LOG);
+extern bool periodic_rtd _DEFVAL(false);
extern char * stat_delimiter _DEFVAL(";");
extern bool timeout_exit _DEFVAL(false);
@@ -188,6 +217,7 @@
extern unsigned int max_multi_socket _DEFVAL
(DEFAULT_MAX_MULTI_SOCKET);
+extern bool skip_rlimit _DEFVAL(false);
extern unsigned int timer_resolution _DEFVAL(DEFAULT_TIMER_RESOLUTION);
extern int max_recv_loops _DEFVAL(MAX_RECV_LOOPS_PER_CYCLE);
@@ -197,6 +227,7 @@
extern char local_ip_escaped[42];
extern bool local_ip_is_ipv6;
extern int local_port _DEFVAL(0);
+extern char control_ip[40];
extern int control_port _DEFVAL(0);
extern int buff_size _DEFVAL(65535);
extern int tcp_readsize _DEFVAL(65535);
@@ -222,7 +253,6 @@
extern int lose_packets _DEFVAL(0);
extern double global_lost _DEFVAL(0.0);
extern char remote_host[255];
-#ifdef __3PCC__
extern char twinSippHost[255];
extern char twinSippIp[40];
extern char * master_name;
@@ -230,8 +260,8 @@
extern int twinSippPort _DEFVAL(DEFAULT_3PCC_PORT);
extern bool twinSippMode _DEFVAL(false);
extern bool extendedTwinSippMode _DEFVAL(false);
-#endif
-
+
+extern bool nostdin _DEFVAL(false);
extern bool backgroundMode _DEFVAL(false);
extern bool signalDump _DEFVAL(false);
@@ -266,11 +296,18 @@
// extern field file management
typedef std::map<string, FileContents *> file_map;
extern file_map inFiles;
+typedef std::map<string, str_int_map *> file_index;
+extern file_index infIndex;
extern char *ip_file _DEFVAL(NULL);
extern char *default_file _DEFVAL(NULL);
// free user id list
extern list<int> freeUsers;
+extern list<int> retiredUsers;
+extern AllocVariableTable *globalVariables _DEFVAL(NULL);
+extern AllocVariableTable *userVariables _DEFVAL(NULL);
+typedef std::map<int, VariableTable *> int_vt_map;
+extern int_vt_map userVarMap;
//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);
@@ -278,6 +315,7 @@
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 int sipp_reconnect_socket(struct sipp_socket *socket);
extern void sipp_customize_socket(struct sipp_socket *socket);
extern int delete_socket(int P_socket);
extern int min_socket _DEFVAL(65535);
@@ -291,17 +329,13 @@
/************************ Statistics **************************/
-extern unsigned long total_calls _DEFVAL(0);
extern unsigned long last_report_calls _DEFVAL(0);
extern unsigned long nb_net_send_errors _DEFVAL(0);
extern unsigned long nb_net_cong _DEFVAL(0);
extern unsigned long nb_net_recv_errors _DEFVAL(0);
extern bool cpu_max _DEFVAL(false);
extern bool outbound_congestion _DEFVAL(false);
-extern unsigned int open_calls_peak _DEFVAL(0);
-extern unsigned long open_calls_peak_time _DEFVAL(0);
extern int open_calls_user_setting _DEFVAL(0);
-extern int nb_out_of_the_blue _DEFVAL(0);
extern int resynch_send _DEFVAL(0);
extern int resynch_recv _DEFVAL(0);
extern unsigned long rtp_pckts _DEFVAL(0);
@@ -315,7 +349,6 @@
/************* Rate Control & Contexts variables **************/
-extern unsigned int open_calls _DEFVAL(0);
extern int last_running_calls _DEFVAL(0);
extern int last_woken_calls _DEFVAL(0);
extern int last_paused_calls _DEFVAL(0);
@@ -323,7 +356,6 @@
extern unsigned long last_rate_change_time _DEFVAL(0);
extern unsigned long last_report_time _DEFVAL(0);
extern unsigned long last_dump_time _DEFVAL(0);
-extern unsigned long calls_since_last_rate_change _DEFVAL(0);
/********************** Clock variables ***********************/
@@ -349,10 +381,13 @@
extern int user_port _DEFVAL(0);
extern char hostname[80];
extern bool is_ipv6 _DEFVAL(false);
-extern int start_calls _DEFVAL(0);
+
extern int reset_number _DEFVAL(0);
extern int reset_close _DEFVAL(1);
extern int reset_sleep _DEFVAL(1000);
+extern bool sendbuffer_warn _DEFVAL(false);
+/* A list of sockets pending reset. */
+extern set<struct sipp_socket *> sockets_pending_reset;
extern struct addrinfo * local_addr_storage;
@@ -395,54 +430,36 @@
extern FILE * logfile _DEFVAL(0);
extern FILE * messagef _DEFVAL(0);
extern FILE * shortmessagef _DEFVAL(0);
+extern FILE * countf _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);
+// should we overwrite the existing files?
+extern bool messagef_overwrite _DEFVAL(true);
+extern bool shortmessagef_overwrite _DEFVAL(true);
+extern bool errorf_overwrite _DEFVAL(true);
+extern bool logfile_overwrite _DEFVAL(true);
//extern bool useTimeoutf _DEFVAL(0);
extern bool dumpInFile _DEFVAL(0);
extern bool dumpInRtt _DEFVAL(0);
+extern bool useCountf _DEFVAL(0);
extern char * scenario_file;
extern char * slave_cfg_file;
-#define TRACE_MSG(arg) \
-{ \
- if(messagef) { \
- FILE * s = messagef; \
- fprintf arg; \
- fflush(messagef); \
- } \
-}
-
-#define TRACE_SHORTMSG(arg) \
-{ \
- if(shortmessagef) { \
- FILE * s = shortmessagef;\
- fprintf arg; \
- fflush(shortmessagef); \
- } \
-}
-
-#define LOG_MSG(arg) \
-{ \
- if(logfile) { \
- FILE * s = logfile; \
- fprintf arg; \
- fflush(logfile); \
- } \
-}
-
-// TODO: finish the -trace_timeout option implementation
-
-/* #define TRACE_TIMEOUT(arg) \
-{ \
- if(timeoutf) { \
- FILE * s = timeoutf; \
- fprintf arg; \
- fflush(timeoutf); \
- } \
-} */
+extern unsigned long long max_log_size _DEFVAL(0);
+extern unsigned long long ringbuffer_size _DEFVAL(0);
+extern int ringbuffer_files _DEFVAL(0);
+
+extern char screen_last_error[32768];
+extern char screen_logfile[MAX_PATH] _DEFVAL("");
+extern FILE * screen_errorf _DEFVAL(NULL);
+
+void rotate_messagef();
+void rotate_shortmessagef();
+void rotate_logfile();
+void rotate_errorf();
/********************* Mini-Parser Routines *******************/
@@ -471,6 +488,7 @@
char *buf;
size_t len;
size_t offset;
+ struct sockaddr_storage addr;
struct socketbuf *next;
};
@@ -491,6 +509,7 @@
BIO *ss_bio; /* The underlying BIO descriptor for this socket. */
#endif
struct sockaddr_storage ss_remote_sockaddr; /* Who we are talking to. */
+ struct sockaddr_storage ss_dest; /* Who we are talking to. */
int ss_pollidx; /* The index of this socket in our poll structures. */
@@ -503,7 +522,7 @@
};
/* Write data to a socket. */
-int write_socket(struct sipp_socket *socket, char *buffer, ssize_t len, int flags);
+int write_socket(struct sipp_socket *socket, char *buffer, ssize_t len, int flags, struct sockaddr_storage *dest);
/* Mark a socket as "bad". */
void sipp_socket_invalidate(struct sipp_socket *socket);
/* Actually free the socket. */
@@ -535,9 +554,9 @@
char *get_peer_addr(char *);
int get_decimal_from_hex(char hex);
-int reset_connections() ;
-int close_calls();
-int close_calls(struct sipp_socket *);
+bool reconnect_allowed();
+void reset_connection(struct sipp_socket *);
+void close_calls(struct sipp_socket *);
int close_connections();
int open_connections();
void timeout_alarm(int);
@@ -559,4 +578,15 @@
#undef extern
#endif
+/* THis must go after the GLOBALS_FULL_DEFINITION, because we need the extern keyword. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+int TRACE_MSG(char *fmt, ...);
+int TRACE_SHORTMSG(char *fmt, ...);
+int LOG_MSG(char *fmt, ...);
+#ifdef __cplusplus
+}
+#endif
+
#endif // __SIPP__
More information about the Pkg-voip-commits
mailing list