Imported Upstream version 3.3 debian upstream upstream/3.3
authorDevon Kearns <dookie@kali.org>
Sat, 29 Dec 2012 13:48:32 +0000 (06:48 -0700)
committerDevon Kearns <dookie@kali.org>
Sat, 29 Dec 2012 13:48:32 +0000 (06:48 -0700)
157 files changed:
.svn/entries [new file with mode: 0644]
.svn/format [new file with mode: 0644]
.svn/pristine/02/02893a884faf4d5a1df45f2c319b224df77d8419.svn-base [new file with mode: 0644]
.svn/pristine/0a/0aaf683e77811cb843db05fedf0a872a584909cd.svn-base [new file with mode: 0644]
.svn/pristine/0b/0b8b4f1cb5bacdf3e675fd5d5051c27dd761cf67.svn-base [new file with mode: 0644]
.svn/pristine/10/100c365defacbefaeda173fe46245b8598f60d0c.svn-base [new file with mode: 0644]
.svn/pristine/10/10bf87b898627aae081ffd5921d6cef530858f1b.svn-base [new file with mode: 0644]
.svn/pristine/13/13e8578621505a8052ecc535d648e74ba902aa89.svn-base [new file with mode: 0644]
.svn/pristine/15/155bc6dc48ca304c64623e236eb973e81cd22160.svn-base [new file with mode: 0644]
.svn/pristine/19/191294568b803c2c0f6052cb28cb6fc47b1abfe2.svn-base [new file with mode: 0644]
.svn/pristine/1a/1a3e6d9755b1ab3af8f467169f1a45883318b4b7.svn-base [new file with mode: 0644]
.svn/pristine/1a/1a9e747748578ee6e80f36e0872728f99f13e96a.svn-base [new file with mode: 0644]
.svn/pristine/1d/1d1031ec6d2ea227dd27301dfbba52c309470380.svn-base [new file with mode: 0644]
.svn/pristine/1e/1e8c026bba4efe969be5f1245e5a3bbaf72b5c32.svn-base [new file with mode: 0644]
.svn/pristine/20/20ae0b6f9bff8bfc53ec4ed44a5235fe5d4d5acd.svn-base [new file with mode: 0644]
.svn/pristine/23/23b51a463d005c6a70c78a3d9bb1f1ec916638bc.svn-base [new file with mode: 0644]
.svn/pristine/24/24e5b54ca002bf58b50c4cfe5b1b4e07cdce3551.svn-base [new file with mode: 0644]
.svn/pristine/25/25d87e38c5d28b8334e23ee497204a6af30802be.svn-base [new file with mode: 0644]
.svn/pristine/25/25e936df1456a85f68f9119ce5412c3638d9c28f.svn-base [new file with mode: 0644]
.svn/pristine/26/265b602d3b19c124e701acb19b0f7ed841dc7f8f.svn-base [new file with mode: 0644]
.svn/pristine/27/2783dae16b735021061dca8c09b45da224b7188e.svn-base [new file with mode: 0644]
.svn/pristine/2b/2bafa06fe2558f7ec7b0943b8342a1388fc612a6.svn-base [new file with mode: 0644]
.svn/pristine/38/382515f67b48271ff1e05467f92b1555ffca47d5.svn-base [new file with mode: 0644]
.svn/pristine/39/3946511838b77bab13ff4badbb3194b7b280b102.svn-base [new file with mode: 0644]
.svn/pristine/3a/3a257ab799a75b5ab8f4e884c9f0a2673e570c63.svn-base [new file with mode: 0644]
.svn/pristine/3a/3a9e2ec8fa7d24e99b2ed8675c9bfbd5d5ad042a.svn-base [new file with mode: 0644]
.svn/pristine/3b/3b18f05aa9e78ad4885f19e22504323d86bc4950.svn-base [new file with mode: 0644]
.svn/pristine/3d/3dab738c05f1c9ec39ad6e4f1fc7190e3fde0959.svn-base [new file with mode: 0644]
.svn/pristine/43/430b398faa305fcc0fe37911a11c68d7e93aa89a.svn-base [new file with mode: 0644]
.svn/pristine/48/486edbaf0d6fed69d275b8e77a1e361e2cfa4104.svn-base [new file with mode: 0644]
.svn/pristine/4b/4b6b29037c03d08413a3361b345d383bd0e42074.svn-base [new file with mode: 0644]
.svn/pristine/5a/5af40a52720390135fcd52d3f50e2adcbaf40783.svn-base [new file with mode: 0644]
.svn/pristine/62/625343b3630ca1d2096532008068511b9bed7e0b.svn-base [new file with mode: 0644]
.svn/pristine/69/6995438b54fe1f4c76dbed117ff31da5a38b6443.svn-base [new file with mode: 0644]
.svn/pristine/6a/6a09a552b075722ae227226b724b7ad4f58d2251.svn-base [new file with mode: 0644]
.svn/pristine/6d/6d3671023710b3e2668472dd7fc9e51707dd26bd.svn-base [new file with mode: 0644]
.svn/pristine/75/75a5d9264f03b354aba0c6ef88bbad74421ba1c6.svn-base [new file with mode: 0644]
.svn/pristine/7d/7df67e2a4e0db2e6cf0c7c91b383f7428e5ef2eb.svn-base [new file with mode: 0644]
.svn/pristine/81/81c8ec22f2ca8b22b9c9e7e19efae2ac56502dc8.svn-base [new file with mode: 0644]
.svn/pristine/87/87acbbbec48609aea78c13697ad1a3c932d38809.svn-base [new file with mode: 0644]
.svn/pristine/8a/8a0b61545a9a5e43611e46f28ebe66ef589ad477.svn-base [new file with mode: 0644]
.svn/pristine/8d/8d2cdfa4ab6e34390f7702693ce1a63474870476.svn-base [new file with mode: 0644]
.svn/pristine/8e/8e30f75c3776b8c51ae72c3f3f7363aea2980a78.svn-base [new file with mode: 0644]
.svn/pristine/90/901018780d52b4e1d232d27196f025908c050ef4.svn-base [new file with mode: 0644]
.svn/pristine/91/91ba91537ae28893e08616de5c6da0f430ae0bb5.svn-base [new file with mode: 0644]
.svn/pristine/91/91e4a83e1b2afb30d6710ac7c33e12850c29755d.svn-base [new file with mode: 0644]
.svn/pristine/9d/9d11951dac5e34b930ec8e49025eab452f8d6b7e.svn-base [new file with mode: 0644]
.svn/pristine/9d/9dc51d34eb64c5ba564b94cc0e58e55ae6899e6d.svn-base [new file with mode: 0644]
.svn/pristine/9e/9edc14025f401352bab3d2b03842beecb12cf2c8.svn-base [new file with mode: 0644]
.svn/pristine/9f/9f013c812ee8f7cd3c2178e9b4ff894e61797243.svn-base [new file with mode: 0644]
.svn/pristine/a0/a069afc1547f56e3788ede91368b1bcd3a9fdd6c.svn-base [new file with mode: 0644]
.svn/pristine/a4/a44a1e45a0009362badcc1c3c943a62eca57fc65.svn-base [new file with mode: 0644]
.svn/pristine/a4/a4b86d0c07dc784cb4e918e638e4fa8101813d7f.svn-base [new file with mode: 0644]
.svn/pristine/a5/a59b84435af1093de224420413e013871c590a7d.svn-base [new file with mode: 0644]
.svn/pristine/a8/a883012bdc4dc29913a8c3a3e3398c1c47841ff4.svn-base [new file with mode: 0644]
.svn/pristine/ac/ac3284d5473cb0dcc66df587a0d96449d6567757.svn-base [new file with mode: 0644]
.svn/pristine/ad/add6a3c235857d7738dd00b19bde3489e61fe587.svn-base [new file with mode: 0644]
.svn/pristine/af/afd1de4a843746a32a1027e4e2fe5db48412d5aa.svn-base [new file with mode: 0644]
.svn/pristine/b0/b061db5633387dc0326420d53bbe441871594ec1.svn-base [new file with mode: 0644]
.svn/pristine/b3/b32b59f27627155414488ba44b52d8c29dc63fe1.svn-base [new file with mode: 0644]
.svn/pristine/c1/c17529654ea8f8030f82199317d6dc96c164da4e.svn-base [new file with mode: 0644]
.svn/pristine/c2/c2b99d17fe15d6da6dab8b59f794638d4316056d.svn-base [new file with mode: 0644]
.svn/pristine/c7/c78566832feff9f5f421c2855761859e6e4a0565.svn-base [new file with mode: 0644]
.svn/pristine/cc/cc326530f11cc5f886cb73282f46be641d7a0646.svn-base [new file with mode: 0644]
.svn/pristine/ce/cef5b36a4dd89491fc9f9933ac1cc6fe95b6370c.svn-base [new file with mode: 0644]
.svn/pristine/cf/cfc85a0c76f1d21276d66742ba50162311f728c0.svn-base [new file with mode: 0644]
.svn/pristine/d2/d219a36d80aea6867e0b39afc2a3c4f042f0db5d.svn-base [new file with mode: 0644]
.svn/pristine/d4/d48aecce153974abae8a9347c0c4ace830e9dada.svn-base [new file with mode: 0644]
.svn/pristine/da/da65cd32944d3f7cc636541911a6f14d4a542bd3.svn-base [new file with mode: 0644]
.svn/pristine/df/df25a21fa005bd74d1d5a8edfe0cb1bb3b02787b.svn-base [new file with mode: 0644]
.svn/pristine/e3/e32d17238333aba7fa479add3af2bc9dbd5814a1.svn-base [new file with mode: 0644]
.svn/pristine/e5/e58c10ecbe5e18e741260b3a1f9c15bad54b4fea.svn-base [new file with mode: 0644]
.svn/pristine/e5/e5a4d49fedad0344fccc4529f33f5775e2b84c0e.svn-base [new file with mode: 0644]
.svn/pristine/ea/ea6f93fe49fb4ee4e3f779de2d993d98f48b55d7.svn-base [new file with mode: 0644]
.svn/pristine/ef/eff59a44cf610c80dfec2f551b693e80ff1606c5.svn-base [new file with mode: 0644]
.svn/pristine/fb/fb1b7ba52214dd82d64e35a984a4e52fcc060766.svn-base [new file with mode: 0644]
.svn/pristine/fc/fc5093463168a2452314441cb7b32e0ee426cbaa.svn-base [new file with mode: 0644]
.svn/pristine/fd/fd8847e11d44ba15f8c40106024c657570ff7800.svn-base [new file with mode: 0644]
.svn/pristine/fd/fdd921899cde84b19a9836b4ccc0eb5cd6c11513.svn-base [new file with mode: 0644]
.svn/wc.db [new file with mode: 0644]
LICENSE.txt [new file with mode: 0644]
MEDIA.txt [new file with mode: 0644]
Makefile [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
README.txt [new file with mode: 0644]
THANKS [new file with mode: 0644]
actions.cpp [new file with mode: 0644]
actions.hpp [new file with mode: 0644]
auth.c [new file with mode: 0644]
call.cpp [new file with mode: 0644]
call.hpp [new file with mode: 0644]
comp.c [new file with mode: 0644]
comp.h [new file with mode: 0644]
configure.ac [new file with mode: 0644]
deadcall.cpp [new file with mode: 0644]
deadcall.hpp [new file with mode: 0644]
fortune.cpp [new file with mode: 0644]
infile.cpp [new file with mode: 0644]
infile.hpp [new file with mode: 0644]
listener.cpp [new file with mode: 0644]
listener.hpp [new file with mode: 0644]
local.mk [new file with mode: 0644]
md5.c [new file with mode: 0644]
md5.h [new file with mode: 0644]
message.cpp [new file with mode: 0644]
message.hpp [new file with mode: 0644]
milenage.c [new file with mode: 0644]
milenage.h [new file with mode: 0644]
opentask.cpp [new file with mode: 0644]
opentask.hpp [new file with mode: 0644]
pcap/dtmf_2833_0.pcap [new file with mode: 0644]
pcap/dtmf_2833_1.pcap [new file with mode: 0644]
pcap/dtmf_2833_2.pcap [new file with mode: 0644]
pcap/dtmf_2833_3.pcap [new file with mode: 0644]
pcap/dtmf_2833_4.pcap [new file with mode: 0644]
pcap/dtmf_2833_5.pcap [new file with mode: 0644]
pcap/dtmf_2833_6.pcap [new file with mode: 0644]
pcap/dtmf_2833_7.pcap [new file with mode: 0644]
pcap/dtmf_2833_8.pcap [new file with mode: 0644]
pcap/dtmf_2833_9.pcap [new file with mode: 0644]
pcap/dtmf_2833_pound.pcap [new file with mode: 0644]
pcap/dtmf_2833_star.pcap [new file with mode: 0644]
pcap/g711a.pcap [new file with mode: 0644]
prepare_pcap.c [new file with mode: 0644]
prepare_pcap.h [new file with mode: 0644]
reporttask.cpp [new file with mode: 0644]
reporttask.hpp [new file with mode: 0644]
rijndael.c [new file with mode: 0644]
rijndael.h [new file with mode: 0644]
scenario.cpp [new file with mode: 0644]
scenario.hpp [new file with mode: 0644]
screen.cpp [new file with mode: 0644]
screen.hpp [new file with mode: 0644]
send_packets.c [new file with mode: 0644]
send_packets.h [new file with mode: 0644]
sipp.cpp [new file with mode: 0644]
sipp.dtd [new file with mode: 0644]
sipp.hpp [new file with mode: 0644]
socketowner.cpp [new file with mode: 0644]
socketowner.hpp [new file with mode: 0644]
sslcommon.h [new file with mode: 0644]
sslinit.c [new file with mode: 0644]
sslthreadsafe.c [new file with mode: 0644]
stat.cpp [new file with mode: 0644]
stat.hpp [new file with mode: 0644]
task.cpp [new file with mode: 0644]
task.hpp [new file with mode: 0644]
tools/monitor/README.txt [new file with mode: 0644]
tools/monitor/auto_script [new file with mode: 0755]
tools/monitor/fullcsv [new file with mode: 0755]
tools/monitor/snmparser [new file with mode: 0755]
variables.cpp [new file with mode: 0644]
variables.hpp [new file with mode: 0644]
watchdog.cpp [new file with mode: 0644]
watchdog.hpp [new file with mode: 0644]
xp_parser.c [new file with mode: 0644]
xp_parser.h [new file with mode: 0644]

diff --git a/.svn/entries b/.svn/entries
new file mode 100644 (file)
index 0000000..48082f7
--- /dev/null
@@ -0,0 +1 @@
+12
diff --git a/.svn/format b/.svn/format
new file mode 100644 (file)
index 0000000..48082f7
--- /dev/null
@@ -0,0 +1 @@
+12
diff --git a/.svn/pristine/02/02893a884faf4d5a1df45f2c319b224df77d8419.svn-base b/.svn/pristine/02/02893a884faf4d5a1df45f2c319b224df77d8419.svn-base
new file mode 100644 (file)
index 0000000..1620036
--- /dev/null
@@ -0,0 +1,6281 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Author : Richard GAYRAUD - 04 Nov 2003
+ *           Marc LAMBERTON
+ *           Olivier JACQUES
+ *           Herve PELLAN
+ *           David MANSUTTI
+ *           Francois-Xavier Kowalski
+ *           Gerard Lyonnaz
+ *           Francois Draperi (for dynamic_id)
+ *           From Hewlett Packard Company.
+ *           F. Tarek Rogers
+ *           Peter Higginson
+ *           Vincent Luba
+ *           Shriram Natarajan
+ *           Guillaume Teissier from FTR&D
+ *           Clement Chen
+ *           Wolfgang Beck
+ *           Charles P Wright from IBM Research
+ *           Martin Van Leeuwen
+ *           Andy Aicken
+ *          Michael Hirschbichler
+ */
+
+#define GLOBALS_FULL_DEFINITION
+
+#include <dlfcn.h>
+#include "sipp.hpp"
+#include "assert.h"
+
+void sipp_usleep(unsigned long usec);
+
+void rotate_messagef();
+void rotate_calldebugf();
+void rotate_shortmessagef();
+void rotate_logfile();
+
+#ifdef _USE_OPENSSL
+SSL_CTX  *sip_trp_ssl_ctx = NULL; /* For SSL cserver context */
+SSL_CTX  *sip_trp_ssl_ctx_client = NULL; /* For SSL cserver context */
+SSL_CTX  *twinSipp_sip_trp_ssl_ctx_client = NULL; /* For SSL cserver context */
+
+enum ssl_init_status {
+  SSL_INIT_NORMAL, /* 0   Normal completion    */
+  SSL_INIT_ERROR   /* 1   Unspecified error    */
+};
+
+#define CALL_BACK_USER_DATA "ksgr"
+
+int passwd_call_back_routine(char  *buf , int size , int flag, void *passwd)
+{
+  strncpy(buf, (char *)(passwd), size);
+  buf[size - 1] = '\0';
+  return(strlen(buf));
+}
+#endif
+
+bool do_hide = true;
+bool show_index = false;
+
+static struct sipp_socket *sipp_allocate_socket(bool use_ipv6, int transport, int fd, int accepting);
+struct sipp_socket *ctrl_socket = NULL;
+struct sipp_socket *stdin_socket = NULL;
+
+int command_mode = 0;
+char *command_buffer = NULL;
+
+/* These could be local to main, but for the option processing table. */
+static int argiFileName;
+
+/***************** Option Handling Table *****************/
+struct sipp_option {
+       const char *option;
+       const char *help;
+       int type;
+       void *data;
+       /* Pass 0: Help and other options that should exit immediately. */
+       /* Pass 1: All other options. */
+       /* Pass 2: Scenario parsing. */
+       int pass;
+};
+
+#define SIPP_OPTION_HELP          1
+#define SIPP_OPTION_INT                   2
+#define SIPP_OPTION_SETFLAG       3
+#define SIPP_OPTION_UNSETFLAG     4
+#define SIPP_OPTION_STRING        5
+#define SIPP_OPTION_ARGI          6
+#define SIPP_OPTION_TIME_SEC      7
+#define SIPP_OPTION_FLOAT         8
+#define SIPP_OPTION_BOOL         10 
+#define SIPP_OPTION_VERSION      11
+#define SIPP_OPTION_TRANSPORT    12
+#define SIPP_OPTION_NEED_SSL     13
+#define SIPP_OPTION_IP           14
+#define SIPP_OPTION_MAX_SOCKET   15
+#define SIPP_OPTION_CSEQ         16
+#define SIPP_OPTION_SCENARIO     17
+#define SIPP_OPTION_RSA                  18
+#define SIPP_OPTION_LIMIT        19
+#define SIPP_OPTION_USERS        20
+#define SIPP_OPTION_KEY                  21
+#define SIPP_OPTION_3PCC         22
+#define SIPP_OPTION_TDMMAP       23
+#define SIPP_OPTION_TIME_MS      24
+#define SIPP_OPTION_SLAVE_CFG     25
+#define SIPP_OPTION_3PCC_EXTENDED 26
+#define SIPP_OPTION_INPUT_FILE   27
+#define SIPP_OPTION_TIME_MS_LONG  28
+#define SIPP_OPTION_LONG          29
+#define SIPP_OPTION_LONG_LONG     30
+#define SIPP_OPTION_DEFAULTS      31
+#define SIPP_OPTION_OOC_SCENARIO  32
+#define SIPP_OPTION_INDEX_FILE    33
+#define SIPP_OPTION_VAR                  34
+#define SIPP_OPTION_RTCHECK      35
+#define SIPP_OPTION_LFNAME       36
+#define SIPP_OPTION_LFOVERWRITE          37
+#define SIPP_OPTION_PLUGIN       38
+#define SIPP_OPTION_NEED_SCTP    39
+
+/* Put Each option, its help text, and type in this table. */
+struct sipp_option options_table[] = {
+       {"v", "Display version and copyright information.", SIPP_OPTION_VERSION, NULL, 0},
+
+       {"h", NULL, SIPP_OPTION_HELP, NULL, 0},
+       {"help", NULL, SIPP_OPTION_HELP, NULL, 0},
+
+       {"aa", "Enable automatic 200 OK answer for INFO, UPDATE and NOTIFY messages.", SIPP_OPTION_SETFLAG, &auto_answer, 1},
+       {"auth_uri", "Force the value of the URI for authentication.\n"
+                     "By default, the URI is composed of remote_ip:remote_port.", SIPP_OPTION_STRING, &auth_uri, 1},
+    {"au", "Set authorization username for authentication challenges. Default is taken from -s argument", SIPP_OPTION_STRING, &auth_username, 1},
+       {"ap", "Set the password for authentication challenges. Default is 'password'", SIPP_OPTION_STRING, &auth_password, 1},
+       {"base_cseq", "Start value of [cseq] for each call.", SIPP_OPTION_CSEQ, NULL, 1},
+       {"bg", "Launch SIPp in background mode.", SIPP_OPTION_SETFLAG, &backgroundMode, 1},
+       {"bind_local", "Bind socket to local IP address, i.e. the local IP address is used as the source IP address.  If SIPp runs in server mode it will only listen on the local IP address instead of all IP addresses.", SIPP_OPTION_SETFLAG, &bind_local, 1},
+       {"buff_size", "Set the send and receive buffer size.", SIPP_OPTION_INT, &buff_size, 1},
+
+       {"calldebug_file", "Set the name of the call debug file.", SIPP_OPTION_LFNAME, &calldebug_lfi, 1},
+       {"calldebug_overwrite", "Overwrite the call debug file (default true).", SIPP_OPTION_LFOVERWRITE, &calldebug_lfi, 1},
+
+       {"cid_str", "Call ID string (default %u-%p@%s).  %u=call_number, %s=ip_address, %p=process_number, %%=% (in any order).", SIPP_OPTION_STRING, &call_id_string, 1},
+       {"ci", "Set the local control IP address", SIPP_OPTION_IP, control_ip, 1},
+       {"cp", "Set the local control port number. Default is 8888.", SIPP_OPTION_INT, &control_port, 1},
+
+       {"d", "Controls the length of calls. More precisely, this controls the duration of 'pause' instructions in the scenario, if they do not have a 'milliseconds' section. Default value is 0 and default unit is milliseconds.", SIPP_OPTION_TIME_MS, &duration, 1},
+       {"deadcall_wait", "How long the Call-ID and final status of calls should be kept to improve message and error logs (default unit is ms).", SIPP_OPTION_TIME_MS, &deadcall_wait, 1},
+       {"default_behaviors", "Set the default behaviors that SIPp will use.  Possbile values are:\n"
+               "- all\tUse all default behaviors\n"
+               "- none\tUse no default behaviors\n"
+               "- bye\tSend byes for aborted calls\n"
+               "- abortunexp\tAbort calls on unexpected messages\n"
+               "- pingreply\tReply to ping requests\n"
+               "If a behavior is prefaced with a -, then it is turned off.  Example: all,-bye\n",
+               SIPP_OPTION_DEFAULTS, &default_behaviors, 1},
+
+       {"error_file", "Set the name of the error log file.", SIPP_OPTION_LFNAME, &error_lfi, 1},
+       {"error_overwrite", "Overwrite the error log file (default true).", SIPP_OPTION_LFOVERWRITE, &error_lfi, 1},
+
+       {"f", "Set the statistics report frequency on screen. Default is 1 and default unit is seconds.", SIPP_OPTION_TIME_SEC, &report_freq, 1},
+       {"fd", "Set the statistics dump log report frequency. Default is 60 and default unit is seconds.", SIPP_OPTION_TIME_SEC, &report_freq_dumpLog, 1},
+
+       {"i", "Set the local IP address for 'Contact:','Via:', and 'From:' headers. Default is primary host IP address.\n", SIPP_OPTION_IP, local_ip, 1},
+       {"inf", "Inject values from an external CSV file during calls into the scenarios.\n"
+                "First line of this file say whether the data is to be read in sequence (SEQUENTIAL), random (RANDOM), or user (USER) order.\n"
+               "Each line corresponds to one call and has one or more ';' delimited data fields. Those fields can be referred as [field0], [field1], ... in the xml scenario file.  Several CSV files can be used simultaneously (syntax: -inf f1.csv -inf f2.csv ...)", SIPP_OPTION_INPUT_FILE, NULL, 1},
+       {"infindex", "file field\nCreate an index of file using field.  For example -inf users.csv -infindex users.csv 0 creates an index on the first key.", SIPP_OPTION_INDEX_FILE, NULL, 1 },
+
+       {"ip_field", "Set which field from the injection file contains the IP address from which the client will send its messages.\n"
+                     "If this option is omitted and the '-t ui' option is present, then field 0 is assumed.\n"
+                    "Use this option together with '-t ui'", SIPP_OPTION_INT, &peripfield, 1},
+
+
+       {"l", "Set the maximum number of simultaneous calls. Once this limit is reached, traffic is decreased until the number of open calls goes down. Default:\n"
+             "  (3 * call_duration (s) * rate).", SIPP_OPTION_LIMIT, NULL, 1},
+
+       {"log_file", "Set the name of the log actions log file.", SIPP_OPTION_LFNAME, &log_lfi, 1},
+       {"log_overwrite", "Overwrite the log actions log file (default true).", SIPP_OPTION_LFOVERWRITE, &log_lfi, 1},
+
+       {"lost", "Set the number of packets to lose by default (scenario specifications override this value).", SIPP_OPTION_FLOAT, &global_lost, 1},
+       {"rtcheck", "Select the retransmisison detection method: full (default) or loose.", SIPP_OPTION_RTCHECK, &rtcheck, 1},
+       {"m", "Stop the test and exit when 'calls' calls are processed", SIPP_OPTION_LONG, &stop_after, 1},
+       {"mi", "Set the local media IP address (default: local primary host IP address)", SIPP_OPTION_IP, media_ip, 1},
+        {"master","3pcc extended mode: indicates the master number", SIPP_OPTION_3PCC_EXTENDED, &master_name, 1},
+       {"max_recv_loops", "Set the maximum number of messages received read per cycle. Increase this value for high traffic level.  The default value is 1000.", SIPP_OPTION_INT, &max_recv_loops, 1},
+       {"max_sched_loops", "Set the maximum number of calsl run per event loop. Increase this value for high traffic level.  The default value is 1000.", SIPP_OPTION_INT, &max_sched_loops, 1},
+       {"max_reconnect", "Set the the maximum number of reconnection.", SIPP_OPTION_INT, &reset_number, 1},
+       {"max_retrans", "Maximum number of UDP retransmissions before call ends on timeout.  Default is 5 for INVITE transactions and 7 for others.", SIPP_OPTION_INT, &max_udp_retrans, 1},
+       {"max_invite_retrans", "Maximum number of UDP retransmissions for invite transactions before call ends on timeout.", SIPP_OPTION_INT, &max_invite_retrans, 1},
+       {"max_non_invite_retrans", "Maximum number of UDP retransmissions for non-invite transactions before call ends on timeout.", SIPP_OPTION_INT, &max_non_invite_retrans, 1},
+       {"max_log_size", "What is the limit for error and message log file sizes.", SIPP_OPTION_LONG_LONG, &max_log_size, 1},
+       {"max_socket", "Set the max number of sockets to open simultaneously. This option is significant if you use one socket per call. Once this limit is reached, traffic is distributed over the sockets already opened. Default value is 50000", SIPP_OPTION_MAX_SOCKET, NULL, 1},
+
+       {"mb", "Set the RTP echo buffer size (default: 2048).", SIPP_OPTION_INT, &media_bufsize, 1},
+       {"message_file", "Set the name of the message log file.", SIPP_OPTION_LFNAME, &message_lfi, 1},
+       {"message_overwrite", "Overwrite the message log file (default true).", SIPP_OPTION_LFOVERWRITE, &message_lfi, 1},
+       {"mp", "Set the local RTP echo port number. Default is 6000.", SIPP_OPTION_INT, &user_media_port, 1},
+
+       {"nd", "No Default. Disable all default behavior of SIPp which are the following:\n"
+               "- On UDP retransmission timeout, abort the call by sending a BYE or a CANCEL\n"
+               "- On receive timeout with no ontimeout attribute, abort the call by sending a BYE or a CANCEL\n"
+               "- On unexpected BYE send a 200 OK and close the call\n"
+               "- On unexpected CANCEL send a 200 OK and close the call\n"
+               "- On unexpected PING send a 200 OK and continue the call\n"
+               "- On any other unexpected message, abort the call by sending a BYE or a CANCEL\n",
+               SIPP_OPTION_UNSETFLAG, &default_behaviors, 1},
+       {"nr", "Disable retransmission in UDP mode.", SIPP_OPTION_UNSETFLAG, &retrans_enabled, 1},
+
+       {"nostdin", "Disable stdin.\n", SIPP_OPTION_SETFLAG, &nostdin, 1},
+
+       {"p", "Set the local port number.  Default is a random free port chosen by the system.", SIPP_OPTION_INT, &user_port, 1},
+       {"pause_msg_ign", "Ignore the messages received during a pause defined in the scenario ", SIPP_OPTION_SETFLAG, &pause_msg_ign, 1},
+       {"periodic_rtd", "Reset response time partition counters each logging interval.", SIPP_OPTION_SETFLAG, &periodic_rtd, 1},
+       {"plugin", "Load a plugin.", SIPP_OPTION_PLUGIN, NULL, 1},
+
+       {"r", "Set the call rate (in calls per seconds).  This value can be"
+             "changed during test by pressing '+','_','*' or '/'. Default is 10.\n"
+             "pressing '+' key to increase call rate by 1 * rate_scale,\n"
+              "pressing '-' key to decrease call rate by 1 * rate_scale,\n"
+              "pressing '*' key to increase call rate by 10 * rate_scale,\n"
+              "pressing '/' key to decrease call rate by 10 * rate_scale.\n"
+              "If the -rp option is used, the call rate is calculated with the period in ms given by the user.", SIPP_OPTION_FLOAT, &rate, 1},
+       {"rp", "Specify the rate period for the call rate.  Default is 1 second and default unit is milliseconds.  This allows you to have n calls every m milliseconds (by using -r n -rp m).\n"
+               "Example: -r 7 -rp 2000 ==> 7 calls every 2 seconds.\n         -r 10 -rp 5s => 10 calls every 5 seconds.", SIPP_OPTION_TIME_MS, &rate_period_ms, 1},
+       {"rate_scale", "Control the units for the '+', '-', '*', and '/' keys.", SIPP_OPTION_FLOAT, &rate_scale, 1},
+       {"rate_increase", "Specify the rate increase every -fd units (default is seconds).  This allows you to increase the load for each independent logging period.\n"
+                      "Example: -rate_increase 10 -fd 10s\n"
+                      "  ==> increase calls by 10 every 10 seconds.", SIPP_OPTION_INT, &rate_increase, 1},
+       {"rate_max", "If -rate_increase is set, then quit after the rate reaches this value.\n"
+                      "Example: -rate_increase 10 -rate_max 100\n"
+                      "  ==> increase calls by 10 until 100 cps is hit.", SIPP_OPTION_INT, &rate_max, 1},
+       {"no_rate_quit", "If -rate_increase is set, do not quit after the rate reaches -rate_max.", SIPP_OPTION_UNSETFLAG, &rate_quit, 1},
+       {"recv_timeout", "Global receive timeout. Default unit is milliseconds. If the expected message is not received, the call times out and is aborted.", SIPP_OPTION_TIME_MS_LONG, &defl_recv_timeout, 1},
+       {"send_timeout", "Global send timeout. Default unit is milliseconds. If a message is not sent (due to congestion), the call times out and is aborted.", SIPP_OPTION_TIME_MS_LONG, &defl_send_timeout, 1},
+       {"sleep", "How long to sleep for at startup. Default unit is seconds.", SIPP_OPTION_TIME_SEC, &sleeptime, 1},
+       {"reconnect_close", "Should calls be closed on reconnect?", SIPP_OPTION_BOOL, &reset_close, 1},
+       {"reconnect_sleep", "How long (in milliseconds) to sleep between the close and reconnect?", SIPP_OPTION_TIME_MS, &reset_sleep, 1},
+       {"ringbuffer_files", "How many error/message files should be kept after rotation?", SIPP_OPTION_INT, &ringbuffer_files, 1},
+       {"ringbuffer_size", "How large should error/message files be before they get rotated?", SIPP_OPTION_LONG_LONG, &ringbuffer_size, 1},
+       {"rsa", "Set the remote sending address to host:port for sending the messages.", SIPP_OPTION_RSA, NULL, 1},
+       {"rtp_echo", "Enable RTP echo. RTP/UDP packets received on port defined by -mp are echoed to their sender.\n"
+                     "RTP/UDP packets coming on this port + 2 are also echoed to their sender (used for sound and video echo).",
+                    SIPP_OPTION_SETFLAG, &rtp_echo_enabled, 1},
+       {"rtt_freq", "freq is mandatory. Dump response times every freq calls in the log file defined by -trace_rtt. Default value is 200.",
+                    SIPP_OPTION_LONG, &report_freq_dumpRtt, 1},
+       {"s", "Set the username part of the resquest URI. Default is 'service'.", SIPP_OPTION_STRING, &service, 1},
+       {"sd", "Dumps a default scenario (embeded in the sipp executable)", SIPP_OPTION_SCENARIO, NULL, 0},
+       {"sf", "Loads an alternate xml scenario file.  To learn more about XML scenario syntax, use the -sd option to dump embedded scenarios. They contain all the necessary help.", SIPP_OPTION_SCENARIO, NULL, 2},
+       {"shortmessage_file", "Set the name of the short message log file.", SIPP_OPTION_LFNAME, &shortmessage_lfi, 1},
+       {"shortmessage_overwrite", "Overwrite the short message log file (default true).", SIPP_OPTION_LFOVERWRITE, &shortmessage_lfi, 1},
+       {"oocsf", "Load out-of-call scenario.", SIPP_OPTION_OOC_SCENARIO, NULL, 2},
+       {"oocsn", "Load out-of-call scenario.", SIPP_OPTION_OOC_SCENARIO, NULL, 2},
+       {"skip_rlimit", "Do not perform rlimit tuning of file descriptor limits.  Default: false.", SIPP_OPTION_SETFLAG, &skip_rlimit, 1},
+       {"slave", "3pcc extended mode: indicates the slave number", SIPP_OPTION_3PCC_EXTENDED, &slave_number, 1},
+       {"slave_cfg", "3pcc extended mode: indicates the file where the master and slave addresses are stored", SIPP_OPTION_SLAVE_CFG, NULL, 1},
+       {"sn", "Use a default scenario (embedded in the sipp executable). If this option is omitted, the Standard SipStone UAC scenario is loaded.\n"
+               "Available values in this version:\n\n"
+               "- 'uac'      : Standard SipStone UAC (default).\n"
+               "- 'uas'      : Simple UAS responder.\n"
+               "- 'regexp'   : Standard SipStone UAC - with regexp and variables.\n"
+               "- 'branchc'  : Branching and conditional branching in scenarios - client.\n"
+               "- 'branchs'  : Branching and conditional branching in scenarios - server.\n\n"
+               "Default 3pcc scenarios (see -3pcc option):\n\n"
+               "- '3pcc-C-A' : Controller A side (must be started after all other 3pcc scenarios)\n"
+               "- '3pcc-C-B' : Controller B side.\n"
+               "- '3pcc-A'   : A side.\n"
+               "- '3pcc-B'   : B side.\n", SIPP_OPTION_SCENARIO, NULL, 2},
+
+       {"stat_delimiter", "Set the delimiter for the statistics file", SIPP_OPTION_STRING, &stat_delimiter, 1},
+       {"stf", "Set the file name to use to dump statistics", SIPP_OPTION_ARGI, &argiFileName, 1},
+
+       {"t", "Set the transport mode:\n"
+              "- u1: UDP with one socket (default),\n"
+              "- un: UDP with one socket per call,\n"
+              "- ui: UDP with one socket per IP address The IP addresses must be defined in the injection file.\n"
+              "- t1: TCP with one socket,\n"
+              "- tn: TCP with one socket per call,\n"
+              "- l1: TLS with one socket,\n"
+              "- ln: TLS with one socket per call,\n"
+              "- s1: SCTP with one socket (default),\n"
+              "- sn: SCTP with one socket per call,\n"
+              "- c1: u1 + compression (only if compression plugin loaded),\n"
+              "- cn: un + compression (only if compression plugin loaded).  This plugin is not provided with sipp.\n"
+             , SIPP_OPTION_TRANSPORT, NULL, 1},
+
+       {"timeout", "Global timeout. Default unit is seconds.  If this option is set, SIPp quits after nb units (-timeout 20s quits after 20 seconds).", SIPP_OPTION_TIME_SEC, &global_timeout, 1},
+       {"timeout_error", "SIPp fails if the global timeout is reached is set (-timeout option required).", SIPP_OPTION_SETFLAG, &timeout_error, 1},
+       {"timer_resol", "Set the timer resolution. Default unit is milliseconds.  This option has an impact on timers precision."
+                      "Small values allow more precise scheduling but impacts CPU usage."
+                      "If the compression is on, the value is set to 50ms. The default value is 10ms.", SIPP_OPTION_TIME_MS, &timer_resolution, 1},
+
+       {"T2", "Global T2-timer in milli seconds", SIPP_OPTION_TIME_MS, &global_t2, 1},
+
+       {"sendbuffer_warn", "Produce warnings instead of errors on SendBuffer failures.", SIPP_OPTION_BOOL, &sendbuffer_warn, 1},
+
+       {"trace_msg", "Displays sent and received SIP messages in <scenario file name>_<pid>_messages.log", SIPP_OPTION_SETFLAG, &useMessagef, 1},
+  {"trace_shortmsg", "Displays sent and received SIP messages as CSV in <scenario file name>_<pid>_shortmessages.log", SIPP_OPTION_SETFLAG, &useShortMessagef, 1},
+       {"trace_screen", "Dump statistic screens in the <scenario_name>_<pid>_screens.log file when quitting SIPp. Useful to get a final status report in background mode (-bg option).", SIPP_OPTION_SETFLAG, &useScreenf, 1},
+       {"trace_err", "Trace all unexpected messages in <scenario file name>_<pid>_errors.log.", SIPP_OPTION_SETFLAG, &print_all_responses, 1},
+//     {"trace_timeout", "Displays call ids for calls with timeouts in <scenario file name>_<pid>_timeout.log", SIPP_OPTION_SETFLAG, &useTimeoutf, 1},
+       {"trace_calldebug", "Dumps debugging information about aborted calls to <scenario_name>_<pid>_calldebug.log file.", SIPP_OPTION_SETFLAG, &useCallDebugf, 1},
+       {"trace_stat", "Dumps all statistics in <scenario_name>_<pid>.csv file. Use the '-h stat' option for a detailed description of the statistics file content.", SIPP_OPTION_SETFLAG, &dumpInFile, 1},
+       {"trace_counts", "Dumps individual message counts in a CSV file.", SIPP_OPTION_SETFLAG, &useCountf, 1},
+       {"trace_rtt", "Allow tracing of all response times in <scenario file name>_<pid>_rtt.csv.", SIPP_OPTION_SETFLAG, &dumpInRtt, 1},
+       {"trace_logs", "Allow tracing of <log> actions in <scenario file name>_<pid>_logs.log.", SIPP_OPTION_SETFLAG, &useLogf, 1},
+
+       {"users", "Instead of starting calls at a fixed rate, begin 'users' calls at startup, and keep the number of calls constant.", SIPP_OPTION_USERS, NULL, 1},
+
+       {"watchdog_interval", "Set gap between watchdog timer firings.  Default is 400.", SIPP_OPTION_TIME_MS, &watchdog_interval, 1},
+       {"watchdog_reset", "If the watchdog timer has not fired in more than this time period, then reset the max triggers counters.  Default is 10 minutes.", SIPP_OPTION_TIME_MS, &watchdog_reset, 1},
+       {"watchdog_minor_threshold", "If it has been longer than this period between watchdog executions count a minor trip.  Default is 500.", SIPP_OPTION_TIME_MS, &watchdog_minor_threshold, 1},
+       {"watchdog_major_threshold", "If it has been longer than this period between watchdog executions count a major trip.  Default is 3000.", SIPP_OPTION_TIME_MS, &watchdog_major_threshold, 1},
+       {"watchdog_major_maxtriggers", "How many times the major watchdog timer can be tripped before the test is terminated.  Default is 10.", SIPP_OPTION_INT, &watchdog_major_maxtriggers, 1},
+       {"watchdog_minor_maxtriggers", "How many times the minor watchdog timer can be tripped before the test is terminated.  Default is 120.", SIPP_OPTION_INT, &watchdog_minor_maxtriggers, 1},
+
+#ifdef _USE_OPENSSL
+       {"tls_cert", "Set the name for TLS Certificate file. Default is 'cacert.pem", SIPP_OPTION_STRING, &tls_cert_name, 1},
+       {"tls_key", "Set the name for TLS Private Key file. Default is 'cakey.pem'", SIPP_OPTION_STRING, &tls_key_name, 1},
+       {"tls_crl", "Set the name for Certificate Revocation List file. If not specified, X509 CRL is not activated.", SIPP_OPTION_STRING, &tls_crl_name, 1},
+#else
+       {"tls_cert", NULL, SIPP_OPTION_NEED_SSL, NULL, 1},
+       {"tls_key", NULL, SIPP_OPTION_NEED_SSL, NULL, 1},
+       {"tls_crl", NULL, SIPP_OPTION_NEED_SSL, NULL, 1},
+#endif
+       {"3pcc", "Launch the tool in 3pcc mode (\"Third Party call control\"). The passed ip address is depending on the 3PCC role.\n"
+                 "- When the first twin command is 'sendCmd' then this is the address of the remote twin socket.  SIPp will try to connect to this address:port to send the twin command (This instance must be started after all other 3PCC scenarii).\n"
+                 "    Example: 3PCC-C-A scenario.\n"
+                 "- When the first twin command is 'recvCmd' then this is the address of the local twin socket. SIPp will open this address:port to listen for twin command.\n"
+                "    Example: 3PCC-C-B scenario.", SIPP_OPTION_3PCC, NULL, 1},
+       {"tdmmap", "Generate and handle a table of TDM circuits.\n"
+                   "A circuit must be available for the call to be placed.\n"
+                   "Format: -tdmmap {0-3}{99}{5-8}{1-31}", SIPP_OPTION_TDMMAP, NULL, 1},
+       {"key", "keyword value\nSet the generic parameter named \"keyword\" to \"value\".", SIPP_OPTION_KEY, NULL, 1},
+       {"set", "variable value\nSet the global variable parameter named \"variable\" to \"value\".", SIPP_OPTION_VAR, NULL, 3},
+#ifdef USE_SCTP
+       {"multihome", "Set multihome address for SCTP", SIPP_OPTION_IP, multihome_ip, 1},
+       {"heartbeat", "Set heartbeat interval in ms for SCTP", SIPP_OPTION_INT, &heartbeat, 1},
+       {"assocmaxret", "Set association max retransmit counter for SCTP", SIPP_OPTION_INT, &assocmaxret, 1},
+       {"pathmaxret", "Set path max retransmit counter for SCTP", SIPP_OPTION_INT, &pathmaxret, 1},
+       {"pmtu", "Set path MTU for SCTP", SIPP_OPTION_INT, &pmtu, 1},
+       {"gracefulclose", "If true, SCTP association will be closed with SHUTDOWN (default).\n If false, SCTP association will be closed by ABORT.\n", SIPP_OPTION_BOOL, &gracefulclose, 1},
+#else
+       {"multihome", NULL, SIPP_OPTION_NEED_SCTP, NULL, 1},
+       {"heartbeat", NULL, SIPP_OPTION_NEED_SCTP, NULL, 1},
+       {"assocmaxret", NULL, SIPP_OPTION_NEED_SCTP, NULL, 1},
+       {"pathmaxret", NULL, SIPP_OPTION_NEED_SCTP, NULL, 1},
+       {"pmtu", NULL, SIPP_OPTION_NEED_SCTP, NULL, 1},
+       {"gracefulclose", NULL, SIPP_OPTION_NEED_SCTP, NULL, 1},
+#endif
+       {"dynamicStart", "variable value\nSet the start offset of dynamic_id varaiable",  SIPP_OPTION_INT, &startDynamicId, 1},
+       {"dynamicMax",   "variable value\nSet the maximum of dynamic_id variable     ",   SIPP_OPTION_INT, &maxDynamicId,   1},
+       {"dynamicStep",  "variable value\nSet the increment of dynamic_id variable",      SIPP_OPTION_INT, &stepDynamicId,  1}
+};
+
+struct sipp_option *find_option(const char *option) {
+       int i;
+       int max = sizeof(options_table)/sizeof(options_table[0]);
+
+       /* Allow options to start with '-' or '--' */
+       if (option[0] != '-') {
+         return NULL;
+       }
+       option++;
+       if (option[0] == '-') {
+         option++;
+       }
+
+       for (i = 0; i < max; i++) {
+         if (!strcmp(options_table[i].option, option)) {
+           return &(options_table[i]);
+         }
+       }
+
+       return NULL;
+};
+
+/***************** System Portability Features *****************/
+
+unsigned long long getmicroseconds()
+{
+  struct timeval LS_system_time;
+  unsigned long long VI_micro;
+  static unsigned long long VI_micro_base = 0;
+
+  gettimeofday(&LS_system_time, NULL);
+  VI_micro = (((unsigned long long) LS_system_time.tv_sec) * 1000000LL) + LS_system_time.tv_usec;
+  if (!VI_micro_base) VI_micro_base = VI_micro - 1;
+  VI_micro = VI_micro - VI_micro_base;
+
+  clock_tick = VI_micro / 1000LL;
+
+  return VI_micro;
+}
+
+unsigned long getmilliseconds()
+{
+  return getmicroseconds() / 1000LL;
+}
+
+
+#ifdef _USE_OPENSSL
+/****** SSL error handling                         *************/
+const char *sip_tls_error_string(SSL *ssl, int size) {
+  int err;
+  err=SSL_get_error(ssl, size);
+  switch(err) {
+    case SSL_ERROR_NONE:
+      return "No error";
+    case SSL_ERROR_WANT_WRITE:
+      return "SSL_read returned SSL_ERROR_WANT_WRITE";
+    case SSL_ERROR_WANT_READ:
+      return "SSL_read returned SSL_ERROR_WANT_READ";
+    case SSL_ERROR_WANT_X509_LOOKUP:
+      return "SSL_read returned SSL_ERROR_WANT_X509_LOOKUP";
+      break;
+    case SSL_ERROR_SYSCALL:
+      if(size<0) { /* not EOF */
+       return strerror(errno);
+      } else { /* EOF */
+        return "SSL socket closed on SSL_read";
+      }
+  }
+  return "Unknown SSL Error.";
+}
+
+/****** Certificate Verification Callback FACILITY *************/
+int sip_tls_verify_callback(int ok , X509_STORE_CTX *store)
+{
+  char data[512];
+  
+  if (!ok) {
+     X509 *cert = X509_STORE_CTX_get_current_cert(store);
+
+     X509_NAME_oneline(X509_get_issuer_name(cert),
+                                   data,512);
+     WARNING("TLS verification error for issuer: '%s'", data);
+     X509_NAME_oneline(X509_get_subject_name(cert),
+                                   data,512);
+     WARNING("TLS verification error for subject: '%s'", data);
+  }
+  return ok;
+}
+
+/***********  Load the CRL's into SSL_CTX **********************/
+int sip_tls_load_crls( SSL_CTX *ctx , char *crlfile)
+{
+  X509_STORE          *store;
+  X509_LOOKUP         *lookup;
+
+  /*  Get the X509_STORE from SSL context */
+  if (!(store = SSL_CTX_get_cert_store(ctx))) {
+    return (-1);
+  }
+
+  /* Add lookup file to X509_STORE */
+  if (!(lookup = X509_STORE_add_lookup(store,X509_LOOKUP_file()))) {
+    return (-1);
+  }
+
+  /* Add the CRLS to the lookpup object */
+  if (X509_load_crl_file(lookup,crlfile,X509_FILETYPE_PEM) != 1) {
+    return (-1);
+  }
+
+  /* Set the flags of the store so that CRLS's are consulted */
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+  X509_STORE_set_flags( store,X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
+#else
+#warning This version of OpenSSL (<0.9.7) cannot handle CRL files in capath
+  ERROR("This version of OpenSSL (<0.9.7) cannot handle CRL files in capath");
+#endif
+
+  return (1);
+}
+
+/************* Prepare the SSL context ************************/
+static ssl_init_status FI_init_ssl_context (void)
+{
+  sip_trp_ssl_ctx = SSL_CTX_new( TLSv1_method() ); 
+  if ( sip_trp_ssl_ctx == NULL ) {
+    ERROR("FI_init_ssl_context: SSL_CTX_new with TLSv1_method failed");
+    return SSL_INIT_ERROR;
+  }
+
+  sip_trp_ssl_ctx_client = SSL_CTX_new( TLSv1_method() );
+  if ( sip_trp_ssl_ctx_client == NULL)
+  {
+    ERROR("FI_init_ssl_context: SSL_CTX_new with TLSv1_method failed");
+    return SSL_INIT_ERROR;
+  }
+
+  /*  Load the trusted CA's */
+  SSL_CTX_load_verify_locations(sip_trp_ssl_ctx, tls_cert_name, NULL);
+  SSL_CTX_load_verify_locations(sip_trp_ssl_ctx_client, tls_cert_name, NULL);
+  
+  /*  CRL load from application specified only if specified on the command line */
+  if (strlen(tls_crl_name) != 0) {
+    if(sip_tls_load_crls(sip_trp_ssl_ctx,tls_crl_name) == -1) {
+      ERROR("FI_init_ssl_context: Unable to load CRL file (%s)", tls_crl_name);
+      return SSL_INIT_ERROR;
+    }
+  
+    if(sip_tls_load_crls(sip_trp_ssl_ctx_client,tls_crl_name) == -1) {
+      ERROR("FI_init_ssl_context: Unable to load CRL (client) file (%s)", tls_crl_name);
+      return SSL_INIT_ERROR;
+    }
+    /* The following call forces to process the certificates with the */
+    /* initialised SSL_CTX                                            */
+    SSL_CTX_set_verify(sip_trp_ssl_ctx,
+                       SSL_VERIFY_PEER |
+                       SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+                       sip_tls_verify_callback);
+
+    SSL_CTX_set_verify(sip_trp_ssl_ctx_client,
+                       SSL_VERIFY_PEER |
+                       SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+                       sip_tls_verify_callback);
+  }
+
+
+  /* Selection Cipher suits - load the application specified ciphers */
+  SSL_CTX_set_default_passwd_cb_userdata(sip_trp_ssl_ctx,
+                                             (void *)CALL_BACK_USER_DATA );
+  SSL_CTX_set_default_passwd_cb_userdata(sip_trp_ssl_ctx_client,
+                                             (void *)CALL_BACK_USER_DATA );
+  SSL_CTX_set_default_passwd_cb( sip_trp_ssl_ctx,
+                                             passwd_call_back_routine );
+  SSL_CTX_set_default_passwd_cb( sip_trp_ssl_ctx_client,
+                                             passwd_call_back_routine );
+
+  if ( SSL_CTX_use_certificate_file(sip_trp_ssl_ctx,
+                                        tls_cert_name,
+                                        SSL_FILETYPE_PEM ) != 1 ) {
+    ERROR("FI_init_ssl_context: SSL_CTX_use_certificate_file failed");
+    return SSL_INIT_ERROR;
+  }
+
+  if ( SSL_CTX_use_certificate_file(sip_trp_ssl_ctx_client,
+                                        tls_cert_name,
+                                        SSL_FILETYPE_PEM ) != 1 ) {
+    ERROR("FI_init_ssl_context: SSL_CTX_use_certificate_file (client) failed");
+    return SSL_INIT_ERROR;
+  }
+  if ( SSL_CTX_use_PrivateKey_file(sip_trp_ssl_ctx,
+                                       tls_key_name,
+                                       SSL_FILETYPE_PEM ) != 1 ) {
+    ERROR("FI_init_ssl_context: SSL_CTX_use_PrivateKey_file failed");
+    return SSL_INIT_ERROR;
+  }
+
+  if ( SSL_CTX_use_PrivateKey_file(sip_trp_ssl_ctx_client,
+                                       tls_key_name,
+                                       SSL_FILETYPE_PEM ) != 1 ) {
+    ERROR("FI_init_ssl_context: SSL_CTX_use_PrivateKey_file (client) failed");
+    return SSL_INIT_ERROR;
+  }
+
+  return SSL_INIT_NORMAL;
+}
+
+int send_nowait_tls(SSL *ssl, const void *msg, int len, int flags)
+{
+  int initial_fd_flags;
+  int rc;
+  int fd;
+  int fd_flags;
+  if ( (fd = SSL_get_fd(ssl)) == -1 ) {
+    return (-1);
+  }
+  fd_flags = fcntl(fd, F_GETFL , NULL);
+  initial_fd_flags = fd_flags;
+  fd_flags |= O_NONBLOCK;
+  fcntl(fd, F_SETFL , fd_flags);
+  rc = SSL_write(ssl,msg,len);
+  if ( rc <= 0 ) {
+    return(rc);
+  }
+  fcntl(fd, F_SETFL , initial_fd_flags);
+  return rc;
+}
+#endif 
+
+int send_nowait(int s, const void *msg, int len, int flags)
+{
+#if defined(MSG_DONTWAIT) && !defined(__SUNOS)
+  return send(s, msg, len, flags | MSG_DONTWAIT);
+#else
+  int fd_flags = fcntl(s, F_GETFL , NULL);
+  int initial_fd_flags;
+  int rc;
+
+  initial_fd_flags = fd_flags;
+  //  fd_flags &= ~O_ACCMODE; // Remove the access mode from the value
+  fd_flags |= O_NONBLOCK;
+  fcntl(s, F_SETFL , fd_flags);
+  
+  rc = send(s, msg, len, flags);
+
+  fcntl(s, F_SETFL , initial_fd_flags);
+
+  return rc;
+#endif 
+}
+
+#ifdef USE_SCTP
+int send_sctp_nowait(int s, const void *msg, int len, int flags)
+{
+  struct sctp_sndrcvinfo sinfo;
+  memset(&sinfo, 0, sizeof(sinfo));
+  sinfo.sinfo_flags = SCTP_UNORDERED; // according to RFC4168 5.1
+  sinfo.sinfo_stream = 0;
+
+#if defined(MSG_DONTWAIT) && !defined(__SUNOS)
+  return sctp_send(s, msg, len, &sinfo, flags | MSG_DONTWAIT);
+#else
+  int fd_flags = fcntl(s, F_GETFL, NULL);
+  int initial_fd_flags;
+  int rc;
+
+  initial_fd_flags = fd_flags;
+  fd_flags |= O_NONBLOCK;
+  fcntl(s, F_SETFL , fd_flags);
+
+  rc = sctp_send(s, msg, len, &sinfo, flags);
+
+  fcntl(s, F_SETFL, initial_fd_flags);
+
+  return rc;
+#endif
+}
+#endif
+
+char * get_inet_address(struct sockaddr_storage * addr)
+{
+  static char * ip_addr = NULL;
+
+  if (!ip_addr) {
+    ip_addr = (char *)malloc(1024*sizeof(char));
+  }
+  if (getnameinfo(_RCAST(struct sockaddr *, addr),
+                  SOCK_ADDR_SIZE(addr),
+                  ip_addr,
+                  1024,
+                  NULL,
+                  0,
+                  NI_NUMERICHOST) != 0) {
+    strcpy(ip_addr, "addr not supported");
+  }
+
+  return ip_addr;
+}
+
+void get_host_and_port(const char * addr, char * host, int * port)
+{
+  /* Separate the port number (if any) from the host name.
+   * Thing is, the separator is a colon (':').  The colon may also exist
+   * in the host portion if the host is specified as an IPv6 address (see
+   * RFC 2732).  If that's the case, then we need to skip past the IPv6
+   * address, which should be contained within square brackets ('[',']').
+   */
+  const char *has_brackets;
+  int len;
+
+  has_brackets = strchr(addr, '[');
+  if (has_brackets != NULL) {
+    has_brackets = strchr(has_brackets, ']');
+  }
+  if (has_brackets == NULL) {
+    /* addr is not a []-enclosed IPv6 address, but might still be IPv6 (without
+     * a port), or IPv4 or a hostname (with or without a port) */
+    char *first_colon_location;
+    char *second_colon_location;
+
+    len = strlen(addr) + 1;
+    memmove(host, addr, len);
+
+    first_colon_location = strchr(host, ':');
+    if (first_colon_location == NULL) {
+      /* No colon - just set the port to 0 */
+      *port = 0;
+    } else {
+      second_colon_location = strchr(first_colon_location + 1, ':');
+      if (second_colon_location != NULL) {
+        /* Found a second colon in addr - so this is an IPv6 address
+         * without a port. Set the port to 0 */
+        *port = 0;
+      } else {
+        /* IPv4 address or hostname with a colon in it - convert the colon to
+         * a NUL terminator, and set the value after it as the port */
+        *first_colon_location = '\0';
+        *port = atol(first_colon_location + 1);
+      }
+    }
+
+  } else {                                      /* If '['..']' found,       */
+    const char *initial_bracket;                /* extract the remote_host  */
+    char *second_bracket;
+    char *colon_before_port;
+
+    initial_bracket = strchr( addr, '[' );
+    initial_bracket++; /* Step forward one character */
+    len = strlen(initial_bracket) + 1;
+    memmove(host, initial_bracket, len);
+
+    second_bracket = strchr( host, ']' );
+    *second_bracket = '\0';
+
+    /* Check for a port specified after the ] */
+    colon_before_port = strchr(second_bracket + 1, ':');
+    if (colon_before_port != NULL) {
+      *port = atol(colon_before_port + 1);
+    } else {
+      *port = 0;
+    }
+  }
+}
+
+static unsigned char tolower_table[256];
+
+void init_tolower_table() {
+  for (int i = 0; i < 256; i++) {
+    tolower_table[i] = tolower(i);
+  }
+}
+
+/* This is simpler than doing a regular tolower, because there are no branches.
+ * We also inline it, so that we don't have function call overheads.
+ *
+ * An alternative to a table would be to do (c | 0x20), but that only works if
+ * we are sure that we are searching for characters (or don't care if they are
+ * not characters. */
+unsigned char inline mytolower(unsigned char c) {
+  return tolower_table[c];
+}
+
+char * strcasestr2(char *s, char *find) {
+  char c, sc;
+  size_t len;
+
+  if ((c = *find++) != 0) {
+    c = mytolower((unsigned char)c);
+    len = strlen(find);
+    do {
+      do {
+        if ((sc = *s++) == 0)
+        return (NULL);
+      } while ((char)mytolower((unsigned char)sc) != c);
+    } while (strncasecmp(s, find, len) != 0);
+    s--;
+  }
+  return ((char *)s);
+}
+
+char * strncasestr(char *s, char *find, size_t n) {
+  char *end = s + n;
+  char c, sc;
+  size_t len;
+
+  if ((c = *find++) != 0) {
+    c = mytolower((unsigned char)c);
+    len = strlen(find);
+    end -= (len - 1);
+    do {
+      do {
+        if ((sc = *s++) == 0)
+         return (NULL);
+       if (s >= end)
+         return (NULL);
+      } while ((char)mytolower((unsigned char)sc) != c);
+    } while (strncasecmp(s, find, len) != 0);
+    s--;
+  }
+  return ((char *)s);
+}
+
+int get_decimal_from_hex(char hex) {
+  if (isdigit(hex))
+    return hex - '0';
+  else
+    return tolower(hex) - 'a' + 10;
+}
+
+
+/******************** Recv Poll Processing *********************/
+
+int                  pollnfds;
+struct pollfd        pollfiles[SIPP_MAXFDS];
+struct sipp_socket  *sockets[SIPP_MAXFDS];
+
+static int pending_messages = 0;
+
+map<string, struct sipp_socket *>     map_perip_fd;
+
+/***************** Check of the message received ***************/
+
+bool sipMsgCheck (const char *P_msg, int P_msgSize, struct sipp_socket *socket) {
+  const char C_sipHeader[] = "SIP/2.0" ;
+
+  if (socket == twinSippSocket || socket == localTwinSippSocket ||
+      is_a_peer_socket(socket) || is_a_local_socket(socket))
+       return true;
+
+  if (strstr(P_msg, C_sipHeader) !=  NULL) {
+    return true ;
+  }
+
+  return false ;
+}
+
+/************** Statistics display & User control *************/
+
+void print_stats_in_file(FILE * f, int last)
+{
+  static char temp_str[256];
+  int divisor;
+
+#define SIPP_ENDL "\r\n"
+
+  /* We are not initialized yet. */
+  if (!display_scenario) {
+    return;
+  }
+
+  /* Optional timestamp line for files only */
+  if(f != stdout) {
+    time_t tim;
+    time(&tim);
+    fprintf(f, "  Timestamp: %s" SIPP_ENDL, ctime(&tim));
+  }
+  
+  /* Header line with global parameters */
+  if (users >= 0) {
+    sprintf(temp_str, "%d (%d ms)", users, duration);
+  } else {
+    sprintf(temp_str, "%3.1f(%d ms)/%5.3fs", rate, duration, (double)rate_period_ms / 1000.0);
+  }
+  unsigned long long total_calls = display_scenario->stats->GetStat(CStat::CPT_C_IncomingCallCreated) + display_scenario->stats->GetStat(CStat::CPT_C_OutgoingCallCreated);
+  if( creationMode == MODE_SERVER) {
+    fprintf
+      (f,
+       "  Port   Total-time  Total-calls  Transport" 
+       SIPP_ENDL
+       "  %-5d %6lu.%02lu s     %8llu  %s"
+       SIPP_ENDL SIPP_ENDL,
+       local_port,
+       clock_tick / 1000, (clock_tick % 1000) / 10,
+       total_calls,
+       TRANSPORT_TO_STRING(transport));
+  } else {
+    assert(creationMode == MODE_CLIENT);
+    if (users >= 0) {
+      fprintf(f, "     Users (length)");
+    } else {
+      fprintf(f, "  Call-rate(length)");
+    }
+    fprintf(f, "   Port   Total-time  Total-calls  Remote-host" SIPP_ENDL
+       "%19s   %-5d %6lu.%02lu s     %8llu  %s:%d(%s)" SIPP_ENDL SIPP_ENDL,
+       temp_str,
+       local_port,
+       clock_tick / 1000, (clock_tick % 1000) / 10,
+       total_calls,
+       remote_ip,
+       remote_port,
+       TRANSPORT_TO_STRING(transport));
+  }
+  
+  /* 1st line */
+  if(total_calls < stop_after) {
+    sprintf(temp_str, "%llu new calls during %lu.%03lu s period ",
+       display_scenario->stats->GetStat(CStat::CPT_PD_IncomingCallCreated) +
+       display_scenario->stats->GetStat(CStat::CPT_PD_OutgoingCallCreated),
+       (clock_tick-last_report_time) / 1000,
+       ((clock_tick-last_report_time) % 1000));
+  } else {
+    sprintf(temp_str, "Call limit reached (-m %lu), %lu.%03lu s period ",
+            stop_after,
+            (clock_tick-last_report_time) / 1000, 
+            ((clock_tick-last_report_time) % 1000));
+  }
+  divisor = scheduling_loops; if(!divisor) { divisor = 1; }
+  fprintf(f,"  %-38s %lu ms scheduler resolution" 
+         SIPP_ENDL,
+         temp_str,
+         (clock_tick-last_report_time) / divisor);
+
+  /* 2nd line */
+  if( creationMode == MODE_SERVER) {
+    sprintf(temp_str, "%llu calls", display_scenario->stats->GetStat(CStat::CPT_C_CurrentCall));
+  } else {
+    sprintf(temp_str, "%llu calls (limit %d)", display_scenario->stats->GetStat(CStat::CPT_C_CurrentCall), open_calls_allowed);
+  }
+  fprintf(f,"  %-38s Peak was %llu calls, after %llu s" SIPP_ENDL,
+         temp_str, 
+         display_scenario->stats->GetStat(CStat::CPT_C_CurrentCallPeak),
+         display_scenario->stats->GetStat(CStat::CPT_C_CurrentCallPeakTime));
+  fprintf(f,"  %d Running, %d Paused, %d Woken up" SIPP_ENDL,
+        last_running_calls, last_paused_calls, last_woken_calls);
+  last_woken_calls = 0;
+
+  /* 3rd line dead call msgs, and optional out-of-call msg */
+  sprintf(temp_str,"%llu dead call msg (discarded)",
+      display_scenario->stats->GetStat(CStat::CPT_G_C_DeadCallMsgs));
+  fprintf(f,"  %-37s", temp_str);
+  if( creationMode == MODE_CLIENT) {
+    sprintf(temp_str,"%llu out-of-call msg (discarded)",
+            display_scenario->stats->GetStat(CStat::CPT_G_C_OutOfCallMsgs));
+    fprintf(f,"  %-37s", temp_str);
+  }
+  fprintf(f,SIPP_ENDL);
+
+  if(compression) {
+    fprintf(f,"  Comp resync: %d sent, %d recv" , 
+           resynch_send, resynch_recv);
+    fprintf(f,SIPP_ENDL);
+  }
+
+  /* 4th line , sockets and optional errors */ 
+  sprintf(temp_str,"%d open sockets", 
+          pollnfds);
+  fprintf(f,"  %-38s", temp_str);
+  if(nb_net_recv_errors || nb_net_send_errors || nb_net_cong) {
+    fprintf(f,"  %lu/%lu/%lu %s errors (send/recv/cong)" SIPP_ENDL,
+           nb_net_send_errors, 
+           nb_net_recv_errors,
+           nb_net_cong,
+           TRANSPORT_TO_STRING(transport));
+  } else {
+    fprintf(f,SIPP_ENDL);
+  }
+
+#ifdef PCAPPLAY
+  /* if has media abilities */
+  if (hasMedia != 0) {
+    sprintf(temp_str, "%lu Total RTP pckts sent ",
+            rtp_pckts_pcap);
+    if (clock_tick-last_report_time) {
+       fprintf(f,"  %-38s %lu.%03lu last period RTP rate (kB/s)" SIPP_ENDL,
+              temp_str,
+              (rtp_bytes_pcap)/(clock_tick-last_report_time),
+              (rtp_bytes_pcap)%(clock_tick-last_report_time));
+    }
+    rtp_bytes_pcap = 0;
+    rtp2_bytes_pcap = 0;
+  }
+#endif
+
+  /* 5th line, RTP echo statistics */
+  if (rtp_echo_enabled && (media_socket > 0)) {
+    sprintf(temp_str, "%lu Total echo RTP pckts 1st stream",
+            rtp_pckts);
+
+    // AComment: Fix for random coredump when using RTP echo
+    if (clock_tick-last_report_time) {
+       fprintf(f,"  %-38s %lu.%03lu last period RTP rate (kB/s)" SIPP_ENDL,
+              temp_str,
+              (rtp_bytes)/(clock_tick-last_report_time),
+              (rtp_bytes)%(clock_tick-last_report_time));
+    }
+    /* second stream statitics: */
+    sprintf(temp_str, "%lu Total echo RTP pckts 2nd stream",
+            rtp2_pckts);
+
+    // AComment: Fix for random coredump when using RTP echo
+    if (clock_tick-last_report_time) {
+      fprintf(f,"  %-38s %lu.%03lu last period RTP rate (kB/s)" SIPP_ENDL,
+             temp_str,
+             (rtp2_bytes)/(clock_tick-last_report_time),
+             (rtp2_bytes)%(clock_tick-last_report_time));
+    }
+    rtp_bytes = 0;
+    rtp2_bytes = 0;
+  }
+
+  /* Scenario counters */
+  fprintf(f,SIPP_ENDL);
+  if(!lose_packets) {
+    fprintf(f,"                                 "
+           "Messages  Retrans   Timeout   Unexpected-Msg" 
+           SIPP_ENDL);
+  } else {
+    fprintf(f,"                                 "
+           "Messages  Retrans   Timeout   Unexp.    Lost" 
+           SIPP_ENDL);
+  }
+  for(unsigned long index = 0;
+      index < display_scenario->messages.size();
+      index ++) {
+    message *curmsg = display_scenario->messages[index];
+
+    if(do_hide && curmsg->hide) {
+      continue;
+    }
+    if (show_index) {
+       fprintf(f, "%-2lu:", index);
+    }
+    
+    if(SendingMessage *src = curmsg -> send_scheme) {
+      if (src->isResponse()) {
+       sprintf(temp_str, "%d", src->getCode());
+      } else {
+       sprintf(temp_str, "%s", src->getMethod());
+      }
+
+      if(creationMode == MODE_SERVER) {
+        fprintf(f,"  <---------- %-10s ", temp_str);
+      } else {
+        fprintf(f,"  %10s ----------> ", temp_str);
+      }
+      if (curmsg -> start_rtd) {
+       fprintf(f, " B-RTD%d ", curmsg -> start_rtd);
+      } else if (curmsg -> stop_rtd) {
+       fprintf(f, " E-RTD%d ", curmsg -> stop_rtd);
+      } else {
+       fprintf(f, "        ");
+      }
+
+      if(curmsg -> retrans_delay) {
+        fprintf(f,"%-9lu %-9lu %-9lu %-9s" ,
+               curmsg -> nb_sent,
+               curmsg -> nb_sent_retrans,
+               curmsg -> nb_timeout,
+               "" /* Unexpected */);
+      } else {
+        fprintf(f,"%-9lu %-9lu %-9s %-9s" ,
+               curmsg -> nb_sent,
+               curmsg -> nb_sent_retrans,
+               "", /* Timeout. */
+               "" /* Unexpected. */);
+      }
+    } else if(curmsg -> recv_response) {
+      if(creationMode == MODE_SERVER) {
+       fprintf(f,"  ----------> %-10d ", curmsg -> recv_response);
+      } else { 
+       fprintf(f,"  %10d <---------- ", curmsg -> recv_response);
+      }
+
+      if (curmsg -> start_rtd) {
+       fprintf(f, " B-RTD%d ", curmsg -> start_rtd);
+      } else if (curmsg -> stop_rtd) {
+       fprintf(f, " E-RTD%d ", curmsg -> stop_rtd);
+      } else {
+       fprintf(f, "        ");
+      }
+
+      if(curmsg->retrans_delay) {
+        fprintf(f,"%-9ld %-9ld %-9ld %-9ld" ,
+               curmsg->nb_recv,
+               curmsg->nb_recv_retrans,
+               curmsg->nb_timeout,
+               curmsg->nb_unexp);
+      } else {
+        fprintf(f,"%-9ld %-9ld %-9ld %-9ld" ,
+               curmsg -> nb_recv,
+               curmsg -> nb_recv_retrans,
+               curmsg -> nb_timeout,
+               curmsg -> nb_unexp);
+      }
+    } else if (curmsg -> pause_distribution ||
+              (curmsg -> pause_variable != -1)) {
+      char *desc = curmsg->pause_desc;
+      if (!desc) {
+       desc = (char *)malloc(24);
+       if (curmsg->pause_distribution) {
+         desc[0] = '\0';
+         curmsg->pause_distribution->timeDescr(desc, 23);
+       } else {
+         snprintf(desc, 23, "$%s", display_scenario->allocVars->getName(curmsg->pause_variable));
+       }
+       desc[23] = '\0';
+       curmsg->pause_desc = desc;
+      }
+      int len = strlen(desc) < 9 ? 9 : strlen(desc);
+
+      if(creationMode == MODE_SERVER) {
+       fprintf(f,"  [%9s] Pause%*s", desc, 23 - len > 0 ? 23 - len : 0, "");
+      } else {
+       fprintf(f,"       Pause [%9s]%*s", desc, 18 - len > 0 ? 18 - len : 0, "");
+      }
+
+      fprintf(f,"%-9d", curmsg->sessions);
+      fprintf(f,"                     %-9lu" , curmsg->nb_unexp);
+    } else if(curmsg -> recv_request) {
+      if(creationMode == MODE_SERVER) {
+       fprintf(f,"  ----------> %-10s ", curmsg -> recv_request);
+      } else {
+       fprintf(f,"  %10s <---------- ", curmsg -> recv_request);
+      }
+
+      if (curmsg -> start_rtd) {
+       fprintf(f, " B-RTD%d ", curmsg -> start_rtd);
+      } else if (curmsg -> stop_rtd) {
+       fprintf(f, " E-RTD%d ", curmsg -> stop_rtd);
+      } else {
+       fprintf(f, "        ");
+      }
+
+      fprintf(f,"%-9ld %-9ld %-9ld %-9ld" ,
+         curmsg -> nb_recv,
+         curmsg -> nb_recv_retrans,
+         curmsg -> nb_timeout,
+         curmsg -> nb_unexp);
+    }
+    else if(curmsg -> M_type == MSG_TYPE_NOP) {
+      if (curmsg->display_str) {
+       fprintf(f," %s", curmsg->display_str);
+      } else {
+       fprintf(f,"              [ NOP ]              ");
+      }
+    }
+    else if(curmsg -> M_type == MSG_TYPE_RECVCMD) {
+      fprintf(f,"    [ Received Command ]         ");
+      if(curmsg->retrans_delay) {
+        fprintf(f,"%-9ld %-9s %-9ld %-9s" ,
+                curmsg->M_nbCmdRecv,
+                "",
+                curmsg->nb_timeout,
+                "");
+      } else {
+         fprintf(f,"%-9ld %-9s           %-9s" ,
+                curmsg -> M_nbCmdRecv,
+                "",
+                "");
+      }
+    } else if(curmsg -> M_type == MSG_TYPE_SENDCMD) {
+      fprintf(f,"        [ Sent Command ]         ");
+      fprintf(f,"%-9lu %-9s           %-9s" ,
+             curmsg -> M_nbCmdSent,
+             "",
+             "");
+    }
+    else {
+      ERROR("Scenario command not implemented in display\n");
+    }
+    
+    if(lose_packets && (curmsg -> nb_lost)) {
+      fprintf(f," %-9lu" SIPP_ENDL,
+             curmsg -> nb_lost);
+    } else {
+      fprintf(f,SIPP_ENDL);
+    }
+    
+    if(curmsg -> crlf) {
+      fprintf(f,SIPP_ENDL);
+    }
+  }
+}
+
+void print_count_file(FILE *f, int header) {
+  char temp_str[256];
+
+  if (!main_scenario || (!header && !main_scenario->stats)) {
+       return;
+  }
+
+  if (header) {
+    fprintf(f, "CurrentTime%sElapsedTime%s", stat_delimiter, stat_delimiter);
+  } else {
+    struct timeval currentTime, startTime;
+    GET_TIME(&currentTime);
+    main_scenario->stats->getStartTime(&startTime);
+    unsigned long globalElapsedTime = CStat::computeDiffTimeInMs (&currentTime, &startTime);
+    fprintf(f, "%s%s", CStat::formatTime(&currentTime), stat_delimiter);
+    fprintf(f, "%s%s", CStat::msToHHMMSSmmm(globalElapsedTime), stat_delimiter);
+  }
+
+  for(unsigned int index = 0; index < main_scenario->messages.size(); index ++) {
+    message *curmsg = main_scenario->messages[index];
+    if(curmsg->hide) {
+      continue;
+    }
+
+    if(SendingMessage *src = curmsg -> send_scheme) {
+      if(header) {
+       if (src->isResponse()) {
+         sprintf(temp_str, "%d_%d_", index, src->getCode());
+       } else {
+         sprintf(temp_str, "%d_%s_", index, src->getMethod());
+       }
+
+       fprintf(f, "%sSent%s", temp_str, stat_delimiter);
+       fprintf(f, "%sRetrans%s", temp_str, stat_delimiter);
+       if(curmsg -> retrans_delay) {
+         fprintf(f, "%sTimeout%s", temp_str, stat_delimiter);
+       }
+       if(lose_packets) {
+         fprintf(f, "%sLost%s", temp_str, stat_delimiter);
+       }
+      } else {
+       fprintf(f, "%lu%s", curmsg->nb_sent, stat_delimiter);
+       fprintf(f, "%lu%s", curmsg->nb_sent_retrans, stat_delimiter);
+       if(curmsg -> retrans_delay) {
+         fprintf(f, "%lu%s", curmsg->nb_timeout, stat_delimiter);
+       }
+       if(lose_packets) {
+         fprintf(f, "%lu%s", curmsg->nb_lost, stat_delimiter);
+       }
+      }
+    } else if(curmsg -> recv_response) {
+      if(header) {
+       sprintf(temp_str, "%u_%d_", index, curmsg->recv_response);
+
+       fprintf(f, "%sRecv%s", temp_str, stat_delimiter);
+       fprintf(f, "%sRetrans%s", temp_str, stat_delimiter);
+       fprintf(f, "%sTimeout%s", temp_str, stat_delimiter);
+       fprintf(f, "%sUnexp%s", temp_str, stat_delimiter);
+       if(lose_packets) {
+         fprintf(f, "%sLost%s", temp_str, stat_delimiter);
+       }
+      } else {
+       fprintf(f, "%lu%s", curmsg->nb_recv, stat_delimiter);
+       fprintf(f, "%lu%s", curmsg->nb_recv_retrans, stat_delimiter);
+       fprintf(f, "%lu%s", curmsg->nb_timeout, stat_delimiter);
+       fprintf(f, "%lu%s", curmsg->nb_unexp, stat_delimiter);
+       if(lose_packets) {
+         fprintf(f, "%lu%s", curmsg->nb_lost, stat_delimiter);
+       }
+      }
+    } else if(curmsg -> recv_request) {
+      if(header) {
+       sprintf(temp_str, "%u_%s_", index, curmsg->recv_request);
+
+       fprintf(f, "%sRecv%s", temp_str, stat_delimiter);
+       fprintf(f, "%sRetrans%s", temp_str, stat_delimiter);
+       fprintf(f, "%sTimeout%s", temp_str, stat_delimiter);
+       fprintf(f, "%sUnexp%s", temp_str, stat_delimiter);
+       if(lose_packets) {
+         fprintf(f, "%sLost%s", temp_str, stat_delimiter);
+       }
+      } else {
+       fprintf(f, "%lu%s", curmsg->nb_recv, stat_delimiter);
+       fprintf(f, "%lu%s", curmsg->nb_recv_retrans, stat_delimiter);
+       fprintf(f, "%lu%s", curmsg->nb_timeout, stat_delimiter);
+       fprintf(f, "%lu%s", curmsg->nb_unexp, stat_delimiter);
+       if(lose_packets) {
+         fprintf(f, "%lu%s", curmsg->nb_lost, stat_delimiter);
+       }
+      }
+    } else if (curmsg -> pause_distribution ||
+       curmsg -> pause_variable) {
+
+      if(header) {
+       sprintf(temp_str, "%d_Pause_", index);
+       fprintf(f, "%sSessions%s", temp_str, stat_delimiter);
+       fprintf(f, "%sUnexp%s", temp_str, stat_delimiter);
+      } else {
+       fprintf(f, "%d%s", curmsg->sessions, stat_delimiter);
+       fprintf(f, "%lu%s", curmsg->nb_unexp, stat_delimiter);
+      }
+    } else if(curmsg -> M_type == MSG_TYPE_NOP) {
+      /* No output. */
+    }  else if(curmsg -> M_type == MSG_TYPE_RECVCMD) {
+      if(header) {
+       sprintf(temp_str, "%d_RecvCmd", index);
+       fprintf(f, "%s%s", temp_str, stat_delimiter);
+       fprintf(f, "%s_Timeout%s", temp_str, stat_delimiter);
+      } else {
+       fprintf(f, "%lu%s", curmsg->M_nbCmdRecv, stat_delimiter);
+       fprintf(f, "%lu%s", curmsg->nb_timeout, stat_delimiter);
+      }
+    } else if(curmsg -> M_type == MSG_TYPE_SENDCMD) {
+      if(header) {
+       sprintf(temp_str, "%d_SendCmd", index);
+       fprintf(f, "%s%s", temp_str, stat_delimiter);
+      } else {
+       fprintf(f, "%lu%s", curmsg->M_nbCmdSent, stat_delimiter);
+      }
+    } else {
+      ERROR("Unknown count file message type:");
+    }
+  }
+  fprintf(f, "\n");
+  fflush(f);
+}
+
+void print_header_line(FILE *f, int last)
+{  
+  switch(currentScreenToDisplay)
+    {
+    case DISPLAY_STAT_SCREEN :
+      fprintf(f,"----------------------------- Statistics Screen ------- [1-9]: Change Screen --" SIPP_ENDL);
+      break;
+    case DISPLAY_REPARTITION_SCREEN :
+      fprintf(f,"---------------------------- Repartition Screen ------- [1-9]: Change Screen --" SIPP_ENDL);
+      break;
+    case DISPLAY_VARIABLE_SCREEN  :
+      fprintf(f,"----------------------------- Variables Screen -------- [1-9]: Change Screen --" SIPP_ENDL);
+      break;
+    case DISPLAY_TDM_MAP_SCREEN  :
+      fprintf(f,"------------------------------ TDM map Screen --------- [1-9]: Change Screen --" SIPP_ENDL);
+      break;
+    case DISPLAY_SECONDARY_REPARTITION_SCREEN :
+      fprintf(f,"--------------------------- Repartition %d Screen ------ [1-9]: Change Screen --" SIPP_ENDL, currentRepartitionToDisplay);
+      break;
+    case DISPLAY_SCENARIO_SCREEN :
+    default:
+      fprintf(f,"------------------------------ Scenario Screen -------- [1-9]: Change Screen --" SIPP_ENDL);
+      break;
+    }
+}
+
+void print_bottom_line(FILE *f, int last)
+{
+  if(last) {
+    fprintf(f,"------------------------------ Test Terminated --------------------------------" SIPP_ENDL);
+  } else if(quitting) {
+    fprintf(f,"------- Waiting for active calls to end. Press [q] again to force exit. -------" SIPP_ENDL );
+  } else if(paused) {
+    fprintf(f,"----------------- Traffic Paused - Press [p] again to resume ------------------" SIPP_ENDL );
+  } else if(cpu_max) {
+    fprintf(f,"-------------------------------- CPU CONGESTED ---------------------------------" SIPP_ENDL);
+  } else if(outbound_congestion) {
+    fprintf(f,"------------------------------ OUTBOUND CONGESTION -----------------------------" SIPP_ENDL);
+  } else {
+    if (creationMode == MODE_CLIENT) {
+      switch(thirdPartyMode) {
+      case MODE_MASTER :
+        fprintf(f,"-----------------------3PCC extended mode - Master side -------------------------" SIPP_ENDL);
+        break;
+      case MODE_3PCC_CONTROLLER_A :
+        fprintf(f,"----------------------- 3PCC Mode - Controller A side -------------------------" SIPP_ENDL);
+        break;
+      case MODE_3PCC_NONE:
+       fprintf(f,"------ [+|-|*|/]: Adjust rate ---- [q]: Soft exit ---- [p]: Pause traffic -----" SIPP_ENDL);
+       break;
+      default:
+       ERROR("Internal error: creationMode=%d, thirdPartyMode=%d", creationMode, thirdPartyMode);
+      }
+    } else {
+      assert(creationMode == MODE_SERVER);
+      switch(thirdPartyMode) {
+      case MODE_3PCC_A_PASSIVE :
+        fprintf(f,"------------------ 3PCC Mode - Controller A side (passive) --------------------" SIPP_ENDL);
+        break;
+      case MODE_3PCC_CONTROLLER_B :
+        fprintf(f,"----------------------- 3PCC Mode - Controller B side -------------------------" SIPP_ENDL);
+        break;
+      case MODE_MASTER_PASSIVE :
+        fprintf(f,"------------------ 3PCC extended mode - Master side (passive) --------------------" SIPP_ENDL);
+        break;
+      case MODE_SLAVE :
+        fprintf(f,"----------------------- 3PCC extended mode - Slave side -------------------------" SIPP_ENDL);
+        break; 
+      case MODE_3PCC_NONE:
+        fprintf(f,"------------------------------ Sipp Server Mode -------------------------------" SIPP_ENDL);
+       break;
+      default:
+       ERROR("Internal error: creationMode=%d, thirdPartyMode=%d", creationMode, thirdPartyMode);
+      }
+    }
+  }
+  fprintf(f,SIPP_ENDL);
+  fflush(stdout);
+}
+
+void print_tdm_map()
+{
+  int interval = 0;
+  int i = 0;
+  int in_use = 0;
+  interval = (tdm_map_a+1) * (tdm_map_b+1) * (tdm_map_c+1);
+
+  printf("TDM Circuits in use:"  SIPP_ENDL);
+  while (i<interval) {
+    if (tdm_map[i]) {
+      printf("*");
+      in_use++;
+    } else {
+      printf(".");
+    }
+    i++;
+    if (i%(tdm_map_c+1) == 0) printf(SIPP_ENDL);
+  }
+  printf(SIPP_ENDL);
+  printf("%d/%d circuits (%d%%) in use", in_use, interval, int(100*in_use/interval));
+  printf(SIPP_ENDL);
+  for(unsigned int i=0; i<(display_scenario->messages.size() + 8 - int(interval/(tdm_map_c+1))); i++) {
+    printf(SIPP_ENDL);
+  }
+}
+
+void print_variable_list()
+{
+  CActions  * actions;
+  CAction   * action;
+  int printed = 0;
+  bool found;
+
+  printf("Action defined Per Message :" SIPP_ENDL);
+  printed++;
+  found = false;
+  for(unsigned int i=0; i<display_scenario->messages.size(); i++)
+  {
+    message *curmsg = display_scenario->messages[i];
+    actions = curmsg->M_actions;
+    if(actions != NULL)
+    {
+      switch(curmsg->M_type)
+      {
+       case MSG_TYPE_RECV:
+         printf("=> Message[%d] (Receive Message) - "
+             "[%d] action(s) defined :" SIPP_ENDL,
+             i,
+             actions->getActionSize());
+         printed++;
+         break;
+       case MSG_TYPE_RECVCMD:
+         printf("=> Message[%d] (Receive Command Message) - "
+             "[%d] action(s) defined :" SIPP_ENDL,
+             i,
+             actions->getActionSize());
+         printed++;
+         break;
+       default:
+         printf("=> Message[%d] - [%d] action(s) defined :" SIPP_ENDL,
+             i,
+             actions->getActionSize());
+         printed++;
+         break;
+      }
+
+      for(int j=0; j<actions->getActionSize(); j++)
+      {
+       action = actions->getAction(j);
+       if(action != NULL)
+       {
+         printf("   --> action[%d] = ", j);
+         action->afficheInfo();
+         printf(SIPP_ENDL);
+         printed++;
+         found = true;
+       }
+      }
+    }
+  }
+  if(!found) {
+       printed++;
+       printf("=> No action found on any messages"SIPP_ENDL);
+  }
+  
+  printf(SIPP_ENDL);
+  for(unsigned int i=0; i<(display_scenario->messages.size() + 5 - printed); i++) {
+    printf(SIPP_ENDL);
+  }
+}
+
+/* Function to dump all available screens in a file */
+void print_screens(void)
+{
+  int oldScreen = currentScreenToDisplay;
+  int oldRepartition = currentRepartitionToDisplay;
+
+  currentScreenToDisplay = DISPLAY_SCENARIO_SCREEN;  
+  print_header_line(   screenf, 0);
+  print_stats_in_file( screenf, 0);
+  print_bottom_line(   screenf, 0);
+
+  currentScreenToDisplay = DISPLAY_STAT_SCREEN;  
+  print_header_line(   screenf, 0);
+  display_scenario->stats->displayStat(screenf);
+  print_bottom_line(   screenf, 0);
+
+  currentScreenToDisplay = DISPLAY_REPARTITION_SCREEN;
+  print_header_line(   screenf, 0);
+  display_scenario->stats->displayRepartition(screenf);
+  print_bottom_line(   screenf, 0);
+
+  currentScreenToDisplay = DISPLAY_SECONDARY_REPARTITION_SCREEN;
+  for (currentRepartitionToDisplay = 2; currentRepartitionToDisplay <= display_scenario->stats->nRtds(); currentRepartitionToDisplay++) {
+    print_header_line(   screenf, 0);
+    display_scenario->stats->displayRtdRepartition(screenf, currentRepartitionToDisplay);
+    print_bottom_line(   screenf, 0);
+  }
+
+  currentScreenToDisplay = oldScreen;
+  currentRepartitionToDisplay = oldRepartition;
+}
+
+void print_statistics(int last)
+{
+  static int first = 1;
+
+  if(backgroundMode == false && display_scenario) {
+    if(!last) {
+      screen_clear();
+    }
+
+    if(first) {
+      first = 0;
+      printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+             "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
+    }
+    if (command_mode) {
+       printf(SIPP_ENDL);
+    }
+    print_header_line(stdout,last);
+    switch(currentScreenToDisplay) {
+      case DISPLAY_STAT_SCREEN :
+        display_scenario->stats->displayStat(stdout);
+        break;
+      case DISPLAY_REPARTITION_SCREEN :
+        display_scenario->stats->displayRepartition(stdout);
+        break;
+      case DISPLAY_VARIABLE_SCREEN  :
+        print_variable_list();
+        break;
+      case DISPLAY_TDM_MAP_SCREEN  :
+        print_tdm_map();
+        break;
+      case DISPLAY_SECONDARY_REPARTITION_SCREEN :
+       display_scenario->stats->displayRtdRepartition(stdout, currentRepartitionToDisplay);
+       break;
+      case DISPLAY_SCENARIO_SCREEN :
+      default:
+        print_stats_in_file(stdout, last);
+        break;
+    }
+    print_bottom_line(stdout,last);
+    if (!last && screen_last_error[0]) {
+       char *errstart = screen_last_error;
+       int colonsleft = 4;/* We want to skip the time. */
+       while (*errstart && colonsleft) {
+         if (*errstart == ':') {
+               colonsleft--;
+         }
+         errstart++;
+       }
+       while (isspace(*errstart)) {
+         errstart++;
+       }
+       if (strlen(errstart) > 60) {
+         printf("Last Error: %.60s..." SIPP_ENDL, errstart);
+       } else {
+         printf("Last Error: %s" SIPP_ENDL, errstart);
+       }
+       fflush(stdout);
+    }
+    if (command_mode) {
+       printf("Command: %s", command_buffer ? command_buffer : "");
+       fflush(stdout);
+    }
+    if(last) { fprintf(stdout,"\n"); }
+  }
+}
+
+void sipp_sigusr1(int /* not used */)
+{
+  /* Smooth exit: do not place any new calls and exit */
+  quitting+=10;
+}
+
+void sipp_sigusr2(int /* not used */)
+{
+  if (!signalDump) {
+     signalDump = true ;
+  }
+}
+
+bool process_key(int c) {
+    switch (c) {
+    case '1':
+      currentScreenToDisplay = DISPLAY_SCENARIO_SCREEN;
+      print_statistics(0);
+      break;
+
+    case '2':
+      currentScreenToDisplay = DISPLAY_STAT_SCREEN;
+      print_statistics(0);
+      break;
+
+    case '3':
+      currentScreenToDisplay = DISPLAY_REPARTITION_SCREEN;
+      print_statistics(0);
+      break;
+
+    case '4':
+      currentScreenToDisplay = DISPLAY_VARIABLE_SCREEN;
+      print_statistics(0);
+      break;
+
+    case '5':
+      if (use_tdmmap) {
+        currentScreenToDisplay = DISPLAY_TDM_MAP_SCREEN;
+        print_statistics(0);
+      }
+      break;
+
+    /* Screens 6, 7, 8, 9  are for the extra RTD repartitions. */
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      currentScreenToDisplay = DISPLAY_SECONDARY_REPARTITION_SCREEN;
+      currentRepartitionToDisplay = (c - '6') + 2;
+      print_statistics(0);
+      break;
+
+    case '+':
+      if (users >= 0) {
+       opentask::set_users((int)(users + 1 * rate_scale));
+      } else {
+       opentask::set_rate(rate + 1 * rate_scale);
+      }
+      print_statistics(0);
+      break;
+
+    case '-':
+      if (users >= 0) {
+       opentask::set_users((int)(users - 1 * rate_scale));
+      } else {
+       opentask::set_rate(rate - 1 * rate_scale);
+      }
+      print_statistics(0);
+      break;
+
+    case '*':
+      if (users >= 0) {
+       opentask::set_users((int)(users + 10 * rate_scale));
+      } else {
+       opentask::set_rate(rate + 10 * rate_scale);
+      }
+      print_statistics(0);
+      break;
+
+    case '/':
+      if (users >= 0) {
+       opentask::set_users((int)(users - 10 * rate_scale));
+      } else {
+       opentask::set_rate(rate - 10 * rate_scale);
+      }
+      print_statistics(0);
+      break;
+
+    case 'p':
+      if(paused) { 
+       opentask::set_paused(false);
+      } else {
+       opentask::set_paused(true);
+      }
+      print_statistics(0);
+      break;
+
+    case 's':
+      if (screenf) {
+       print_screens();
+      }
+      break;
+
+    case 'q':
+      quitting+=10;
+      print_statistics(0);
+      break;
+
+    case 'Q':
+      /* We are going to break, so we never have a chance to press q twice. */
+      quitting+=20;
+      print_statistics(0);
+      break;
+    }
+    return false;
+}
+
+void trim(char *s) {
+  char *p = s;
+  while(isspace(*p)) {
+    p++;
+  }
+  int l = strlen(p);
+  for (int i = l - 1; i >= 0 && isspace(p[i]); i--) {
+    p[i] = '\0';
+  }
+  memmove(s, p, l + 1);
+}
+
+void process_set(char *what) {
+  char *rest = strchr(what, ' ');
+  if (rest) {
+       *rest++ = '\0';
+       trim(rest);
+  } else {
+       WARNING("The set command requires two arguments (attribute and value)");
+       return;
+  }
+
+  if (!strcmp(what, "rate")) {
+    char *end;
+    double drest = strtod(rest, &end);
+
+    if (users >= 0) {
+      WARNING("Rates can not be set in a user-based benchmark.");
+    } else if (*end) {
+      WARNING("Invalid rate value: \"%s\"", rest);
+    } else {
+      opentask::set_rate(drest);
+    }
+  } else if (!strcmp(what, "rate-scale")) {
+    char *end;
+    double drest = strtod(rest, &end);
+    if (*end) {
+      WARNING("Invalid rate-scale value: \"%s\"", rest);
+    } else {
+      rate_scale = drest;
+    }
+  } else if (!strcmp(what, "users")) {
+    char *end;
+    int urest = strtol(rest, &end, 0);
+
+    if (users < 0) {
+      WARNING("Users can not be changed at run time for a rate-based benchmark.");
+    } else if (*end) {
+      WARNING("Invalid users value: \"%s\"", rest);
+    } else if (urest < 0) {
+      WARNING("Invalid users value: \"%s\"", rest);
+    } else {
+      opentask::set_users(urest);
+    }
+  } else if (!strcmp(what, "limit")) {
+    char *end;
+    unsigned long lrest = strtoul(rest, &end, 0);
+    if (users >= 0) {
+      WARNING("Can not set call limit for a user-based benchmark.");
+    } else if (*end) {
+      WARNING("Invalid limit value: \"%s\"", rest);
+    } else {
+      open_calls_allowed = lrest;
+      open_calls_user_setting = 1;
+    }
+  } else if (!strcmp(what, "display")) {
+    if (!strcmp(rest, "main")) {
+      display_scenario = main_scenario;
+    } else if (!strcmp(rest, "ooc")) {
+      display_scenario = ooc_scenario;
+    } else {
+       WARNING("Unknown display scenario: %s", rest);
+    }
+  } else if (!strcmp(what, "hide")) {
+    if (!strcmp(rest, "true")) {
+      do_hide = true;
+    } else if (!strcmp(rest, "false")) {
+      do_hide = false;
+    } else {
+      WARNING("Invalid bool: %s", rest);
+    }
+  } else if (!strcmp(what, "index")) {
+    if (!strcmp(rest, "true")) {
+      show_index = true;
+    } else if (!strcmp(rest, "false")) {
+      show_index = false;
+    } else {
+      WARNING("Invalid bool: %s", rest);
+    }
+  } else {
+    WARNING("Unknown set attribute: %s", what);
+  }
+}
+
+void log_off(struct logfile_info *lfi) {
+  if (lfi->fptr) {
+    fflush(lfi->fptr);
+    fclose(lfi->fptr);
+    lfi->fptr = NULL;
+    lfi->overwrite = false;
+  }
+}
+
+void process_trace(char *what) {
+  bool on = false;
+  char *rest = strchr(what, ' ');
+  if (rest) {
+       *rest++ = '\0';
+       trim(rest);
+  } else {
+       WARNING("The trace command requires two arguments (log and [on|off])");
+       return;
+  }
+
+  if (!strcmp(rest, "on")) {
+       on = true;
+  }
+  else if (!strcmp(rest, "off")) {
+       on = false;
+  }
+  else if (!strcmp(rest, "true")) {
+       on = true;
+  }
+  else if (!strcmp(rest, "false")) {
+       on = false;
+  }
+  else {
+       WARNING("The trace command's second argument must be on or off.");
+       return;
+  }
+
+  if (!strcmp(what, "error")) {
+    if (on == !!print_all_responses) {
+      return;
+    }
+    if (on) {
+      print_all_responses = 1;
+    } else {
+      print_all_responses = 0;
+      log_off(&error_lfi);
+    }
+  } else if (!strcmp(what, "logs")) {
+    if (on == !!log_lfi.fptr) {
+      return;
+    }
+    if (on) {
+      useLogf = 1;
+      rotate_logfile();
+    } else {
+      useLogf = 0;
+      log_off(&log_lfi);
+    }
+  } else if (!strcmp(what, "messages")) {
+    if (on == !!message_lfi.fptr) {
+      return;
+    }
+    if (on) {
+      useMessagef = 1;
+      rotate_logfile();
+    } else {
+      useMessagef = 0;
+      log_off(&message_lfi);
+    }
+  } else if (!strcmp(what, "shortmessages")) {
+    if (on == !!shortmessage_lfi.fptr) {
+      return;
+    }
+
+    if (on) {
+      useShortMessagef = 1;
+      rotate_shortmessagef();
+    } else {
+      useShortMessagef = 0;
+      log_off(&shortmessage_lfi);
+    }
+  } else {
+    WARNING("Unknown log file: %s", what);
+  }
+}
+
+void process_dump(char *what) {
+  if (!strcmp(what, "tasks")) {
+    dump_tasks();
+  } else if (!strcmp(what, "variables")) {
+    display_scenario->allocVars->dump();
+  } else {
+    WARNING("Unknown dump type: %s", what);
+  }
+}
+
+void process_reset(char *what) {
+  if (!strcmp(what, "stats")) {
+    main_scenario->stats->computeStat(CStat::E_RESET_C_COUNTERS);
+  } else {
+    WARNING("Unknown reset type: %s", what);
+  }
+}
+
+bool process_command(char *command) {
+  trim(command);
+
+  char *rest = strchr(command, ' ');
+  if (rest) {
+       *rest++ = '\0';
+       trim(rest);
+  }
+
+  if (!strcmp(command, "set")) {
+       process_set(rest);
+  } else if (!strcmp(command, "trace")) {
+       process_trace(rest);
+  } else if (!strcmp(command, "dump")) {
+       process_dump(rest);
+  } else if (!strcmp(command, "reset")) {
+       process_reset(rest);
+  } else {
+       WARNING("Unrecognized command: \"%s\"", command);
+  }
+
+  return false;
+}
+
+
+int handle_ctrl_socket() {
+  unsigned char bufrcv [SIPP_MAX_MSG_SIZE];
+
+  int ret = recv(ctrl_socket->ss_fd,bufrcv,sizeof(bufrcv) - 1,0);
+  if (ret <= 0) {
+    return ret;
+  }
+
+  if (bufrcv[0] == 'c') {
+    /* No 'c', but we need one for '\0'. */
+    char *command = (char *)malloc(ret);
+    if (!command) {
+      ERROR("Out of memory allocated command buffer.");
+    }
+    memcpy(command, bufrcv + 1, ret - 1);
+    command[ret - 1] = '\0';
+    process_command(command);
+    free(command);
+  } else {
+    process_key(bufrcv[0]);
+  }
+  return 0;
+}
+
+void setup_ctrl_socket() {
+  int port, firstport;
+  int try_counter = 60;
+  struct sockaddr_storage ctl_sa;
+
+  int sock = socket(AF_INET,SOCK_DGRAM,0);
+  if (sock == -1) {
+    ERROR_NO("Unable to create remote control socket!");
+  }
+
+  if (control_port) {
+    port = control_port;
+    /* If the user specified the control port, then we must assume they know
+     * what they want, and should not cycle. */
+    try_counter = 1;
+  } else {
+    /* Allow 60 control sockets on the same system */
+    /* (several SIPp instances)                   */
+    port = DEFAULT_CTRL_SOCKET_PORT;
+  }
+  firstport = port;
+
+  memset(&ctl_sa,0,sizeof(struct sockaddr_storage));
+  if (control_ip[0]) {
+    struct addrinfo hints;
+    struct addrinfo *addrinfo;
+
+    memset((char*)&hints, 0, sizeof(hints));
+    hints.ai_flags  = AI_PASSIVE;
+    hints.ai_family = PF_UNSPEC;
+
+    if (getaddrinfo(control_ip, NULL, &hints, &addrinfo) != 0) {
+      ERROR("Unknown control address '%s'.\n"
+         "Use 'sipp -h' for details", control_ip);
+    }
+
+    memcpy(&ctl_sa, addrinfo->ai_addr, SOCK_ADDR_SIZE(_RCAST(struct sockaddr_storage *,addrinfo->ai_addr)));
+    freeaddrinfo(addrinfo);
+  } else {
+    ((struct sockaddr_in *)&ctl_sa)->sin_family = AF_INET;
+    ((struct sockaddr_in *)&ctl_sa)->sin_addr.s_addr = INADDR_ANY;
+  }
+
+  while (try_counter) {
+    ((struct sockaddr_in *)&ctl_sa)->sin_port = htons(port);
+    if (!bind(sock,(struct sockaddr *)&ctl_sa,sizeof(struct sockaddr_in))) {
+      /* Bind successful */
+      break;
+    }
+    try_counter--;
+    port++;
+  }
+
+  if (try_counter == 0) {
+    if (control_port) {
+      ERROR_NO("Unable to bind remote control socket to UDP port %d",
+                  control_port);
+    } else {
+      WARNING("Unable to bind remote control socket (tried UDP ports %d-%d): %s",
+                  firstport, port - 1, strerror(errno));
+    }
+    return;
+  }
+
+  ctrl_socket = sipp_allocate_socket(0, T_UDP, sock, 0);
+  if (!ctrl_socket) {
+    ERROR_NO("Could not setup control socket!\n");
+  }
+}
+
+void setup_stdin_socket() {
+  fcntl(fileno(stdin), F_SETFL, fcntl(fileno(stdin), F_GETFL) | O_NONBLOCK);
+  stdin_socket = sipp_allocate_socket(0, T_UDP, fileno(stdin), 0);
+  if (!stdin_socket) {
+    ERROR_NO("Could not setup keyboard (stdin) socket!\n");
+  }
+}
+
+void handle_stdin_socket() {
+  int c;
+  int chars = 0;
+
+  if (feof(stdin)) {
+    sipp_close_socket(stdin_socket);
+    stdin_socket = NULL;
+    return;
+  }
+
+  while (((c = screen_readkey()) != -1)) {
+    chars++;
+    if (command_mode) {
+      if (c == '\n') {
+       bool quit = process_command(command_buffer);
+       if (quit) {
+         return;
+       }
+       command_buffer[0] = '\0';
+       command_mode = 0;
+       printf(SIPP_ENDL);
+      }
+#ifndef __SUNOS
+      else if (c == KEY_BACKSPACE || c == KEY_DC)
+#else
+      else if (c == 14)
+#endif
+      {
+       int command_len = strlen(command_buffer);
+       if (command_len > 0) {
+         command_buffer[command_len--] = '\0';
+       }
+      } else {
+       int command_len = strlen(command_buffer);
+       command_buffer = (char *)realloc(command_buffer, command_len + 2);
+       command_buffer[command_len++] = c;
+       command_buffer[command_len] = '\0';
+       putchar(c);
+       fflush(stdout);
+      }
+    } else if (c == 'c') {
+      command_mode = 1;
+      command_buffer = (char *)realloc(command_buffer, 1);
+      command_buffer[0] = '\0';
+      printf("Command: ");
+      fflush(stdout);
+    } else {
+      process_key(c);
+    }
+  }
+  if (chars == 0) {
+    /* We did not read any characters, even though we should have. */
+    sipp_close_socket(stdin_socket);
+    stdin_socket = NULL;
+  }
+}
+
+/*************************** Mini SIP parser ***************************/
+
+char * get_peer_tag(char *msg)
+{
+  char        * to_hdr;
+  char        * ptr; 
+  char        * end_ptr;
+  static char   tag[MAX_HEADER_LEN];
+  int           tag_i = 0;
+  
+  to_hdr = strstr(msg, "\r\nTo:");
+  if(!to_hdr) to_hdr = strstr(msg, "\r\nto:");
+  if(!to_hdr) to_hdr = strstr(msg, "\r\nTO:");
+  if(!to_hdr) to_hdr = strstr(msg, "\r\nt:");
+  if(!to_hdr) {
+    ERROR("No valid To: header in reply");
+  }
+
+  // Remove CRLF
+  to_hdr += 2;
+
+  end_ptr = strchr(to_hdr,'\n');
+
+  ptr = strchr(to_hdr, '>');
+  if (!ptr) {
+    return NULL;
+  }
+  
+  ptr = strchr(to_hdr, ';'); 
+  
+  if(!ptr) {
+    return NULL;
+  }
+  
+  to_hdr = ptr;
+
+  ptr = strstr(to_hdr, "tag");
+  if(!ptr) { ptr = strstr(to_hdr, "TAG"); }
+  if(!ptr) { ptr = strstr(to_hdr, "Tag"); }
+
+  if(!ptr) {
+    return NULL;
+  }
+
+  if (ptr>end_ptr) {
+    return NULL ;
+  }
+  
+  ptr = strchr(ptr, '='); 
+  
+  if(!ptr) {
+    ERROR("Invalid tag param in To: header");
+  }
+
+  ptr ++;
+
+  while((*ptr)         && 
+        (*ptr != ' ')  && 
+        (*ptr != ';')  && 
+        (*ptr != '\t') && 
+        (*ptr != '\t') && 
+        (*ptr != '\r') &&  
+        (*ptr != '\n') && 
+        (*ptr)) {
+    tag[tag_i++] = *(ptr++);
+  }
+  tag[tag_i] = 0;
+  
+  return tag;
+}
+
+char * get_incoming_header_content(char* message, char * name)
+{
+  /* non reentrant. consider accepting char buffer as param */
+  static char last_header[MAX_HEADER_LEN * 10];
+  char * src, *dest, *ptr;
+
+  /* returns empty string in case of error */
+  memset(last_header, 0, sizeof(last_header));
+
+  if((!message) || (!strlen(message))) {
+    return last_header;
+  }
+
+  src = message;
+  dest = last_header;
+  
+  /* for safety's sake */
+  if (NULL == name || NULL == strrchr(name, ':')) {
+      return last_header;
+  }
+
+  while((src = strstr(src, name))) {
+
+      /* just want the header's content */
+      src += strlen(name);
+
+    ptr = strchr(src, '\n');
+    
+    /* Multiline headers always begin with a tab or a space
+     * on the subsequent lines */
+    while((ptr) &&
+          ((*(ptr+1) == ' ' ) ||
+           (*(ptr+1) == '\t')    )) {
+      ptr = strchr(ptr + 1, '\n'); 
+    }
+
+    if(ptr) { *ptr = 0; }
+    // Add "," when several headers are present
+    if (dest != last_header) {
+      dest += sprintf(dest, ",");
+    }
+    dest += sprintf(dest, "%s", src);
+    if(ptr) { *ptr = '\n'; }
+    
+    src++;
+  }
+  
+  if(dest == last_header) {
+    return last_header;
+  }
+
+  *(dest--) = 0;
+
+  /* Remove trailing whitespaces, tabs, and CRs */
+  while ((dest > last_header) && 
+         ((*dest == ' ') || (*dest == '\r')|| (*dest == '\t'))) {
+    *(dest--) = 0;
+  }
+
+  /* remove enclosed CRs in multilines */
+  while((ptr = strchr(last_header, '\r'))) {
+    /* Use strlen(ptr) to include trailing zero */
+    memmove(ptr, ptr+1, strlen(ptr));
+  }
+
+  return last_header;
+}
+
+char * get_incoming_first_line(char * message)
+{
+  /* non reentrant. consider accepting char buffer as param */
+  static char last_header[MAX_HEADER_LEN * 10];
+  char * src, *dest;
+
+  /* returns empty string in case of error */
+  memset(last_header, 0, sizeof(last_header));
+
+  if((!message) || (!strlen(message))) {
+    return last_header;
+  }
+
+  src = message;
+  dest = last_header;
+  
+  int i=0;
+  while (*src){
+    if((*src=='\n')||(*src=='\r')){
+      break;
+    }
+    else
+    {
+      last_header[i]=*src;
+    }
+    i++;
+    src++;
+  }
+  
+  return last_header;
+}
+
+
+char * get_call_id(char *msg)
+{
+  static char call_id[MAX_HEADER_LEN];
+  char * ptr1, * ptr2, * ptr3, backup;
+  bool short_form;
+
+  call_id[0] = '\0';
+
+  short_form = false;
+
+  ptr1 = strstr(msg, "Call-ID:");
+  if(!ptr1) { ptr1 = strstr(msg, "Call-Id:"); }
+  if(!ptr1) { ptr1 = strstr(msg, "Call-id:"); }
+  if(!ptr1) { ptr1 = strstr(msg, "call-Id:"); }
+  if(!ptr1) { ptr1 = strstr(msg, "call-id:"); }
+  if(!ptr1) { ptr1 = strstr(msg, "CALL-ID:"); }
+  // For short form, we need to make sure we start from beginning of line
+  // For others, no need to
+  if(!ptr1) { ptr1 = strstr(msg, "\r\ni:"); short_form = true;}
+  if(!ptr1) {
+    WARNING("(1) No valid Call-ID: header in reply '%s'", msg);
+    return call_id;
+  }
+  
+  if (short_form) {
+    ptr1 += 4;
+  } else {
+    ptr1 += 8;
+  }
+  
+  while((*ptr1 == ' ') || (*ptr1 == '\t')) { ptr1++; }
+  
+  if(!(*ptr1)) {
+    WARNING("(2) No valid Call-ID: header in reply");
+    return call_id;
+  }
+  
+  ptr2 = ptr1;
+
+  while((*ptr2) && 
+        (*ptr2 != ' ') && 
+        (*ptr2 != '\t') && 
+        (*ptr2 != '\r') && 
+        (*ptr2 != '\n')) { 
+    ptr2 ++;
+  } 
+
+  if(!*ptr2) {
+    WARNING("(3) No valid Call-ID: header in reply");
+    return call_id;
+  }
+
+  backup = *ptr2;
+  *ptr2 = 0;
+  if ((ptr3 = strstr(ptr1, "///")) != 0) ptr1 = ptr3+3;
+  strcpy(call_id, ptr1);
+  *ptr2 = backup;
+  return (char *) call_id;
+}
+
+unsigned long int get_cseq_value(char *msg) {
+  char *ptr1;
+
+  // no short form for CSeq:
+  ptr1 = strstr(msg, "\r\nCSeq:");
+  if(!ptr1) { ptr1 = strstr(msg, "\r\nCSEQ:"); }
+  if(!ptr1) { ptr1 = strstr(msg, "\r\ncseq:"); }
+  if(!ptr1) { ptr1 = strstr(msg, "\r\nCseq:"); }
+  if(!ptr1) { WARNING("No valid Cseq header in request %s", msg); return 0;}
+  ptr1 += 7;
+  while((*ptr1 == ' ') || (*ptr1 == '\t')) {++ptr1;}
+  if(!(*ptr1)) { WARNING("No valid Cseq data in header"); return 0;}
+  return strtoul(ptr1, NULL, 10);
+}
+
+unsigned long get_reply_code(char *msg)
+{
+  while((msg) && (*msg != ' ') && (*msg != '\t')) msg ++;
+  while((msg) && ((*msg == ' ') || (*msg == '\t'))) msg ++;
+
+  if ((msg) && (strlen(msg)>0)) {
+    return atol(msg);
+  } else {
+    return 0;
+  }
+}
+
+/*************************** I/O functions ***************************/
+
+/* Allocate a socket buffer. */
+struct socketbuf *alloc_socketbuf(char *buffer, size_t size, int copy, struct sockaddr_storage *dest) {
+  struct socketbuf *socketbuf;
+
+  socketbuf = (struct socketbuf *)malloc(sizeof(struct socketbuf));
+  if (!socketbuf) {
+       ERROR("Could not allocate socket buffer!\n");
+  }
+  memset(socketbuf, 0, sizeof(struct socketbuf));
+  if (copy) {
+    socketbuf->buf = (char *)malloc(size);
+    if (!socketbuf->buf) {
+      ERROR("Could not allocate socket buffer data!\n");
+    }
+    memcpy(socketbuf->buf, buffer, size);
+  } else {
+    socketbuf->buf = buffer;
+  }
+  socketbuf->len = size;
+  socketbuf->offset = 0;
+  if (dest) {
+    memcpy(&socketbuf->addr, dest, SOCK_ADDR_SIZE(dest));
+  }
+  socketbuf->next = NULL;
+
+  return socketbuf;
+}
+
+/* Free a poll buffer. */
+void free_socketbuf(struct socketbuf *socketbuf) {
+  free(socketbuf->buf);
+  free(socketbuf);
+}
+
+size_t decompress_if_needed(int sock, char *buff,  size_t len, void **st)
+{
+  if(compression && len) {
+    if (useMessagef == 1) {      
+    struct timeval currentTime;
+    GET_TIME (&currentTime);
+    TRACE_MSG("----------------------------------------------- %s\n"
+               "Compressed message received, header :\n"
+               "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x "
+               "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
+               CStat::formatTime(&currentTime, true),
+               buff[0] , buff[1] , buff[2] , buff[3],
+               buff[4] , buff[5] , buff[6] , buff[7],
+               buff[8] , buff[9] , buff[10], buff[11],
+               buff[12], buff[13], buff[14], buff[15]);
+    }
+    
+    int rc = comp_uncompress(st,
+                             buff, 
+                             (unsigned int *) &len);
+    
+    switch(rc) {
+    case COMP_OK:
+      TRACE_MSG("Compressed message decompressed properly.\n");
+      break;
+
+    case COMP_REPLY:
+      TRACE_MSG("Compressed message KO, sending a reply (resynch).\n");
+      sendto(sock,
+             buff, 
+             len, 
+             0,
+             (sockaddr *)(void *)&remote_sockaddr,
+             SOCK_ADDR_SIZE(&remote_sockaddr));
+      resynch_send++;
+      return 0;
+
+    case COMP_DISCARD:
+      TRACE_MSG("Compressed message discarded by pluggin.\n");
+      resynch_recv++;
+      return 0;
+
+    default:
+    case COMP_KO:
+      ERROR("Compression pluggin error");
+      return 0;
+    }
+  }
+  return len;
+}
+
+#ifdef USE_SCTP
+void sipp_sctp_peer_params(struct sipp_socket *socket)
+{
+  if (heartbeat > 0 || pathmaxret > 0)
+  {
+   struct sctp_paddrparams peerparam;
+   memset(&peerparam, 0, sizeof(peerparam));
+
+   sockaddr* addresses;
+   int addresscount = sctp_getpaddrs(socket->ss_fd, 0, &addresses);
+   if (addresscount < 1) WARNING("sctp_getpaddrs, errno=%d", errno);
+
+   for (int i = 0; i < addresscount; i++)
+   {
+     memset(&peerparam.spp_address, 0, sizeof(peerparam.spp_address));
+     struct sockaddr_storage* peeraddress = (struct sockaddr_storage*) &addresses[i];
+     memcpy(&peerparam.spp_address, peeraddress, SOCK_ADDR_SIZE(peeraddress));
+
+     peerparam.spp_hbinterval = heartbeat;
+     peerparam.spp_pathmaxrxt = pathmaxret;
+     if (heartbeat > 0) peerparam.spp_flags = SPP_HB_ENABLE;
+
+     if (pmtu > 0) {
+         peerparam.spp_pathmtu = pmtu;
+         peerparam.spp_flags |= SPP_PMTUD_DISABLE;
+     }
+
+     if (setsockopt(socket->ss_fd, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS,
+                 &peerparam, sizeof(peerparam)) == -1) {
+      sctp_freepaddrs(addresses);
+      WARNING("setsockopt(SCTP_PEER_ADDR_PARAMS) failed, errno=%d", errno);
+     }
+    }
+    sctp_freepaddrs(addresses);
+  }
+}
+#endif
+
+void sipp_customize_socket(struct sipp_socket *socket)
+{
+  unsigned int buffsize = buff_size;
+
+  /* Allows fast TCP reuse of the socket */
+  if (socket->ss_transport == T_TCP || socket->ss_transport == T_TLS ||
+          socket->ss_transport == T_SCTP) {
+    int sock_opt = 1;
+
+    if (setsockopt(socket->ss_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&sock_opt,
+                   sizeof (sock_opt)) == -1) {
+      ERROR_NO("setsockopt(SO_REUSEADDR) failed");
+    }
+
+#ifdef USE_SCTP
+    if (socket->ss_transport == T_SCTP)
+    {
+       struct sctp_event_subscribe event;
+       memset(&event, 0, sizeof(event));
+       event.sctp_data_io_event = 1;
+       event.sctp_association_event = 1;
+       event.sctp_shutdown_event = 1;
+       if (setsockopt(socket->ss_fd,IPPROTO_SCTP, SCTP_EVENTS, &event,
+                   sizeof(event)) == -1) {
+        ERROR_NO("setsockopt(SCTP_EVENTS) failed, errno=%d",errno);
+       }
+
+       if (assocmaxret > 0)
+       {
+        struct sctp_assocparams associnfo;
+        memset(&associnfo, 0, sizeof(associnfo));
+        associnfo.sasoc_asocmaxrxt = assocmaxret;
+        if (setsockopt(socket->ss_fd, IPPROTO_SCTP, SCTP_ASSOCINFO, &associnfo,
+                    sizeof(associnfo)) == -1) {
+          WARNING("setsockopt(SCTP_ASSOCINFO) failed, errno=%d", errno);
+        }
+       }
+
+       if (setsockopt(socket->ss_fd, IPPROTO_SCTP, SCTP_NODELAY,
+                   (void *)&sock_opt, sizeof (sock_opt)) == -1) {
+        WARNING("setsockopt(SCTP_NODELAY) failed, errno=%d", errno);
+       }
+    }
+#endif
+
+#ifndef SOL_TCP
+#define SOL_TCP 6
+#endif
+    if (socket->ss_transport != T_SCTP)
+    {
+    if (setsockopt(socket->ss_fd, SOL_TCP, TCP_NODELAY, (void *)&sock_opt,
+                    sizeof (sock_opt)) == -1) {
+      {
+        ERROR_NO("setsockopt(TCP_NODELAY) failed");
+      }
+    }
+    }
+
+    {
+      struct linger linger;
+
+      linger.l_onoff = 1;
+      linger.l_linger = 1;
+      if (setsockopt (socket->ss_fd, SOL_SOCKET, SO_LINGER,
+                      &linger, sizeof (linger)) < 0) {
+        ERROR_NO("Unable to set SO_LINGER option");
+      }
+    }
+  }
+
+    /* Increase buffer sizes for this sockets */
+  if(setsockopt(socket->ss_fd,
+                SOL_SOCKET,
+                SO_SNDBUF,
+                &buffsize,
+                sizeof(buffsize))) {
+    ERROR_NO("Unable to set socket sndbuf");
+  }
+
+  buffsize = buff_size;
+  if(setsockopt(socket->ss_fd,
+                SOL_SOCKET,
+                SO_RCVBUF,
+                &buffsize,
+                sizeof(buffsize))) {
+    ERROR_NO("Unable to set socket rcvbuf");
+  }
+}
+
+static ssize_t socket_write_primitive(struct sipp_socket *socket, char *buffer, size_t len, struct sockaddr_storage *dest) {
+  ssize_t rc;
+
+  /* Refuse to write to invalid sockets. */
+  if (socket->ss_invalid) {
+    WARNING("Returning EPIPE on invalid socket: %p (%d)\n", socket, socket->ss_fd);
+    errno = EPIPE;
+    return -1;
+  }
+
+  /* Always check congestion before sending. */
+  if (socket->ss_congested) {
+    errno = EWOULDBLOCK;
+    return -1;
+  }
+
+  switch(socket->ss_transport) {
+    case T_TLS:
+#ifdef _USE_OPENSSL
+      rc = send_nowait_tls(socket->ss_ssl, buffer, len, 0);
+#else
+      errno = EOPNOTSUPP;
+      rc = -1;
+#endif
+      break;
+    case T_SCTP:
+#ifdef USE_SCTP
+     {
+      TRACE_MSG("socket_write_primitive %d\n", socket->sctpstate);
+      if (socket->sctpstate == SCTP_DOWN)
+      {
+       errno = EPIPE;
+       return -1;
+      }
+      else if (socket->sctpstate == SCTP_CONNECTING)
+      {
+       errno = EWOULDBLOCK;
+       return -1;
+      }
+      rc = send_sctp_nowait(socket->ss_fd, buffer, len, 0);
+     }
+#else
+      errno = EOPNOTSUPP;
+      rc = -1;
+#endif
+      break;
+    case T_TCP:
+      rc = send_nowait(socket->ss_fd, buffer, len, 0);
+      break;
+    case T_UDP:
+      if(compression) {
+       static char comp_msg[SIPP_MAX_MSG_SIZE];
+       strcpy(comp_msg, buffer);
+       if(comp_compress(&socket->ss_comp_state,
+             comp_msg,
+             (unsigned int *) &len) != COMP_OK) {
+         ERROR("Compression pluggin error");
+       }
+       buffer = (char *)comp_msg;
+
+       TRACE_MSG("---\nCompressed message len: %d\n", len);
+      }
+
+      rc = sendto(socket->ss_fd, buffer, len, 0, (struct sockaddr *)dest, SOCK_ADDR_SIZE(dest));
+
+      break;
+    default:
+      ERROR("Internal error, unknown transport type %d\n", socket->ss_transport);
+  }
+
+  return rc;
+}
+
+/* This socket is congested, mark it as such and add it to the poll files. */
+int enter_congestion(struct sipp_socket *socket, int again) {
+  socket->ss_congested = true;
+
+  TRACE_MSG("Problem %s on socket  %d and poll_idx  is %d \n",
+       again == EWOULDBLOCK ? "EWOULDBLOCK" : "EAGAIN",
+       socket->ss_fd, socket->ss_pollidx);
+
+  pollfiles[socket->ss_pollidx].events |= POLLOUT;
+
+#ifdef USE_SCTP
+  if (!(socket->ss_transport == T_SCTP &&
+              socket->sctpstate == SCTP_CONNECTING))
+#endif
+    nb_net_cong++;
+  return -1;
+}
+
+
+static int write_error(struct sipp_socket *socket, int ret) {
+  const char *errstring = strerror(errno);
+
+#ifndef EAGAIN
+  int again = (errno == EWOULDBLOCK) ? errno : 0;
+#else
+  int again = ((errno == EAGAIN) || (errno == EWOULDBLOCK)) ? errno : 0;
+
+  /* Scrub away EAGAIN from the rest of the code. */
+  if (errno == EAGAIN) {
+       errno = EWOULDBLOCK;
+  }
+#endif
+
+  if(again) {
+    return enter_congestion(socket, again);
+  }
+
+  if ((socket->ss_transport == T_TCP || socket->ss_transport == T_SCTP)
+          && errno == EPIPE) {
+    nb_net_send_errors++;
+    close(socket->ss_fd);
+    socket->ss_fd = -1;
+    sockets_pending_reset.insert(socket);
+    if (reconnect_allowed()) {
+      WARNING("Broken pipe on TCP connection, remote peer "
+         "probably closed the socket");
+    } else {
+      ERROR("Broken pipe on TCP connection, remote peer "
+         "probably closed the socket");
+    }
+    return -1;
+  }
+
+#ifdef _USE_OPENSSL
+  if (socket->ss_transport == T_TLS) {
+    errstring = sip_tls_error_string(socket->ss_ssl, ret);
+  }
+#endif
+
+  WARNING("Unable to send %s message: %s", TRANSPORT_TO_STRING(socket->ss_transport), errstring);
+  nb_net_send_errors++;
+  return -1;
+}
+
+static int read_error(struct sipp_socket *socket, int ret) {
+  const char *errstring = strerror(errno);
+#ifdef _USE_OPENSSL
+  if (socket->ss_transport == T_TLS) {
+    errstring = sip_tls_error_string(socket->ss_ssl, ret);
+  }
+#endif
+
+  assert(ret <= 0);
+
+#ifdef EAGAIN
+  /* Scrub away EAGAIN from the rest of the code. */
+  if (errno == EAGAIN) {
+    errno = EWOULDBLOCK;
+  }
+#endif
+
+  /* We have only non-blocking reads, so this should not occur. */
+  if (ret < 0) {
+    assert(errno != EAGAIN);
+  }
+
+  if (socket->ss_transport == T_TCP || socket->ss_transport == T_TLS) {
+    if (ret == 0) {
+      /* The remote side closed the connection. */
+      if(socket->ss_control) {
+        if(localTwinSippSocket) sipp_close_socket(localTwinSippSocket);
+        if (extendedTwinSippMode) {
+          close_peer_sockets();
+          close_local_sockets();
+          free_peer_addr_map();
+          WARNING("One of the twin instances has ended -> exiting");
+          quitting += 20;
+          }else if(twinSippMode) {
+           if(twinSippSocket) sipp_close_socket(twinSippSocket);
+           if(thirdPartyMode == MODE_3PCC_CONTROLLER_B) {
+             WARNING("3PCC controller A has ended -> exiting");
+             quitting += 20;
+           }else {
+             quitting = 1;
+           }
+        }
+      }else {
+       /* The socket was closed "cleanly", but we may have calls that need to
+        * be destroyed.  Also, if these calls are not complete, and attempt to
+        * send again we may "ressurect" the socket by reconnecting it.*/
+        sipp_socket_invalidate(socket);
+        if (reset_close) {
+         close_calls(socket);
+       }
+      }
+      return 0;
+    }
+
+    close(socket->ss_fd);
+    socket->ss_fd = -1;
+    sockets_pending_reset.insert(socket);
+
+    nb_net_recv_errors++;
+    if (reconnect_allowed()) {
+      WARNING("Error on TCP connection, remote peer probably closed the socket: %s", errstring);
+    } else {
+      ERROR("Error on TCP connection, remote peer probably closed the socket: %s", errstring);
+    }
+    return -1;
+  }
+
+  WARNING("Unable to receive %s message: %s", TRANSPORT_TO_STRING(socket->ss_transport), errstring);
+  nb_net_recv_errors++;
+  return -1;
+}
+
+/* Flush any output buffers for this socket. */
+static int flush_socket(struct sipp_socket *socket) {
+  struct socketbuf *buf;
+  int ret;
+
+  while ((buf = socket->ss_out)) {
+    ssize_t size = buf->len - buf->offset;
+    ret = socket_write_primitive(socket, buf->buf + buf->offset, size, &buf->addr);
+    TRACE_MSG("Wrote %d of %d bytes in an output buffer.\n", ret, size);
+    if (ret == size) {
+      /* Everything is great, throw away this buffer. */
+      socket->ss_out = buf->next;
+      free_socketbuf(buf);
+    } else if (ret <= 0) {
+      /* Handle connection closes and errors. */
+      return write_error(socket, ret);
+    } else {
+      /* We have written more of the partial buffer. */
+      buf->offset += ret;
+      errno = EWOULDBLOCK;
+      enter_congestion(socket, EWOULDBLOCK);
+      return -1;
+    }
+  }
+
+  return 0;
+}
+
+void buffer_write(struct sipp_socket *socket, char *buffer, size_t len, struct sockaddr_storage *dest) {
+  struct socketbuf *buf = socket->ss_out;
+
+  if (!buf) {
+       socket->ss_out = alloc_socketbuf(buffer, len, DO_COPY, dest);
+       TRACE_MSG("Added first buffered message to socket %d\n", socket->ss_fd);
+       return;
+  }
+
+  while(buf->next) {
+       buf = buf->next;
+  }
+
+  buf->next = alloc_socketbuf(buffer, len, DO_COPY, dest);
+  TRACE_MSG("Appended buffered message to socket %d\n", socket->ss_fd);
+}
+
+void buffer_read(struct sipp_socket *socket, struct socketbuf *newbuf) {
+  struct socketbuf *buf = socket->ss_in;
+  struct socketbuf *prev = buf;
+
+  if (!buf) {
+       socket->ss_in = newbuf;
+       return;
+  }
+
+  while(buf->next) {
+       prev = buf;
+       buf = buf->next;
+  }
+
+  prev->next = newbuf;
+}
+
+/* Write data to a socket. */
+int write_socket(struct sipp_socket *socket, char *buffer, ssize_t len, int flags, struct sockaddr_storage *dest) {
+  int rc;
+  if ( socket == NULL ) {
+    //FIX coredump when trying to send data but no master yet ... ( for example after unexpected mesdsage)
+    return 0;
+  }
+
+  if (socket->ss_out) {
+    rc = flush_socket(socket);
+    TRACE_MSG("Attempted socket flush returned %d\r\n", rc);
+    if (rc < 0) {
+      if ((errno == EWOULDBLOCK) && (flags & WS_BUFFER)) {
+       buffer_write(socket, buffer, len, dest);
+       return len;
+      } else {
+       return rc;
+      }
+    }
+  }
+
+  rc = socket_write_primitive(socket, buffer, len, dest);
+
+  if (rc == len) {
+    /* Everything is great. */
+    if (useMessagef == 1) {
+      struct timeval currentTime;
+      GET_TIME (&currentTime);
+      TRACE_MSG("----------------------------------------------- %s\n"
+           "%s %smessage sent (%d bytes):\n\n%.*s\n",
+           CStat::formatTime(&currentTime, true),
+           TRANSPORT_TO_STRING(socket->ss_transport),
+           socket->ss_control ? "control " : "",
+           len, len, buffer);
+    }
+  } else if (rc <= 0) {
+    if ((errno == EWOULDBLOCK) && (flags & WS_BUFFER)) {
+      buffer_write(socket, buffer, len, dest);
+      enter_congestion(socket, errno);
+      return len;
+    }
+    if (useMessagef == 1) {
+      struct timeval currentTime;
+      GET_TIME (&currentTime);
+      TRACE_MSG("----------------------------------------------- %s\n"
+           "Error sending %s message:\n\n%.*s\n",
+           CStat::formatTime(&currentTime, true),
+           TRANSPORT_TO_STRING(socket->ss_transport),
+           len, buffer);
+    }
+    return write_error(socket, errno);
+  } else {
+    /* We have a truncated message, which must be handled internally to the write function. */
+    if (useMessagef == 1) {
+      struct timeval currentTime;
+      GET_TIME (&currentTime);
+      TRACE_MSG("----------------------------------------------- %s\n"
+           "Truncation sending %s message (%d of %d sent):\n\n%.*s\n",
+           CStat::formatTime(&currentTime, true),
+           TRANSPORT_TO_STRING(socket->ss_transport),
+           rc, len, len, buffer);
+    }
+    buffer_write(socket, buffer + rc, len - rc, dest);
+    enter_congestion(socket, errno);
+  }
+
+  return rc;
+}
+
+/****************************** Network Interface *******************/
+
+/* Our message detection states: */
+#define CFM_NORMAL 0 /* No CR Found, searchign for \r\n\r\n. */
+#define CFM_CONTROL 1 /* Searching for 27 */
+#define CFM_CR 2 /* CR Found, Searching for \n\r\n */
+#define CFM_CRLF 3 /* CRLF Found, Searching for \r\n */
+#define CFM_CRLFCR 4 /* CRLFCR Found, Searching for \n */
+#define CFM_CRLFCRLF 5 /* We've found the end of the headers! */
+
+void merge_socketbufs(struct socketbuf *socketbuf) {
+  struct socketbuf *next = socketbuf->next;
+  int newsize;
+  char *newbuf;
+
+  if (!next) {
+    return;
+  }
+
+  if (next->offset) {
+    ERROR("Internal error: can not merge a socketbuf with a non-zero offset.");
+  }
+
+  if (socketbuf->offset) {
+    memmove(socketbuf->buf, socketbuf->buf + socketbuf->offset, socketbuf->len - socketbuf->offset);
+    socketbuf->len -= socketbuf->offset;
+    socketbuf->offset = 0;
+  }
+
+  newsize = socketbuf->len + next->len;
+
+  newbuf = (char *)realloc(socketbuf->buf, newsize);
+  if (!newbuf) {
+    ERROR("Could not allocate memory to merge socket buffers!");
+  }
+  memcpy(newbuf + socketbuf->len, next->buf, next->len);
+  socketbuf->buf = newbuf;
+  socketbuf->len = newsize;
+  socketbuf->next = next->next;
+  free_socketbuf(next);
+}
+
+/* Check for a message in the socket and return the length of the first
+ * message.  If this is UDP, the only check is if we have buffers.  If this is
+ * TCP or TLS we need to parse out the content-length. */
+static int check_for_message(struct sipp_socket *socket) {
+  struct socketbuf *socketbuf = socket->ss_in;
+  int state = socket->ss_control ? CFM_CONTROL : CFM_NORMAL;
+  const char *l;
+
+  if (!socketbuf)
+    return 0;
+
+  if (socket->ss_transport == T_UDP || socket->ss_transport == T_SCTP) {
+    return socketbuf->len;
+  }
+
+  int len = 0;
+
+  while (socketbuf->offset + len < socketbuf->len) {
+    char c = socketbuf->buf[socketbuf->offset + len];
+
+    switch(state) {
+      case CFM_CONTROL:
+       /* For CMD Message the escape char is the end of message */
+       if (c == 27) {
+         return len + 1; /* The plus one includes the control character. */
+       }
+       break;
+      case CFM_NORMAL:
+       if (c == '\r') {
+         state = CFM_CR;
+       }
+       break;
+      case CFM_CR:
+       if (c == '\n') {
+         state = CFM_CRLF;
+       } else {
+         state = CFM_NORMAL;
+       }
+       break;
+      case CFM_CRLF:
+       if (c == '\r') {
+         state = CFM_CRLFCR;
+       } else {
+         state = CFM_NORMAL;
+       }
+       break;
+      case CFM_CRLFCR:
+       if (c == '\n') {
+         state = CFM_CRLFCRLF;
+       } else {
+         state = CFM_NORMAL;
+       }
+       break;
+    }
+
+    /* Head off failing because the buffer does not contain the whole header. */
+    if (socketbuf->offset + len == socketbuf->len - 1) {
+      merge_socketbufs(socketbuf);
+    }
+
+    if (state == CFM_CRLFCRLF) {
+      break;
+    }
+
+    len++;
+  }
+
+  /* We did not find the end-of-header marker. */
+  if (state != CFM_CRLFCRLF) {
+    return 0;
+  }
+
+  /* Find the content-length header. */
+  if ((l = strncasestr(socketbuf->buf + socketbuf->offset, "\r\nContent-Length:", len))) {
+    l += strlen("\r\nContent-Length:");
+  } else if ((l = strncasestr(socketbuf->buf + socketbuf->offset, "\r\nl:", len))) {
+    l += strlen("\r\nl:");
+  } else {
+    /* There is no header, so the content-length is zero. */
+    return len + 1;
+  }
+
+  /* Skip spaces. */
+  while(isspace(*l)) {
+    if (*l == '\r' || *l == '\n') {
+      /* We ran into an end-of-line, so there is no content-length. */
+      return len + 1;
+    }
+    l++;
+  }
+
+  /* Do the integer conversion, we only allow '\r' or spaces after the integer. */
+  char *endptr;
+  int content_length = strtol(l, &endptr, 10);
+  if (*endptr != '\r' && !isspace(*endptr)) {
+    content_length = 0;
+  }
+
+  /* Now that we know how large this message is, we make sure we have the whole thing. */
+  do
+  {
+    /* It is in this buffer. */
+    if (socketbuf->offset + len + content_length < socketbuf->len) {
+      return len + content_length + 1;
+    }
+    if (socketbuf->next == NULL) {
+      /* There is no buffer to merge, so we fail. */
+      return 0;
+    }
+    /* We merge ourself with the next buffer. */
+    merge_socketbufs(socketbuf);
+  }
+  while (1);
+}
+
+#ifdef USE_SCTP
+static void handleSCTPNotify(struct sipp_socket* socket,char* buffer)
+{
+ union sctp_notification *notifMsg;
+
+ notifMsg = (union sctp_notification *)buffer;
+
+ TRACE_MSG("SCTP Notification: %d\n",
+            ntohs(notifMsg->sn_header.sn_type));
+ if (notifMsg->sn_header.sn_type == SCTP_ASSOC_CHANGE)
+ {
+   TRACE_MSG("SCTP_ASSOC_CHANGE\n");
+   if (notifMsg->sn_assoc_change.sac_state == SCTP_COMM_UP)
+   {
+     TRACE_MSG("SCTP_COMM_UP\n");
+     socket->sctpstate = SCTP_UP;
+     sipp_sctp_peer_params(socket);
+
+     /* Send SCTP message right after association is up */
+     socket->ss_congested = false;
+     flush_socket(socket);
+     return -2;
+   }
+   else
+   {
+      TRACE_MSG("else: %d\n",notifMsg->sn_assoc_change.sac_state);
+      return 0;
+   }
+ }
+ else if (notifMsg->sn_header.sn_type == SCTP_SHUTDOWN_EVENT)
+ {
+   TRACE_MSG("SCTP_SHUTDOWN_EVENT\n");
+   return 0;
+ }
+ return -2;
+}
+
+void set_multihome_addr(struct sipp_socket* socket,int port)
+{
+  if (strlen(multihome_ip)>0)
+  {
+     struct addrinfo * multi_addr;
+     struct addrinfo   hints;
+     memset((char*)&hints, 0, sizeof(hints));
+     hints.ai_flags  = AI_PASSIVE;
+     hints.ai_family = PF_UNSPEC;
+
+     if (getaddrinfo(multihome_ip, NULL, &hints, &multi_addr) != 0)
+     {
+      ERROR("Can't get multihome IP address in getaddrinfo, multihome_ip='%s'",multihome_ip);
+     }
+
+     struct sockaddr_storage secondaryaddress;
+     memset(&secondaryaddress, 0, sizeof(secondaryaddress));
+
+     memcpy(&secondaryaddress, multi_addr->ai_addr, SOCK_ADDR_SIZE(_RCAST(struct sockaddr_storage *,multi_addr->ai_addr)));
+     freeaddrinfo(multi_addr);
+
+     if (port>0)
+     {
+      if (secondaryaddress.ss_family==AF_INET) ((struct sockaddr_in*)&secondaryaddress)->sin_port=htons(port);
+      else if (secondaryaddress.ss_family==AF_INET6) ((struct sockaddr_in6*)&secondaryaddress)->sin6_port=htons(port);
+     }
+
+     int ret = sctp_bindx(socket->ss_fd, (struct sockaddr *) &secondaryaddress,
+             1, SCTP_BINDX_ADD_ADDR);
+     if (ret < 0)
+     {
+      WARNING("Can't bind to multihome address, errno='%d'", errno);
+     }
+  }
+}
+#endif
+
+/* Pull up to tcp_readsize data bytes out of the socket into our local buffer. */
+static int empty_socket(struct sipp_socket *socket) {
+
+  int readsize=0;
+  if (socket->ss_transport == T_UDP || socket->ss_transport == T_SCTP) {
+      readsize = SIPP_MAX_MSG_SIZE;
+  } else {
+      readsize = tcp_readsize;
+  }
+
+  struct socketbuf *socketbuf;
+  char *buffer;
+  int ret;
+  /* Where should we start sending packets to, ideally we should begin to parse
+   * the Via, Contact, and Route headers.  But for now SIPp always sends to the
+   * host specified on the command line; or for UAS mode to the address that
+   * sent the last message. */
+  sipp_socklen_t addrlen = sizeof(struct sockaddr_storage);
+
+  buffer = (char *)malloc(readsize);
+  if (!buffer) {
+    ERROR("Could not allocate memory for read!");
+  }
+  socketbuf = alloc_socketbuf(buffer, readsize, NO_COPY, NULL);
+
+  switch(socket->ss_transport) {
+    case T_TCP:
+    case T_UDP:
+      ret = recvfrom(socket->ss_fd, buffer, readsize, 0, (struct sockaddr *)&socketbuf->addr,  &addrlen);
+      break;
+    case T_TLS:
+#ifdef _USE_OPENSSL
+      ret = SSL_read(socket->ss_ssl, buffer, readsize);
+      /* XXX: Check for clean shutdown. */
+#else
+      ERROR("TLS support is not enabled!");
+#endif
+      break;
+    case T_SCTP:
+#ifdef USE_SCTP
+      struct sctp_sndrcvinfo recvinfo;
+      memset(&recvinfo, 0, sizeof(recvinfo));
+      int msg_flags = 0;
+
+      ret = sctp_recvmsg(socket->ss_fd, (void*)buffer, readsize,
+              (struct sockaddr *) &socketbuf->addr, &addrlen, &recvinfo, &msg_flags);
+
+      if (MSG_NOTIFICATION & msg_flags)
+      {
+       errno = 0;
+       handleSCTPNotify(socket, buffer);
+       ret = -2;
+      }
+#else
+      ERROR("SCTP support is not enabled!");
+#endif
+      break;
+  }
+  if (ret <= 0) {
+    free_socketbuf(socketbuf);
+    return ret;
+  }
+
+  socketbuf->len = ret;
+
+  buffer_read(socket, socketbuf);
+
+  /* Do we have a complete SIP message? */
+  if (!socket->ss_msglen) {
+    if (int msg_len = check_for_message(socket)) {
+      socket->ss_msglen = msg_len;
+      pending_messages++;
+    }
+  }
+
+  return ret;
+}
+
+void sipp_socket_invalidate(struct sipp_socket *socket) {
+  int pollidx;
+
+  if (socket->ss_invalid) {
+    return;
+  }
+
+#ifdef _USE_OPENSSL
+  if (SSL *ssl = socket->ss_ssl) {
+    SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
+    SSL_free(ssl);
+  }
+#endif
+
+  shutdown(socket->ss_fd, SHUT_RDWR);
+
+#ifdef USE_SCTP
+  if (socket->ss_transport==T_SCTP && !gracefulclose)
+  {
+   struct linger ling={1,0};
+   if (setsockopt (socket->ss_fd, SOL_SOCKET, SO_LINGER, &ling, sizeof (ling)) < 0) {
+        WARNING("Unable to set SO_LINGER option for SCTP close");
+      }
+  }
+#endif
+
+  close(socket->ss_fd);
+  socket->ss_fd = -1;
+
+  if((pollidx = socket->ss_pollidx) >= pollnfds) {
+    ERROR("Pollset error: index %d is greater than number of fds %d!", pollidx, pollnfds);
+  }
+
+  socket->ss_invalid = true;
+  socket->ss_pollidx = -1;
+
+  /* Adds call sockets in the array */
+  assert(pollnfds > 0);
+
+  pollnfds--;
+  pollfiles[pollidx] = pollfiles[pollnfds];
+  sockets[pollidx] = sockets[pollnfds];
+  sockets[pollidx]->ss_pollidx = pollidx;
+  sockets[pollnfds] = NULL;
+
+  if (socket->ss_msglen)
+  {
+     pending_messages--;
+  }
+
+#ifdef USE_SCTP
+  if (socket->ss_transport == T_SCTP) {
+      socket->sctpstate=SCTP_DOWN;
+  }
+#endif
+}
+
+void sipp_close_socket (struct sipp_socket *socket) {
+  int count = --socket->ss_count;
+
+  if (count > 0) {
+    return;
+  }
+
+  sipp_socket_invalidate(socket);
+  free(socket);
+}
+
+static ssize_t read_message(struct sipp_socket *socket, char *buf, size_t len, struct sockaddr_storage *src) {
+  size_t avail;
+
+  if (!socket->ss_msglen)
+    return 0;
+  if (socket->ss_msglen > len)
+    ERROR("There is a message waiting in sockfd(%d) that is bigger (%d bytes) than the read size.",
+           socket->ss_fd, socket->ss_msglen);
+
+  len = socket->ss_msglen;
+
+  avail = socket->ss_in->len - socket->ss_in->offset;
+  if (avail > len) {
+    avail = len;
+  }
+
+  memcpy(buf, socket->ss_in->buf + socket->ss_in->offset, avail);
+  memcpy(src, &socket->ss_in->addr, SOCK_ADDR_SIZE(&socket->ss_in->addr));
+
+  /* Update our buffer and return value. */
+  buf[avail] = '\0';
+  /* For CMD Message the escape char is the end of message */ 
+  if((socket->ss_control) && buf[avail-1] == 27 ) buf[avail-1] = '\0';
+
+  socket->ss_in->offset += avail;
+
+  /* Have we emptied the buffer? */
+  if (socket->ss_in->offset == socket->ss_in->len) {
+    struct socketbuf *next = socket->ss_in->next;
+    free_socketbuf(socket->ss_in);
+    socket->ss_in = next;
+  }
+
+  if (int msg_len = check_for_message(socket)) {
+    socket->ss_msglen = msg_len;
+  } else {
+    socket->ss_msglen = 0;
+    pending_messages--;
+  }
+
+  if (useMessagef == 1) {
+    struct timeval currentTime;
+    GET_TIME (&currentTime);
+    TRACE_MSG("----------------------------------------------- %s\n"
+         "%s %smessage received [%d] bytes :\n\n%s\n",
+         CStat::formatTime(&currentTime, true),
+         TRANSPORT_TO_STRING(socket->ss_transport),
+         socket->ss_control ? "control " : "",
+         avail, buf);
+  }
+
+  return avail;
+}
+
+void process_message(struct sipp_socket *socket, char *msg, ssize_t msg_size, struct sockaddr_storage *src) {
+  // TRACE_MSG(" msg_size %d and pollset_index is %d \n", msg_size, pollset_index));
+  if(msg_size <= 0) {
+    return;
+  }
+  if (sipMsgCheck(msg, msg_size, socket) == false) {
+    WARNING("non SIP message discarded");
+    return;
+  }
+
+  char *call_id = get_call_id(msg);
+  if (call_id[0] == '\0') {
+    WARNING("SIP message without Call-ID discarded");
+    return;
+  }
+  listener *listener_ptr = get_listener(call_id);
+  if (useShortMessagef == 1) {
+              struct timeval currentTime;
+              GET_TIME (&currentTime);
+              TRACE_SHORTMSG("%s\tR\t%s\tCSeq:%s\t%s\n",
+              CStat::formatTime(&currentTime),call_id, get_incoming_header_content(msg,"CSeq:"), get_incoming_first_line(msg));
+          } 
+
+  if(!listener_ptr)
+  {
+    if(thirdPartyMode == MODE_3PCC_CONTROLLER_B || thirdPartyMode == MODE_3PCC_A_PASSIVE
+       || thirdPartyMode == MODE_MASTER_PASSIVE || thirdPartyMode == MODE_SLAVE)
+    {
+      // Adding a new OUTGOING call !
+      main_scenario->stats->computeStat(CStat::E_CREATE_OUTGOING_CALL);
+      call *new_ptr = new call(call_id, local_ip_is_ipv6, 0, use_remote_sending_addr ? &remote_sending_sockaddr : &remote_sockaddr);
+      if (!new_ptr) {
+       ERROR("Out of memory allocating a call!");
+      }
+
+      outbound_congestion = false;
+      if((socket != main_socket) &&
+         (socket != tcp_multiplex) &&
+         (socket != localTwinSippSocket) &&
+         (socket != twinSippSocket) &&
+         (!is_a_local_socket(socket))) {
+       new_ptr->associate_socket(socket);
+       socket->ss_count++;
+      } else {
+       /* We need to hook this call up to a real *call* socket. */
+       if (!multisocket) {
+         switch(transport) {
+           case T_UDP:
+             new_ptr->associate_socket(main_socket);
+             main_socket->ss_count++;
+             break;
+           case T_TCP:
+           case T_SCTP:
+           case T_TLS:
+             new_ptr->associate_socket(tcp_multiplex);
+             tcp_multiplex->ss_count++;
+             break;
+         }
+       }
+      }
+      listener_ptr = new_ptr;
+    }
+    else if(creationMode == MODE_SERVER)
+    {
+      if (quitting >= 1) {
+       CStat::globalStat(CStat::E_OUT_OF_CALL_MSGS);
+       TRACE_MSG("Discarded message for new calls while quitting\n");
+       return;
+      }
+
+      // Adding a new INCOMING call !
+      main_scenario->stats->computeStat(CStat::E_CREATE_INCOMING_CALL);
+      listener_ptr = new call(call_id, socket, use_remote_sending_addr ? &remote_sending_sockaddr : src);
+      if (!listener_ptr) {
+       ERROR("Out of memory allocating a call!");
+      }
+    }
+    else // mode != from SERVER and 3PCC Controller B
+    {
+      // This is a message that is not relating to any known call
+      if (ooc_scenario) {
+       if(!get_reply_code(msg)){
+        char *msg_start = strdup(msg);
+        char *msg_start_end = msg_start;
+        while (!isspace(*msg_start_end) && (*msg_start_end != '\0')) {
+            msg_start_end++;
+        }
+        *msg_start_end = '\0';
+           ooc_scenario->stats->computeStat(CStat::E_CREATE_INCOMING_CALL);
+        WARNING("Received out-of-call %s message, using the out-of-call scenario", msg_start);
+        free(msg_start);
+           /* This should have the real address that the message came from. */
+           call *call_ptr = new call(ooc_scenario, socket, use_remote_sending_addr ? &remote_sending_sockaddr : src, call_id, 0 /* no user. */, socket->ss_ipv6, true, false);
+           if (!call_ptr) {
+             ERROR("Out of memory allocating a call!");
+           }
+           CStat::globalStat(CStat::E_AUTO_ANSWERED);
+           call_ptr->process_incoming(msg, src);
+         } else {
+           /* We received a response not relating to any known call */
+           /* Do nothing, even if in auto answer mode */
+           CStat::globalStat(CStat::E_OUT_OF_CALL_MSGS);
+         }
+    } else if (auto_answer &&
+              ((strstr(msg, "NOTIFY") == msg)  ||
+               (strstr(msg, "INFO")   == msg)  ||
+               (strstr(msg, "UPDATE") == msg))) {
+         // If auto answer mode, try to answer the incoming message
+         // with automaticResponseMode
+         // call is discarded before exiting the block
+         if(!get_reply_code(msg)){
+           aa_scenario->stats->computeStat(CStat::E_CREATE_INCOMING_CALL);
+           /* This should have the real address that the message came from. */
+           call *call_ptr = new call(aa_scenario, socket, use_remote_sending_addr ? &remote_sending_sockaddr : src, call_id, 0 /* no user. */, socket->ss_ipv6, true, false);
+           if (!call_ptr) {
+            ERROR("Out of memory allocating a call!");
+         }
+         CStat::globalStat(CStat::E_AUTO_ANSWERED);
+         call_ptr->process_incoming(msg, src);
+       } else {
+      fprintf(stderr, "%s", msg);
+         /* We received a response not relating to any known call */
+         /* Do nothing, even if in auto answer mode */
+         CStat::globalStat(CStat::E_OUT_OF_CALL_MSGS);
+       }
+      } else {
+       CStat::globalStat(CStat::E_OUT_OF_CALL_MSGS);
+       WARNING("Discarding message which can't be mapped to a known SIPp call:\n%s", msg);
+      }
+    }
+  }
+
+  /* If the call was not created above, we just drop this message. */
+  if (!listener_ptr) {
+    return;
+  }
+
+  if((socket == localTwinSippSocket) || (socket == twinSippSocket) || (is_a_local_socket(socket)))
+  {
+    listener_ptr -> process_twinSippCom(msg);
+  }
+  else
+  {
+    listener_ptr -> process_incoming(msg, src);
+  }
+}
+
+void pollset_process(int wait)
+{
+  int rs; /* Number of times to execute recv().
+            For TCP with 1 socket per call:
+                no. of events returned by poll
+            For UDP and TCP with 1 global socket:
+                recv_count is a flag that stays up as
+                long as there's data to read */
+
+  int loops = max_recv_loops;
+
+  /* What index should we try reading from? */
+  static int read_index;
+
+  if (read_index >= pollnfds) {
+    read_index = 0;
+  }
+
+  /* We need to process any messages that we have left over. */
+  while (pending_messages && (loops > 0)) {
+    getmilliseconds();
+    if (sockets[read_index]->ss_msglen) {
+       struct sockaddr_storage src;
+       char msg[SIPP_MAX_MSG_SIZE];
+       ssize_t len = read_message(sockets[read_index], msg, sizeof(msg), &src);
+       if (len > 0) {
+         process_message(sockets[read_index], msg, len, &src);
+       } else {
+         assert(0);
+       }
+       loops--;
+      }
+    read_index = (read_index + 1) % pollnfds;
+  }
+
+  /* Don't read more data if we still have some left over. */
+  if (pending_messages) {
+    return;
+  }
+
+  /* Get socket events. */
+  rs = poll(pollfiles, pollnfds, wait ? 1 : 0);
+  if((rs < 0) && (errno == EINTR)) {
+    return;
+  }
+
+  /* We need to flush all sockets and pull data into all of our buffers. */
+  for(int poll_idx = 0; rs > 0 && poll_idx < pollnfds; poll_idx++) {
+    struct sipp_socket *sock = sockets[poll_idx];
+    int events = 0;
+    int ret = 0;
+
+    assert(sock);
+
+    if(pollfiles[poll_idx].revents & POLLOUT)
+    {
+
+#ifdef USE_SCTP
+      if (transport == T_SCTP && sock->sctpstate != SCTP_UP) ;
+      else
+#endif
+      {
+      /* We can flush this socket. */
+      TRACE_MSG("Exit problem event on socket %d \n", sock->ss_fd);
+      pollfiles[poll_idx].events &= ~POLLOUT;
+      sock->ss_congested = false;
+
+      flush_socket(sock);
+      events++;
+    }
+    }
+
+    if(pollfiles[poll_idx].revents & POLLIN) {
+      /* We can empty this socket. */
+      if ((transport == T_TCP || transport == T_TLS || transport == T_SCTP) && sock == main_socket) {
+       struct sipp_socket *new_sock = sipp_accept_socket(sock);
+       if (!new_sock) {
+         ERROR_NO("Accepting new TCP connection.\n");
+       }
+      } else if (sock == ctrl_socket) {
+       handle_ctrl_socket();
+      } else if (sock == stdin_socket) {
+       handle_stdin_socket();
+      } else if (sock == localTwinSippSocket) {
+       if (thirdPartyMode == MODE_3PCC_CONTROLLER_B) {
+         twinSippSocket = sipp_accept_socket(sock);
+         if (!twinSippMode) {
+           ERROR_NO("Accepting new TCP connection on Twin SIPp Socket.\n");
+         }
+         twinSippSocket->ss_control = 1;
+       } else {
+         /*3pcc extended mode: open a local socket
+           which will be used for reading the infos sent by this remote
+           twin sipp instance (slave or master) */
+         if(local_nb == MAX_LOCAL_TWIN_SOCKETS) {
+           ERROR("Max number of twin instances reached\n");
+         }
+
+         struct sipp_socket *localSocket = sipp_accept_socket(sock);
+         localSocket->ss_control = 1;
+         local_sockets[local_nb] = localSocket;
+         local_nb++;
+         if(!peers_connected){
+           connect_to_all_peers();
+         }
+       }
+      }
+      else {
+       if ((ret = empty_socket(sock)) <= 0) {
+#ifdef USE_SCTP
+               if (sock->ss_transport==T_SCTP && ret==-2) ;
+          else
+#endif
+          {
+         ret = read_error(sock, ret);
+         if (ret == 0) {
+           /* If read_error() then the poll_idx now belongs
+            * to the newest/last socket added to the sockets[].
+            * Need to re-do the same poll_idx for the "new" socket. */
+           poll_idx--;
+           events++;
+           rs--;
+           continue;
+         }
+       }
+      }
+         }
+      events++;
+    }
+
+    pollfiles[poll_idx].revents = 0;
+    if (events) {
+      rs--;
+    }
+  }
+
+  if (read_index >= pollnfds) {
+    read_index = 0;
+  }
+
+  /* We need to process any new messages that we read. */
+  while (pending_messages && (loops > 0)) {
+    getmilliseconds();
+
+    if (sockets[read_index]->ss_msglen) {
+      char msg[SIPP_MAX_MSG_SIZE];
+      struct sockaddr_storage src;
+      ssize_t len;
+
+      len = read_message(sockets[read_index], msg, sizeof(msg), &src);
+      if (len > 0) {
+       process_message(sockets[read_index], msg, len, &src);
+      } else {
+       assert(0);
+      }
+      loops--;
+    }
+    read_index = (read_index + 1) % pollnfds;
+  }
+
+  cpu_max = loops <= 0;
+}
+
+void timeout_alarm(int param){
+  if (timeout_error) {
+    ERROR("%s timed out after '%.3lf' seconds", scenario_file, ((double)clock_tick / 1000LL));
+  }
+  quitting = 1;
+  timeout_exit = true;
+}
+
+/* Send loop & trafic generation*/
+
+void traffic_thread()
+{
+  /* create the file */
+  char         L_file_name [MAX_PATH];
+  sprintf (L_file_name, "%s_%d_screen.log", scenario_file, getpid());
+
+  getmilliseconds();
+
+  /* Arm the global timer if needed */
+  if (global_timeout > 0) { 
+    signal(SIGALRM, timeout_alarm);
+    alarm(global_timeout / 1000);
+  }
+
+  // Dump (to create file on disk) and showing screen at the beginning even if
+  // the report period is not reached
+  stattask::report();
+  screentask::report(false);
+
+  while(1) {
+    scheduling_loops++;
+    getmilliseconds();
+
+    if (signalDump) {
+       /* Screen dumping in a file */
+       if (screenf) {
+          print_screens();
+       } else {
+         /* If the -trace_screen option has not been set, */
+         /* create the file at this occasion              */
+         screenf = fopen(L_file_name, "a");
+        if (!screenf) {
+            WARNING("Unable to create '%s'", L_file_name);
+         }
+        print_screens();
+        fclose(screenf);
+        screenf = 0;
+       }
+
+       if(dumpInRtt) {
+          main_scenario->stats->dumpDataRtt ();
+       }
+
+       signalDump = false ;
+    }
+
+    while (sockets_pending_reset.begin() != sockets_pending_reset.end()) {
+       reset_connection(*(sockets_pending_reset.begin()));
+       sockets_pending_reset.erase(sockets_pending_reset.begin());
+    }
+
+    if ((main_scenario->stats->GetStat(CStat::CPT_C_IncomingCallCreated) + main_scenario->stats->GetStat(CStat::CPT_C_OutgoingCallCreated)) >= stop_after) {
+       quitting = 1;
+    }
+    if (quitting) {
+      if (quitting > 11) {
+        /* Force exit: abort all calls */
+       abort_all_tasks();
+      }
+      /* Quitting and no more openned calls, close all */
+      if(!main_scenario->stats->GetStat(CStat::CPT_C_CurrentCall)) {
+       /* We can have calls that do not count towards our open-call count (e.g., dead calls). */
+       abort_all_tasks();
+
+       for (int i = 0; i < pollnfds; i++) {
+         sipp_close_socket(sockets[i]);
+       }
+
+       screentask::report(true);
+       stattask::report();
+       if (screenf) {
+         print_screens();
+       }
+
+        screen_exit(EXIT_TEST_RES_UNKNOWN);
+      }
+    }
+
+    getmilliseconds();
+
+    /* Schedule all pending calls and process their timers */
+    task_list *running_tasks;
+    if((clock_tick - last_timer_cycle) > timer_resolution) {
+
+      /* Just for the count. */
+      running_tasks = get_running_tasks();
+      last_running_calls = running_tasks->size();
+
+      /* If we have expired paused calls, move them to the run queue. */
+      last_woken_calls += expire_paused_tasks();
+
+      last_paused_calls = paused_tasks_count();
+
+      last_timer_cycle = clock_tick;
+    }
+
+    /* We should never get so busy with running calls that we can't process some messages. */
+    int loops = max_sched_loops;
+
+    /* Now we process calls that are on the run queue. */
+    running_tasks = get_running_tasks();
+
+    /* Workaround hpux problem with iterators. Deleting the
+     * current object when iterating breaks the iterator and
+     * leads to iterate again on the destroyed (deleted)
+     * object. Thus, we have to wait ont step befere actual
+     * deletion of the object*/
+    task * last = NULL;
+
+    task_list::iterator iter;
+    for(iter = running_tasks->begin(); iter != running_tasks->end(); iter++) {
+      if(last) {
+       last -> run();
+       if (sockets_pending_reset.begin() != sockets_pending_reset.end()) {
+         last = NULL;
+         break;
+       }
+      }
+      last = *iter;
+      if (--loops <= 0) {
+       break;
+      }
+    }
+    if(last) {
+      last -> run();
+    }
+    while (sockets_pending_reset.begin() != sockets_pending_reset.end()) {
+      reset_connection(*(sockets_pending_reset.begin()));
+      sockets_pending_reset.erase(sockets_pending_reset.begin());
+    }
+
+    /* Update the clock. */
+    getmilliseconds();
+    /* Receive incoming messages */
+    pollset_process(running_tasks->size() == 0);
+  }
+}
+
+/*************** RTP ECHO THREAD ***********************/
+/* param is a pointer to RTP socket */
+
+void rtp_echo_thread (void * param)
+{
+  char *msg = (char*)alloca(media_bufsize);
+  size_t nr, ns;
+  sipp_socklen_t len;
+  struct sockaddr_storage remote_rtp_addr;
+
+
+   int                   rc;
+   sigset_t              mask;
+   sigfillset(&mask); /* Mask all allowed signals */
+   rc = pthread_sigmask(SIG_BLOCK, &mask, NULL);
+
+  for (;;) {
+    len = sizeof(remote_rtp_addr);
+    nr = recvfrom(*(int *)param, 
+                  msg, 
+                  media_bufsize, 0, 
+                  (sockaddr *)(void *) &remote_rtp_addr, 
+                  &len);
+
+    if (((long)nr) < 0) {
+      WARNING("%s %i",
+                 "Error on RTP echo reception - stopping echo - errno=", 
+                 errno);
+      return;
+    }
+    ns = sendto(*(int *)param, msg, nr, 
+                0, (sockaddr *)(void *) &remote_rtp_addr, 
+                len);
+
+    if (ns != nr) {
+      WARNING("%s %i",
+                 "Error on RTP echo transmission - stopping echo - errno=", 
+                 errno);
+      return;
+    }
+    
+    if (*(int *)param==media_socket) {    
+    rtp_pckts++;
+    rtp_bytes += ns;
+  }
+    else {
+      /* packets on the second RTP stream */
+      rtp2_pckts++;
+      rtp2_bytes += ns;
+    }
+  }
+}
+
+/* Wrap the help text. */
+char *wrap(const char *in, int offset, int size) {
+  int pos = 0;
+  int i, j;
+  int l = strlen(in);
+  int alloced = l + 1;
+  char *out = (char *)malloc(alloced);
+  int indent = 0;
+
+  if (!out) {
+    ERROR_NO("malloc");
+  }
+
+  for (i = j = 0; i < l; i++) {
+    out[j++] = in[i];
+    if (in[i] == '\n') {
+      out = (char *)realloc(out, alloced += offset);
+      if (!out) {
+        ERROR_NO("realloc");
+      }
+      pos = 0;
+      for (int k = 0; k < offset; k++) {
+        out[j++] = ' ';
+      }
+      if (indent) {
+        indent = 0;
+      }
+    }
+    if (in[i] == '-' && i > 0 && in[i - 1] == '\n') {
+      indent = 1;
+    }
+    if (++pos > size) {
+      int k;
+      for (k = j - 1; k > 0 && !isspace(out[k]); k--);
+      int useoffset = offset;
+
+      if (indent) {
+        useoffset += 2;
+      }
+
+      if (k == 0 || out[k] == '\n') {
+        pos = 0;
+        out[j++] = '\n';
+        out = (char *)realloc(out, alloced += useoffset);
+        if (!out) {
+          ERROR_NO("realloc");
+        }
+        for (k = 0; k < useoffset; k++) {
+          out[j++] = ' ';
+        }
+      } else {
+        int m;
+        int move_back = 0;
+
+        //printf("Before wrapping (pos = %d, k = %d, j = %d):\n%-*s%s\n", pos, k, j, offset, "", out);
+
+        out[k] = '\n';
+        pos = j - k;
+        // move_back is used to step back in the in and out buffers when a
+        // word is longer than useoffset.
+        if (i > (k + useoffset)) {
+          move_back = i - (k + useoffset);
+          i -= move_back;
+        }
+        k++;
+        out = (char *)realloc(out, alloced += useoffset);
+        if (!out) {
+          ERROR_NO("realloc");
+        }
+        for (m = 0; m < useoffset; m++) {
+          if (k + useoffset + m < alloced) {
+            out[k + useoffset + m] = out[k + m];
+          }
+          out[k + m] = ' ';
+        }
+        j += useoffset - move_back;
+        //printf("After wrapping (pos = %d, k = %d):\n%-*s%s\n", pos, k, offset, "", out);
+      }
+    }
+  }
+  out[j] = '\0';
+
+  return out;
+}
+
+/* Help screen */
+void help() 
+{
+  int i, max;
+
+  printf
+    ("\n"
+     "Usage:\n"
+     "\n"
+     "  sipp remote_host[:remote_port] [options]\n"
+     "\n"
+     "  Available options:\n"
+     "\n");
+
+  /* We automatically generate the help messages based on the options array.
+   * This should hopefully encourage people to write help text when they
+   * introduce a new option and keep the code a bit cleaner. */
+    max = sizeof(options_table)/sizeof(options_table[0]);
+    for (i = 0; i < max; i++) {
+      char *formatted;
+      if (!options_table[i].help) {
+        continue;
+      }
+      formatted = wrap(options_table[i].help, 22, 57);
+      printf("   -%-16s: %s\n\n", options_table[i].option, formatted);
+      free(formatted);
+    }
+
+    printf
+    (
+     "Signal handling:\n"
+     "\n"
+     "   SIPp can be controlled using posix signals. The following signals\n"
+     "   are handled:\n"
+     "   USR1: Similar to press 'q' keyboard key. It triggers a soft exit\n"
+     "         of SIPp. No more new calls are placed and all ongoing calls\n"
+     "         are finished before SIPp exits.\n"
+     "         Example: kill -SIGUSR1 732\n"
+     "   USR2: Triggers a dump of all statistics screens in\n"
+     "         <scenario_name>_<pid>_screens.log file. Especially useful \n"
+     "         in background mode to know what the current status is.\n"
+     "         Example: kill -SIGUSR2 732\n"
+     "\n"
+     "Exit code:\n"
+     "\n"
+     "   Upon exit (on fatal error or when the number of asked calls (-m\n"
+     "   option) is reached, sipp exits with one of the following exit\n"
+     "   code:\n"
+     "    0: All calls were successful\n"
+     "    1: At least one call failed\n"
+     "   97: exit on internal command. Calls may have been processed\n"
+     "   99: Normal exit without calls processed\n"
+     "   -1: Fatal error\n"
+     "   -2: Fatal error binding a socket\n"
+     "\n"
+     "\n"
+     "Example:\n"
+     "\n"
+     "   Run sipp with embedded server (uas) scenario:\n"
+     "     ./sipp -sn uas\n"
+     "   On the same host, run sipp with embedded client (uac) scenario\n"
+     "     ./sipp -sn uac 127.0.0.1\n"
+     "\n");
+}
+
+
+void help_stats() 
+{
+  printf(
+"\n"
+"  The  -trace_stat option dumps all statistics in the\n"
+"  <scenario_name.csv> file. The dump starts with one header\n" 
+"  line with all counters. All following lines are 'snapshots' of \n"
+"  statistics counter given the statistics report frequency\n"
+"  (-fd option). This file can be easily imported in any\n"
+"  spreadsheet application, like Excel.\n"
+"\n"
+"  In counter names, (P) means 'Periodic' - since last\n"
+"  statistic row and (C) means 'Cumulated' - since sipp was\n"
+"  started.\n"
+"\n"
+"  Available statistics are:\n"
+"\n"
+"  - StartTime: \n"
+"    Date and time when the test has started.\n"
+"\n"
+"  - LastResetTime:\n"
+"    Date and time when periodic counters where last reseted.\n"
+"\n"
+"  - CurrentTime:\n"
+"    Date and time of the statistic row.\n"
+"\n"
+"  - ElapsedTime:\n"
+"    Elapsed time.\n"
+"\n"
+"  - CallRate:\n"
+"    Call rate (calls per seconds).\n"
+"\n"
+"  - IncomingCall:\n"
+"    Number of incoming calls.\n"
+"\n"
+"  - OutgoingCall:\n"
+"    Number of outgoing calls.\n"
+"\n"
+"  - TotalCallCreated:\n"
+"    Number of calls created.\n"
+"\n"
+"  - CurrentCall:\n"
+"    Number of calls currently ongoing.\n"
+"\n"
+"  - SuccessfulCall:\n"
+"    Number of successful calls.\n"
+"\n"
+"  - FailedCall:\n"
+"    Number of failed calls (all reasons).\n"
+"\n"
+"  - FailedCannotSendMessage:\n"
+"    Number of failed calls because Sipp cannot send the\n"
+"    message (transport issue).\n"
+"\n"
+"  - FailedMaxUDPRetrans:\n"
+"    Number of failed calls because the maximum number of\n"
+"    UDP retransmission attempts has been reached.\n"
+"\n"
+"  - FailedUnexpectedMessage:\n"
+"    Number of failed calls because the SIP message received\n"
+"    is not expected in the scenario.\n"
+"\n"
+"  - FailedCallRejected:\n"
+"    Number of failed calls because of Sipp internal error.\n"
+"    (a scenario sync command is not recognized or a scenario\n"
+"    action failed or a scenario variable assignment failed).\n"
+"\n"
+"  - FailedCmdNotSent:\n"
+"    Number of failed calls because of inter-Sipp\n"
+"    communication error (a scenario sync command failed to\n"
+"    be sent).\n"
+"\n"
+"  - FailedRegexpDoesntMatch:\n"
+"    Number of failed calls because of regexp that doesn't\n"
+"    match (there might be several regexp that don't match\n"
+"    during the call but the counter is increased only by\n"
+"    one).\n"
+"\n"
+"  - FailedRegexpShouldntMatch:\n"
+"    Number of failed calls because of regexp that shouldn't\n"
+"    match (there might be several regexp that shouldn't match\n"
+"    during the call but the counter is increased only by\n"
+"    one).\n"
+"\n"
+"  - FailedRegexpHdrNotFound:\n"
+"    Number of failed calls because of regexp with hdr    \n"
+"    option but no matching header found.\n"
+"\n"
+"  - OutOfCallMsgs:\n"
+"    Number of SIP messages received that cannot be associated\n"
+"    to an existing call.\n"
+"\n"
+"  - AutoAnswered:\n"
+"    Number of unexpected specific messages received for new Call-ID.\n"
+"    The message has been automatically answered by a 200 OK\n"
+"    Currently, implemented for 'PING' message only.\n"
+"\n");
+}
+
+/************* exit handler *****************/
+
+void print_last_stats()
+{
+  interrupt = 1;
+  // print last current screen
+  print_statistics(1);
+  // and print statistics screen
+  currentScreenToDisplay = DISPLAY_STAT_SCREEN;
+  print_statistics(1);
+  if (main_scenario) {
+    stattask::report();
+  }
+}
+
+void freeInFiles() {
+  for (file_map::iterator file_it = inFiles.begin(); file_it != inFiles.end(); file_it++) {
+    delete file_it->second;
+  }
+}
+
+void freeUserVarMap() {
+  for (int_vt_map::iterator vt_it = userVarMap.begin(); vt_it != userVarMap.end(); vt_it++) {
+    vt_it->second->putTable();
+    userVarMap[vt_it->first] = NULL;
+  }
+}
+
+void releaseGlobalAllocations()
+{
+  delete main_scenario;
+  delete ooc_scenario;
+  delete aa_scenario;
+  free_default_messages();
+  freeInFiles();
+  freeUserVarMap();
+  delete globalVariables;
+}
+
+void stop_all_traces()
+{
+  message_lfi.fptr = NULL;
+  log_lfi.fptr = NULL;
+  if(dumpInRtt) dumpInRtt = 0;
+  if(dumpInFile) dumpInFile = 0;
+}
+
+char* remove_pattern(char* P_buffer, char* P_extensionPattern) {
+
+  char *L_ptr = P_buffer;
+
+  if (P_extensionPattern == NULL) {
+    return P_buffer ;
+  }
+
+  if (P_buffer == NULL) {
+    return P_buffer ;
+  }
+
+  L_ptr = strstr(P_buffer, P_extensionPattern) ;
+  if (L_ptr != NULL) {
+    *L_ptr = '\0' ;
+  }
+
+  return P_buffer ;
+}
+
+static struct sipp_socket *sipp_allocate_socket(bool use_ipv6, int transport, int fd, int accepting) {
+  struct sipp_socket *ret = NULL;
+
+  ret = (struct sipp_socket *)malloc(sizeof(struct sipp_socket));
+  if (!ret) {
+    ERROR("Could not allocate a sipp_socket structure.");
+  }
+  memset(ret, 0, sizeof(struct sipp_socket));
+
+
+  ret->ss_transport = transport;
+  ret->ss_control = false;
+  ret->ss_ipv6 = use_ipv6;
+  ret->ss_fd = fd;
+  ret->ss_comp_state = NULL;
+  ret->ss_count = 1;
+  ret->ss_changed_dest = false;
+
+  /* Initialize all sockets with our destination address. */
+  memcpy(&ret->ss_remote_sockaddr, &remote_sockaddr, sizeof(ret->ss_remote_sockaddr));
+
+#ifdef _USE_OPENSSL
+  ret->ss_ssl = NULL;
+
+  if ( transport == T_TLS ) {
+    if ((ret->ss_bio = BIO_new_socket(fd,BIO_NOCLOSE)) == NULL) {
+      ERROR("Unable to create BIO object:Problem with BIO_new_socket()\n");
+    }
+
+    if (!(ret->ss_ssl = SSL_new(accepting ? sip_trp_ssl_ctx : sip_trp_ssl_ctx_client))) {
+      ERROR("Unable to create SSL object : Problem with SSL_new() \n");
+    }
+
+    SSL_set_bio(ret->ss_ssl,ret->ss_bio,ret->ss_bio);
+  }
+#endif
+
+  ret->ss_in = NULL;
+  ret->ss_out = NULL;
+  ret->ss_msglen = 0;
+  ret->ss_congested = false;
+  ret->ss_invalid = false;
+
+  /* Store this socket in the tables. */
+  ret->ss_pollidx = pollnfds++;
+  sockets[ret->ss_pollidx] = ret;
+  pollfiles[ret->ss_pollidx].fd      = ret->ss_fd;
+  pollfiles[ret->ss_pollidx].events  = POLLIN | POLLERR;
+  pollfiles[ret->ss_pollidx].revents = 0;
+
+  return ret;
+}
+
+static struct sipp_socket *sipp_allocate_socket(bool use_ipv6, int transport, int fd) {
+       return sipp_allocate_socket(use_ipv6, transport, fd, 0);
+}
+
+int socket_fd(bool use_ipv6, int transport) {
+  int socket_type;
+  int protocol=0;
+  int fd;
+
+  switch(transport) {
+    case T_UDP:
+      socket_type = SOCK_DGRAM;
+      protocol=IPPROTO_UDP;
+      break;
+    case T_SCTP:
+#ifndef USE_SCTP
+      ERROR("You do not have SCTP support enabled!\n");
+#else
+      socket_type = SOCK_STREAM;
+      protocol=IPPROTO_SCTP;
+#endif
+      break;
+    case T_TLS:
+#ifndef _USE_OPENSSL
+      ERROR("You do not have TLS support enabled!\n");
+#endif
+    case T_TCP:
+      socket_type = SOCK_STREAM;
+      break;
+  }
+
+  if((fd = socket(use_ipv6 ? AF_INET6 : AF_INET, socket_type, protocol))== -1) {
+    ERROR("Unable to get a %s socket (3)", TRANSPORT_TO_STRING(transport));
+  }
+
+  return fd;
+}
+
+struct sipp_socket *new_sipp_socket(bool use_ipv6, int transport) {
+  struct sipp_socket *ret;
+  int fd = socket_fd(use_ipv6, transport);
+
+#if defined(__SUNOS)
+  if (fd < 256)
+  {
+    int newfd = fcntl(fd, F_DUPFD, 256);
+    if (newfd <= 0)
+    {
+      // Typically, (24)(Too many open files) is the error here
+      WARNING("Unable to get a different %s socket, errno=%d(%s)",
+              TRANSPORT_TO_STRING(transport), errno, strerror(errno));
+
+      // Keep the original socket fd.
+      newfd = fd;
+    }
+    else
+    {
+      close(fd);
+    }
+    fd = newfd;
+  }
+#endif
+
+  ret  = sipp_allocate_socket(use_ipv6, transport, fd);
+  if (!ret) {
+    close(fd);
+    ERROR("Could not allocate new socket structure!");
+  }
+  return ret;
+}
+
+struct sipp_socket *new_sipp_call_socket(bool use_ipv6, int transport, bool *existing) {
+  struct sipp_socket *sock = NULL;
+  static int next_socket;
+  if (pollnfds >= max_multi_socket) {  // we must take the main socket into account
+    /* Find an existing socket that matches transport and ipv6 parameters. */
+    int first = next_socket;
+    do
+    {
+      int test_socket = next_socket;
+      next_socket = (next_socket + 1) % pollnfds;
+
+      if (sockets[test_socket]->ss_call_socket) {
+       /* Here we need to check that the address is the default. */
+       if (sockets[test_socket]->ss_ipv6 != use_ipv6) {
+         continue;
+       }
+       if (sockets[test_socket]->ss_transport != transport) {
+         continue;
+       }
+       if (sockets[test_socket]->ss_changed_dest) {
+         continue;
+       }
+
+       sock = sockets[test_socket];
+       sock->ss_count++;
+       *existing = true;
+       break;
+      }
+    }
+    while (next_socket != first);
+    if (next_socket == first) {
+      ERROR("Could not find an existing call socket to re-use!");
+    }
+  } else {
+    sock = new_sipp_socket(use_ipv6, transport);
+    sock->ss_call_socket = true;
+    *existing = false;
+  }
+  return sock;
+}
+
+struct sipp_socket *sipp_accept_socket(struct sipp_socket *accept_socket) {
+  struct sipp_socket *ret;
+  struct sockaddr_storage remote_sockaddr;
+  int fd;
+  sipp_socklen_t addrlen = sizeof(remote_sockaddr);
+
+  if((fd = accept(accept_socket->ss_fd, (struct sockaddr *)&remote_sockaddr, &addrlen))== -1) {
+    ERROR("Unable to accept on a %s socket: %s", TRANSPORT_TO_STRING(transport), strerror(errno));
+  }
+
+#if defined(__SUNOS)
+  if (fd < 256)
+  {
+    int newfd = fcntl(fd, F_DUPFD, 256);
+    if (newfd <= 0)
+    {
+      // Typically, (24)(Too many open files) is the error here
+      WARNING("Unable to get a different %s socket, errno=%d(%s)",
+               TRANSPORT_TO_STRING(transport), errno, strerror(errno));
+
+      // Keep the original socket fd.
+      newfd = fd;
+    }
+    else
+    {
+      close(fd);
+    }
+    fd = newfd;
+  }
+#endif
+
+
+  ret  = sipp_allocate_socket(accept_socket->ss_ipv6, accept_socket->ss_transport, fd, 1);
+  if (!ret) {
+       close(fd);
+       ERROR_NO("Could not allocate new socket!");
+  }
+
+  memcpy(&ret->ss_remote_sockaddr, &remote_sockaddr, sizeof(ret->ss_remote_sockaddr));
+  /* We should connect back to the address which connected to us if we
+   * experience a TCP failure. */
+  memcpy(&ret->ss_dest, &remote_sockaddr, sizeof(ret->ss_remote_sockaddr));
+
+  if (ret->ss_transport == T_TLS) {
+#ifdef _USE_OPENSSL
+    int err;
+    if ((err = SSL_accept(ret->ss_ssl)) < 0) {
+      ERROR("Error in SSL_accept: %s\n", sip_tls_error_string(accept_socket->ss_ssl, err));
+    }
+#else
+    ERROR("You need to compile SIPp with TLS support");
+#endif
+  }
+
+  return ret;
+}
+
+int sipp_bind_socket(struct sipp_socket *socket, struct sockaddr_storage *saddr, int *port) {
+  int ret;
+  int len;
+
+
+#ifdef USE_SCTP
+  if (transport==T_SCTP && multisocket==1 && *port==-1)
+  {
+   if (socket->ss_ipv6)
+   {
+    (_RCAST(struct sockaddr_in6 *, saddr))->sin6_port=0;
+   }
+   else
+   {
+    (_RCAST(struct sockaddr_in *, saddr))->sin_port=0;
+   }
+  }
+#endif
+
+  if (socket->ss_ipv6) {
+    len = sizeof(struct sockaddr_in6);
+  } else {
+    len = sizeof(struct sockaddr_in);
+  }
+
+  if((ret = bind(socket->ss_fd, (sockaddr *)saddr, len))) {
+    return ret;
+  }
+
+  if (!port) {
+    return 0;
+  }
+
+  if ((ret = getsockname(socket->ss_fd, (sockaddr *)saddr, (sipp_socklen_t *) &len))) {
+    return ret;
+  }
+
+  if (socket->ss_ipv6) {
+    *port = ntohs((short)((_RCAST(struct sockaddr_in6 *, saddr))->sin6_port));
+  } else {
+    *port = ntohs((short)((_RCAST(struct sockaddr_in *, saddr))->sin_port));
+  }
+
+#ifdef USE_SCTP
+  bool isany=false;
+
+  if (socket->ss_ipv6) {
+    if (memcmp(&(_RCAST(struct sockaddr_in6 *, saddr)->sin6_addr),&in6addr_any,sizeof(in6_addr))==0) isany=true;
+  } else {
+    isany= (_RCAST(struct sockaddr_in *, saddr)->sin_addr.s_addr==INADDR_ANY);
+  }
+
+  if (transport==T_SCTP && !isany) set_multihome_addr(socket,*port);
+#endif
+
+  return 0;
+}
+
+int sipp_do_connect_socket(struct sipp_socket *socket) {
+  int ret;
+
+  assert(socket->ss_transport == T_TCP || socket->ss_transport == T_TLS || socket->ss_transport == T_SCTP);
+
+#ifdef USE_SCTP
+  if (socket->ss_transport==T_SCTP)
+  {
+   int port=-1;
+   sipp_bind_socket(socket, &local_sockaddr, &port);
+  }
+#endif
+
+  errno = 0;
+  ret = connect(socket->ss_fd, (struct sockaddr *)&socket->ss_dest, SOCK_ADDR_SIZE(&socket->ss_dest));
+  if (ret < 0) {
+    return ret;
+  }
+
+  if (socket->ss_transport == T_TLS) {
+#ifdef _USE_OPENSSL
+    int err;
+    if ((err = SSL_connect(socket->ss_ssl)) < 0) {
+      ERROR("Error in SSL connection: %s\n", sip_tls_error_string(socket->ss_ssl, err));
+    }
+#else
+    ERROR("You need to compile SIPp with TLS support");
+#endif
+  }
+
+#ifdef USE_SCTP
+     if (socket->ss_transport == T_SCTP) {
+         socket->sctpstate = SCTP_CONNECTING;
+     }
+#endif
+
+  return 0;
+}
+
+int sipp_connect_socket(struct sipp_socket *socket, struct sockaddr_storage *dest) {
+  memcpy(&socket->ss_dest, dest, SOCK_ADDR_SIZE(dest));
+  return sipp_do_connect_socket(socket);
+}
+
+int sipp_reconnect_socket(struct sipp_socket *socket) {
+  assert(socket->ss_fd == -1);
+
+  socket->ss_fd = socket_fd(socket->ss_ipv6, socket->ss_transport);
+  if (socket->ss_fd == -1) {
+    ERROR_NO("Could not obtain new socket: ");
+  }
+
+  if (socket->ss_invalid) {
+#ifdef _USE_OPENSSL
+    socket->ss_ssl = NULL;
+
+    if ( transport == T_TLS ) {
+      if ((socket->ss_bio = BIO_new_socket(socket->ss_fd,BIO_NOCLOSE)) == NULL) {
+       ERROR("Unable to create BIO object:Problem with BIO_new_socket()\n");
+      }
+
+      if (!(socket->ss_ssl = SSL_new(sip_trp_ssl_ctx_client))) {
+       ERROR("Unable to create SSL object : Problem with SSL_new() \n");
+      }
+
+      SSL_set_bio(socket->ss_ssl,socket->ss_bio,socket->ss_bio);
+    }
+#endif
+
+    /* Store this socket in the tables. */
+    socket->ss_pollidx = pollnfds++;
+    sockets[socket->ss_pollidx] = socket;
+    pollfiles[socket->ss_pollidx].fd      = socket->ss_fd;
+    pollfiles[socket->ss_pollidx].events  = POLLIN | POLLERR;
+    pollfiles[socket->ss_pollidx].revents = 0;
+
+    socket->ss_invalid = false;
+  }
+
+  return sipp_do_connect_socket(socket);
+}
+
+#ifdef SIPP_UNITTEST
+
+int main()
+{
+    /* Unit testing function */
+    char ipv6_addr_brackets[] = "[fe80::92a4:deff:fe74:7af5]";
+    char ipv6_addr_port[] = "[fe80::92a4:deff:fe74:7af5]:999";
+    char ipv6_addr[] = "fe80::92a4:deff:fe74:7af5";
+    char ipv4_addr_port[] = "127.0.0.1:999";
+    char ipv4_addr[] = "127.0.0.1";
+    char hostname_port[] = "sipp.sf.net:999";
+    char hostname[] = "sipp.sf.net";
+    int port_result = -1;
+    char host_result[255];
+    char orig_addr[255];
+
+#define TEST_GET_HOST_AND_PORT(VAR, EXPECTED_HOST, EXPECTED_PORT) {\
+    strcpy(host_result,""); \
+    strcpy(orig_addr,VAR); \
+    get_host_and_port(VAR, host_result, &port_result); \
+    if ((strcmp(host_result, EXPECTED_HOST) != 0) || (port_result != EXPECTED_PORT)) \
+    {fprintf(stderr, "get_host_and_port fails for address %s - results are %s and %d, expected %s and %d\n", orig_addr, host_result, port_result, EXPECTED_HOST, EXPECTED_PORT);};\
+}
+
+    TEST_GET_HOST_AND_PORT(ipv6_addr, "fe80::92a4:deff:fe74:7af5", 0)
+    TEST_GET_HOST_AND_PORT(ipv6_addr_brackets, "fe80::92a4:deff:fe74:7af5", 0)
+    TEST_GET_HOST_AND_PORT(ipv6_addr_port, "fe80::92a4:deff:fe74:7af5", 999)
+    TEST_GET_HOST_AND_PORT(ipv4_addr, "127.0.0.1", 0)
+    TEST_GET_HOST_AND_PORT(ipv4_addr_port, "127.0.0.1", 999)
+    TEST_GET_HOST_AND_PORT(hostname, "sipp.sf.net", 0)
+    TEST_GET_HOST_AND_PORT(hostname_port, "sipp.sf.net", 999)
+
+    return 0;
+}
+
+#else
+
+/* Main */
+int main(int argc, char *argv[])
+{
+  int                  argi = 0;
+  struct sockaddr_storage   media_sockaddr;
+  pthread_t            pthread2_id,  pthread3_id;
+  int                  L_maxSocketPresent = 0;
+  unsigned int         generic_count = 0;
+  bool                 slave_masterSet = false;
+  
+  generic[0] = NULL;
+
+  /* At least one argument is needed */
+  if(argc < 2) {
+    help();
+    exit(EXIT_OTHER);
+  }
+  {
+    /* Ignore the SIGPIPE signal */
+    struct sigaction action_pipe;
+    memset(&action_pipe, 0, sizeof(action_pipe));
+    action_pipe.sa_handler=SIG_IGN;
+    sigaction(SIGPIPE, &action_pipe, NULL);
+
+    /* The Window Size change Signal is also useless, and causes failures. */
+#ifdef SIGWINCH
+    sigaction(SIGWINCH, &action_pipe, NULL);
+#endif
+
+    /* sig usr1 management */
+    struct sigaction action_usr1;
+    memset(&action_usr1, 0, sizeof(action_usr1));
+    action_usr1.sa_handler = sipp_sigusr1;
+    sigaction(SIGUSR1, &action_usr1, NULL);
+
+    /* sig usr2 management */
+    struct sigaction action_usr2;
+    memset(&action_usr2, 0, sizeof(action_usr2));
+    action_usr2.sa_handler = sipp_sigusr2;
+    sigaction(SIGUSR2, &action_usr2, NULL);
+  }
+
+  screen_set_exename((char *)"sipp");
+  
+  pid = getpid();
+  memset(local_ip, 0, 40);
+#ifdef USE_SCTP
+  memset(multihome_ip, 0, 40);
+#endif
+  memset(media_ip,0, 40);
+  memset(control_ip,0, 40);
+  memset(media_ip_escaped,0, 42);
+  
+  /* Load compression pluggin if available */
+  comp_load();
+
+  /* Initialize the tolower table. */
+  init_tolower_table();
+
+  /* Initialize our global variable structure. */
+  globalVariables = new AllocVariableTable(NULL);
+  userVariables = new AllocVariableTable(globalVariables);
+
+  /* Command line parsing */
+#define REQUIRE_ARG() if((++argi) >= argc) { ERROR("Missing argument for param '%s'.\n" \
+                                    "Use 'sipp -h' for details",  argv[argi - 1]); }
+#define CHECK_PASS() if (option->pass != pass) { break; }
+
+  for (int pass = 0; pass <= 3; pass++) {
+    for(argi = 1; argi < argc; argi++) {
+      struct sipp_option *option = find_option(argv[argi]);
+      if (!option) {
+       if((argv[argi])[0] != '-') {
+         strcpy(remote_host, argv[argi]);
+         continue;
+       }
+       help();
+       ERROR("Invalid argument: '%s'.\n"
+           "Use 'sipp -h' for details", argv[argi]);
+      }
+
+      switch(option->type)
+      {
+       case SIPP_OPTION_HELP:
+         if(((argi+1) < argc) && (!strcmp(argv[argi+1], "stat"))) {
+           help_stats();
+         } else {
+           help();
+         }
+         exit(EXIT_OTHER);
+       case SIPP_OPTION_VERSION:
+         printf("\n SIPp v3.3-beta1"
+#ifdef _USE_OPENSSL
+             "-TLS"
+#endif
+#ifdef USE_SCTP
+             "-SCTP"
+#endif
+#ifdef PCAPPLAY
+             "-PCAP"
+#endif
+             ", version %s, built %s, %s.\n\n",
+             SIPP_VERSION, __DATE__, __TIME__); 
+
+         printf
+           (" This program is free software; you can redistribute it and/or\n"
+            " modify it under the terms of the GNU General Public License as\n"
+            " published by the Free Software Foundation; either version 2 of\n"
+            " the License, or (at your option) any later version.\n"
+            "\n"
+            " This program is distributed in the hope that it will be useful,\n"
+            " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+            " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+            " GNU General Public License for more details.\n"
+            "\n"
+            " You should have received a copy of the GNU General Public\n"
+            " License along with this program; if not, write to the\n"
+            " Free Software Foundation, Inc.,\n"
+            " 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA\n"
+            "\n"
+            " Author: see source files.\n\n");
+         exit(EXIT_OTHER);
+       case SIPP_OPTION_INT:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         *((int *)option->data) = get_long(argv[argi], argv[argi-1]);
+         break;
+        case SIPP_OPTION_LONG:
+          REQUIRE_ARG();
+          CHECK_PASS();
+          *((long *)option->data) = get_long(argv[argi], argv[argi-1]);
+          break; 
+        case SIPP_OPTION_LONG_LONG:
+          REQUIRE_ARG();
+          CHECK_PASS();
+          *((unsigned long long *)option->data) = get_long_long(argv[argi], argv[argi-1]);
+          break;
+       case SIPP_OPTION_TIME_SEC:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         *((long *)option->data) = get_time(argv[argi], argv[argi-1], 1000);
+         break;
+       case SIPP_OPTION_TIME_MS:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         *((int *)option->data) = get_time(argv[argi], argv[argi-1], 1);
+         break;
+        case SIPP_OPTION_TIME_MS_LONG:
+          REQUIRE_ARG();
+          CHECK_PASS();
+          *((long *)option->data) = get_time(argv[argi], argv[argi-1], 1);
+          break;
+       case SIPP_OPTION_BOOL:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         *((bool *)option->data) = get_bool(argv[argi], argv[argi-1]);
+         break;
+       case SIPP_OPTION_FLOAT:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         *((double *)option->data) = get_double(argv[argi], argv[argi-1]);
+         break;
+       case SIPP_OPTION_STRING:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         *((char **)option->data) = argv[argi];
+         break;
+       case SIPP_OPTION_ARGI:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         *((int *)option->data) = argi;
+         break;
+       case SIPP_OPTION_INPUT_FILE:
+         {
+           REQUIRE_ARG();
+           CHECK_PASS();
+           FileContents *data = new FileContents(argv[argi]);
+           char *name = argv[argi];
+           if (strrchr(name, '/')) {
+             name = strrchr(name, '/') + 1;
+           } else if (strrchr(name, '\\')) {
+             name = strrchr(name, '\\') + 1;
+           }
+           assert(name);
+           inFiles[name] = data;
+           /* By default, the first file is used for IP address input. */
+           if (!ip_file) {
+             ip_file = name;
+           }
+           if (!default_file) {
+             default_file = name;
+           }
+         }
+         break;
+       case SIPP_OPTION_INDEX_FILE:
+         REQUIRE_ARG();
+         REQUIRE_ARG();
+         CHECK_PASS();
+         {
+           char *fileName = argv[argi - 1];
+           char *endptr;
+           int field;
+
+           if (inFiles.find(fileName) == inFiles.end()) {
+             ERROR("Could not find file for -infindex: %s", argv[argi - 1]);
+           }
+
+           field = strtoul(argv[argi], &endptr, 0);
+           if (*endptr) {
+             ERROR("Invalid field specification for -infindex: %s", argv[argi]);
+           }
+
+           inFiles[fileName]->index(field);
+         }
+         break;
+       case SIPP_OPTION_SETFLAG:
+         CHECK_PASS();
+         *((bool *)option->data) = true;
+         break;
+       case SIPP_OPTION_UNSETFLAG:
+         CHECK_PASS();
+         *((bool *)option->data) = false;
+         break;
+       case SIPP_OPTION_TRANSPORT:
+         REQUIRE_ARG();
+         CHECK_PASS();
+
+         if (strlen(argv[argi]) != 2) {
+           ERROR("Invalid argument for -t param : '%s'.\n"
+               "Use 'sipp -h' for details",  argv[argi]);
+         }
+
+         switch(argv[argi][0]) {
+           case 'u':
+             transport = T_UDP;
+             break;
+           case 't':
+             transport = T_TCP;
+             break;
+           case 's':
+#ifdef USE_SCTP
+             transport = T_SCTP;
+#else
+             ERROR("To use SCTP transport you must compile SIPp with lksctp");
+#endif
+             break;
+           case 'l':
+#ifdef _USE_OPENSSL
+             transport = T_TLS;
+             if ( init_OpenSSL() != 1) {
+               printf("OpenSSL Initialization problem\n");
+               exit ( -1);
+             }
+#else
+             ERROR("To use a TLS transport you must compile SIPp with OpenSSL");
+#endif
+             break;
+           case 'c':
+             if(strlen(comp_error)) {
+               ERROR("No " COMP_PLUGGIN " pluggin available:\n%s", comp_error);
+             }
+             transport = T_UDP;
+             compression = 1;
+         }
+         switch(argv[argi][1]) {
+           case '1':
+             multisocket = 0;
+             peripsocket = 0;
+             break;
+           case 'n':
+             multisocket = 1;
+             peripsocket = 0;
+             break;
+           case 'i':
+             multisocket = 1;
+             peripsocket = 1;
+             socket_close = false;
+             break;
+         }
+
+         if (peripsocket && transport != T_UDP) {
+           ERROR("You can only use a perip socket with UDP!\n");
+         }
+         break;
+  case SIPP_OPTION_NEED_SCTP:
+         CHECK_PASS();
+         ERROR("SCTP support is required for the %s option.", argv[argi]);
+         break;
+       case SIPP_OPTION_NEED_SSL:
+         CHECK_PASS();
+         ERROR("OpenSSL is required for the %s option.", argv[argi]);
+         break;
+       case SIPP_OPTION_MAX_SOCKET:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         max_multi_socket = get_long(argv[argi], argv[argi - 1]);
+         maxSocketPresent = true ;
+         break;
+       case SIPP_OPTION_CSEQ:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         base_cseq = get_long(argv[argi], argv[argi - 1]);
+         base_cseq--;
+         break;
+       case SIPP_OPTION_IP:
+         {
+           int dummy_port;
+           char *ptr = (char *)option->data;
+           REQUIRE_ARG();
+           CHECK_PASS();
+
+           strcpy(ptr, argv[argi]);
+           get_host_and_port(ptr, ptr, &dummy_port);
+         }
+         break;
+       case SIPP_OPTION_LIMIT:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         if (users >= 0) {
+           ERROR("Can not set open call limit (-l) when -users is specified.");
+         }
+         open_calls_allowed = get_long(argv[argi], argv[argi - 1]);
+         open_calls_user_setting = 1;
+         break;
+       case SIPP_OPTION_USERS:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         users = open_calls_allowed = get_long(argv[argi], argv[argi - 1]);
+         open_calls_user_setting = 1;
+         break;
+       case SIPP_OPTION_KEY:
+         REQUIRE_ARG();
+         REQUIRE_ARG();
+         CHECK_PASS();
+
+         if (generic_count+1 >= sizeof(generic)/sizeof(generic[0])) {
+           ERROR("Too many generic parameters %d",generic_count+1);
+         }
+         generic[generic_count++] = &argv[argi - 1];
+         generic[generic_count] = NULL;
+         break;
+       case SIPP_OPTION_VAR:
+         REQUIRE_ARG();
+         REQUIRE_ARG();
+         CHECK_PASS();
+
+         {
+           int varId = globalVariables->find(argv[argi  - 1], false);
+           if (varId == -1) {
+               globalVariables->dump();
+               ERROR("Can not set the global variable %s, because it does not exist.", argv[argi - 1]);
+           }
+           globalVariables->getVar(varId)->setString(strdup(argv[argi]));
+         }
+         break;
+       case SIPP_OPTION_3PCC:
+         if(slave_masterSet){
+           ERROR("-3PCC option is not compatible with -master and -slave options\n");
+         }
+         if(extendedTwinSippMode){
+           ERROR("-3pcc and -slave_cfg options are not compatible\n");
+         } 
+         REQUIRE_ARG();
+         CHECK_PASS();
+         twinSippMode = true;
+         strcpy(twinSippHost, argv[argi]);
+         get_host_and_port(twinSippHost, twinSippHost, &twinSippPort);
+         break;
+       case SIPP_OPTION_SCENARIO:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         if (!strcmp(argv[argi - 1], "-sf")) {
+           scenario_file = new char [strlen(argv[argi])+1] ;
+           sprintf(scenario_file,"%s", argv[argi]);
+           scenario_file = remove_pattern (scenario_file, (char*)".xml");
+           if (useLogf == 1) {
+             rotate_logfile();
+           }
+           main_scenario = new scenario(argv[argi], 0);
+           main_scenario->stats->setFileName(scenario_file, (char*)".csv");
+         } else if (!strcmp(argv[argi - 1], "-sn")) {
+           int i = find_scenario(argv[argi]);
+
+           main_scenario = new scenario(0, i);
+           scenario_file = new char [strlen(argv[argi])+1] ;
+           sprintf(scenario_file,"%s", argv[argi]);
+           main_scenario->stats->setFileName(argv[argi], (char*)".csv");
+         } else if (!strcmp(argv[argi - 1], "-sd")) {
+           int i = find_scenario(argv[argi]);
+           fprintf(stdout, "%s", default_scenario[i]);
+           exit(EXIT_OTHER);
+         } else {
+           ERROR("Internal error, I don't recognize %s as a scenario option\n", argv[argi] - 1);
+         }
+         break;
+       case SIPP_OPTION_OOC_SCENARIO:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         if (!strcmp(argv[argi - 1], "-oocsf")) {
+           ooc_scenario = new scenario(argv[argi], 0);
+         } else if (!strcmp(argv[argi - 1], "-oocsn")) {
+           int i = find_scenario(argv[argi]);
+           ooc_scenario = new scenario(0, i);
+         } else {
+           ERROR("Internal error, I don't recognize %s as a scenario option\n", argv[argi] - 1);
+         }
+         break;
+       case SIPP_OPTION_SLAVE_CFG: 
+         REQUIRE_ARG();
+         CHECK_PASS();
+         if(twinSippMode){
+           ERROR("-slave_cfg and -3pcc options are not compatible\n");
+         }
+         extendedTwinSippMode = true;
+         slave_cfg_file = new char [strlen(argv[argi])+1] ;
+         sprintf(slave_cfg_file,"%s", argv[argi]);
+         parse_slave_cfg();
+         break;
+       case SIPP_OPTION_3PCC_EXTENDED:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         if(slave_masterSet){
+           ERROR("-slave and -master options are not compatible\n");
+         }
+         if(twinSippMode){
+           ERROR("-master and -slave options are not compatible with -3PCC option\n");
+         }
+         *((char **)option->data) = argv[argi];
+         slave_masterSet = true;
+         break;
+       case SIPP_OPTION_RSA: {
+         REQUIRE_ARG();
+         CHECK_PASS();
+         char *remote_s_address ;
+         int   remote_s_p = DEFAULT_PORT;
+         int   temp_remote_s_p;
+
+         temp_remote_s_p = 0;
+         remote_s_address = argv[argi] ;
+         get_host_and_port(remote_s_address, remote_s_address, &temp_remote_s_p);
+         if (temp_remote_s_p != 0) {
+           remote_s_p = temp_remote_s_p;
+         }
+         struct addrinfo   hints;
+         struct addrinfo * local_addr;
+
+         printf("Resolving remote sending address %s...\n", remote_s_address);
+
+         memset((char*)&hints, 0, sizeof(hints));
+         hints.ai_flags  = AI_PASSIVE;
+         hints.ai_family = PF_UNSPEC;
+
+         /* FIXME: add DNS SRV support using liburli? */
+         if (getaddrinfo(remote_s_address,
+               NULL,
+               &hints,
+               &local_addr) != 0) {
+           ERROR("Unknown remote host '%s'.\n"
+               "Use 'sipp -h' for details", remote_s_address);
+         }
+
+         memcpy(&remote_sending_sockaddr,
+             local_addr->ai_addr,
+             SOCK_ADDR_SIZE(
+               _RCAST(struct sockaddr_storage *, local_addr->ai_addr)));
+
+         if (remote_sending_sockaddr.ss_family == AF_INET) {
+           (_RCAST(struct sockaddr_in *, &remote_sending_sockaddr))->sin_port =
+             htons((short)remote_s_p);
+         } else {
+           (_RCAST(struct sockaddr_in6 *, &remote_sending_sockaddr))->sin6_port =
+             htons((short)remote_s_p);
+         }
+         use_remote_sending_addr = 1 ;
+
+         freeaddrinfo(local_addr);
+         break;
+       }
+       case SIPP_OPTION_RTCHECK:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         if (!strcmp(argv[argi], "full")) {
+           *((int *)option->data) = RTCHECK_FULL;
+         } else if (!strcmp(argv[argi], "loose")) {
+           *((int *)option->data) = RTCHECK_LOOSE;
+         } else {
+           ERROR("Unknown retransmission detection method: %s\n", argv[argi]);
+         }
+         break;
+       case SIPP_OPTION_TDMMAP: {
+          REQUIRE_ARG();
+         CHECK_PASS();
+         int i1, i2, i3, i4, i5, i6, i7;
+
+         if (sscanf(argv[argi], "{%d-%d}{%d}{%d-%d}{%d-%d}", &i1, &i2, &i3, &i4, &i5, &i6, &i7) == 7) {
+           use_tdmmap = true;
+           tdm_map_a = i2 - i1;
+           tdm_map_x = i1;
+           tdm_map_h = i3;
+           tdm_map_b = i5 - i4;
+           tdm_map_y = i4;
+           tdm_map_c = i7 - i6;
+           tdm_map_z = i6;
+         } else {
+           ERROR("Parameter -tdmmap must be of form {%%d-%%d}{%%d}{%%d-%%d}{%%d-%%d}");
+         }
+         break;
+       }
+       case SIPP_OPTION_DEFAULTS: {
+           unsigned long *ptr = (unsigned long *)option->data;
+           char *token;
+
+           REQUIRE_ARG();
+           CHECK_PASS();
+
+           *ptr = 0;
+
+           token = argv[argi];
+           while ((token = strtok(token, ","))) {
+               if (!strcmp(token, "none")) {
+                 *ptr = 0;
+               } else {
+                 unsigned long mask = 0;
+                 int mode = 1;
+                 char *p = token;
+                 if (token[0] == '+') {
+                   mode = 1;
+                   p++;
+                 } else if (token[0] == '-') {
+                   mode = -1;
+                   p++;
+                 }
+                 if (!strcmp(p, "all")) {
+                   mask = DEFAULT_BEHAVIOR_ALL;
+                 } else if (!strcmp(p, "bye")) {
+                   mask = DEFAULT_BEHAVIOR_BYE;
+                 } else if (!strcmp(p, "abortunexp")) {
+                   mask = DEFAULT_BEHAVIOR_ABORTUNEXP;
+                 } else if (!strcmp(p, "pingreply")) {
+                   mask = DEFAULT_BEHAVIOR_PINGREPLY;
+                 } else {
+                   ERROR("Unknown default behavior: '%s'\n", token);
+                 }
+                 switch(mode) {
+                   case 0:
+                     *ptr = mask;
+                     break;
+                   case 1:
+                     *ptr |= mask;
+                     break;
+                   case -1:
+                     *ptr &= ~mask;
+                     break;
+                   default:
+                    assert(0);
+                 }
+               }
+               token = NULL;
+           }
+           break;
+         }
+       case SIPP_OPTION_LFNAME:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         ((struct logfile_info*)option->data)->fixedname = true;
+         strcpy(((struct logfile_info*)option->data)->file_name, argv[argi]);
+         break;
+       case SIPP_OPTION_LFOVERWRITE:
+         REQUIRE_ARG();
+         CHECK_PASS();
+         ((struct logfile_info*)option->data)->fixedname = true;
+         ((struct logfile_info*)option->data)->overwrite = get_bool(argv[argi], argv[argi-1]);
+         break;
+       case SIPP_OPTION_PLUGIN: {
+           void *handle;
+           char *error;
+           int (*init)();
+           int ret;
+
+           REQUIRE_ARG();
+           CHECK_PASS();
+
+           handle = dlopen(argv[argi], RTLD_NOW);
+           if (!handle) {
+             ERROR("Could not open plugin %s: %s", argv[argi], dlerror());
+           }
+
+           init = (int (*)())dlsym(handle, "init");
+           if((error = (char *) dlerror())) {
+             ERROR("Could not locate init function in %s: %s", argv[argi], dlerror());
+           }
+
+           ret = init();
+           if (ret != 0) {
+             ERROR("Plugin %s initialization failed.", argv[argi]);
+           }
+         }
+         break;
+       default:
+         ERROR("Internal error: I don't recognize the option type for %s\n", argv[argi]);
+      }
+    }
+  }
+
+  if((extendedTwinSippMode && !slave_masterSet) || (!extendedTwinSippMode && slave_masterSet)){
+    ERROR("-slave_cfg option must be used with -slave or -master option\n");
+  }
+
+  if (peripsocket) {
+    if (!ip_file) {
+      ERROR("You must use the -inf option when using -t ui.\n"
+               "Use 'sipp -h' for details");
+    }
+  }
+
+  if (ringbuffer_size && max_log_size) {
+    ERROR("Ring Buffer options and maximum log size are mutually exclusive.");
+  }
+
+  if (global_lost) {
+    lose_packets = 1;
+  }
+
+  /* trace file setting */
+  if (scenario_file == NULL) {
+    scenario_file = new char [ 5 ] ;
+    sprintf(scenario_file, "%s", "sipp");
+  }
+
+   screen_init(print_last_stats);
+
+#ifdef _USE_OPENSSL
+    if ((transport == T_TLS) && (FI_init_ssl_context() != SSL_INIT_NORMAL))
+    {
+      ERROR("FI_init_ssl_context() failed");
+    }
+#endif
+
+  if (useMessagef == 1) {
+    rotate_messagef();
+  }
+  
+  if (useShortMessagef == 1) {
+    rotate_shortmessagef();
+  }
+
+  if (useCallDebugf) {
+    rotate_calldebugf();
+  }
+  
+  if (useScreenf == 1) {
+    char L_file_name [MAX_PATH];
+    sprintf (L_file_name, "%s_%d_screen.log", scenario_file, getpid());
+    screenf = fopen(L_file_name, "w");
+    if(!screenf) {
+      ERROR("Unable to create '%s'", L_file_name);
+    }
+  }  
+
+   // TODO: finish the -trace_timeout option implementation    
+
+ /* if (useTimeoutf == 1) {
+    char L_file_name [MAX_PATH];
+    sprintf (L_file_name, "%s_%d_timeout.log", scenario_file, getpid());
+    timeoutf = fopen(L_file_name, "w");
+    if(!timeoutf) {
+      ERROR("Unable to create '%s'", L_file_name);
+    }
+  } */
+
+  if (useCountf == 1) {
+    char L_file_name [MAX_PATH];
+    sprintf (L_file_name, "%s_%d_counts.csv", scenario_file, getpid());
+    countf = fopen(L_file_name, "w");
+    if(!countf) {
+      ERROR("Unable to create '%s'", L_file_name);
+    }
+    print_count_file(countf, 1);
+  }
+
+  if (dumpInRtt == 1) {
+     main_scenario->stats->initRtt((char*)scenario_file, (char*)".csv",
+                                report_freq_dumpRtt);
+  }
+
+  if ((maxSocketPresent) && (max_multi_socket > FD_SETSIZE) ) {
+     L_maxSocketPresent = 1;
+  }
+
+  /* Initialization:  boost open file limit to the max (AgM)*/
+  if (!skip_rlimit) {
+    struct rlimit rlimit;
+
+    if (getrlimit (RLIMIT_NOFILE, &rlimit) < 0) {
+      ERROR_NO("getrlimit error");
+    }
+
+    if (rlimit.rlim_max >
+#ifndef __CYGWIN
+       ((L_maxSocketPresent) ?  (unsigned int)max_multi_socket : FD_SETSIZE)
+#else
+       FD_SETSIZE
+#endif
+       ) {
+      fprintf (stderr, "Warning: open file limit > FD_SETSIZE; "
+               "limiting max. # of open files to FD_SETSIZE = %d\n",
+               FD_SETSIZE);
+
+      rlimit.rlim_max =
+#ifndef __CYGWIN
+          (L_maxSocketPresent) ?  (unsigned int)max_multi_socket+min_socket : FD_SETSIZE ;
+#else
+
+         FD_SETSIZE;
+#endif
+    }
+
+    rlimit.rlim_cur = rlimit.rlim_max;
+    if (setrlimit (RLIMIT_NOFILE, &rlimit) < 0) {
+      ERROR("Unable to increase the open file limit to FD_SETSIZE = %d",
+               FD_SETSIZE);
+    }
+  }
+  
+  /* Load default scenario in case nothing was loaded */
+  if(!main_scenario) {
+    main_scenario = new scenario(0, 0);
+    main_scenario->stats->setFileName((char*)"uac", (char*)".csv");
+    sprintf(scenario_file,"uac");
+  }
+  /*
+  if(!ooc_scenario) {
+    ooc_scenario = new scenario(0, find_scenario("ooc_default"));
+    ooc_scenario->stats->setFileName((char*)"ooc_default", (char*)".csv");
+  }
+  */
+  display_scenario = main_scenario;
+  aa_scenario = new scenario(0, find_scenario("ooc_dummy"));
+  aa_scenario->stats->setFileName((char*)"ooc_dummy", (char*)".csv");
+
+  init_default_messages();
+  for (int i = 1; i <= users; i++) {
+    freeUsers.push_back(i);
+    userVarMap[i] = new VariableTable(userVariables);
+  }
+
+  if(argiFileName) {
+    main_scenario->stats->setFileName(argv[argiFileName]);
+  }
+  // setup option form cmd line
+  call::maxDynamicId   = maxDynamicId;
+  call::startDynamicId = startDynamicId;
+  call::dynamicId      = startDynamicId;
+  call::stepDynamicId  = stepDynamicId;
+
+
+  /* Now Initialize the scenarios. */
+  main_scenario->runInit();
+  if(ooc_scenario) {
+    ooc_scenario->runInit();
+  }
+
+  /* In which mode the tool is launched ? */
+  main_scenario->computeSippMode();
+  if (ooc_scenario && sendMode == MODE_SERVER) {
+      ERROR("SIPp cannot use out-of-call scenarios when running in server mode");
+  }
+
+  /* checking if we need to launch the tool in background mode */ 
+  if(backgroundMode == true)
+    {
+      pid_t l_pid;
+      switch(l_pid = fork())
+        {
+        case -1:
+          // error when forking !
+          ERROR_NO("Forking error");
+          exit(EXIT_FATAL_ERROR);
+        case 0:
+          // child process - poursuing the execution
+         // close all of our file descriptors
+         {
+           int nullfd = open("/dev/null", O_RDWR);
+
+           dup2(nullfd, fileno(stdin));
+           dup2(nullfd, fileno(stdout));
+           dup2(nullfd, fileno(stderr));
+
+           close(nullfd);
+         }
+          break;
+        default:
+          // parent process - killing the parent - the child get the parent pid
+          printf("Background mode - PID=[%d]\n", l_pid);
+          exit(EXIT_OTHER);
+        }
+    }
+
+    sipp_usleep(sleeptime * 1000);
+
+  /* Create the statistics reporting task. */
+  stattask::initialize();
+  /* Create the screen update task. */
+  screentask::initialize();
+  /* Create a watchdog task. */
+  if (watchdog_interval) {
+    new watchdog(watchdog_interval, watchdog_reset, watchdog_major_threshold, watchdog_major_maxtriggers, watchdog_minor_threshold, watchdog_minor_maxtriggers);
+  }
+
+  /* Setting the rate and its dependant params (open_calls_allowed) */
+  /* If we are a client, then create the task to open new calls. */
+  if (creationMode == MODE_CLIENT) {
+    opentask::initialize();
+    opentask::set_rate(rate);
+  }
+
+  open_connections();
+
+  /* Defaults for media sockets */
+  if (media_ip[0] == '\0') {
+      strcpy(media_ip, local_ip);
+    }
+  if (media_ip_escaped[0] == '\0') {
+    strcpy(media_ip_escaped, local_ip);
+  }
+  if (local_ip_is_ipv6) {
+    media_ip_is_ipv6 = true;
+  } else {
+    media_ip_is_ipv6 = false;
+  }
+
+  /* Always create and Bind RTP socket */
+  /* to avoid ICMP                     */
+  if (1) {
+    /* retrieve RTP local addr */
+    struct addrinfo   hints;
+    struct addrinfo * local_addr;
+
+    memset((char*)&hints, 0, sizeof(hints));
+    hints.ai_flags  = AI_PASSIVE;
+    hints.ai_family = PF_UNSPEC;
+
+    /* Resolving local IP */
+    if (getaddrinfo(media_ip,
+                    NULL,
+                    &hints,
+                    &local_addr) != 0) {
+      ERROR("Unknown RTP address '%s'.\n"
+               "Use 'sipp -h' for details", media_ip);
+    }
+    
+    memset(&media_sockaddr,0,sizeof(struct sockaddr_storage));
+    media_sockaddr.ss_family = local_addr->ai_addr->sa_family;
+    
+    memcpy(&media_sockaddr,
+           local_addr->ai_addr,
+           SOCK_ADDR_SIZE(
+             _RCAST(struct sockaddr_storage *,local_addr->ai_addr)));
+    freeaddrinfo(local_addr);
+
+    if((media_socket = socket(media_ip_is_ipv6 ? AF_INET6 : AF_INET,
+                              SOCK_DGRAM, 0)) == -1) {
+      char msg[512];
+      sprintf(msg, "Unable to get the audio RTP socket (IP=%s, port=%d)", media_ip, media_port);
+      ERROR_NO(msg);
+    }
+    /* create a second socket for video */
+    if((media_socket_video = socket(media_ip_is_ipv6 ? AF_INET6 : AF_INET,
+                                    SOCK_DGRAM, 0)) == -1) {
+      char msg[512];
+      sprintf(msg, "Unable to get the video RTP socket (IP=%s, port=%d)", media_ip, media_port+2);
+      ERROR_NO(msg);
+    }
+
+    int try_counter;
+    int max_tries = user_media_port ? 1 : 100;
+    media_port = user_media_port ? user_media_port : DEFAULT_MEDIA_PORT;
+    for (try_counter = 0; try_counter < max_tries; try_counter++) {
+
+      if (media_sockaddr.ss_family == AF_INET) {
+       (_RCAST(struct sockaddr_in *,&media_sockaddr))->sin_port =
+         htons((short)media_port);
+      } else {
+       (_RCAST(struct sockaddr_in6 *,&media_sockaddr))->sin6_port =
+         htons((short)media_port);
+       media_ip_is_ipv6 = true;
+      }
+      strcpy(media_ip_escaped, media_ip);
+
+      if(bind(media_socket,
+           (sockaddr *)(void *)&media_sockaddr,
+           SOCK_ADDR_SIZE(&media_sockaddr)) == 0) {
+       break;
+      }
+
+      media_port++;
+    }
+
+    if (try_counter >= max_tries) {
+      char msg[512];
+      sprintf(msg, "Unable to bind audio RTP socket (IP=%s, port=%d)", media_ip, media_port);
+      ERROR_NO(msg);
+    }
+
+    /*---------------------------------------------------------
+       Bind the second socket to media_port+2 
+       (+1 is reserved for RTCP) 
+    ----------------------------------------------------------*/
+
+    if (media_sockaddr.ss_family == AF_INET) {
+     (_RCAST(struct sockaddr_in *,&media_sockaddr))->sin_port =
+       htons((short)media_port+2);
+     strcpy(media_ip_escaped, media_ip);
+    } else {
+      (_RCAST(struct sockaddr_in6 *,&media_sockaddr))->sin6_port =
+        htons((short)media_port+2);
+      media_ip_is_ipv6 = true;
+      strcpy(media_ip_escaped, media_ip);
+    }
+
+    if(bind(media_socket_video, 
+            (sockaddr *)(void *)&media_sockaddr,
+            SOCK_ADDR_SIZE(&media_sockaddr))) {
+      char msg[512];
+      sprintf(msg, "Unable to bind video RTP socket (IP=%s, port=%d)", media_ip, media_port+2);
+      ERROR_NO(msg);
+    }
+    /* Second socket bound */
+  }
+
+  /* Creating the remote control socket thread */
+  setup_ctrl_socket();
+  if (!nostdin) {
+    setup_stdin_socket();
+  }
+
+  if ((media_socket > 0) && (rtp_echo_enabled)) {
+    if (pthread_create
+        (&pthread2_id,
+         NULL,
+         (void *(*)(void *)) rtp_echo_thread,
+         (void*)&media_socket) 
+        == -1) {
+      ERROR_NO("Unable to create RTP echo thread");
+    }
+  }
+
+
+  /* Creating second RTP echo thread for video */
+  if ((media_socket_video > 0) && (rtp_echo_enabled)) {
+    if (pthread_create
+        (&pthread3_id,
+         NULL,
+         (void *(*)(void *)) rtp_echo_thread,
+         (void*)&media_socket_video) 
+        == -1) {
+      ERROR_NO("Unable to create second RTP echo thread");
+      }
+    }
+
+  traffic_thread();
+
+  if (scenario_file != NULL) {
+    delete [] scenario_file ;
+    scenario_file = NULL ;
+  }
+
+}
+
+#endif
+
+void sipp_usleep(unsigned long usec) {
+       if (usec >= 1000000) {
+               sleep(usec / 1000000);
+       }
+       usec %= 1000000;
+       usleep(usec);
+}
+
+bool reconnect_allowed() {
+  if (reset_number == -1) {
+    return true;
+  }
+  return (reset_number > 0);
+}
+
+void reset_connection(struct sipp_socket *socket) {
+  if (!reconnect_allowed()) {
+      ERROR_NO("Max number of reconnections reached");
+    }
+
+  if (reset_number != -1) {
+       reset_number--;
+  }
+
+  if (reset_close) {
+    WARNING("Closing calls, because of TCP reset or close!");
+    close_calls(socket);
+  }
+
+  /* Sleep for some period of time before the reconnection. */
+  usleep(1000 * reset_sleep);
+
+  if (sipp_reconnect_socket(socket) < 0) {
+    WARNING_NO("Could not reconnect TCP socket");
+    close_calls(socket);
+  } else {
+    WARNING("Socket required a reconnection.");
+  }
+}
+
+/* Close just those calls for a given socket (e.g., if the remote end closes
+ * the connection. */
+void close_calls(struct sipp_socket *socket) {
+  owner_list *owners = get_owners_for_socket(socket);
+  owner_list::iterator owner_it;
+  socketowner *owner_ptr = NULL;
+
+  for (owner_it = owners->begin(); owner_it != owners->end(); owner_it++) {
+    owner_ptr = *owner_it;
+    if(owner_ptr) {
+      owner_ptr->tcpClose();
+    }
+  }
+
+  delete owners;
+}
+
+int open_connections() {
+  int status=0;
+  local_port = 0;
+  
+  if(!strlen(remote_host)) {
+    if((sendMode != MODE_SERVER)) {
+      ERROR("Missing remote host parameter. This scenario requires it");
+    }
+  } else {
+    int temp_remote_port;
+    get_host_and_port(remote_host, remote_host, &temp_remote_port);
+    if (temp_remote_port != 0) {
+      remote_port = temp_remote_port;
+    }
+    /* Resolving the remote IP */
+    {
+      struct addrinfo   hints;
+      struct addrinfo * local_addr;
+
+      fprintf(stderr,"Resolving remote host '%s'... ", remote_host);
+
+      memset((char*)&hints, 0, sizeof(hints));
+      hints.ai_flags  = AI_PASSIVE;
+      hints.ai_family = PF_UNSPEC;
+
+      /* FIXME: add DNS SRV support using liburli? */
+      if (getaddrinfo(remote_host,
+                      NULL,
+                      &hints,
+                      &local_addr) != 0) {
+        ERROR("Unknown remote host '%s'.\n"
+                 "Use 'sipp -h' for details", remote_host);
+      }
+
+      memset(&remote_sockaddr, 0, sizeof( remote_sockaddr ));
+      memcpy(&remote_sockaddr,
+             local_addr->ai_addr,
+             SOCK_ADDR_SIZE(
+               _RCAST(struct sockaddr_storage *,local_addr->ai_addr)));
+
+      freeaddrinfo(local_addr);
+
+      strcpy(remote_ip, get_inet_address(&remote_sockaddr));
+      if (remote_sockaddr.ss_family == AF_INET) {
+        (_RCAST(struct sockaddr_in *, &remote_sockaddr))->sin_port =
+          htons((short)remote_port);
+        strcpy(remote_ip_escaped, remote_ip); 
+      } else {
+        (_RCAST(struct sockaddr_in6 *, &remote_sockaddr))->sin6_port =
+          htons((short)remote_port);
+        sprintf(remote_ip_escaped, "[%s]", remote_ip); 
+      }
+      fprintf(stderr,"Done.\n");
+    }
+   }
+
+  if(gethostname(hostname,64) != 0) {
+    ERROR_NO("Can't get local hostname in 'gethostname(hostname,64)'");
+  }
+  
+  {
+    char            * local_host = NULL;
+    struct addrinfo * local_addr;
+    struct addrinfo   hints;
+
+    if (!strlen(local_ip)) {
+      local_host = (char *)hostname;
+    } else {
+      local_host = (char *)local_ip;
+    }
+
+    memset((char*)&hints, 0, sizeof(hints));
+    hints.ai_flags  = AI_PASSIVE;
+    hints.ai_family = PF_UNSPEC;
+
+    /* Resolving local IP */
+    if (getaddrinfo(local_host, NULL, &hints, &local_addr) != 0) {
+      ERROR("Can't get local IP address in getaddrinfo, local_host='%s', local_ip='%s'",
+         local_host,
+         local_ip);
+    }
+    // store local addr info for rsa option
+    getaddrinfo(local_host, NULL, &hints, &local_addr_storage);
+
+    memset(&local_sockaddr,0,sizeof(struct sockaddr_storage));
+    local_sockaddr.ss_family = local_addr->ai_addr->sa_family;
+
+    if (!strlen(local_ip)) {
+      strcpy(local_ip,
+         get_inet_address(
+           _RCAST(struct sockaddr_storage *, local_addr->ai_addr)));
+    } else {
+          memcpy(&local_sockaddr,
+         local_addr->ai_addr,
+         SOCK_ADDR_SIZE(
+         _RCAST(struct sockaddr_storage *,local_addr->ai_addr)));
+    }
+    freeaddrinfo(local_addr);
+
+    if (local_sockaddr.ss_family == AF_INET6) {
+      local_ip_is_ipv6 = true;
+      sprintf(local_ip_escaped, "[%s]", local_ip);
+    } else {
+      strcpy(local_ip_escaped, local_ip);
+    }
+  }
+
+  /* Creating and binding the local socket */
+  if ((main_socket = new_sipp_socket(local_ip_is_ipv6, transport)) == NULL) {
+    ERROR_NO("Unable to get the local socket");
+  }
+
+  sipp_customize_socket(main_socket);
+
+  /* Trying to bind local port */
+  char peripaddr[256];
+  if(!user_port) {
+    unsigned short l_port;
+    for(l_port = DEFAULT_PORT;
+        l_port < (DEFAULT_PORT + 60);
+        l_port++) {
+
+      // Bind socket to local_ip
+      if (bind_local || peripsocket) {
+       struct addrinfo * local_addr;
+       struct addrinfo   hints;
+       memset((char*)&hints, 0, sizeof(hints));
+       hints.ai_flags  = AI_PASSIVE;
+       hints.ai_family = PF_UNSPEC;
+
+       if (peripsocket) {
+         // On some machines it fails to bind to the self computed local
+         // IP address.
+         // For the socket per IP mode, bind the main socket to the
+         // first IP address specified in the inject file.
+         inFiles[ip_file]->getField(0, peripfield, peripaddr, sizeof(peripaddr));
+         if (getaddrinfo(peripaddr,
+               NULL,
+               &hints,
+               &local_addr) != 0) {
+           ERROR("Unknown host '%s'.\n"
+               "Use 'sipp -h' for details", peripaddr);
+         }
+       } else {
+         if (getaddrinfo(local_ip,
+               NULL,
+               &hints,
+               &local_addr) != 0) {
+           ERROR("Unknown host '%s'.\n"
+               "Use 'sipp -h' for details", peripaddr);
+         }
+       }
+       memcpy(&local_sockaddr,
+           local_addr->ai_addr,
+           SOCK_ADDR_SIZE(
+             _RCAST(struct sockaddr_storage *, local_addr->ai_addr)));
+       freeaddrinfo(local_addr);
+      }
+      if (local_ip_is_ipv6) {
+       (_RCAST(struct sockaddr_in6 *, &local_sockaddr))->sin6_port
+         = htons((short)l_port);
+      } else {
+       (_RCAST(struct sockaddr_in *, &local_sockaddr))->sin_port
+         = htons((short)l_port);
+      }
+      if(sipp_bind_socket(main_socket, &local_sockaddr, &local_port) == 0) {
+       break;
+      }
+    }
+  }
+
+  if(!local_port) {
+    /* Not already binded, use user_port of 0 to leave
+     * the system choose a port. */
+
+    if (bind_local || peripsocket) {
+      struct addrinfo * local_addr;
+      struct addrinfo   hints;
+      memset((char*)&hints, 0, sizeof(hints));
+      hints.ai_flags  = AI_PASSIVE;
+      hints.ai_family = PF_UNSPEC;
+       
+      if (peripsocket) {
+        // On some machines it fails to bind to the self computed local
+        // IP address.
+        // For the socket per IP mode, bind the main socket to the
+        // first IP address specified in the inject file.
+       inFiles[ip_file]->getField(0, peripfield, peripaddr, sizeof(peripaddr));
+        if (getaddrinfo(peripaddr,
+                         NULL,
+                         &hints,
+                         &local_addr) != 0) {
+           ERROR("Unknown host '%s'.\n"
+                    "Use 'sipp -h' for details", peripaddr);
+        }
+      } else {
+        if (getaddrinfo(local_ip,
+                        NULL,
+                        &hints,
+                        &local_addr) != 0) {
+           ERROR("Unknown host '%s'.\n"
+                   "Use 'sipp -h' for details", peripaddr);
+        }
+      }
+      memcpy(&local_sockaddr,
+             local_addr->ai_addr,
+             SOCK_ADDR_SIZE(
+               _RCAST(struct sockaddr_storage *, local_addr->ai_addr)));
+      freeaddrinfo(local_addr);
+    }
+
+    if (local_ip_is_ipv6) {
+      (_RCAST(struct sockaddr_in6 *, &local_sockaddr))->sin6_port
+          = htons((short)user_port);        
+    } else {
+      (_RCAST(struct sockaddr_in *, &local_sockaddr))->sin_port
+          = htons((short)user_port); 
+    }
+    if(sipp_bind_socket(main_socket, &local_sockaddr, &local_port)) {
+      ERROR_NO("Unable to bind main socket");
+    }
+  }
+
+  if (peripsocket) {
+    // Add the main socket to the socket per subscriber map
+    map_perip_fd[peripaddr] = main_socket;
+  }
+
+  // Create additional server sockets when running in socket per
+  // IP address mode.
+  if (peripsocket && sendMode == MODE_SERVER) {
+    struct sockaddr_storage server_sockaddr;
+    struct addrinfo * local_addr;
+    struct addrinfo   hints;
+    memset((char*)&hints, 0, sizeof(hints));
+    hints.ai_flags  = AI_PASSIVE;
+    hints.ai_family = PF_UNSPEC;
+
+    char peripaddr[256];
+    struct sipp_socket *sock;
+    unsigned int lines = inFiles[ip_file]->numLines();
+    for (unsigned int i = 0; i < lines; i++) {
+      inFiles[ip_file]->getField(i, peripfield, peripaddr, sizeof(peripaddr));
+      map<string, struct sipp_socket *>::iterator j;
+      j = map_perip_fd.find(peripaddr);
+
+      if (j == map_perip_fd.end()) {
+        if((sock = new_sipp_socket(is_ipv6, transport)) == NULL) {
+          ERROR_NO("Unable to get server socket");
+        }
+
+        if (getaddrinfo(peripaddr,
+                        NULL,
+                        &hints,
+                        &local_addr) != 0) {
+            ERROR("Unknown remote host '%s'.\n"
+                     "Use 'sipp -h' for details", peripaddr);
+          }
+
+        memcpy(&server_sockaddr,
+              local_addr->ai_addr,
+              SOCK_ADDR_SIZE(
+                 _RCAST(struct sockaddr_storage *, local_addr->ai_addr)));
+        freeaddrinfo(local_addr);
+
+        if (is_ipv6) {
+          (_RCAST(struct sockaddr_in6 *, &server_sockaddr))->sin6_port
+              = htons((short)local_port);
+        } else {
+          (_RCAST(struct sockaddr_in *, &server_sockaddr))->sin_port
+              = htons((short)local_port);
+        }
+
+        sipp_customize_socket(sock);
+        if(sipp_bind_socket(sock, &server_sockaddr, NULL)) {
+          ERROR_NO("Unable to bind server socket");
+        }
+
+        map_perip_fd[peripaddr] = sock;
+      }
+    }
+  }
+
+  if((!multisocket) && (transport == T_TCP || transport == T_TLS || transport == T_SCTP) &&
+   (sendMode != MODE_SERVER)) {
+    if((tcp_multiplex = new_sipp_socket(local_ip_is_ipv6, transport)) == NULL) {
+      ERROR_NO("Unable to get a TCP socket");
+    }
+
+    /* OJA FIXME: is it correct? */
+    if (use_remote_sending_addr) {
+        remote_sockaddr = remote_sending_sockaddr ;
+    }
+    sipp_customize_socket(tcp_multiplex);
+
+    if(sipp_connect_socket(tcp_multiplex, &remote_sockaddr)) {
+      if(reset_number >0){
+             WARNING("Failed to reconnect\n");
+             sipp_close_socket(main_socket);
+             reset_number--;
+             return 1;
+          }else{
+      if(errno == EINVAL){
+        /* This occurs sometime on HPUX but is not a true INVAL */
+        ERROR_NO("Unable to connect a TCP socket, remote peer error.\n"
+              "Use 'sipp -h' for details");
+      } else {
+        ERROR_NO("Unable to connect a TCP socket.\n"
+                 "Use 'sipp -h' for details");
+      }
+    }
+    }
+
+  }
+
+
+  if(transport == T_TCP || transport == T_TLS || transport == T_SCTP) {
+    if(listen(main_socket->ss_fd, 100)) {
+      ERROR_NO("Unable to listen main socket");
+    }
+  }
+
+  /* Trying to connect to Twin Sipp in 3PCC mode */
+  if(twinSippMode) {
+    if(thirdPartyMode == MODE_3PCC_CONTROLLER_A || thirdPartyMode == MODE_3PCC_A_PASSIVE) {
+       connect_to_peer(twinSippHost, twinSippPort, &twinSipp_sockaddr, twinSippIp, &twinSippSocket);
+     }else if(thirdPartyMode == MODE_3PCC_CONTROLLER_B){
+       connect_local_twin_socket(twinSippHost);
+      }else{
+       ERROR("TwinSipp Mode enabled but thirdPartyMode is different "
+              "from 3PCC_CONTROLLER_B and 3PCC_CONTROLLER_A\n");
+      }
+   }else if (extendedTwinSippMode){       
+     if (thirdPartyMode == MODE_MASTER || thirdPartyMode == MODE_MASTER_PASSIVE) {
+       strcpy(twinSippHost,get_peer_addr(master_name));
+       get_host_and_port(twinSippHost, twinSippHost, &twinSippPort);
+       connect_local_twin_socket(twinSippHost);
+       connect_to_all_peers();
+     }else if(thirdPartyMode == MODE_SLAVE) {
+       strcpy(twinSippHost,get_peer_addr(slave_number));
+       get_host_and_port(twinSippHost, twinSippHost, &twinSippPort);
+       connect_local_twin_socket(twinSippHost);
+     }else{
+        ERROR("extendedTwinSipp Mode enabled but thirdPartyMode is different "
+              "from MASTER and SLAVE\n");
+     }
+    }
+
+  return status;
+            }
+
+
+void connect_to_peer(char *peer_host, int peer_port, struct sockaddr_storage *peer_sockaddr, char *peer_ip, struct sipp_socket **peer_socket) {
+
+          /* Resolving the  peer IP */
+      printf("Resolving peer address : %s...\n",peer_host);
+      struct addrinfo   hints;
+      struct addrinfo * local_addr;
+      memset((char*)&hints, 0, sizeof(hints));
+      hints.ai_flags  = AI_PASSIVE;
+      hints.ai_family = PF_UNSPEC;
+      is_ipv6 = false;
+      /* Resolving twin IP */
+      if (getaddrinfo(peer_host,
+                      NULL,
+                      &hints,
+                      &local_addr) != 0) {
+
+ERROR("Unknown peer host '%s'.\n"
+                       "Use 'sipp -h' for details", peer_host);
+            }
+
+      memcpy(peer_sockaddr,
+             local_addr->ai_addr,
+             SOCK_ADDR_SIZE(
+               _RCAST(struct sockaddr_storage *,local_addr->ai_addr)));
+
+      freeaddrinfo(local_addr);
+
+      if (peer_sockaddr->ss_family == AF_INET) {
+       (_RCAST(struct sockaddr_in *,peer_sockaddr))->sin_port =
+         htons((short)peer_port);
+      } else {
+        (_RCAST(struct sockaddr_in6 *,peer_sockaddr))->sin6_port =
+          htons((short)peer_port);
+        is_ipv6 = true;
+      }
+      strcpy(peer_ip, get_inet_address(peer_sockaddr));
+      if((*peer_socket = new_sipp_socket(is_ipv6, T_TCP)) == NULL) {
+       ERROR_NO("Unable to get a twin sipp TCP socket");
+      }
+
+      /* Mark this as a control socket. */
+      (*peer_socket)->ss_control = 1;
+
+      if(sipp_connect_socket(*peer_socket, peer_sockaddr)) {
+       if(errno == EINVAL) {
+         /* This occurs sometime on HPUX but is not a true INVAL */
+         ERROR_NO("Unable to connect a twin sipp TCP socket\n "
+             ", remote peer error.\n"
+             "Use 'sipp -h' for details");
+       } else {
+         ERROR_NO("Unable to connect a twin sipp socket "
+             "\n"
+             "Use 'sipp -h' for details");
+       }
+      }
+
+      sipp_customize_socket(*peer_socket);
+}
+
+struct sipp_socket **get_peer_socket(char * peer)
+{
+    struct sipp_socket **peer_socket;
+    T_peer_infos infos;
+    peer_map::iterator peer_it;
+    peer_it = peers.find(peer_map::key_type(peer));
+    if(peer_it != peers.end()) {
+      infos = peer_it->second;
+      peer_socket = &(infos.peer_socket);
+      return peer_socket;
+     }
+     else {
+       ERROR("get_peer_socket: Peer %s not found\n", peer);
+    }
+   return NULL;
+}
+
+char * get_peer_addr(char * peer)
+{
+    char * addr;
+    peer_addr_map::iterator peer_addr_it;
+    peer_addr_it = peer_addrs.find(peer_addr_map::key_type(peer)); 
+    if(peer_addr_it != peer_addrs.end()){
+       addr =  peer_addr_it->second;
+       return addr;
+       }
+     else{
+       ERROR("get_peer_addr: Peer %s not found\n", peer);
+       }
+   return NULL;
+}
+
+bool is_a_peer_socket(struct sipp_socket *peer_socket)
+{
+    peer_socket_map::iterator peer_socket_it;
+    peer_socket_it = peer_sockets.find(peer_socket_map::key_type(peer_socket));
+    if(peer_socket_it == peer_sockets.end()){
+       return false;
+      }else{
+       return true;
+      }
+}
+
+void connect_local_twin_socket(char * twinSippHost)
+{
+          /* Resolving the listener IP */
+            printf("Resolving listener address : %s...\n", twinSippHost);
+            struct addrinfo   hints;
+            struct addrinfo * local_addr;
+            memset((char*)&hints, 0, sizeof(hints));
+            hints.ai_flags  = AI_PASSIVE;
+            hints.ai_family = PF_UNSPEC;
+            is_ipv6 = false;
+
+            /* Resolving twin IP */
+            if (getaddrinfo(twinSippHost,
+                           NULL,
+                           &hints,
+                           &local_addr) != 0) {
+               ERROR("Unknown twin host '%s'.\n"
+                        "Use 'sipp -h' for details", twinSippHost);
+                }
+             memcpy(&twinSipp_sockaddr,
+                    local_addr->ai_addr,
+                    SOCK_ADDR_SIZE(
+                      _RCAST(struct sockaddr_storage *,local_addr->ai_addr)));
+
+             if (twinSipp_sockaddr.ss_family == AF_INET) {
+              (_RCAST(struct sockaddr_in *,&twinSipp_sockaddr))->sin_port =
+                htons((short)twinSippPort);
+             } else {
+               (_RCAST(struct sockaddr_in6 *,&twinSipp_sockaddr))->sin6_port =
+                 htons((short)twinSippPort);
+               is_ipv6 = true;
+             }
+             strcpy(twinSippIp, get_inet_address(&twinSipp_sockaddr));
+
+            if((localTwinSippSocket = new_sipp_socket(is_ipv6, T_TCP)) == NULL) {
+              ERROR_NO("Unable to get a listener TCP socket ");
+            }
+
+           memset(&localTwin_sockaddr, 0, sizeof(struct sockaddr_storage));
+           if (!is_ipv6) {
+               localTwin_sockaddr.ss_family = AF_INET;
+            (_RCAST(struct sockaddr_in *,&localTwin_sockaddr))->sin_port =
+             htons((short)twinSippPort);
+           } else {
+             localTwin_sockaddr.ss_family = AF_INET6;
+             (_RCAST(struct sockaddr_in6 *,&localTwin_sockaddr))->sin6_port =
+               htons((short)twinSippPort);
+           }
+
+           // add socket option to allow the use of it without the TCP timeout
+           // This allows to re-start the controller B (or slave) without timeout after its exit
+           int reuse = 1;
+           setsockopt(localTwinSippSocket->ss_fd,SOL_SOCKET,SO_REUSEADDR,(int *)&reuse,sizeof(reuse));
+           sipp_customize_socket(localTwinSippSocket);
+
+          if(sipp_bind_socket(localTwinSippSocket, &localTwin_sockaddr, 0)) {
+            ERROR_NO("Unable to bind twin sipp socket ");
+          }
+
+          if(listen(localTwinSippSocket->ss_fd, 100)) {
+            ERROR_NO("Unable to listen twin sipp socket in ");
+          }
+}
+
+void close_peer_sockets()
+{
+ peer_map::iterator peer_it;
+ T_peer_infos infos;
+
+ for(peer_it = peers.begin(); peer_it != peers.end(); peer_it++){
+     infos = peer_it->second;
+     sipp_close_socket(infos.peer_socket);
+     infos.peer_socket = NULL ;
+     peers[std::string(peer_it->first)] = infos;
+ }
+
+ peers_connected = 0;
+}
+
+void close_local_sockets(){
+   for (int i = 0; i< local_nb; i++){
+     sipp_close_socket(local_sockets[i]);
+     local_sockets[i] = NULL;
+   }
+}
+
+void connect_to_all_peers(){
+     peer_map::iterator peer_it;
+     T_peer_infos infos;
+     for (peer_it = peers.begin(); peer_it != peers.end(); peer_it++){
+         infos = peer_it->second;
+         get_host_and_port(infos.peer_host, infos.peer_host, &infos.peer_port);
+         connect_to_peer(infos.peer_host, infos.peer_port,&(infos.peer_sockaddr), infos.peer_ip, &(infos.peer_socket));
+         peer_sockets[infos.peer_socket] = peer_it->first;
+         peers[std::string(peer_it->first)] = infos;
+     }
+     peers_connected = 1;
+}
+
+bool is_a_local_socket(struct sipp_socket *s){
+  for (int i = 0; i< local_nb + 1; i++){
+    if(local_sockets[i] == s) return true;
+  }
+  return (false);
+}
+
+void free_peer_addr_map() {
+  peer_addr_map::iterator peer_addr_it;
+  for (peer_addr_it = peer_addrs.begin(); peer_addr_it != peer_addrs.end(); peer_addr_it++){
+       free(peer_addr_it->second);
+  }
+}
+
+void rotatef(struct logfile_info *lfi) {
+  char L_rotate_file_name [MAX_PATH];
+
+  if (!lfi->fixedname) {
+    sprintf (lfi->file_name, "%s_%d_%s.log", scenario_file, getpid(), lfi->name);
+  }
+
+  if (ringbuffer_files > 0) {
+    if (!lfi->ftimes) {
+       lfi->ftimes = (struct logfile_id *)calloc(ringbuffer_files, sizeof(struct logfile_id));
+    }
+    /* We need to rotate away an existing file. */
+    if (lfi->nfiles == ringbuffer_files) {
+      if ((lfi->ftimes)[0].n) {
+       sprintf(L_rotate_file_name, "%s_%d_%s_%lu.%d.log", scenario_file, getpid(), lfi->name, (lfi->ftimes)[0].start, (lfi->ftimes)[0].n);
+      } else {
+       sprintf(L_rotate_file_name, "%s_%d_%s_%lu.log", scenario_file, getpid(), lfi->name, (lfi->ftimes)[0].start);
+      }
+      unlink(L_rotate_file_name);
+      lfi->nfiles--;
+      memmove(lfi->ftimes, &((lfi->ftimes)[1]), sizeof(struct logfile_id) * (lfi->nfiles));
+    }
+    if (lfi->starttime) {
+      (lfi->ftimes)[lfi->nfiles].start = lfi->starttime;
+      (lfi->ftimes)[lfi->nfiles].n = 0;
+      /* If we have the same time, then we need to append an identifier. */
+      if (lfi->nfiles && ((lfi->ftimes)[lfi->nfiles].start == (lfi->ftimes)[lfi->nfiles - 1].start)) {
+         (lfi->ftimes)[lfi->nfiles].n = (lfi->ftimes)[lfi->nfiles - 1].n + 1;
+      }
+      if ((lfi->ftimes)[lfi->nfiles].n) {
+       sprintf(L_rotate_file_name, "%s_%d_%s_%lu.%d.log", scenario_file, getpid(), lfi->name, (lfi->ftimes)[lfi->nfiles].start, (lfi->ftimes)[lfi->nfiles].n);
+      } else {
+       sprintf(L_rotate_file_name, "%s_%d_%s_%lu.log", scenario_file, getpid(), lfi->name, (lfi->ftimes)[lfi->nfiles].start);
+      }
+      lfi->nfiles++;
+      fflush(lfi->fptr);
+      fclose(lfi->fptr);
+      lfi->fptr = NULL;
+      rename(lfi->file_name, L_rotate_file_name);
+    }
+  }
+
+  time(&lfi->starttime);
+  if (lfi->overwrite) {
+    lfi->fptr = fopen(lfi->file_name, "w");
+  } else {
+    lfi->fptr = fopen(lfi->file_name, "a");
+    lfi->overwrite = true;
+  }
+  if(lfi->check && !lfi->fptr) {
+    /* We can not use the error functions from this function, as we may be rotating the error log itself! */
+    ERROR("Unable to create '%s'", lfi->file_name);
+  }
+}
+
+void rotate_calldebugf() {
+  rotatef(&calldebug_lfi);
+}
+
+void rotate_messagef() {
+  rotatef(&message_lfi);
+}
+
+
+void rotate_shortmessagef() {
+  rotatef(&shortmessage_lfi);
+}
+
+
+void rotate_logfile() {
+  rotatef(&log_lfi);
+}
+
+void rotate_errorf() {
+  rotatef(&error_lfi);
+  strcpy(screen_logfile, error_lfi.file_name);
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int _trace (struct logfile_info *lfi, char *fmt, va_list ap) {
+  int ret = 0;
+  if(lfi->fptr) {
+    ret = vfprintf(lfi->fptr, fmt, ap);
+    fflush(lfi->fptr);
+
+    lfi->count += ret;
+
+    if (max_log_size && lfi->count > max_log_size) {
+      fclose(lfi->fptr);
+      lfi->fptr = NULL;
+    }
+
+    if (ringbuffer_size && lfi->count > ringbuffer_size) {
+      rotatef(lfi);
+      lfi->count = 0;
+    }
+  }
+  return ret;
+}
+
+
+int TRACE_MSG(char *fmt, ...) {
+  int ret;
+  va_list ap;
+
+  va_start(ap, fmt);
+  ret = _trace(&message_lfi, fmt, ap);
+  va_end(ap);
+
+  return ret;
+}
+
+int TRACE_SHORTMSG(char *fmt, ...) {
+  int ret;
+  va_list ap;
+
+  va_start(ap, fmt);
+  ret = _trace(&shortmessage_lfi, fmt, ap);
+  va_end(ap);
+
+  return ret;
+}
+
+int LOG_MSG(char *fmt, ...) {
+  int ret;
+  va_list ap;
+
+  va_start(ap, fmt);
+  ret = _trace(&log_lfi, fmt, ap);
+  va_end(ap);
+
+  return ret;
+}
+
+int TRACE_CALLDEBUG(char *fmt, ...) {
+  int ret;
+  va_list ap;
+
+  va_start(ap, fmt);
+  ret = _trace(&calldebug_lfi, fmt, ap);
+  va_end(ap);
+
+  return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/.svn/pristine/0a/0aaf683e77811cb843db05fedf0a872a584909cd.svn-base b/.svn/pristine/0a/0aaf683e77811cb843db05fedf0a872a584909cd.svn-base
new file mode 100644 (file)
index 0000000..1521c84
--- /dev/null
@@ -0,0 +1,736 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Authors : Benjamin GAUTHIER - 24 Mar 2004
+ *            Joseph BANINO
+ *            Olivier JACQUES
+ *            Richard GAYRAUD
+ *            From Hewlett Packard Company.
+ *           
+ */
+
+#ifndef __STAT_H__
+#define __STAT_H__
+
+
+#define TIME_LENGTH 64
+#define DEFAULT_FILE_NAME (char*)"dumpFile"
+#define DEFAULT_EXTENSION (char*)".csv"
+
+#define MAX_CHAR_BUFFER_SIZE          1024
+
+#include <ctime> 
+#include <sys/time.h> 
+#include <time.h> 
+#include <iostream>
+#include <fstream>
+#include <stdio.h>
+
+#ifdef HAVE_GSL
+#include <gsl/gsl_rng.h>
+#include <gsl/gsl_randist.h>
+#include <gsl/gsl_cdf.h>
+#endif
+
+#include "variables.hpp"
+
+using namespace std;
+
+/*
+__________________________________________________________________________
+
+              C S t a t    C L A S S
+__________________________________________________________________________
+*/
+
+  /**
+   * This class provides some means to compute and display statistics.
+   * This is a singleton class.
+   */
+
+class CStat {
+public:
+
+  /* 
+   * This struct is used for repartition table
+   * border max is the max value allow for this range
+   * nbInThisBorder is the counter of value in this range
+   */
+  typedef struct _T_dynamicalRepartition
+  {
+    unsigned int  borderMax;
+    unsigned long nbInThisBorder; 
+  } T_dynamicalRepartition; 
+
+  typedef struct _T_value_rtt 
+  {
+    double  date ;
+    int  rtd_no ;
+    double  rtt  ;
+  } T_value_rtt, *T_pValue_rtt ; 
+
+  /**
+   * Actions on counters
+   */
+  enum E_Action
+  {
+    E_NO_ACTION,
+    E_CREATE_OUTGOING_CALL,
+    E_CREATE_INCOMING_CALL,
+    E_CALL_FAILED, 
+    E_CALL_SUCCESSFULLY_ENDED,
+    E_RESET_C_COUNTERS,
+    E_RESET_PD_COUNTERS,
+    E_RESET_PL_COUNTERS,
+    E_ADD_CALL_DURATION,
+    E_ADD_RESPONSE_TIME_DURATION,
+    E_FAILED_CANNOT_SEND_MSG,
+    E_FAILED_MAX_UDP_RETRANS,
+    E_FAILED_TCP_CONNECT,
+    E_FAILED_TCP_CLOSED,
+    E_FAILED_UNEXPECTED_MSG,
+    E_FAILED_CALL_REJECTED,
+    E_FAILED_CMD_NOT_SENT,
+    E_FAILED_REGEXP_DOESNT_MATCH,
+    E_FAILED_REGEXP_SHOULDNT_MATCH,
+    E_FAILED_REGEXP_HDR_NOT_FOUND,
+    E_FAILED_OUTBOUND_CONGESTION,
+    E_FAILED_TIMEOUT_ON_RECV,
+    E_FAILED_TIMEOUT_ON_SEND,
+    E_OUT_OF_CALL_MSGS,
+    E_WATCHDOG_MAJOR,
+    E_WATCHDOG_MINOR,
+    E_DEAD_CALL_MSGS,
+    E_FATAL_ERRORS,
+    E_WARNING,
+    E_RETRANSMISSION,
+    E_AUTO_ANSWERED,
+    E_ADD_GENERIC_COUNTER
+  };
+  /**
+   * Counters management
+   */
+  enum E_CounterName
+  {
+  // Per-Scenario Counters
+  // Cumulative counters
+  CPT_C_IncomingCallCreated,
+  CPT_C_OutgoingCallCreated,
+  CPT_C_SuccessfulCall,
+  CPT_C_FailedCall,
+  CPT_C_CurrentCall,
+  CPT_C_CurrentCallPeak,
+  CPT_C_CurrentCallPeakTime,
+  CPT_C_NbOfCallUsedForAverageCallLength,
+  CPT_C_AverageCallLength_Sum,
+  CPT_C_AverageCallLength_Squares,
+  CPT_C_FailedCallCannotSendMessage,
+  CPT_C_FailedCallMaxUdpRetrans,
+  CPT_C_FailedCallTcpConnect,
+  CPT_C_FailedCallTcpClosed,
+  CPT_C_FailedCallUnexpectedMessage,
+  CPT_C_FailedCallCallRejected,
+  CPT_C_FailedCallCmdNotSent,
+  CPT_C_FailedCallRegexpDoesntMatch,
+  CPT_C_FailedCallRegexpShouldntMatch,
+  CPT_C_FailedCallRegexpHdrNotFound,
+  CPT_C_FailedOutboundCongestion,
+  CPT_C_FailedTimeoutOnRecv,
+  CPT_C_FailedTimeoutOnSend,
+  CPT_C_Retransmissions,
+
+  // Periodic Display counter
+  CPT_PD_IncomingCallCreated, // must be first (RESET_PD_COUNTER macro)
+  CPT_PD_OutgoingCallCreated,
+  CPT_PD_SuccessfulCall,
+  CPT_PD_FailedCall,
+  CPT_PD_CurrentCallPeak,
+  CPT_PD_CurrentCallPeakTime,
+  CPT_PD_NbOfCallUsedForAverageCallLength,
+  CPT_PD_AverageCallLength_Sum,
+  CPT_PD_AverageCallLength_Squares,
+  CPT_PD_NbOfCallUsedForAverageResponseTime,
+  CPT_PD_NbOfCallUsedForAverageResponseTime_2, // This must match or exceed MAX_RTD_INFO
+  CPT_PD_NbOfCallUsedForAverageResponseTime_3, // This must match or exceed MAX_RTD_INFO
+  CPT_PD_NbOfCallUsedForAverageResponseTime_4, // This must match or exceed MAX_RTD_INFO
+  CPT_PD_NbOfCallUsedForAverageResponseTime_5, // This must match or exceed MAX_RTD_INFO
+  CPT_PD_AverageResponseTime_Sum,
+  CPT_PD_AverageResponseTime_Sum_2,
+  CPT_PD_AverageResponseTime_Sum_3,
+  CPT_PD_AverageResponseTime_Sum_4,
+  CPT_PD_AverageResponseTime_Sum_5,
+  CPT_PD_AverageResponseTime_Squares,
+  CPT_PD_AverageResponseTime_Squares_2,
+  CPT_PD_AverageResponseTime_Squares_3,
+  CPT_PD_AverageResponseTime_Squares_4,
+  CPT_PD_AverageResponseTime_Squares_5,
+  CPT_PD_FailedCallCannotSendMessage,
+  CPT_PD_FailedCallMaxUdpRetrans,
+  CPT_PD_FailedCallTcpConnect,
+  CPT_PD_FailedCallTcpClosed,
+  CPT_PD_FailedCallUnexpectedMessage,
+  CPT_PD_FailedCallCallRejected,
+  CPT_PD_FailedCallCmdNotSent,
+  CPT_PD_FailedCallRegexpDoesntMatch,
+  CPT_PD_FailedCallRegexpShouldntMatch,
+  CPT_PD_FailedCallRegexpHdrNotFound,
+  CPT_PD_FailedOutboundCongestion,
+  CPT_PD_FailedTimeoutOnRecv,
+  CPT_PD_FailedTimeoutOnSend,
+  CPT_PD_Retransmissions,
+
+  // Periodic logging counter
+  CPT_PL_IncomingCallCreated, // must be first (RESET_PL_COUNTER macro)
+  CPT_PL_OutgoingCallCreated,
+  CPT_PL_SuccessfulCall,
+  CPT_PL_FailedCall,
+  CPT_PL_CurrentCallPeak,
+  CPT_PL_CurrentCallPeakTime,
+  CPT_PL_NbOfCallUsedForAverageCallLength,
+  CPT_PL_AverageCallLength_Sum,
+  /* The squares let us compute the standard deviation. */
+  CPT_PL_AverageCallLength_Squares,
+  CPT_PL_NbOfCallUsedForAverageResponseTime,
+  CPT_PL_NbOfCallUsedForAverageResponseTime_2,
+  CPT_PL_NbOfCallUsedForAverageResponseTime_3,
+  CPT_PL_NbOfCallUsedForAverageResponseTime_4,
+  CPT_PL_NbOfCallUsedForAverageResponseTime_5,
+  CPT_PL_AverageResponseTime_Sum,
+  CPT_PL_AverageResponseTime_Sum_2,
+  CPT_PL_AverageResponseTime_Sum_3,
+  CPT_PL_AverageResponseTime_Sum_4,
+  CPT_PL_AverageResponseTime_Sum_5,
+  CPT_PL_AverageResponseTime_Squares,
+  CPT_PL_AverageResponseTime_Squares_2,
+  CPT_PL_AverageResponseTime_Squares_3,
+  CPT_PL_AverageResponseTime_Squares_4,
+  CPT_PL_AverageResponseTime_Squares_5,
+  CPT_PL_FailedCallCannotSendMessage,
+  CPT_PL_FailedCallMaxUdpRetrans,
+  CPT_PL_FailedCallTcpConnect,
+  CPT_PL_FailedCallTcpClosed,
+  CPT_PL_FailedCallUnexpectedMessage,
+  CPT_PL_FailedCallCallRejected,
+  CPT_PL_FailedCallCmdNotSent,
+  CPT_PL_FailedCallRegexpDoesntMatch,
+  CPT_PL_FailedCallRegexpShouldntMatch,
+  CPT_PL_FailedCallRegexpHdrNotFound,
+  CPT_PL_FailedOutboundCongestion,
+  CPT_PL_FailedTimeoutOnRecv,
+  CPT_PL_FailedTimeoutOnSend,
+  CPT_PL_Retransmissions,
+
+  E_NB_COUNTER,
+
+  // Global Counters
+  // Cumulative counters
+  CPT_G_C_OutOfCallMsgs,
+  CPT_G_C_DeadCallMsgs,
+  CPT_G_C_FatalErrors,
+  CPT_G_C_Warnings,
+  CPT_G_C_WatchdogMajor,
+  CPT_G_C_WatchdogMinor,
+  CPT_G_C_AutoAnswered,
+  // Periodic Display counter
+  CPT_G_PD_OutOfCallMsgs,
+  CPT_G_PD_DeadCallMsgs,
+  CPT_G_PD_FatalErrors,
+  CPT_G_PD_Warnings,
+  CPT_G_PD_WatchdogMajor,
+  CPT_G_PD_WatchdogMinor,
+  CPT_G_PD_AutoAnswered, // must be last (RESET_PD_COUNTER)
+
+  // Periodic logging counter
+  CPT_G_PL_OutOfCallMsgs,
+  CPT_G_PL_DeadCallMsgs,
+  CPT_G_PL_FatalErrors,
+  CPT_G_PL_Warnings,
+  CPT_G_PL_WatchdogMajor,
+  CPT_G_PL_WatchdogMinor,
+  CPT_G_PL_AutoAnswered, // must be last (RESET_PL_COUNTER)
+
+  E_NB_G_COUNTER,
+
+  };
+
+  /*
+  ** exported methods
+  */
+
+  /**
+   * Constructor.
+   */
+  CStat ();
+
+  /**
+   * Destructor.
+   */
+  ~CStat ();
+
+
+  /**
+   * Delete the single instance of the class.
+   *
+   * Only one instance of CStat exists in the component. This
+   * instance is deleted when the close method is called.
+   */
+  void close (); 
+
+  /**
+   * ComputeStat Methods are used to modify counter value
+   * It's the main interface to update counter
+   *
+   * @return 0 if the action is known
+   *        -1 else
+   */
+  int computeStat (E_Action P_action);
+  int computeStat (E_Action P_action, unsigned long P_value);
+  int computeStat (E_Action P_action, unsigned long P_value, int which);
+
+  /* This works for global counters and does not require an instance. */
+  static int globalStat (E_Action P_action);
+
+  /**
+   * ComputeRtt Methods are used to calculate the response time
+   */
+  void computeRtt ( unsigned long long P_start_time, unsigned long long P_stop_time, int which);
+
+  /**
+   * GetStat Method is used to retrieve a counter value
+   *
+   * @return the counter value
+   **/
+  unsigned long long GetStat (E_CounterName P_counter);
+  
+  /* Get the current start time. */
+  void getStartTime(struct timeval *t);
+
+  /**
+   * formatTime.
+   *
+   * This method converts a struct timeval parameter into a printable string
+   * in the format given in parameter.
+   *
+   * @param P_tv.
+   * @return a pointer on a static string containing formated time
+   */
+  static char* formatTime (struct timeval* P_tv, bool microseconds = false);
+
+  /**
+   * setRepartitionCallLength 
+   * - set the unsigned int table passed in parameter as the repartition table 
+   *   for call length. This is done by calling the initRepartition methode on 
+   *   the M_CallLengthRepartition variable.
+   * - set the char* list of int (must be separeted with coma as the 
+   *   repartition table for call length
+   *   This is done by calling the createIntegerTable to transform the char* 
+   *   list into unsigned int list. Then the initRepartition methode is 
+   *   call with the created unsigned int list and the M_CallLengthRepartition 
+   *   variable
+   *
+   * setRepartitionResponseTime
+   *   Same than setRepartitionCallLength with the variable
+   *  M_ResponseTimeRepartition variableinstead of M_CallLengthRepartition 
+   *  variable
+   */
+  void setRepartitionCallLength   (unsigned int* repartition, int nombre);
+  void setRepartitionCallLength   (char * liste);
+  void setRepartitionResponseTime (unsigned int* repartition, int nombre);
+  void setRepartitionResponseTime (char * liste);
+
+  /* define the file name to use to dump statistic in file */
+  void setFileName                (char * name);
+  void setFileName                (char * name, char * extension);
+  void initRtt             (char * name, char * extension, unsigned long P_value);
+
+  /**
+   * Display data periodically updated on screen.
+   */
+  void displayData (FILE *f);
+  void displayStat(FILE *f);
+  void displayRepartition(FILE *f);
+  void displayRtdRepartition (FILE *f, int which);
+
+  /**
+   * Dump data periodically in the file M_FileName
+   */
+  void dumpData ();
+
+  void dumpDataRtt ();
+
+  /**
+   * initialize the class variable member
+   */
+  int init();
+
+  /**
+   * computeDiffTimeInMs.
+   *
+   * This method calculates elaped time in ms
+   *
+   * @param tf = final date
+   * @param ti = initial date
+   *
+   * @return number of ms between the 2 dates
+   */
+  static long computeDiffTimeInMs (struct timeval* tf, struct timeval* ti);
+
+  /**
+   * msToHHMMSS.
+   *
+   * This converts an unsigned long containing a number of ms
+   * into a string expressing the same value in format HH:MM:SS.
+   *
+   * @param P_ms.
+   *
+   * @return a pointer on a static string containing formated time
+   */
+  static char* msToHHMMSS (unsigned long P_ms);
+
+  /**
+   * msToHHMMSSmm.
+   *
+   * This converts an unsigned long containing a number of ms
+   * into a string expressing the same value in format HH:MM:SS:mmm.
+   *
+   * @param P_ms.
+   *
+   * @return a pointer on a static string containing formated time
+   */
+  static char* msToHHMMSSmmm (unsigned long P_ms);
+
+  /* Get a counter ID by name. */
+  int findCounter(const char *counter, bool alloc);
+  int findRtd(const char *name, bool start);
+  void validateRtds();
+  int nRtds();
+
+private:
+  unsigned long long       M_counters[E_NB_COUNTER];
+  static unsigned long long M_G_counters[E_NB_G_COUNTER - E_NB_COUNTER];
+
+#define GENERIC_C 0
+#define GENERIC_PD 1
+#define GENERIC_PL 2
+#define GENERIC_TYPES 3
+  unsigned long long      *M_genericCounters;
+
+  str_int_map             M_genericMap;
+  int_str_map             M_revGenericMap;
+  int_str_map             M_genericDisplay;
+
+  str_int_map             rtd_started;
+  str_int_map             rtd_stopped;
+
+#define RTD_COUNT 0
+#define RTD_SUM 1
+#define RTD_SUMSQ 2
+#define RTD_TYPES 3
+  unsigned long long      *M_rtdInfo;
+  str_int_map             M_rtdMap;
+  int_str_map             M_revRtdMap;
+
+  T_dynamicalRepartition** M_ResponseTimeRepartition;
+  T_dynamicalRepartition*  M_CallLengthRepartition;
+  int                      M_SizeOfResponseTimeRepartition;
+  int                      M_SizeOfCallLengthRepartition;
+  struct timeval           M_startTime;
+  struct timeval           M_pdStartTime;
+  struct timeval           M_plStartTime;
+
+  bool                     M_headerAlreadyDisplayed;
+  char*                    M_fileName;
+  ofstream*                M_outputStream;
+
+  bool                     M_headerAlreadyDisplayedRtt ;
+  char*                    M_fileNameRtt               ;
+  ofstream*                M_outputStreamRtt           ;
+  double                   M_time_ref                  ;
+
+  T_pValue_rtt             M_dumpRespTime              ;
+  unsigned int             M_counterDumpRespTime       ;
+  unsigned long            M_report_freq_dumpRtt       ;
+
+  /**
+   * initRepartition
+   * This methode is used to create the repartition table with a table of 
+   * unsigned int the reparition is created like following, with Vi the given 
+   * value in the table
+   * 0    <= x <  V1  
+   * V1   <= x <  V2 
+   *  ...
+   * Vn-1 <= x <  Vn
+   *         x >= Vn
+   * So the repartition table have the size n+1 if the given table has a size 
+   * of n */
+  void  initRepartition(unsigned int* repartition, int nombre,
+                        T_dynamicalRepartition ** tabRepartition, int* nbTab);
+  
+  /**
+   * createIntegerTable
+   * this method try to create a table of unsigned int with the list of char* 
+   * passed in parameters
+   * if it succed, it's return true (1)
+   * else it's return false (0)
+   */
+  int  createIntegerTable(char * P_listeStr, 
+                          unsigned int ** listeInteger, 
+                          int * sizeOfList);
+
+  /**
+   * isWellFormed
+   * this method check if the char* passed in parameter in really a list of  
+   * integer separated with comma.
+   * if yes, it's return true (1)
+   * else, it's return false (0)
+   */
+  int  isWellFormed(char * P_listeStr, int * nombre);
+
+  /**
+   * updateRepartition
+   * The method looks for the place to set the value passed in parameter
+   * Once found, the associated counter is incremented
+   */
+  void  updateRepartition( T_dynamicalRepartition* tabRepart, 
+                           int sizeOfTab, 
+                           unsigned long value);
+
+  /**
+   * resetRepartition
+   * Zeros out all repartition counters.
+   */
+  void  resetRepartition(T_dynamicalRepartition* P_tabReport,
+                         int P_sizeOfTab);
+  /**
+   * displayRepartition
+   * Display the repartition passed in parameter at the screen
+   */
+  void  displayRepartition(FILE *f,
+                           T_dynamicalRepartition * tabRepartition, 
+                           int sizeOfTab);
+
+  /**
+   * sRepartitionHeader
+   * return a string with the range description of the given repartition
+   */
+  char* sRepartitionHeader(T_dynamicalRepartition * tabRepartition, 
+                           int sizeOfTab,
+                           char* P_repartitionName);
+
+  /**
+   * sRepartitionInfo
+   * return a string with the number of value in the differente range of the 
+   * given repartition
+   */
+  char* sRepartitionInfo(T_dynamicalRepartition * tabRepartition, 
+                         int sizeOfTab);
+
+  /**
+   * UpdateAverageCounter
+   * This methode compute the real moyenne with the passed value on the given 
+   * counter
+   */
+  void updateAverageCounter(E_CounterName P_SumCounter,
+                            E_CounterName P_NbOfCallUsed,
+                            E_CounterName P_Squares,
+                            unsigned long P_value);
+
+  /**
+   * computeStdev
+   * This method computes the standard deviation using our recorded mean
+   * and recorded mean square.
+   */
+  double computeStdev(E_CounterName P_SumCounter,
+                             E_CounterName P_NbOfCallUsed,
+                             E_CounterName P_Squares);
+
+  /**
+   * computeMean
+   * This method computes the recorded sum and count.
+   */
+  double computeMean(E_CounterName P_SumCounter,
+                             E_CounterName P_NbOfCallUsed);
+
+  double computeRtdMean(int which, int type);
+  double computeRtdStdev(int which, int type);
+
+  /**
+   * Effective C++
+   *
+   * To prevent public copy ctor usage: no implementation
+   */
+  CStat (const CStat&);
+  
+  /**
+   * Effective C++
+   *
+   * To prevent public operator= usage: no implementation
+   */
+  CStat& operator=(const CStat&);
+};
+
+/**
+ * This abstract class provides the ability to sample from a distribution.
+ */
+class CSample {
+public:
+       virtual double sample() = 0;
+       virtual int textDescr(char *s, int len) = 0;
+       virtual int timeDescr(char *s, int len) = 0;
+       virtual double cdfInv(double percentile) = 0;
+       virtual ~CSample();
+private:
+};
+
+/* Always return a fixed value for the sample. */
+class CFixed : public CSample {
+public:
+       CFixed(double value);
+       double sample();
+       int textDescr(char *s, int len);
+       int timeDescr(char *s, int len);
+       double cdfInv(double percentile);
+private:
+       double value;
+};
+
+/* Return the default scenario duration. */
+class CDefaultPause : public CSample {
+public:
+       CDefaultPause();
+       double sample();
+       int textDescr(char *s, int len);
+       int timeDescr(char *s, int len);
+       double cdfInv(double percentile);
+private:
+};
+
+/* Uniform distribution. */
+class CUniform : public CSample {
+public:
+       CUniform(double min, double max);
+       double sample();
+       int textDescr(char *s, int len);
+       int timeDescr(char *s, int len);
+       double cdfInv(double percentile);
+private:
+       double min, max;
+};
+
+#ifdef HAVE_GSL
+/* Normal distribution. */
+class CNormal : public CSample {
+public:
+       CNormal(double mean, double stdev);
+       double sample();
+       int textDescr(char *s, int len);
+       int timeDescr(char *s, int len);
+       double cdfInv(double percentile);
+protected:
+       double mean, stdev;
+       gsl_rng *rng;
+};
+
+/* Lognormal distribution. */
+class CLogNormal : public CNormal {
+public:
+       CLogNormal(double mean, double stdev) : CNormal(mean, stdev) {};
+       double sample();
+       int textDescr(char *s, int len);
+       int timeDescr(char *s, int len);
+       double cdfInv(double percentile);
+};
+
+/* Exponential distribution. */
+class CExponential : public CSample {
+public:
+       CExponential(double mean);
+       double sample();
+       int textDescr(char *s, int len);
+       int timeDescr(char *s, int len);
+       double cdfInv(double percentile);
+private:
+       double mean;
+       gsl_rng *rng;
+};
+
+/* Weibull distribution. */
+class CWeibull : public CSample {
+public:
+       CWeibull(double lambda, double k);
+       double sample();
+       int textDescr(char *s, int len);
+       int timeDescr(char *s, int len);
+       double cdfInv(double percentile);
+private:
+       double lambda, k;
+       gsl_rng *rng;
+};
+
+/* Pareto distribution. */
+class CPareto : public CSample {
+public:
+       CPareto(double k, double xsubm);
+       double sample();
+       int textDescr(char *s, int len);
+       int timeDescr(char *s, int len);
+       double cdfInv(double percentile);
+protected:
+       double k, xsubm;
+       gsl_rng *rng;
+};
+
+/* Generalized Pareto distribution. */
+class CGPareto : public CSample {
+public:
+       CGPareto(double shape, double scale, double location);
+       double sample();
+       int textDescr(char *s, int len);
+       int timeDescr(char *s, int len);
+       double cdfInv(double percentile);
+protected:
+       double shape, scale, location;
+       gsl_rng *rng;
+};
+
+
+/* Gamma distribution. */
+class CGamma : public CSample {
+public:
+       CGamma(double k, double theta);
+       double sample();
+       int textDescr(char *s, int len);
+       int timeDescr(char *s, int len);
+       double cdfInv(double percentile);
+protected:
+       double k, theta;
+       gsl_rng *rng;
+};
+
+/* Negative Binomial distribution. */
+class CNegBin : public CSample {
+public:
+       CNegBin(double p, double n);
+       double sample();
+       int textDescr(char *s, int len);
+       int timeDescr(char *s, int len);
+       double cdfInv(double percentile);
+protected:
+       double p, n;
+       gsl_rng *rng;
+};
+#endif
+
+#endif // __STAT_H__
diff --git a/.svn/pristine/0b/0b8b4f1cb5bacdf3e675fd5d5051c27dd761cf67.svn-base b/.svn/pristine/0b/0b8b4f1cb5bacdf3e675fd5d5051c27dd761cf67.svn-base
new file mode 100644 (file)
index 0000000..8e3f1b0
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Authors : Benjamin GAUTHIER - 24 Mar 2004
+ *            Joseph BANINO
+ *            Olivier JACQUES
+ *            Richard GAYRAUD
+ *            From Hewlett Packard Company.
+ */
+
+#ifndef _CACTIONS
+#define _CACTIONS
+
+#include "variables.hpp"
+#include "message.hpp"
+class CSample;
+
+#ifdef PCAPPLAY
+#include "prepare_pcap.h"
+#endif
+
+#define MAX_ACTION_MESSAGE 3
+
+class CAction
+{
+  public:
+    enum T_ActionType
+    {
+      E_AT_NO_ACTION = 0,
+      E_AT_ASSIGN_FROM_REGEXP,
+      E_AT_CHECK,
+      E_AT_ASSIGN_FROM_VALUE,
+      E_AT_ASSIGN_FROM_SAMPLE,
+      E_AT_ASSIGN_FROM_STRING,
+      E_AT_ASSIGN_FROM_INDEX,
+      E_AT_ASSIGN_FROM_GETTIMEOFDAY,
+      E_AT_JUMP,
+      E_AT_LOOKUP,
+      E_AT_INSERT,
+      E_AT_REPLACE,
+      E_AT_PAUSE_RESTORE,
+      E_AT_LOG_TO_FILE,
+      E_AT_LOG_WARNING,
+      E_AT_LOG_ERROR,
+      E_AT_EXECUTE_CMD,
+      E_AT_EXEC_INTCMD,
+      E_AT_VAR_ADD,
+      E_AT_VAR_SUBTRACT,
+      E_AT_VAR_MULTIPLY,
+      E_AT_VAR_DIVIDE,
+      E_AT_VAR_TEST,
+      E_AT_VAR_TO_DOUBLE,
+      E_AT_VAR_STRCMP,
+      E_AT_VAR_TRIM,
+      E_AT_VERIFY_AUTH,
+      E_AT_SET_DEST,
+      E_AT_CLOSE_CON,
+#ifdef PCAPPLAY
+      E_AT_PLAY_PCAP_AUDIO,
+      E_AT_PLAY_PCAP_VIDEO,
+#endif
+      E_AT_NB_ACTION
+    };
+
+    enum T_LookingPlace
+    {
+      E_LP_MSG = 0,
+      E_LP_HDR,
+      E_LP_BODY,
+      E_LP_VAR,
+      E_LP_NB_LOOKING_PLACE
+    };
+
+    enum T_Comparator
+    {
+      E_C_EQ,
+      E_C_NE,
+      E_C_GT,
+      E_C_LT,
+      E_C_GEQ,
+      E_C_LEQ,
+      E_C_NB_COMPARATOR
+    };
+
+    enum T_IntCmdType
+    {
+      E_INTCMD_INVALID = 0,
+      E_INTCMD_STOPCALL,
+      E_INTCMD_STOP_ALL,
+      E_INTCMD_STOP_NOW
+    };
+
+    typedef struct _T_Action
+    {
+    } T_Action;
+
+    void afficheInfo();
+    const char *comparatorToString(T_Comparator comp);
+    bool compare(VariableTable *variableTable);
+
+    T_ActionType   getActionType();
+    T_VarType      getVarType();
+    T_LookingPlace getLookingPlace();
+    T_Comparator   getComparator();
+    bool           getCheckIt();
+    bool           getCheckItInverse();
+    bool           getCaseIndep();
+    bool           getHeadersOnly();
+    int            getVarId();
+    int            getVarInId();
+    int            getVarIn2Id();
+    int            getOccurence();
+    char*          getLookingChar();
+    char*          getRegularExpression();
+    SendingMessage *getMessage(int n = 0);  /* log specific function  */
+    T_IntCmdType   getIntCmd();   /* exec specific function */
+#ifdef PCAPPLAY
+    pcap_pkts     *getPcapPkts(); /* send_packets specific function */
+#endif
+
+    void setActionType   (T_ActionType   P_value);
+    void setLookingPlace (T_LookingPlace P_value);
+    void setComparator   (T_Comparator   P_value);
+    void setCheckIt      (bool           P_value);
+    void setCheckItInverse (bool           P_value);
+    void setVarId        (int            P_value);
+    void setVarInId      (int            P_value);
+    void setVarIn2Id      (int            P_value);
+    void setLookingChar  (char*          P_value);
+    void setAction       (CAction        P_action);
+    void setCaseIndep    (bool           P_action);
+    void setOccurence   (int            P_value);
+    void setHeadersOnly  (bool           P_value);
+    void setScenario     (scenario *     P_scenario);
+    void setRegExp       (char*                 P_value);  /* ereg specific function. */
+    int  executeRegExp   (char* P_string, VariableTable *P_callVarTable);
+    void setMessage      (char*          P_value, int n = 0);  /* log specific function  */
+    void setIntCmd       (T_IntCmdType   P_type );  /* exec specific function */
+    void setDistribution (CSample *      P_value);  /* sample specific function  */
+    void setDoubleValue  (double         P_value);  /* assign value specific function  */
+    void setStringValue  (char *         P_value);  /* strcmp value specific function  */
+#ifdef PCAPPLAY
+    void setPcapArgs     (char *         P_value);  /* send_packets specific function */
+    void setPcapArgs     (pcap_pkts   *  P_value);  /* send_packets specific function */
+#endif
+
+    void setSubVarId     (int P_value);
+    int  getSubVarId     (int P_index);
+    void setNbSubVarId   (int P_value);
+    int  getNbSubVarId   ();
+    int* getSubVarId() ;
+    CSample *getDistribution ();  /* sample specific function  */
+    double getDoubleValue ();  /* assign value specific function  */
+    char * getStringValue ();  /* strcmp specific function  */
+
+    CAction(scenario *scenario);
+    ~CAction();
+
+  private:
+      T_ActionType   M_action;
+      T_LookingPlace M_lookingPlace;
+      T_Comparator   M_comp;
+      bool           M_checkIt;
+      bool           M_checkItInverse;
+      bool           M_caseIndep;
+      bool           M_headersOnly;
+      int            M_varId;
+      int            M_varInId;
+      int            M_varIn2Id;
+      int            M_occurence;
+      int            M_nbSubVarId;
+      int            M_maxNbSubVarId;
+      int *          M_subVarId;
+
+      char*          M_lookingChar;
+      /* log specific member  */
+      SendingMessage *M_message[MAX_ACTION_MESSAGE];
+      char *        M_message_str[MAX_ACTION_MESSAGE];
+      /* exec specific member */
+      T_IntCmdType   M_IntCmd;
+      /* sample specific member. */
+      CSample       *M_distribution;
+      /* assign value specific member. */
+      double         M_doubleValue;
+      /* strcmp specific member. */
+      char *         M_stringValue;
+      /* what scenario we belong to. */
+      scenario *     M_scenario;
+      /* Our regular expression. */
+      bool          M_regExpSet;
+      regex_t        M_internalRegExp;
+      char *         M_regularExpression;
+#ifdef PCAPPLAY
+      /* pcap specific member */
+      pcap_pkts  *   M_pcapArgs;
+#endif
+      void setSubString(char** P_target, char* P_source, int P_start, int P_stop);
+};
+
+class CActions
+{
+  public:
+    void afficheInfo();
+    void setAction(CAction *P_action);
+    void reset();
+    int  getActionSize();
+    CAction* getAction(int i);
+    CActions();
+    ~CActions();
+  
+  private:
+    CAction ** M_actionList;
+    int        M_nbAction;
+    int        M_currentSettedAction;
+};
+
+#endif
diff --git a/.svn/pristine/10/100c365defacbefaeda173fe46245b8598f60d0c.svn-base b/.svn/pristine/10/100c365defacbefaeda173fe46245b8598f60d0c.svn-base
new file mode 100644 (file)
index 0000000..879beb0
--- /dev/null
@@ -0,0 +1,664 @@
+/*
+
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA
+ *
+ *  Author : Richard GAYRAUD - 04 Nov 2003
+ *           From Hewlett Packard Company.
+ */
+
+#ifndef __SIPP__
+#define __SIPP__
+
+/* Std C includes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#ifdef USE_SCTP
+#include <netinet/sctp.h>
+#endif
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <signal.h>
+#include <time.h>
+#include <limits.h>
+#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>
+#endif
+
+/* Sipp includes */
+
+#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 "variables.hpp"
+#include "stat.hpp"
+#include "actions.hpp"
+#include "infile.hpp"
+#include "opentask.hpp"
+#include "reporttask.hpp"
+#include "watchdog.hpp"
+/* Open SSL stuff */
+#ifdef _USE_OPENSSL
+#include "sslcommon.h" 
+#endif
+
+
+#ifndef __CYGWIN
+#ifndef FD_SETSIZE
+#define FD_SETSIZE 65000
+#endif
+#else
+#ifndef FD_SETSIZE
+#define FD_SETSIZE 1024
+#endif
+#endif
+
+/* 
+ * If this files is included in the Main, then extern definitions
+ * are removed, and the _DEFAULT macro becomes '= value;'. Else 
+ * extern definition does not contain default values assignment
+ */
+
+#ifdef GLOBALS_FULL_DEFINITION
+#define extern
+#define _DEFVAL(value) = value
+#else
+#define _DEFVAL(value)
+#endif
+
+/************************** Constants **************************/
+
+#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
+#define T_SCTP                     3
+
+#ifdef _USE_OPENSSL
+#define DEFAULT_TLS_CERT           ((char *)"cacert.pem")
+#define DEFAULT_TLS_KEY            ((char *)"cakey.pem")
+#define DEFAULT_TLS_CRL            ((char *)"")
+#endif
+
+#define TRANSPORT_TO_STRING(p)     ((p==T_TCP) ? "TCP" : ((p==T_TLS)? "TLS" : ((p==T_UDP)? "UDP" : "SCTP")))
+
+#define SIPP_MAXFDS                65536
+#define SIPP_MAX_MSG_SIZE          65536
+
+#define MSG_RETRANS_FIRST          0
+#define MSG_RETRANS_RETRANSMISSION 1
+#define MSG_RETRANS_NEVER          2
+
+#define DISPLAY_STAT_SCREEN        1
+#define DISPLAY_REPARTITION_SCREEN 2
+#define DISPLAY_SCENARIO_SCREEN    3
+#define DISPLAY_VARIABLE_SCREEN    4
+#define DISPLAY_TDM_MAP_SCREEN     5
+#define DISPLAY_SECONDARY_REPARTITION_SCREEN 6
+
+#define MAX_RECV_LOOPS_PER_CYCLE   1000
+#define MAX_SCHED_LOOPS_PER_CYCLE  1000
+#define NB_UPDATE_PER_CYCLE        1
+
+#define MAX_PATH                   250
+
+#define MAX_PEER_SIZE              4096  /* 3pcc extended mode: max size of peer names */
+#define MAX_LOCAL_TWIN_SOCKETS     10    /*3pcc extended mode:max number of peers from which 
+                                           cmd messages are received */
+
+/******************** 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
+#define DEFAULT_3PCC_PORT            6060
+#define DEFAULT_SERVICE              ((char *)"service")
+#define DEFAULT_AUTH_PASSWORD        ((char *)"password")
+#define DEFAULT_REPORT_FREQ          1000
+#define DEFAULT_REPORT_FREQ_DUMP_LOG 60000
+#define DEFAULT_TIMER_RESOLUTION     1
+#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 bool              rate_quit               _DEFVAL(true);
+extern int                users                   _DEFVAL(-1);
+extern int               rate_period_ms           _DEFVAL(DEFAULT_RATE_PERIOD_MS);
+extern int                sleeptime               _DEFVAL(0);
+extern unsigned long      defl_recv_timeout       _DEFVAL(0);
+extern unsigned long      defl_send_timeout       _DEFVAL(0);
+extern unsigned long      global_timeout          _DEFVAL(0);
+extern int                transport               _DEFVAL(DEFAULT_TRANSPORT);
+extern bool               retrans_enabled         _DEFVAL(1);
+extern int                rtcheck                _DEFVAL(RTCHECK_FULL);
+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 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 bool               auto_answer             _DEFVAL(false);
+extern int                multisocket             _DEFVAL(0);
+extern int                compression             _DEFVAL(0);
+extern int                peripsocket             _DEFVAL(0);
+extern int                peripfield              _DEFVAL(0);
+extern bool               bind_local              _DEFVAL(false);
+extern void             * monosocket_comp_state   _DEFVAL(0);
+extern char             * service                 _DEFVAL(DEFAULT_SERVICE);
+extern char             * auth_password           _DEFVAL(DEFAULT_AUTH_PASSWORD);
+extern char             * auth_username           _DEFVAL(0);
+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);
+extern bool               timeout_error           _DEFVAL(false);
+
+extern unsigned long      report_freq_dumpRtt     _DEFVAL
+                                                (DEFAULT_FREQ_DUMP_RTT);
+
+extern 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);
+extern int                max_sched_loops         _DEFVAL(MAX_SCHED_LOOPS_PER_CYCLE);
+extern unsigned int       global_t2               _DEFVAL(DEFAULT_T2_TIMER_VALUE);
+extern char               local_ip[40];
+extern char               local_ip_escaped[42];
+extern bool               local_ip_is_ipv6;    
+extern int                local_port              _DEFVAL(0);
+#ifdef USE_SCTP
+extern char               multihome_ip[40];
+extern int                heartbeat               _DEFVAL(0);
+extern int                assocmaxret             _DEFVAL(0);
+extern int                pathmaxret              _DEFVAL(0);
+extern int                pmtu              _DEFVAL(0);
+extern bool               gracefulclose           _DEFVAL(true);
+#endif
+extern char               control_ip[40];
+extern int                control_port            _DEFVAL(0);
+extern int                buff_size               _DEFVAL(65535);
+extern int                tcp_readsize            _DEFVAL(65535);
+#ifdef PCAPPLAY
+extern int                hasMedia                _DEFVAL(0);
+#endif
+extern bool               rtp_echo_enabled        _DEFVAL(0);
+extern char               media_ip[40];
+extern char               media_ip_escaped[42];
+extern int                user_media_port         _DEFVAL(0);
+extern int                media_port              _DEFVAL(0);
+extern size_t             media_bufsize           _DEFVAL(2048);
+extern bool               media_ip_is_ipv6;    
+extern char               remote_ip[40];
+extern char               remote_ip_escaped[42];
+extern int                remote_port             _DEFVAL(DEFAULT_PORT);
+extern unsigned int       pid                     _DEFVAL(0);
+extern bool               print_all_responses     _DEFVAL(false);
+extern unsigned long      stop_after              _DEFVAL(0xffffffff);
+extern int                quitting                _DEFVAL(0);
+extern int                interrupt               _DEFVAL(0);
+extern bool               paused                  _DEFVAL(false);
+extern int                lose_packets            _DEFVAL(0);
+extern double             global_lost             _DEFVAL(0.0);
+extern char               remote_host[255]; 
+extern char               twinSippHost[255];
+extern char               twinSippIp[40];
+extern char             * master_name;
+extern char             * slave_number;
+extern int                twinSippPort            _DEFVAL(DEFAULT_3PCC_PORT);
+extern bool               twinSippMode            _DEFVAL(false);
+extern bool               extendedTwinSippMode    _DEFVAL(false);
+
+extern bool               nostdin                 _DEFVAL(false);        
+extern bool               backgroundMode          _DEFVAL(false);        
+extern bool               signalDump              _DEFVAL(false);        
+
+extern int                currentScreenToDisplay  _DEFVAL
+                                                  (DISPLAY_SCENARIO_SCREEN);
+extern int                currentRepartitionToDisplay  _DEFVAL(1);
+extern unsigned int       base_cseq               _DEFVAL(0);
+extern char             * auth_uri                _DEFVAL(0);
+extern char             * call_id_string          _DEFVAL("%u-%p@%s");
+extern char             **generic[100];
+
+/* TDM map */
+extern bool               use_tdmmap              _DEFVAL(false);
+extern unsigned int       tdm_map_a               _DEFVAL(0);
+extern unsigned int       tdm_map_b               _DEFVAL(0);
+extern unsigned int       tdm_map_c               _DEFVAL(0);
+extern unsigned int       tdm_map_x               _DEFVAL(0);
+extern unsigned int       tdm_map_y               _DEFVAL(0);
+extern unsigned int       tdm_map_z               _DEFVAL(0);
+extern unsigned int       tdm_map_h               _DEFVAL(0);
+extern bool               tdm_map[1024];
+
+#ifdef _USE_OPENSSL
+extern BIO                  *twinSipp_bio ;
+extern SSL                  *twinSipp_ssl ;
+extern char                 *tls_cert_name     _DEFVAL(DEFAULT_TLS_CERT) ;
+extern char                 *tls_key_name      _DEFVAL(DEFAULT_TLS_KEY)  ;
+extern char                 *tls_crl_name      _DEFVAL(DEFAULT_TLS_CRL)  ;
+
+#endif
+
+// 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 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);
+struct sipp_socket *new_sipp_call_socket(bool use_ipv6, int transport, bool *existing);
+struct sipp_socket *sipp_accept_socket(struct sipp_socket *accept_socket);
+extern int     sipp_bind_socket(struct sipp_socket *socket, struct sockaddr_storage *saddr, int *port);
+extern int     sipp_connect_socket(struct sipp_socket *socket, struct sockaddr_storage *dest);
+extern 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);
+extern int      select_socket       _DEFVAL(0);
+extern bool     socket_close        _DEFVAL(true);
+extern bool     test_socket         _DEFVAL(true);
+extern bool     maxSocketPresent    _DEFVAL(false);
+
+extern unsigned long getmilliseconds();
+extern unsigned long long getmicroseconds();
+
+/************************ Statistics **************************/
+
+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 int           open_calls_user_setting      _DEFVAL(0);
+extern int           resynch_send                 _DEFVAL(0);
+extern int           resynch_recv                 _DEFVAL(0);
+extern unsigned long rtp_pckts                    _DEFVAL(0);
+extern unsigned long rtp_bytes                    _DEFVAL(0);
+extern unsigned long rtp_pckts_pcap               _DEFVAL(0);
+extern unsigned long rtp_bytes_pcap               _DEFVAL(0);
+extern unsigned long rtp2_pckts                   _DEFVAL(0);
+extern unsigned long rtp2_bytes                   _DEFVAL(0);
+extern unsigned long rtp2_pckts_pcap              _DEFVAL(0);
+extern unsigned long rtp2_bytes_pcap              _DEFVAL(0);
+
+/************* Rate Control & Contexts variables **************/
+
+extern int           last_running_calls           _DEFVAL(0);
+extern int           last_woken_calls             _DEFVAL(0);
+extern int           last_paused_calls            _DEFVAL(0);
+extern unsigned int  open_calls_allowed           _DEFVAL(0);
+extern unsigned long last_report_time             _DEFVAL(0);
+extern unsigned long last_dump_time               _DEFVAL(0);
+
+/********************** Clock variables ***********************/
+
+extern unsigned long clock_tick                   _DEFVAL(0);
+extern unsigned long scheduling_loops             _DEFVAL(0);
+extern unsigned long last_timer_cycle             _DEFVAL(0);
+
+extern unsigned long watchdog_interval           _DEFVAL(400);
+extern unsigned long watchdog_minor_threshold    _DEFVAL(500);
+extern unsigned long watchdog_minor_maxtriggers          _DEFVAL(120);
+extern unsigned long watchdog_major_threshold    _DEFVAL(3000);
+extern unsigned long watchdog_major_maxtriggers          _DEFVAL(10);
+extern unsigned long watchdog_reset              _DEFVAL(600000);
+
+
+/********************* dynamic Id ************************* */
+extern  int maxDynamicId    _DEFVAL(12000);  // max value for dynamicId; this value is reached 
+extern  int startDynamicId  _DEFVAL(10000);  // offset for first dynamicId  FIXME:in CmdLine
+extern  int stepDynamicId   _DEFVAL(4);      // step of increment for dynamicId
+
+
+
+#define GET_TIME(clock)       \
+{                             \
+  struct timezone tzp;        \
+  gettimeofday (clock, &tzp); \
+}
+
+/*********************** Global Sockets  **********************/
+
+extern struct sipp_socket *main_socket            _DEFVAL(NULL);
+extern struct sipp_socket *main_remote_socket     _DEFVAL(NULL);
+extern struct sipp_socket *tcp_multiplex          _DEFVAL(NULL);
+extern int           media_socket                 _DEFVAL(0);
+extern int           media_socket_video           _DEFVAL(0);
+
+extern struct        sockaddr_storage   local_sockaddr;
+extern struct        sockaddr_storage   localTwin_sockaddr;
+extern int           user_port                    _DEFVAL(0);
+extern char          hostname[80];
+extern bool          is_ipv6                      _DEFVAL(false);
+
+extern int           reset_number                 _DEFVAL(0);
+extern bool         reset_close                  _DEFVAL(true);
+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;
+
+extern struct sipp_socket *twinSippSocket         _DEFVAL(NULL);
+extern struct sipp_socket *localTwinSippSocket    _DEFVAL(NULL);
+extern struct sockaddr_storage twinSipp_sockaddr;
+
+/* 3pcc extended mode */
+typedef struct _T_peer_infos {
+               char                       peer_host[40];
+               int                        peer_port;
+               struct sockaddr_storage    peer_sockaddr;
+               char                       peer_ip[40];
+               struct sipp_socket         *peer_socket ;
+               } T_peer_infos;
+
+typedef std::map<std::string, char * > peer_addr_map;
+extern peer_addr_map peer_addrs;
+typedef std::map<std::string, T_peer_infos> peer_map;
+extern peer_map      peers;
+typedef std::map<struct sipp_socket *, std::string > peer_socket_map;
+extern peer_socket_map peer_sockets;
+extern struct sipp_socket *local_sockets[MAX_LOCAL_TWIN_SOCKETS];
+extern int           local_nb                    _DEFVAL(0);
+extern int           peers_connected             _DEFVAL(0);
+
+extern struct       sockaddr_storage remote_sockaddr;
+extern short         use_remote_sending_addr      _DEFVAL(0);
+extern struct        sockaddr_storage remote_sending_sockaddr;
+
+enum E_Alter_YesNo
+  {
+    E_ALTER_YES=0,
+    E_ALTER_NO
+  };
+
+/************************** Trace Files ***********************/
+
+extern FILE * screenf                             _DEFVAL(0);
+extern FILE * countf                              _DEFVAL(0);
+// extern FILE * timeoutf                            _DEFVAL(0);
+extern bool   useMessagef                         _DEFVAL(0);
+extern bool   useCallDebugf                       _DEFVAL(0);
+extern bool   useShortMessagef                    _DEFVAL(0);
+extern bool   useScreenf                          _DEFVAL(0);
+extern bool   useLogf                             _DEFVAL(0);
+//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;
+
+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("");
+
+/* Log Rotation Functions. */
+struct logfile_id {
+  time_t start;
+  int n;
+};
+
+struct logfile_info {
+       char *name;
+       bool check;
+       FILE *fptr;
+       int nfiles;
+       struct logfile_id *ftimes;
+       char file_name[MAX_PATH];
+       bool overwrite;
+       bool fixedname;
+       time_t starttime;
+       unsigned int count;
+};
+
+#ifdef GLOBALS_FULL_DEFINITION
+#define LOGFILE(name, s, check) \
+       struct logfile_info name = { s, check, NULL, 0, NULL, "", true, false, 0, 0};
+#else
+#define LOGFILE(name, s, check) \
+       extern struct logfile_info name;
+#endif
+LOGFILE(calldebug_lfi, "calldebug", true);
+LOGFILE(message_lfi, "messages", true);
+LOGFILE(shortmessage_lfi, "shortmessages", true);
+LOGFILE(log_lfi, "logs", true);
+LOGFILE(error_lfi, "errors", false);
+
+void rotate_errorf();
+
+/* Screen/Statistics Printing Functions. */
+void print_statistics(int last);
+void print_count_file(FILE *f, int header);
+
+
+/********************* Mini-Parser Routines *******************/
+
+int get_method(char *msg);
+char * get_peer_tag(char *msg);
+unsigned long int get_cseq_value(char *msg);
+unsigned long get_reply_code(char *msg);
+
+/********************** Network Interfaces ********************/
+
+int send_message(int s, void ** comp_state, char * msg);
+#ifdef _USE_OPENSSL
+int send_message_tls(SSL *s, void ** comp_state, char * msg);
+#endif
+
+/* Socket Buffer Management. */
+#define NO_COPY 0
+#define DO_COPY 1
+struct socketbuf *alloc_socketbuf(char *buffer, size_t size, int copy);
+void free_socketbuf(struct socketbuf *socketbuf);
+
+/* These buffers lets us read past the end of the message, and then split it if
+ * required.  This eliminates the need for reading a message octet by octet and
+ * performing a second read for the content length. */
+struct socketbuf {
+       char *buf;
+       size_t len;
+       size_t offset;
+       struct sockaddr_storage addr;
+       struct socketbuf *next;
+};
+
+#ifdef USE_SCTP
+#define SCTP_DOWN 0
+#define SCTP_CONNECTING 1
+#define SCTP_UP 2
+#endif
+/* This is an abstraction of a socket, which provides buffers for input and
+ * output. */
+struct sipp_socket {
+       int  ss_count; /* How many users are there of this socket? */
+
+       int ss_transport; /* T_TCP, T_UDP, or T_TLS. */
+       bool ss_ipv6;
+       bool ss_control; /* Is this a control socket? */
+       bool ss_call_socket; /* Is this a call socket? */
+       bool ss_changed_dest; /* Has the destination changed from default. */
+
+       int ss_fd;      /* The underlying file descriptor for this socket. */
+       void *ss_comp_state; /* The compression state. */
+#ifdef _USE_OPENSSL
+       SSL *ss_ssl;    /* The underlying SSL descriptor for this socket. */
+       BIO *ss_bio;    /* The underlying BIO descriptor for this socket. */
+#endif
+       struct sockaddr_storage ss_remote_sockaddr; /* Who we are talking to. */
+       struct sockaddr_storage ss_dest; /* Who we are talking to. */
+
+
+       int ss_pollidx; /* The index of this socket in our poll structures. */
+       bool ss_congested; /* Is this socket congested? */
+       bool ss_invalid; /* Has this socket been closed remotely? */
+
+       struct socketbuf *ss_in; /* Buffered input. */
+       size_t ss_msglen;       /* Is there a complete SIP message waiting, and if so how big? */
+       struct socketbuf *ss_out; /* Buffered output. */
+#ifdef USE_SCTP
+  int sctpstate;
+#endif
+};
+
+/* Write data to a socket. */
+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. */
+void sipp_close_socket(struct sipp_socket *socket);
+
+#define WS_EAGAIN 1 /* Return EAGAIN if there is no room for writing the message. */
+#define WS_BUFFER 2 /* Buffer the message if there is no room for writing the message. */
+
+
+#if defined (__hpux) || defined (__alpha) && !defined (__FreeBSD__)
+#define sipp_socklen_t  int
+#else
+#define sipp_socklen_t  socklen_t
+#endif
+
+#define SOCK_ADDR_SIZE(a) \
+  (((a)->ss_family == AF_INET) ? sizeof(struct sockaddr_in) \
+                               : sizeof(struct sockaddr_in6))
+
+#if defined(__cplusplus) && defined (__hpux)
+#define _RCAST(type, val) (reinterpret_cast<type> (val))
+#else
+#define _RCAST(type, val) ((type)(val))
+#endif
+
+/********************* Utilities functions  *******************/
+
+char *strcasestr2 ( char *__haystack, char *__needle);
+char *get_peer_addr(char *);
+int get_decimal_from_hex(char hex);
+
+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);
+
+/* extended 3PCC mode */
+struct sipp_socket **get_peer_socket(char *);
+bool is_a_peer_socket(struct sipp_socket *);
+bool is_a_local_socket(struct sipp_socket *);
+void connect_to_peer (char *, int , sockaddr_storage *, char *, struct sipp_socket **);
+void connect_to_all_peers ();
+void connect_local_twin_socket(char *);
+void close_peer_sockets();
+void close_local_sockets();
+void free_peer_addr_map();
+
+/********************* Reset global kludge  *******************/
+
+#ifdef GLOBALS_FULL_DEFINITION
+#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_CALLDEBUG(char *fmt, ...);
+int TRACE_SHORTMSG(char *fmt, ...);
+int LOG_MSG(char *fmt, ...);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __SIPP__
diff --git a/.svn/pristine/10/10bf87b898627aae081ffd5921d6cef530858f1b.svn-base b/.svn/pristine/10/10bf87b898627aae081ffd5921d6cef530858f1b.svn-base
new file mode 100644 (file)
index 0000000..4fb6b98
--- /dev/null
@@ -0,0 +1,167 @@
+# ======================== initialization ===============================
+
+AC_INIT([SIPp], [3.1], [sipp-users@lists.sourceforge.net], [sipp])
+
+AC_CANONICAL_TARGET
+
+AC_CONFIG_SRCDIR([sipp.cpp])
+AC_CONFIG_HEADERS([config.h])
+AM_INIT_AUTOMAKE([foreign dist-xz])
+
+AC_ARG_WITH([openssl],AC_HELP_STRING([--with-openssl], [build with OpenSSL support]), [openssl="$withval"],[openssl="no"])
+AC_ARG_WITH([pcap],AC_HELP_STRING([--with-pcap], [build with pcap support]), [pcap="$withval"],[pcap="no"])
+AC_ARG_WITH([unittest],AC_HELP_STRING([--with-unittest], [build with unit testing framework]), [unittest="$withval"],[unittest="no"])
+AC_ARG_WITH([sctp],AC_HELP_STRING([--with-sctp], [build with SCTP support]), [sctp="$withval"],[sctp="no"])
+
+# ==================== basic compiler settings ==========================
+
+AC_PROG_CC
+AC_PROG_CXX
+AC_HEADER_STDC
+
+case "$host" in
+       *-linux*)
+               CFLAGS="$CFLAGS -D__LINUX"
+               CPPFLAGS="$CPPFLAGS -D__LINUX"
+               ;;
+       *-darwin*)
+               CFLAGS="$CFLAGS -D__DARWIN"
+               CPPFLAGS="$CPPFLAGS -D__DARWIN"
+               ;;
+       *-hpux*)
+               CFLAGS="$CFLAGS -D__HPUX"
+               CPPFLAGS="$CPPFLAGS -D__HPUX"
+               ;;
+       *-freebsd*)
+               CFLAGS="$CFLAGS -D__LINUX"
+               CPPFLAGS="$CPPFLAGS -D__LINUX"
+               ;;
+       *-sunos*)
+               CFLAGS="$CFLAGS -D__SUNOS"
+               CPPFLAGS="$CPPFLAGS -D__SUNOS"
+               ;;
+       *-cygwin*)
+               CFLAGS="$CFLAGS -D__CYGWIN"
+               CPPFLAGS="$CPPFLAGS -D__CYGWIN"
+               ;;
+       *-tru64*)
+               CFLAGS="$CFLAGS -D__OSF1"
+               CPPFLAGS="$CPPFLAGS -D__OSF1"
+               ;;
+esac
+
+# ==================== checks for libraries =============================
+AC_CHECK_LIB(curses,initscr,,[AC_MSG_ERROR([ncurses library missing])])
+AC_CHECK_LIB(pthread, pthread_mutex_init, THREAD_LIBS="-lpthread",
+               AC_MSG_ERROR(pthread library needed!))
+
+# For Linux and SunOS
+AC_SEARCH_LIBS([dlopen], [dl])
+AC_SEARCH_LIBS([dlerror], [dl])
+AC_SEARCH_LIBS([dlsym], [dl])
+
+# For SunOS
+AC_SEARCH_LIBS([inet_addr], [nsl])
+AC_SEARCH_LIBS([inet_ntoa], [nsl])
+
+AC_SEARCH_LIBS([pthread_mutex_init], [pthread])
+AC_SEARCH_LIBS([pthread_mutex_destroy], [pthread])
+AC_SEARCH_LIBS([pthread_mutex_lock], [pthread])
+AC_SEARCH_LIBS([pthread_mutex_unlock], [pthread])
+AC_SEARCH_LIBS([pthread_self], [pthread])
+AC_SEARCH_LIBS([pthread_cancel], [pthread])
+AC_SEARCH_LIBS([pthread_join], [pthread])
+AC_SEARCH_LIBS([pthread_attr_init], [pthread])
+AC_SEARCH_LIBS([pthread_attr_setstacksize], [pthread])
+AC_SEARCH_LIBS([pthread_create], [pthread])
+AC_SEARCH_LIBS([pthread_attr_destroy], [pthread])
+AC_SEARCH_LIBS([pthread_setschedparam], [pthread])
+AC_SEARCH_LIBS([pthread_setcancelstate], [pthread])
+AC_SEARCH_LIBS([pthread_setcanceltype], [pthread])
+AC_SEARCH_LIBS([pthread_exit], [pthread])
+AC_SEARCH_LIBS([pthread_sigmask], [pthread])
+#AC_SEARCH_LIBS([pthread_cleanup_push], [pthread]) <- macro
+#AC_SEARCH_LIBS([pthread_cleanup_pop], [pthread]) <- macro
+
+AC_SEARCH_LIBS([floor], [m])
+AC_SEARCH_LIBS([pow], [m])
+
+# For SunOS
+AC_SEARCH_LIBS([htons], [socket])
+AC_SEARCH_LIBS([ntohs], [socket])
+AC_SEARCH_LIBS([bind], [socket])
+AC_SEARCH_LIBS([freeaddrinfo], [socket])
+AC_SEARCH_LIBS([getaddrinfo], [socket])
+AC_SEARCH_LIBS([listen], [socket])
+AC_SEARCH_LIBS([recvfrom], [socket])
+AC_SEARCH_LIBS([shutdown], [socket])
+
+# For Linux, SunOS and Cygwin
+#AC_CHECK_LIB(stdc++,main,,[AC_MSG_ERROR([stdc++ library missing])])
+
+# Conditional build with OpenSSL
+if test "$openssl" = 'yes'; then
+       AC_CHECK_HEADERS([openssl/md5.h],,[AC_MSG_ERROR([<openssl/md5.h> header missing])])
+       AC_CHECK_HEADERS([openssl/bio.h],,[AC_MSG_ERROR([<openssl/bio.h> header missing])])
+       AC_CHECK_HEADERS([openssl/err.h],,[AC_MSG_ERROR([<openssl/err.h> header missing])])
+       AC_CHECK_HEADERS([openssl/rand.h],,[AC_MSG_ERROR([<openssl/rand.h> header missing])])
+       AC_CHECK_HEADERS([openssl/ssl.h],,[AC_MSG_ERROR([<openssl/ssl.h> header missing])])
+       AC_CHECK_HEADERS([openssl/x509v3.h],,[AC_MSG_ERROR([<openssl/x509v3.h> header missing])])
+       AC_CHECK_LIB([ssl], [SSL_library_init],,[AC_MSG_ERROR([ssl library missing])])
+       AC_CHECK_LIB([crypto], [CRYPTO_num_locks],,[AC_MSG_ERROR([crypto library missing])])
+fi
+# For Makefile.am
+AM_CONDITIONAL(HAVE_OPENSSL, test "$openssl" = "yes")
+
+# Conditional build with SCTP
+if test "$sctp" = 'yes'; then
+       AC_CHECK_HEADERS([netinet/sctp.h],,[AC_MSG_ERROR([<netinet/sctp.h> header missing])])
+       AC_SEARCH_LIBS([sctp_send],[sctp],,[AC_MSG_ERROR([SCTP library missing])])
+       AC_SEARCH_LIBS([sctp_getpaddrs],[sctp],,[AC_MSG_ERROR([SCTP library missing])])
+       AC_SEARCH_LIBS([sctp_freepaddrs],[sctp],,[AC_MSG_ERROR([SCTP library missing])])
+       AC_SEARCH_LIBS([sctp_bindx],[sctp],,[AC_MSG_ERROR([SCTP library missing])])
+       AC_SEARCH_LIBS([sctp_recvmsg],[sctp],,[AC_MSG_ERROR([SCTP library missing])])
+fi
+# For Makefile.am
+AM_CONDITIONAL(HAVE_SCTP, test "$sctp" = "yes")
+
+# Conditional build with pcap
+if test "$pcap" = 'yes'; then
+       AC_CHECK_HEADERS([pcap.h],,[AC_MSG_ERROR([<pcap.h> header missing])])
+       AC_CHECK_LIB([pcap], [pcap_open_offline],,[AC_MSG_ERROR([pcap library missing])])
+       AC_CHECK_LIB([pcap], [pcap_next],,[AC_MSG_ERROR([pcap library missing])])
+       AC_CHECK_LIB([pcap], [pcap_next_ex],,[AC_MSG_ERROR([pcap library missing])])
+       AC_CHECK_LIB([pcap], [pcap_close],,[AC_MSG_ERROR([pcap library missing])])
+fi
+# For Makefile.am
+AM_CONDITIONAL(HAVE_PCAP, test "$pcap" = "yes")
+AM_CONDITIONAL(HAVE_UNITTEST, test "$unittest" = "yes")
+
+# ==================== checks for header files ==========================
+
+AC_FUNC_ALLOCA
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h])
+
+# ===== checks for typedefs, structures and compiler characteristics ====
+
+AC_HEADER_STDBOOL
+AC_C_INLINE
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT8_T
+
+# ==================== checks for library functions =====================
+
+AC_FUNC_FORK
+#AC_FUNC_MALLOC
+#AC_FUNC_REALLOC
+#AC_FUNC_STRTOD
+AC_CHECK_FUNCS([alarm dup2 floor gethostname gettimeofday inet_ntoa memmove memset pow regcomp socket sqrt strcasecmp strchr strcspn strdup strerror strncasecmp strrchr strstr strtol strtoul strtoull])
+
+# ==================== generate files ===================================
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/.svn/pristine/13/13e8578621505a8052ecc535d648e74ba902aa89.svn-base b/.svn/pristine/13/13e8578621505a8052ecc535d648e74ba902aa89.svn-base
new file mode 100644 (file)
index 0000000..6230384
--- /dev/null
@@ -0,0 +1,416 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Copyright (C) 2003 - The Authors
+ *
+ *  Author : Richard GAYRAUD - 04 Nov 2003
+ *           From Hewlett Packard Company.
+ */
+
+/*
+ * Mini xml parser:
+ *
+ * WARNING 1: Only supports printable
+ * ASCII characters in xml files. '\0'
+ * is not a valid character. Returned string are
+ * NULL-terminated.
+ *
+ * WARNING 2: Does not supports multithreading. Works
+ * with static buffer, no memory allocation.
+ */
+
+/*******************  Include files *********************/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "xp_parser.h"
+
+/************* Constants and Global variables ***********/
+
+#define XP_MAX_NAME_LEN   256
+#define XP_MAX_FILE_LEN   65536
+#define XP_MAX_STACK_LEN  256
+
+char   xp_file     [XP_MAX_FILE_LEN + 1];
+char * xp_position [XP_MAX_STACK_LEN];
+int    xp_stack    = 0;
+
+/****************** Internal routines ********************/
+int xp_replace(char *source, char *dest, char *search, char *replace)
+{
+  char *position;
+  char *occurances;
+  int number = 0;
+
+  if (!source || !dest || !search || !replace) {
+    return -1;
+  }
+  dest[0] = '\0';
+  position = source;
+  occurances = strstr(position, search);
+  while (occurances) {
+    strncat(dest, position, occurances - position);
+    strcat(dest, replace); 
+    position = occurances + strlen(search);
+    occurances = strstr(position, search);
+    number++;
+  }
+  strcat(dest, position);
+  return number;
+}
+
+/* This finds the end of something like <send foo="bar">, and does not recurse
+ * into other elements. */
+char * xp_find_start_tag_end(char *ptr)
+{
+  while(*ptr) {
+    if (*ptr == '<') {
+      if ((strstr(ptr,"<!--") == ptr)) {
+        char * comment_end = strstr(ptr, "-->");
+        if(!comment_end) return NULL;
+        ptr = comment_end + 3;
+      } else {
+       return NULL;
+      }
+    } else  if((*ptr == '/') && (*(ptr+1) == '>')) {
+      return ptr;
+    } else if (*ptr == '"') {
+      ptr++;
+      while(*ptr) {
+       if (*ptr == '\\') {
+         ptr += 2;
+       } else if (*ptr=='"') {
+         ptr++;
+         break;
+       } else {
+         ptr++;
+       }
+      }
+    } else if (*ptr == '>') {
+      return ptr;
+    } else {
+      ptr++;
+    }
+  }
+  return ptr;
+}
+
+char * xp_find_local_end()
+{
+  char * ptr = xp_position[xp_stack];
+  int level = 0;
+  
+  while(*ptr) {
+    if (*ptr == '<') {
+      if ((*(ptr+1) == '!') && 
+          (*(ptr+2) == '[') &&
+          (strstr(ptr,"<![CDATA[") == ptr)) {
+        char * cdata_end = strstr(ptr, "]]>");
+        if(!cdata_end) return NULL;
+        ptr = cdata_end + 3;
+      } else if ((*(ptr+1) == '!') && 
+          (*(ptr+2) == '-') &&
+          (strstr(ptr,"<!--") == ptr)) {
+        char * comment_end = strstr(ptr, "-->");
+        if(!comment_end) return NULL;
+        ptr = comment_end + 3;
+      } else if(*(ptr+1) == '/') {
+        level--;
+        if(level < 0) return ptr;
+      } else {
+        level ++;
+      }
+    } else  if((*ptr == '/') && (*(ptr+1) == '>')) {
+      level --;
+      if(level < 0) return ptr;
+    } else if (*ptr == '"') {
+      ptr++;
+      while(*ptr) {
+       if (*ptr == '\\') {
+         ptr ++; /* Skip the slash. */
+       } else if (*ptr=='"') {
+         break;
+       }
+       ptr++;
+      }
+    }
+    ptr++;
+  }
+  return ptr;
+}
+
+/********************* Interface routines ********************/
+
+int xp_set_xml_buffer_from_string(char * str)
+{
+  size_t len = strlen(str);
+
+  if(len > XP_MAX_FILE_LEN) {
+    return 0;
+  }
+
+  strcpy(xp_file, str);
+  xp_stack = 0;
+  xp_position[xp_stack] = xp_file;
+  
+  if(strstr(xp_position[xp_stack], "<?xml") != xp_position[xp_stack]) return 0;
+  if(!strstr(xp_position[xp_stack], "?>")) return 0;
+  xp_position[xp_stack] = xp_position[xp_stack] + 2;
+
+  return 1;
+}
+
+int xp_set_xml_buffer_from_file(char * filename)
+{
+  FILE * f = fopen(filename, "rb");
+  int index = 0;
+  int c;
+
+  if(!f) { return 0; }
+
+  while((c = fgetc(f)) != EOF) {
+    if(c == '\r') continue;
+    xp_file[index++] = c;
+    if(index >= XP_MAX_FILE_LEN) {
+      xp_file[index++] = 0;
+      xp_stack = 0;
+      xp_position[xp_stack] = xp_file;
+      return 0;
+    }
+  }
+  xp_file[index++] = 0;
+  fclose(f);
+
+  xp_stack = 0;
+  xp_position[xp_stack] = xp_file;
+
+  if(strstr(xp_position[xp_stack], "<?xml") != xp_position[xp_stack]) return 0;
+  if(!strstr(xp_position[xp_stack], "?>")) return 0;
+  xp_position[xp_stack] = xp_position[xp_stack] + 2;
+
+  return 1;
+}
+
+char * xp_open_element(int index)
+{
+  char * ptr = xp_position[xp_stack];
+  int level = 0;
+  static char name[XP_MAX_NAME_LEN];
+
+  while(*ptr) {
+    if (*ptr == '<') {
+      if ((*(ptr+1) == '!') && 
+          (*(ptr+2) == '[') &&
+          (strstr(ptr,"<![CDATA[") == ptr)) {
+        char * cdata_end = strstr(ptr, "]]>");
+        if(!cdata_end) return NULL;
+        ptr = cdata_end + 2;
+      } else if ((*(ptr+1) == '!') && 
+          (*(ptr+2) == '-') &&
+          (strstr(ptr,"<!--") == ptr)) {
+        char * comment_end = strstr(ptr, "-->");
+        if(!comment_end) return NULL;
+        ptr = comment_end + 2;
+      } else if (strstr(ptr,"<!DOCTYPE") == ptr) {
+        char * doctype_end = strstr(ptr, ">");
+        if(!doctype_end) return NULL;
+        ptr = doctype_end;
+      } else if(*(ptr+1) == '/') {
+        level--;
+        if(level < 0) return NULL;
+      } else {
+       if(level==0) {
+         if (index) {
+           index --;
+         } else {
+           char * end = xp_find_start_tag_end(ptr + 1);
+           char * p;
+           if(!end) return NULL;
+
+           p = strchr(ptr, ' ');
+           if(p && (p < end))  { end = p; }
+           p = strchr(ptr, '\t');
+           if(p && (p < end))  { end = p; }
+           p = strchr(ptr, '\r');
+           if(p && (p < end))  { end = p; }
+           p = strchr(ptr, '\n');
+           if(p && (p < end))  { end = p; }
+           p = strchr(ptr, '/');
+           if(p && (p < end))  { end = p; }
+
+           memcpy(name, ptr + 1, end-ptr-1);
+           name[end-ptr-1] = 0;
+
+           xp_position[++xp_stack] = end;
+           return name;
+         }
+       }
+
+       /* We want to skip over this particular element .*/
+       ptr = xp_find_start_tag_end(ptr + 1);
+       if (ptr) ptr--;
+       level ++;
+      }
+    } else if((*ptr == '/') && (*(ptr+1) == '>')) {
+      level --;
+      if(level < 0) return NULL;
+    }
+    ptr++;
+  }
+  return NULL;
+}
+
+void xp_close_element()
+{
+  if(xp_stack) {
+    xp_stack--;
+  }
+}
+
+void xp_root()
+{
+  xp_stack = 0;
+}
+
+char * xp_get_value(const char * name)
+{
+  int         index = 0;
+  static char buffer[XP_MAX_FILE_LEN + 1]; 
+  char      * ptr, *end, *check;
+  
+  end = xp_find_start_tag_end(xp_position[xp_stack] + 1);
+  if(!end) return NULL;
+
+  ptr = xp_position[xp_stack];
+  
+  while(*ptr) {
+    ptr = strstr(ptr, name);
+
+    if(!ptr) return NULL;
+    if(ptr > end) return NULL;
+    // FIXME: potential BUG in parser: we must retrieve full word,
+    // so the use of strstr as it is is not enough.
+    // we should check that the retrieved word is not a piece of another one.
+    check = ptr-1;
+    if(check >= xp_position[xp_stack])
+    {
+      if((*check != '\r') && 
+         (*check != '\n') && 
+         (*check != '\t') && 
+         (*check != ' ' )) { ptr += strlen(name); continue; }
+    }
+    else
+      return(NULL);
+
+    ptr += strlen(name);
+    while((*ptr == '\r') || 
+          (*ptr == '\n') || 
+          (*ptr == '\t') || 
+          (*ptr == ' ' )    ) { ptr ++; }
+    if(*ptr != '=') continue;
+    ptr ++;
+    while((*ptr == '\r') || 
+          (*ptr == '\n') || 
+          (*ptr == '\t') || 
+          (*ptr ==  ' ')    ) { ptr ++; }
+    ptr++;
+    if(*ptr) {
+      while(*ptr) {
+       if (*ptr == '\\') {
+         ptr++;
+         switch(*ptr) {
+           case '\\':
+             buffer[index++] = '\\';
+             break;
+           case '"':
+             buffer[index++] = '"';
+             break;
+           case 'n':
+             buffer[index++] = '\n';
+             break;
+           case 't':
+             buffer[index++] = '\t';
+             break;
+           case 'r':
+             buffer[index++] = '\r';
+             break;
+           default:
+             buffer[index++] = '\\';
+             buffer[index++] = *ptr;
+             break;
+         }
+         ptr++;
+       } else if (*ptr=='"') {
+         break;
+       } else {
+         buffer[index++] = *ptr++;
+       }
+        if(index > XP_MAX_FILE_LEN) return NULL;
+      }
+      buffer[index] = 0;
+      return buffer;
+    }
+  }
+  return NULL;
+}
+
+char * xp_get_cdata()
+{
+  static char buffer[XP_MAX_FILE_LEN + 1]; 
+  char      * end = xp_find_local_end();
+  char      * ptr;
+  
+  ptr = strstr(xp_position[xp_stack],"<![CDATA[");
+  if(!ptr) { return NULL; }
+  ptr += 9;
+  if(ptr > end) return NULL;
+  end = strstr(ptr, "]]>");
+  if(!end) { return NULL; }
+  if((end -ptr) > XP_MAX_FILE_LEN) return NULL;
+  memcpy(buffer, ptr, (end-ptr));
+  buffer[end-ptr] = 0;
+  return buffer;
+}
+
+int xp_get_content_length(char * P_buffer) 
+{
+  char * L_ctl_hdr;
+  int    L_content_length = -1 ; 
+  unsigned char   short_form;
+
+  short_form = 0;
+
+  L_ctl_hdr = strstr(P_buffer, "\nContent-Length:");
+  if(!L_ctl_hdr) {L_ctl_hdr = strstr(P_buffer, "\nContent-length:"); }
+  if(!L_ctl_hdr) {L_ctl_hdr = strstr(P_buffer, "\ncontent-Length:"); }
+  if(!L_ctl_hdr) {L_ctl_hdr = strstr(P_buffer, "\ncontent-length:"); }
+  if(!L_ctl_hdr) {L_ctl_hdr = strstr(P_buffer, "\nCONTENT-LENGTH:"); }
+  if(!L_ctl_hdr) {L_ctl_hdr = strstr(P_buffer, "\nl:"); short_form = 1;}
+
+  if( L_ctl_hdr ){
+    if (short_form) {
+      L_ctl_hdr += 3;
+    } else {
+      L_ctl_hdr += 16;
+    }
+    while(isspace(*L_ctl_hdr)) L_ctl_hdr++;
+    sscanf(L_ctl_hdr, "%d", &L_content_length);
+  } 
+  // L_content_length = -1 the message does not contain content-length
+  return (L_content_length); 
+}
+
diff --git a/.svn/pristine/15/155bc6dc48ca304c64623e236eb973e81cd22160.svn-base b/.svn/pristine/15/155bc6dc48ca304c64623e236eb973e81cd22160.svn-base
new file mode 100644 (file)
index 0000000..cbdbbfd
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA
+ *
+ *  Author : Richard GAYRAUD - 04 Nov 2003
+ *           From Hewlett Packard Company.
+ *          Charles P. Wright from IBM Research
+ */
+
+#include "sipp.hpp"
+#include "screen.hpp"
+#include "stat.hpp"
+#include "infile.hpp"
+#include <iostream>
+#include <assert.h>
+
+/* Read MAX_CHAR_BUFFER_SIZE size lines from the "fileName" and populate it in
+ * the fileContents vector. Each line should be terminated with a '\n'
+ */
+FileContents::FileContents(const char *fileName) {
+  ifstream *inFile    = new ifstream(fileName);
+  char      line[MAX_CHAR_BUFFER_SIZE];
+  int virtualLines = 0;
+
+  if (!inFile->good()) {
+    ERROR("Unable to open file %s", fileName);
+  }
+
+  this->fileName = fileName;
+
+  realLinesInFile = lineCounter = numLinesInFile = 0;
+  /* Initialize printf info. */
+  printfFile = false;
+  printfOffset = 0;
+  printfMultiple = 1;
+  
+
+  line[0] = '\0';
+  inFile->getline(line, MAX_CHAR_BUFFER_SIZE);
+
+  if (NULL != strstr(line, "RANDOM")) {
+      usage = InputFileRandomOrder;
+  } else if (NULL != strstr(line, "SEQUENTIAL")) {
+      usage = InputFileSequentialOrder;
+  } else if (NULL != strstr(line, "USER")) {
+      usage = InputFileUser;
+  } else {
+      ERROR("Unknown file type (valid values are RANDOM, SEQUENTIAL, and USER) for %s:%s\n", fileName, line);
+  }
+
+  char *useprintf;
+  if ((useprintf = strstr(line, "PRINTF"))) {
+    /* We are going to operate in printf mode, which uses the line as a format
+     * string for printf with the line number. */
+    useprintf += strlen("PRINTF");
+    if (*useprintf != '=') {
+       ERROR("Invalid file printf specification (requires =) for %s:%s\n", fileName, line);
+    }
+    useprintf++;
+    char *endptr;
+    virtualLines = strtoul(useprintf, &endptr, 0);
+    if (*endptr && *endptr != '\r' && *endptr != '\n' && *endptr != ',') {
+      ERROR("Invalid file printf specification for (invalid end character '%c') %s:%s\n", *endptr, fileName, line);
+    }
+    if (virtualLines == 0) {
+      ERROR("A printf file must have at least one virtual line %s:%s\n", fileName, line);
+    }
+    printfFile = true;
+  }
+
+  if ((useprintf = strstr(line, "PRINTFOFFSET"))) {
+    useprintf += strlen("PRINTFOFFSET");
+    if (*useprintf != '=') {
+       ERROR("Invalid file PRINTFOFFSET specification (requires =) for %s:%s\n", fileName, line);
+    }
+    useprintf++;
+    char *endptr;
+    printfOffset = strtoul(useprintf, &endptr, 0);
+    if (*endptr && *endptr != '\n' && *endptr != ',') {
+      ERROR("Invalid PRINTFOFFSET specification for (invalid end character '%c') %s:%s\n", *endptr, fileName, line);
+    }
+  }
+
+  if ((useprintf = strstr(line, "PRINTFMULTIPLE"))) {
+    useprintf += strlen("PRINTFMULTIPLE");
+    if (*useprintf != '=') {
+       ERROR("Invalid PRINTFMULTIPLE specification (requires =) for %s:%s\n", fileName, line);
+    }
+    useprintf++;
+    char *endptr;
+    printfMultiple = strtoul(useprintf, &endptr, 0);
+    if (*endptr && *endptr != '\n' && *endptr != ',') {
+      ERROR("Invalid PRINTFOFFSET specification for (invalid end character '%c') %s:%s\n", *endptr, fileName, line);
+    }
+  }
+
+  while (!inFile->eof()) {
+    line[0] = '\0';
+    inFile->getline(line, MAX_CHAR_BUFFER_SIZE);
+    if (line[0]) {
+      if ('#' != line[0]) {
+        fileLines.push_back(line);
+        realLinesInFile++; /* this counts number of valid data lines */
+      }
+    } else {
+      break;
+    }
+  }
+
+  if (realLinesInFile == 0) {
+    ERROR("Input file has zero lines: %s\n", fileName);
+  }
+
+  if (printfFile) {
+    numLinesInFile = virtualLines;
+  } else {
+    numLinesInFile = realLinesInFile;
+  }
+
+  delete inFile;
+
+  indexMap = NULL;
+  indexField = -1;
+}
+
+int FileContents::getLine(int line, char *dest, int len) {
+  if (printfFile) {
+    line %= realLinesInFile;
+  }
+  return snprintf(dest, len, "%s", fileLines[line].c_str());
+}
+
+int FileContents::getField(int lineNum, int field, char *dest, int len) {
+  int curfield = field;
+  int curline = lineNum;
+
+  dest[0] = '\0';
+  if (lineNum >= numLinesInFile) {
+    return 0;
+  }
+
+  if (printfFile) {
+       curline %= realLinesInFile;
+  }
+  const string & line = fileLines[curline];
+
+  size_t pos(0), oldpos(0);
+
+  do {
+    oldpos = pos;
+    size_t localpos = line.find(';', oldpos);
+
+    if (localpos != string::npos) {
+      pos = localpos + 1;
+    } else {
+      pos = localpos;
+      break;
+    }
+
+    if (curfield == 0) {
+      break;
+    }
+
+    curfield --;
+  } while (oldpos != string::npos);
+
+
+  if (curfield) {
+      WARNING("Field %d not found in the file %s", field, fileName);
+      return 0;
+  }
+
+
+  if (string::npos == oldpos) {
+    return 0;
+  }
+
+  if (string::npos != pos) {
+    // should not be decremented for fieldN
+    pos -= (oldpos + 1);
+  }
+
+  string x = line.substr(oldpos, pos);
+  if (x.length()) {
+    if (printfFile) {
+      const char *s = x.c_str();
+      int l = strlen(s);
+      int copied = 0;
+      for (int i = 0; i < l; i++) {
+       if (s[i] == '%') {
+         if (s[i + 1] == '%') {
+           dest[copied++] = s[i];
+         } else {
+           const char *format = s + i;
+           i++;
+           while (s[i] != 'd') {
+             if (i == l) {
+               ERROR("Invalid printf injection field (ran off end of line): %s", s);
+             }
+             if (!(isdigit(s[i]) || s[i] == '.' || s[i] == '-')) {
+               ERROR("Invalid printf injection field (only decimal values allowed '%c'): %s", s[i], s);
+             }
+             i++;
+           }
+           assert(s[i] == 'd');
+           char *tmp = (char *)malloc(s + i + 2 - format);
+           if (!tmp) {
+             ERROR("Out of memory!\n");
+           }
+            memcpy(tmp, format, s + i + 1 - format);
+           tmp[s + i + 1 - format] = '\0';
+           copied += sprintf(dest + copied, tmp, printfOffset + (lineNum * printfMultiple));
+           free(tmp);
+         }
+       } else {
+         dest[copied++] = s[i];
+       }
+      }
+      dest[copied] = '\0';
+      return copied;
+    } else {
+      return snprintf(dest, len, "%s", x.c_str());
+    }
+  } else {
+    return 0;
+  }
+}
+
+int FileContents::numLines() {
+  return numLinesInFile;
+}
+
+int FileContents::nextLine(int userId) {
+  switch(usage) {
+    case InputFileRandomOrder:
+      return rand() % numLinesInFile;
+    case InputFileSequentialOrder:
+      {
+       int ret = lineCounter;
+       lineCounter = (lineCounter + 1) % numLinesInFile;
+       return ret;
+      }
+    case InputFileUser:
+      if (userId == 0) {
+       return -1;
+      }
+      if ((userId  - 1) >= numLinesInFile) {
+       ERROR("%s has only %d lines, yet user %d was requested.", fileName, numLinesInFile, userId);
+      }
+      return userId - 1;
+    default:
+      ERROR("Internal error: unknown file usage mode!");
+      return -1;
+  }
+}
+
+void FileContents::dump(void)
+{
+    WARNING("Line choosing strategy is [%s]. m_counter [%d] numLinesInFile [%d] realLinesInFile [%d]",
+               usage == InputFileSequentialOrder ? "SEQUENTIAL" :
+               usage == InputFileRandomOrder ? "RANDOM" :
+               usage == InputFileUser ? "USER" : "UNKNOWN",
+               lineCounter, numLinesInFile, realLinesInFile);
+
+    for (int i = 0; i < realLinesInFile && fileLines[i][0]; i++) {
+        WARNING("%s:%d reads [%s]", fileName, i, fileLines[i].c_str());
+    }
+}
+
+void FileContents::index(int field) {
+  this->indexField = field;
+
+  indexMap = new str_int_map;
+  for (int line = 0; line < numLines(); line++) {
+    reIndex(line);
+  }
+}
+
+int FileContents::lookup(char *key) {
+  if (indexField == -1) {
+    ERROR("Invalid Index File: %s", fileName);
+  }
+  if (!indexMap) {
+    ERROR("Invalid Index File: %s", fileName);
+  }
+
+  str_int_map::iterator index_it = indexMap->find(key);
+  if (index_it == indexMap->end()) {
+    return -1;
+  }
+  return index_it->second;
+}
+
+
+void FileContents::insert(char *value) {
+  if (printfFile) {
+    ERROR("Can not insert or replace into a printf file: %s", fileName);
+  }
+  fileLines.push_back(value);
+  realLinesInFile++;
+  numLinesInFile++;
+  if (indexField != -1) {
+    reIndex(realLinesInFile - 1);
+  }
+  char line[1024];
+  getLine(realLinesInFile - 1, line, sizeof(line));
+  char tmp[1024];
+  getField(realLinesInFile - 1, 0, tmp, sizeof(tmp));
+}
+
+void FileContents::replace(int line, char *value) {
+  if (printfFile) {
+    ERROR("Can not insert or replace into a printf file: %s", fileName);
+  }
+  if (line >= realLinesInFile || line < 0) {
+    ERROR("Invalid line number (%d) for file: %s (%d lines)", line, fileName, realLinesInFile);
+  }
+  deIndex(line);
+  fileLines[line] = value;
+  reIndex(line);
+}
+
+void FileContents::reIndex(int line) {
+  if (indexField == -1) {
+    return;
+  }
+  assert(line >= 0);
+  assert(line < realLinesInFile);
+
+  char tmp[SIPP_MAX_MSG_SIZE];
+  getField(line, indexField, tmp, SIPP_MAX_MSG_SIZE);
+  str_int_map::iterator index_it = indexMap->find(str_int_map::key_type(tmp));
+  if (index_it != indexMap->end()) {
+    indexMap->erase(index_it);
+  }
+  indexMap->insert(pair<str_int_map::key_type,int>(str_int_map::key_type(tmp), line));
+}
+
+void FileContents::deIndex(int line) {
+  if (indexField == -1) {
+    return;
+  }
+  assert(line >= 0);
+  assert(line < realLinesInFile);
+
+  char tmp[SIPP_MAX_MSG_SIZE];
+  getField(line, indexField, tmp, SIPP_MAX_MSG_SIZE);
+  str_int_map::iterator index_it = indexMap->find(str_int_map::key_type(tmp));
+  if (index_it != indexMap->end()) {
+    if (index_it->second == line) {
+      indexMap->erase(index_it);
+    }
+  }
+}
diff --git a/.svn/pristine/19/191294568b803c2c0f6052cb28cb6fc47b1abfe2.svn-base b/.svn/pristine/19/191294568b803c2c0f6052cb28cb6fc47b1abfe2.svn-base
new file mode 100644 (file)
index 0000000..dc4a574
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Copyright (C) 2003 - The Authors
+ *
+ *  Author : Richard GAYRAUD - 04 Nov 2003
+ *           From Hewlett Packard Company.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int    xp_replace(char *source, char *dest, char *search, char *replace);
+int    xp_set_xml_buffer_from_string(char * str);
+int    xp_set_xml_buffer_from_file(char * filename);
+char * xp_open_element(int index);
+void   xp_close_element();
+int    xp_search_element_from_name(char * element, int occurence);
+char * xp_get_value(const char * name);
+char * xp_get_cdata();
+int    xp_get_content_length(char * P_buffer);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/.svn/pristine/1a/1a3e6d9755b1ab3af8f467169f1a45883318b4b7.svn-base b/.svn/pristine/1a/1a3e6d9755b1ab3af8f467169f1a45883318b4b7.svn-base
new file mode 100644 (file)
index 0000000..9b433ab
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Copyright (C) 2003 - The Authors
+ *
+ *  Author : Richard GAYRAUD - 04 Nov 2003
+ *           From Hewlett Packard Company.
+ *
+ */
+
+#define COMP_MAIN
+#include "comp.h"
+
+#include <dlfcn.h>
+#include <string.h>
+
+char * comp_load()
+{
+  void *handle;
+  char *error;
+
+  comp_error[0] = 0;
+  
+  handle = dlopen(COMP_PLUGGIN, RTLD_LAZY);
+  if (!handle) {
+    strcpy(comp_error, dlerror());
+    return comp_error;
+  }
+  
+  *(void **)(&comp_compress) = dlsym(handle, "comp_compress");
+  if((error = (char *) dlerror()))
+    { strcpy(comp_error, error); return comp_error; }
+  
+  *(void **)(&comp_uncompress) = dlsym(handle, "comp_uncompress");
+  if((error = (char *) dlerror()))
+    { strcpy(comp_error, error); return comp_error; }
+  
+  *(void **)(&comp_free) = dlsym(handle, "comp_free");
+  if((error = (char *) dlerror()))
+    { strcpy(comp_error, error); return comp_error; }
+  
+  return 0;
+}
diff --git a/.svn/pristine/1a/1a9e747748578ee6e80f36e0872728f99f13e96a.svn-base b/.svn/pristine/1a/1a9e747748578ee6e80f36e0872728f99f13e96a.svn-base
new file mode 100644 (file)
index 0000000..ae90556
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Author : Guillaume TEISSIER from FTR&D 02/02/2006
+ */
+#ifndef PREPARE_PCAP_H
+#define PREPARE_PCAP_H 1
+#include <pcap.h>
+#include <netinet/in.h>
+#include <netinet/udp.h>
+#include <time.h>
+
+#if defined(__HPUX) || defined(__DARWIN) || defined(__CYGWIN) || defined(__FreeBSD__)
+#define u_int8_t uint8_t
+#define u_int16_t uint16_t
+#define u_int32_t uint32_t
+
+struct iphdr
+  {
+#ifdef _HPUX_LI
+    unsigned int ihl:4;
+    unsigned int version:4;
+#else
+    unsigned int version:4;
+    unsigned int ihl:4;
+#endif
+    u_int8_t tos;
+    u_int16_t tot_len;
+    u_int16_t id;
+    u_int16_t frag_off;
+    u_int8_t ttl;
+    u_int8_t protocol;
+    u_int16_t check;
+    u_int32_t saddr;
+    u_int32_t daddr;
+    /*The options start here. */
+  };
+   
+#endif
+
+typedef struct
+{
+  u_char *data;
+  u_long pktlen;
+  struct timeval ts;
+  int partial_check;
+} pcap_pkt;
+
+#define PCAP_MAXPACKET 1500
+typedef struct
+{
+  char *file;
+  u_int16_t base;
+  u_long max_length;
+  pcap_pkt *max;
+  pcap_pkt *pkts;
+} pcap_pkts;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int check(u_int16_t *, int);
+u_int16_t checksum_carry(int);
+int prepare_pkts(char *, pcap_pkts *);
+void free_pkts(pcap_pkts *);
+#ifdef __cplusplus
+}
+#endif
+#endif /* PREPARE_PCAP_H */
diff --git a/.svn/pristine/1d/1d1031ec6d2ea227dd27301dfbba52c309470380.svn-base b/.svn/pristine/1d/1d1031ec6d2ea227dd27301dfbba52c309470380.svn-base
new file mode 100644 (file)
index 0000000..ba89585
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Author : Richard GAYRAUD - 04 Nov 2003
+ *           From Hewlett Packard Company.
+ *          Charles P. Wright from IBM Research
+ */
+#ifndef __LISTENER__
+#define __LISTENER__
+
+#include <map>
+#include <iterator>
+#include <list>
+#include <sys/types.h>
+#include <string.h>
+#include <assert.h>
+
+#include "sipp.hpp"
+
+class listener {
+public:
+  listener(char *id, bool listening);
+  virtual ~listener();
+  char *getId();
+  virtual bool process_incoming(char * msg, struct sockaddr_storage *src) = 0;
+  virtual bool process_twinSippCom(char * msg) = 0;
+
+protected:
+  void startListening();
+  void stopListening();
+
+  char *id;
+  bool listening;
+};
+
+typedef std::map<std::string, listener *> listener_map;
+listener * get_listener(char *);
+
+#endif
diff --git a/.svn/pristine/1e/1e8c026bba4efe969be5f1245e5a3bbaf72b5c32.svn-base b/.svn/pristine/1e/1e8c026bba4efe969be5f1245e5a3bbaf72b5c32.svn-base
new file mode 100644 (file)
index 0000000..3de84ba
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Copyright (C) 2003 - The Authors
+ *
+ *  Author : Richard GAYRAUD - 04 Nov 2003
+ *           From Hewlett Packard Company.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  char * comp_load();
+
+#ifndef COMP_MAIN
+  extern 
+#endif
+  int (*comp_compress) (void         ** state,
+                        char          * msg,
+                        unsigned int  * msg_len);
+  
+#ifndef COMP_MAIN
+  extern 
+#endif
+  int (*comp_uncompress) (void            ** state,
+                          char             * msg,
+                          unsigned int     * msg_len);
+
+#ifndef COMP_MAIN
+  extern 
+#endif
+
+  void (*comp_free) (void ** state);
+
+#ifndef COMP_MAIN
+  extern 
+#endif
+  char comp_error[255];
+
+#ifdef __hpux
+#define COMP_PLUGGIN "sippcomp.sl"
+#else
+#define COMP_PLUGGIN "sippcomp.so"
+#endif
+
+#define COMP_OK       0
+#define COMP_DISCARD  1
+#define COMP_REPLY    2
+
+#define COMP_KO      -1
+  
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/.svn/pristine/20/20ae0b6f9bff8bfc53ec4ed44a5235fe5d4d5acd.svn-base b/.svn/pristine/20/20ae0b6f9bff8bfc53ec4ed44a5235fe5d4d5acd.svn-base
new file mode 100644 (file)
index 0000000..12c4a6c
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Author : Gundu RAO - 16 Jul 2004
+ *           From Hewlett Packard Company.
+ */
+#ifndef _ccnv_2_common_h_H
+#define _ccnv_2_common_h_H
+
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
+#include <openssl/x509v3.h>
+#include <pthread.h>
+
+#define MUTEX_TYPE pthread_mutex_t
+#define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
+#define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
+#define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
+#define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
+#define THREAD_ID pthread_self( )
+
+/*
+**      Define a global variable for the SSL context
+*/
+
+/* Initialises an SSL context and makes the lib thread safe */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SSL_MAIN
+  extern
+#endif
+  int init_OpenSSL(void);
+
+#ifndef SSL_MAIN
+  extern
+#endif
+  int Thread_setup(void);
+
+#ifndef SSL_MAIN
+  extern
+#endif
+  SSL_CTX *setup_ssl_context(SSL_METHOD *);
+
+#ifndef SSL_MAIN
+  extern
+#endif
+  int SSL_ERROR(void);
+
+#ifndef SSL_MAIN
+//  extern
+#endif
+//    int createAuthHeader(char * user, char * password, char * method, char * uri, char * msgbody, char * auth, char * result);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/.svn/pristine/23/23b51a463d005c6a70c78a3d9bb1f1ec916638bc.svn-base b/.svn/pristine/23/23b51a463d005c6a70c78a3d9bb1f1ec916638bc.svn-base
new file mode 100644 (file)
index 0000000..4e728a5
--- /dev/null
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------
+ *          Example algorithms f1, f1*, f2, f3, f4, f5, f5*
+ *-------------------------------------------------------------------
+ *
+ *  A sample implementation of the example 3GPP authentication and
+ *  key agreement functions f1, f1*, f2, f3, f4, f5 and f5*.  This is
+ *  a byte-oriented implementation of the functions, and of the block
+ *  cipher kernel function Rijndael.
+ *
+ *  This has been coded for clarity, not necessarily for efficiency.
+ *
+ *  The functions f2, f3, f4 and f5 share the same inputs and have
+ *  been coded together as a single function.  f1, f1* and f5* are
+ *  all coded separately.
+ *
+ *-----------------------------------------------------------------*/
+
+#ifndef RIJNDAEL_H
+#define RIJNDAEL_H
+
+
+void RijndaelKeySchedule( u8 key[16] );
+void RijndaelEncrypt( u8 input[16], u8 output[16] );
+
+
+#endif
diff --git a/.svn/pristine/24/24e5b54ca002bf58b50c4cfe5b1b4e07cdce3551.svn-base