[tools] / trunk / publicdemo / sipp / sipp.cpp Repository:
ViewVC logotype

View of /trunk/publicdemo/sipp/sipp.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 70 - (download) (annotate)
Thu May 5 20:35:33 2011 UTC (2 years ago) by jhermanski
File size: 149198 byte(s)
Package all media, etc. needed for Public demo system into one tree
    1 /*
    2  *  This program is free software; you can redistribute it and/or modify
    3  *  it under the terms of the GNU General Public License as published by
    4  *  the Free Software Foundation; either version 2 of the License, or
    5  *  (at your option) any later version.
    6  *
    7  *  This program is distributed in the hope that it will be useful,
    8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10  *  GNU General Public License for more details.
   11  *
   12  *  You should have received a copy of the GNU General Public License
   13  *  along with this program; if not, write to the Free Software
   14  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   15  *
   16  *  Author : Richard GAYRAUD - 04 Nov 2003
   17  *           Marc LAMBERTON
   18  *           Olivier JACQUES
   19  *           Herve PELLAN
   20  *           David MANSUTTI
   21  *           Francois-Xavier Kowalski
   22  *           Gerard Lyonnaz
   23  *           From Hewlett Packard Company.
   24  *           F. Tarek Rogers
   25  *           Peter Higginson
   26  *           Vincent Luba
   27  *           Shriram Natarajan
   28  *           Guillaume Teissier from FTR&D
   29  *           Clement Chen
   30  *           Wolfgang Beck
   31  *           Charles P Wright from IBM Research
   32  */
   33 
   34 #define GLOBALS_FULL_DEFINITION
   35 
   36 #include "sipp.hpp"
   37 #include "assert.h"
   38 
   39 #ifdef _USE_OPENSSL
   40 SSL_CTX  *sip_trp_ssl_ctx = NULL; /* For SSL cserver context */
   41 SSL_CTX  *sip_trp_ssl_ctx_client = NULL; /* For SSL cserver context */
   42 SSL_CTX  *twinSipp_sip_trp_ssl_ctx_client = NULL; /* For SSL cserver context */
   43 
   44 enum ssl_init_status {
   45   SSL_INIT_NORMAL, /* 0   Normal completion    */
   46   SSL_INIT_ERROR   /* 1   Unspecified error    */
   47 };
   48 
   49 #define CALL_BACK_USER_DATA "ksgr"
   50 
   51 int passwd_call_back_routine(char  *buf , int size , int flag, void *passwd)
   52 {
   53   strncpy(buf, (char *)(passwd), size);
   54   buf[size - 1] = '\0';
   55   return(strlen(buf));
   56 }
   57 #endif
   58 
   59 /* These could be local to main, but for the option processing table. */
   60 static int argiFileName;
   61 
   62 /***************** Option Handling Table *****************/
   63 struct sipp_option {
   64   const char *option;
   65   const char *help;
   66   int type;
   67   void *data;
   68   /* Pass 0: Help and other options that should exit immediately. */
   69   /* Pass 1: All other options. */
   70   /* Pass 2: Scenario parsing. */
   71   int pass;
   72 };
   73 
   74 #define SIPP_OPTION_HELP     1
   75 #define SIPP_OPTION_INT      2
   76 #define SIPP_OPTION_SETFLAG    3
   77 #define SIPP_OPTION_UNSETFLAG    4
   78 #define SIPP_OPTION_STRING     5
   79 #define SIPP_OPTION_ARGI     6
   80 #define SIPP_OPTION_TIME_SEC     7
   81 #define SIPP_OPTION_FLOAT    8
   82 #define SIPP_OPTION_BOOL    10
   83 #define SIPP_OPTION_VERSION   11
   84 #define SIPP_OPTION_TRANSPORT   12
   85 #define SIPP_OPTION_NEED_SSL    13
   86 #define SIPP_OPTION_IP      14
   87 #define SIPP_OPTION_MAX_SOCKET    15
   88 #define SIPP_OPTION_CSEQ    16
   89 #define SIPP_OPTION_SCENARIO    17
   90 #define SIPP_OPTION_RSA     18
   91 #define SIPP_OPTION_LIMIT   19
   92 #define SIPP_OPTION_USERS   20
   93 #define SIPP_OPTION_KEY     21
   94 #define SIPP_OPTION_3PCC    22
   95 #define SIPP_OPTION_TDMMAP    23
   96 #define SIPP_OPTION_TIME_MS   24
   97 #define SIPP_OPTION_SLAVE_CFG     25
   98 #define SIPP_OPTION_3PCC_EXTENDED 26
   99 #define SIPP_OPTION_INPUT_FILE    27
  100 #define SIPP_OPTION_TIME_MS_LONG  28
  101 #define SIPP_OPTION_LONG          29
  102 /* Put Each option, its help text, and type in this table. */
  103 struct sipp_option options_table[] = {
  104   {"v", "Display version and copyright information.", SIPP_OPTION_VERSION, NULL, 0},
  105 
  106   {"h", NULL, SIPP_OPTION_HELP, NULL, 0},
  107   {"help", NULL, SIPP_OPTION_HELP, NULL, 0},
  108 
  109   {"aa", "Enable automatic 200 OK answer for INFO, UPDATE and NOTIFY messages.", SIPP_OPTION_SETFLAG, &auto_answer, 1},
  110 #ifdef _USE_OPENSSL
  111   {"auth_uri", "Force the value of the URI for authentication.\n"
  112                      "By default, the URI is composed of remote_ip:remote_port.", SIPP_OPTION_STRING, &auth_uri, 1},
  113 #else
  114   {"auth_uri", NULL, SIPP_OPTION_NEED_SSL, NULL, 1},
  115 #endif
  116 
  117   {"base_cseq", "Start value of [cseq] for each call.", SIPP_OPTION_CSEQ, NULL, 1},
  118   {"bg", "Launch SIPp in background mode.", SIPP_OPTION_SETFLAG, &backgroundMode, 1},
  119   {"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},
  120   {"buff_size", "Set the send and receive buffer size.", SIPP_OPTION_INT, &buff_size, 1},
  121 
  122   {"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},
  123   {"cp", "Set the local control port number. Default is 8888.", SIPP_OPTION_INT, &control_port, 1},
  124 
  125   {"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},
  126 
  127   {"f", "Set the statistics report frequency on screen. Default is 1 and default unit is seconds.", SIPP_OPTION_TIME_SEC, &report_freq, 1},
  128   {"fd", "Set the statistics dump log report frequency. Default is 60 and default unit is seconds.", SIPP_OPTION_TIME_SEC, &report_freq_dumpLog, 1},
  129 
  130   {"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},
  131   {"inf", "Inject values from an external CSV file during calls into the scenarios.\n"
  132                 "First line of this file say whether the data is to be read in sequence (SEQUENTIAL) or random (RANDOM) order.\n"
  133     "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.", SIPP_OPTION_INPUT_FILE, NULL, 1},
  134   {"ip_field", "Set which field from the injection file contains the IP address from which the client will send its messages.\n"
  135                      "If this option is omitted and the '-t ui' option is present, then field 0 is assumed.\n"
  136          "Use this option together with '-t ui'", SIPP_OPTION_INT, &peripfield, 1},
  137 
  138   {"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"
  139         "  (3 * call_duration (s) * rate).", SIPP_OPTION_LIMIT, NULL, 1},
  140 
  141   {"lost", "Set the number of packets to lose by default (scenario specifications override this value).", SIPP_OPTION_FLOAT, &global_lost, 1},
  142   {"m", "Stop the test and exit when 'calls' calls are processed", SIPP_OPTION_LONG, &stop_after, 1},
  143   {"mi", "Set the local media IP address", SIPP_OPTION_IP, media_ip, 1},
  144         {"master","3pcc extended mode: indicates the master number", SIPP_OPTION_3PCC_EXTENDED, &master_name, 1},
  145   {"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},
  146   {"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},
  147   {"max_reconnect", "Set the the maximum number of reconnection.", SIPP_OPTION_INT, &reset_number, 1},
  148   {"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},
  149   {"max_invite_retrans", "Maximum number of UDP retransmissions for invite transactions before call ends on timeout.", SIPP_OPTION_INT, &max_invite_retrans, 1},
  150   {"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},
  151   {"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},
  152 
  153   {"mb", "Set the RTP echo buffer size (default: 2048).", SIPP_OPTION_INT, &media_bufsize, 1},
  154   {"mp", "Set the local RTP echo port number. Default is 6000.", SIPP_OPTION_INT, &user_media_port, 1},
  155 
  156   {"nd", "No Default. Disable all default behavior of SIPp which are the following:\n"
  157           "- On UDP retransmission timeout, abort the call by sending a BYE or a CANCEL\n"
  158           "- On receive timeout with no ontimeout attribute, abort the call by sending a BYE or a CANCEL\n"
  159           "- On unexpected BYE send a 200 OK and close the call\n"
  160           "- On unexpected CANCEL send a 200 OK and close the call\n"
  161           "- On unexpected PING send a 200 OK and continue the call\n"
  162           "- On any other unexpected message, abort the call by sending a BYE or a CANCEL\n",
  163     SIPP_OPTION_UNSETFLAG, &default_behavior, 1},
  164   {"nr", "Disable retransmission in UDP mode.", SIPP_OPTION_UNSETFLAG, &retrans_enabled, 1},
  165 
  166   {"p", "Set the local port number.  Default is a random free port chosen by the system.", SIPP_OPTION_INT, &user_port, 1},
  167   {"pause_msg_ign", "Ignore the messages received during a pause defined in the scenario ", SIPP_OPTION_SETFLAG, &pause_msg_ign, 1},
  168 
  169   {"r", "Set the call rate (in calls per seconds).  This value can be"
  170         "changed during test by pressing '+','_','*' or '/'. Default is 10.\n"
  171         "pressing '+' key to increase call rate by 1,\n"
  172               "pressing '-' key to decrease call rate by 1,\n"
  173               "pressing '*' key to increase call rate by 10,\n"
  174               "pressing '/' key to decrease call rate by 10.\n"
  175               "If the -rp option is used, the call rate is calculated with the period in ms given by the user.", SIPP_OPTION_FLOAT, &rate},
  176   {"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"
  177                "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},
  178   {"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"
  179                       "Example: -rate_increase 10 -fd 10s\n"
  180                       "  ==> increase calls by 10 every 10 seconds.", SIPP_OPTION_INT, &rate_increase, 1},
  181   {"rate_max", "If -rate_increase is set, then quit after the rate reaches this value.\n"
  182                       "Example: -rate_increase 10 -rate_max 100\n"
  183                       "  ==> increase calls by 10 until 100 cps is hit.", SIPP_OPTION_INT, &rate_max, 1},
  184   {"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},
  185   {"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},
  186   {"reconnect_close", "Should calls be closed on reconnect?", SIPP_OPTION_BOOL, &reset_close, 1},
  187   {"reconnect_sleep", "How long (in milliseconds) to sleep between the close and reconnect?", SIPP_OPTION_TIME_MS, &reset_sleep, 1},
  188   {"rsa", "Set the remote sending address to host:port for sending the messages.", SIPP_OPTION_RSA, NULL, 1},
  189   {"rtp_echo", "Enable RTP echo. RTP/UDP packets received on port defined by -mp are echoed to their sender.\n"
  190                      "RTP/UDP packets coming on this port + 2 are also echoed to their sender (used for sound and video echo).",
  191          SIPP_OPTION_SETFLAG, &rtp_echo_enabled, 1},
  192   {"rtt_freq", "freq is mandatory. Dump response times every freq calls in the log file defined by -trace_rtt. Default value is 200.",
  193          SIPP_OPTION_LONG, &report_freq_dumpRtt, 1},
  194   {"s", "Set the username part of the resquest URI. Default is 'service'.", SIPP_OPTION_STRING, &service, 1},
  195   {"sd", "Dumps a default scenario (embeded in the sipp executable)", SIPP_OPTION_SCENARIO, NULL, 0},
  196   {"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},
  197   {"slave", "3pcc extended mode: indicates the slave number", SIPP_OPTION_3PCC_EXTENDED, &slave_number, 1},
  198   {"slave_cfg", "3pcc extended mode: indicates the file where the master and slave addresses are stored", SIPP_OPTION_SLAVE_CFG, NULL, 1},
  199   {"sn", "Use a default scenario (embedded in the sipp executable). If this option is omitted, the Standard SipStone UAC scenario is loaded.\n"
  200                "Available values in this version:\n\n"
  201                "- 'uac'      : Standard SipStone UAC (default).\n"
  202                "- 'uas'      : Simple UAS responder.\n"
  203                "- 'regexp'   : Standard SipStone UAC - with regexp and variables.\n"
  204                "- 'branchc'  : Branching and conditional branching in scenarios - client.\n"
  205                "- 'branchs'  : Branching and conditional branching in scenarios - server.\n\n"
  206                "Default 3pcc scenarios (see -3pcc option):\n\n"
  207                "- '3pcc-C-A' : Controller A side (must be started after all other 3pcc scenarios)\n"
  208                "- '3pcc-C-B' : Controller B side.\n"
  209                "- '3pcc-A'   : A side.\n"
  210                "- '3pcc-B'   : B side.\n", SIPP_OPTION_SCENARIO, NULL, 2},
  211 
  212   {"stat_delimiter", "Set the delimiter for the statistics file", SIPP_OPTION_STRING, &stat_delimiter, 1},
  213   {"stf", "Set the file name to use to dump statistics", SIPP_OPTION_ARGI, &argiFileName, 1},
  214 
  215   {"t", "Set the transport mode:\n"
  216               "- u1: UDP with one socket (default),\n"
  217               "- un: UDP with one socket per call,\n"
  218               "- ui: UDP with one socket per IP address The IP addresses must be defined in the injection file.\n"
  219               "- t1: TCP with one socket,\n"
  220               "- tn: TCP with one socket per call,\n"
  221               "- l1: TLS with one socket,\n"
  222               "- ln: TLS with one socket per call,\n"
  223               "- c1: u1 + compression (only if compression plugin loaded),\n"
  224               "- cn: un + compression (only if compression plugin loaded).\n"
  225         , SIPP_OPTION_TRANSPORT, NULL, 1},
  226 
  227   {"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},
  228   {"timer_resol", "Set the timer resolution. Default unit is milliseconds.  This option has an impact on timers precision."
  229                       "Small values allow more precise scheduling but impacts CPU usage."
  230                       "If the compression is on, the value is set to 50ms. The default value is 10ms.", SIPP_OPTION_TIME_MS, &timer_resolution, 1},
  231   {"trace_msg", "Displays sent and received SIP messages in <scenario file name>_<pid>_messages.log", SIPP_OPTION_SETFLAG, &useMessagef, 1},
  232   {"trace_shortmsg", "Displays sent and received SIP messages as CSV in <scenario file name>_<pid>_shortmessages.log", SIPP_OPTION_SETFLAG, &useShortMessagef, 1},
  233   {"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},
  234   {"trace_err", "Trace all unexpected messages in <scenario file name>_<pid>_errors.log.", SIPP_OPTION_SETFLAG, &print_all_responses, 1},
  235 //  {"trace_timeout", "Displays call ids for calls with timeouts in <scenario file name>_<pid>_timeout.log", SIPP_OPTION_SETFLAG, &useTimeoutf, 1},
  236   {"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},
  237   {"trace_rtt", "Allow tracing of all response times in <scenario file name>_<pid>_rtt.csv.", SIPP_OPTION_SETFLAG, &dumpInRtt, 1},
  238   {"trace_logs", "Allow tracing of <log> actions in <scenario file name>_<pid>_logs.log.", SIPP_OPTION_SETFLAG, &useLogf, 1},
  239 
  240   {"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},
  241 
  242 #ifdef _USE_OPENSSL
  243   {"ap", "Set the password for authentication challenges. Default is 'password", SIPP_OPTION_STRING, &auth_password, 1},
  244   {"tls_cert", "Set the name for TLS Certificate file. Default is 'cacert.pem", SIPP_OPTION_STRING, &tls_cert_name, 1},
  245   {"tls_key", "Set the name for TLS Private Key file. Default is 'cakey.pem'", SIPP_OPTION_STRING, &tls_key_name, 1},
  246   {"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},
  247 #else
  248   {"ap", NULL, SIPP_OPTION_NEED_SSL, NULL, 1},
  249   {"tls_cert", NULL, SIPP_OPTION_NEED_SSL, NULL, 1},
  250   {"tls_key", NULL, SIPP_OPTION_NEED_SSL, NULL, 1},
  251   {"tls_crl", NULL, SIPP_OPTION_NEED_SSL, NULL, 1},
  252 #endif
  253 #ifdef __3PCC__
  254   {"3pcc", "Launch the tool in 3pcc mode (\"Third Party call control\"). The passed ip address is depending on the 3PCC role.\n"
  255                  "- 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"
  256                  "    Example: 3PCC-C-A scenario.\n"
  257                  "- 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"
  258      "    Example: 3PCC-C-B scenario.", SIPP_OPTION_3PCC, NULL, 1},
  259 #endif
  260   {"tdmmap", "Generate and handle a table of TDM circuits.\n"
  261                    "A circuit must be available for the call to be placed.\n"
  262                    "Format: -tdmmap {0-3}{99}{5-8}{1-31}", SIPP_OPTION_TDMMAP, NULL, 1},
  263   {"key", "keyword value\nSet the generic parameter named \"keyword\" to \"value\".", SIPP_OPTION_KEY, NULL, 1},
  264 };
  265 
  266 struct sipp_option *find_option(const char *option) {
  267   int i;
  268   int max = sizeof(options_table)/sizeof(options_table[0]);
  269 
  270   /* Allow options to start with '-' or '--' */
  271   if (option[0] != '-') {
  272     return NULL;
  273   }
  274   option++;
  275   if (option[0] == '-') {
  276     option++;
  277   }
  278 
  279   for (i = 0; i < max; i++) {
  280     if (!strcmp(options_table[i].option, option)) {
  281       return &(options_table[i]);
  282     }
  283   }
  284 
  285   return NULL;
  286 };
  287 
  288 /***************** System Portability Features *****************/
  289 
  290 unsigned long long getmicroseconds()
  291 {
  292   struct timeval LS_system_time;
  293   unsigned long long VI_micro;
  294   static unsigned long long VI_micro_base = 0;
  295 
  296   gettimeofday(&LS_system_time, NULL);
  297   VI_micro = (((unsigned long long) LS_system_time.tv_sec) * 1000000LL) + LS_system_time.tv_usec;
  298   if (!VI_micro_base) VI_micro_base = VI_micro - 1;
  299   VI_micro = VI_micro - VI_micro_base;
  300 
  301   return VI_micro;
  302 }
  303 
  304 unsigned long getmilliseconds()
  305 {
  306   return getmicroseconds() / 1000LL;
  307 }
  308 
  309 
  310 #ifdef _USE_OPENSSL
  311 /****** SSL error handling                         *************/
  312 const char *sip_tls_error_string(SSL *ssl, int size) {
  313   int err;
  314   err=SSL_get_error(ssl, size);
  315   switch(err) {
  316     case SSL_ERROR_NONE:
  317       return "No error";
  318     case SSL_ERROR_WANT_WRITE:
  319       return "SSL_read returned SSL_ERROR_WANT_WRITE";
  320     case SSL_ERROR_WANT_READ:
  321       return "SSL_read returned SSL_ERROR_WANT_READ";
  322     case SSL_ERROR_WANT_X509_LOOKUP:
  323       return "SSL_read returned SSL_ERROR_WANT_X509_LOOKUP";
  324       break;
  325     case SSL_ERROR_SYSCALL:
  326       if(size<0) { /* not EOF */
  327   return strerror(errno);
  328       } else { /* EOF */
  329         return "SSL socket closed on SSL_read";
  330       }
  331   }
  332   return "Unknown SSL Error.";
  333 }
  334 
  335 /****** Certificate Verification Callback FACILITY *************/
  336 int sip_tls_verify_callback(int ok , X509_STORE_CTX *store)
  337 {
  338   char data[512];
  339 
  340   if (!ok) {
  341      X509 *cert = X509_STORE_CTX_get_current_cert(store);
  342 
  343      X509_NAME_oneline(X509_get_issuer_name(cert),
  344                                    data,512);
  345      WARNING_P1("TLS verification error for issuer: '%s'", data);
  346      X509_NAME_oneline(X509_get_subject_name(cert),
  347                                    data,512);
  348      WARNING_P1("TLS verification error for subject: '%s'", data);
  349   }
  350   return ok;
  351 }
  352 
  353 /***********  Load the CRL's into SSL_CTX **********************/
  354 int sip_tls_load_crls( SSL_CTX *ctx , char *crlfile)
  355 {
  356   X509_STORE          *store;
  357   X509_LOOKUP         *lookup;
  358 
  359   /*  Get the X509_STORE from SSL context */
  360   if (!(store = SSL_CTX_get_cert_store(ctx))) {
  361     return (-1);
  362   }
  363 
  364   /* Add lookup file to X509_STORE */
  365   if (!(lookup = X509_STORE_add_lookup(store,X509_LOOKUP_file()))) {
  366     return (-1);
  367   }
  368 
  369   /* Add the CRLS to the lookpup object */
  370   if (X509_load_crl_file(lookup,crlfile,X509_FILETYPE_PEM) != 1) {
  371     return (-1);
  372   }
  373 
  374   /* Set the flags of the store so that CRLS's are consulted */
  375 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
  376   X509_STORE_set_flags( store,X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
  377 #else
  378 #warning This version of OpenSSL (<0.9.7) cannot handle CRL files in capath
  379   ERROR("This version of OpenSSL (<0.9.7) cannot handle CRL files in capath");
  380 #endif
  381 
  382   return (1);
  383 }
  384 
  385 /************* Prepare the SSL context ************************/
  386 static ssl_init_status FI_init_ssl_context (void)
  387 {
  388   sip_trp_ssl_ctx = SSL_CTX_new( TLSv1_method() );
  389   if ( sip_trp_ssl_ctx == NULL ) {
  390     ERROR("FI_init_ssl_context: SSL_CTX_new with TLSv1_method failed");
  391     return SSL_INIT_ERROR;
  392   }
  393 
  394   sip_trp_ssl_ctx_client = SSL_CTX_new( TLSv1_method() );
  395   if ( sip_trp_ssl_ctx_client == NULL)
  396   {
  397     ERROR("FI_init_ssl_context: SSL_CTX_new with TLSv1_method failed");
  398     return SSL_INIT_ERROR;
  399   }
  400 
  401   /*  Load the trusted CA's */
  402   SSL_CTX_load_verify_locations(sip_trp_ssl_ctx, tls_cert_name, NULL);
  403   SSL_CTX_load_verify_locations(sip_trp_ssl_ctx_client, tls_cert_name, NULL);
  404 
  405   /*  CRL load from application specified only if specified on the command line */
  406   if (strlen(tls_crl_name) != 0) {
  407     if(sip_tls_load_crls(sip_trp_ssl_ctx,tls_crl_name) == -1) {
  408       ERROR_P1("FI_init_ssl_context: Unable to load CRL file (%s)", tls_crl_name);
  409       return SSL_INIT_ERROR;
  410     }
  411 
  412     if(sip_tls_load_crls(sip_trp_ssl_ctx_client,tls_crl_name) == -1) {
  413       ERROR_P1("FI_init_ssl_context: Unable to load CRL (client) file (%s)", tls_crl_name);
  414       return SSL_INIT_ERROR;
  415     }
  416     /* The following call forces to process the certificates with the */
  417     /* initialised SSL_CTX                                            */
  418     SSL_CTX_set_verify(sip_trp_ssl_ctx,
  419                        SSL_VERIFY_PEER |
  420                        SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
  421                        sip_tls_verify_callback);
  422 
  423     SSL_CTX_set_verify(sip_trp_ssl_ctx_client,
  424                        SSL_VERIFY_PEER |
  425                        SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
  426                        sip_tls_verify_callback);
  427   }
  428 
  429 
  430   /* Selection Cipher suits - load the application specified ciphers */
  431   SSL_CTX_set_default_passwd_cb_userdata(sip_trp_ssl_ctx,
  432                                              (void *)CALL_BACK_USER_DATA );
  433   SSL_CTX_set_default_passwd_cb_userdata(sip_trp_ssl_ctx_client,
  434                                              (void *)CALL_BACK_USER_DATA );
  435   SSL_CTX_set_default_passwd_cb( sip_trp_ssl_ctx,
  436                                              passwd_call_back_routine );
  437   SSL_CTX_set_default_passwd_cb( sip_trp_ssl_ctx_client,
  438                                              passwd_call_back_routine );
  439 
  440   if ( SSL_CTX_use_certificate_file(sip_trp_ssl_ctx,
  441                                         tls_cert_name,
  442                                         SSL_FILETYPE_PEM ) != 1 ) {
  443     ERROR("FI_init_ssl_context: SSL_CTX_use_certificate_file failed");
  444     return SSL_INIT_ERROR;
  445   }
  446 
  447   if ( SSL_CTX_use_certificate_file(sip_trp_ssl_ctx_client,
  448                                         tls_cert_name,
  449                                         SSL_FILETYPE_PEM ) != 1 ) {
  450     ERROR("FI_init_ssl_context: SSL_CTX_use_certificate_file (client) failed");
  451     return SSL_INIT_ERROR;
  452   }
  453   if ( SSL_CTX_use_PrivateKey_file(sip_trp_ssl_ctx,
  454                                        tls_key_name,
  455                                        SSL_FILETYPE_PEM ) != 1 ) {
  456     ERROR("FI_init_ssl_context: SSL_CTX_use_PrivateKey_file failed");
  457     return SSL_INIT_ERROR;
  458   }
  459 
  460   if ( SSL_CTX_use_PrivateKey_file(sip_trp_ssl_ctx_client,
  461                                        tls_key_name,
  462                                        SSL_FILETYPE_PEM ) != 1 ) {
  463     ERROR("FI_init_ssl_context: SSL_CTX_use_PrivateKey_file (client) failed");
  464     return SSL_INIT_ERROR;
  465   }
  466 
  467   return SSL_INIT_NORMAL;
  468 }
  469 
  470 int send_nowait_tls(SSL *ssl, const void *msg, int len, int flags)
  471 {
  472   int initial_fd_flags;
  473   int rc;
  474   int fd;
  475   int fd_flags;
  476   if ( (fd = SSL_get_fd(ssl)) == -1 ) {
  477     return (-1);
  478   }
  479   fd_flags = fcntl(fd, F_GETFL , NULL);
  480   initial_fd_flags = fd_flags;
  481   fd_flags |= O_NONBLOCK;
  482   fcntl(fd, F_SETFL , fd_flags);
  483   rc = SSL_write(ssl,msg,len);
  484   if ( rc <= 0 ) {
  485     return(rc);
  486   }
  487   fcntl(fd, F_SETFL , initial_fd_flags);
  488   return rc;
  489 }
  490 #endif
  491 
  492 int send_nowait(int s, const void *msg, int len, int flags)
  493 {
  494 #if defined(MSG_DONTWAIT) && !defined(__SUNOS)
  495   return send(s, msg, len, flags | MSG_DONTWAIT);
  496 #else
  497   int fd_flags = fcntl(s, F_GETFL , NULL);
  498   int initial_fd_flags;
  499   int rc;
  500 
  501   initial_fd_flags = fd_flags;
  502   //  fd_flags &= ~O_ACCMODE; // Remove the access mode from the value
  503   fd_flags |= O_NONBLOCK;
  504   fcntl(s, F_SETFL , fd_flags);
  505 
  506   rc = send(s, msg, len, flags);
  507 
  508   fcntl(s, F_SETFL , initial_fd_flags);
  509 
  510   return rc;
  511 #endif
  512 }
  513 
  514 char * get_inet_address(struct sockaddr_storage * addr)
  515 {
  516   static char * ip_addr = NULL;
  517 
  518   if (!ip_addr) {
  519     ip_addr = (char *)malloc(1024*sizeof(char));
  520   }
  521   if (getnameinfo(_RCAST(struct sockaddr *, addr),
  522                   SOCK_ADDR_SIZE(addr),
  523                   ip_addr,
  524                   1024,
  525                   NULL,
  526                   0,
  527                   NI_NUMERICHOST) != 0) {
  528     strcpy(ip_addr, "addr not supported");
  529   }
  530 
  531   return ip_addr;
  532 }
  533 
  534 void get_host_and_port(char * addr, char * host, int * port)
  535 {
  536   /* Separate the port number (if any) from the host name.
  537    * Thing is, the separator is a colon (':').  The colon may also exist
  538    * in the host portion if the host is specified as an IPv6 address (see
  539    * RFC 2732).  If that's the case, then we need to skip past the IPv6
  540    * address, which should be contained within square brackets ('[',']').
  541    */
  542   char *p;
  543   p = strchr( addr, '[' );                      /* Look for '['.            */
  544   if( p != NULL ) {                             /* If found, look for ']'.  */
  545     p = strchr( p, ']' );
  546   }
  547   if( p == NULL ) {                             /* If '['..']' not found,   */
  548     p = addr;                                   /* scan the whole string.   */
  549   } else {                                      /* If '['..']' found,       */
  550     char *p1;                                   /* extract the remote_host  */
  551     char *p2;
  552     p1 = strchr( addr, '[' );
  553     p2 = strchr( addr, ']' );
  554     *p2 = '\0';
  555     strcpy(host, p1 + 1);
  556     *p2 = ']';
  557   }
  558   /* Starting at <p>, which is either the start of the host substring
  559    * or the end of the IPv6 address, find the last colon character.
  560    */
  561   p = strchr( p, ':' );
  562   if( NULL != p ) {
  563     *p = '\0';
  564     *port = atol(p + 1);
  565   } else {
  566     *port = 0;
  567   }
  568 }
  569 
  570 static unsigned char tolower_table[256];
  571 
  572 void init_tolower_table() {
  573   for (int i = 0; i < 256; i++) {
  574     tolower_table[i] = tolower(i);
  575   }
  576 }
  577 
  578 /* This is simpler than doing a regular tolower, because there are no branches.
  579  * We also inline it, so that we don't have function call overheads.
  580  *
  581  * An alternative to a table would be to do (c | 0x20), but that only works if
  582  * we are sure that we are searching for characters (or don't care if they are
  583  * not characters. */
  584 unsigned char inline mytolower(unsigned char c) {
  585   return tolower_table[c];
  586 }
  587 
  588 char * strcasestr2(char *s, char *find) {
  589   char c, sc;
  590   size_t len;
  591 
  592   if ((c = *find++) != 0) {
  593     c = mytolower((unsigned char)c);
  594     len = strlen(find);
  595     do {
  596       do {
  597         if ((sc = *s++) == 0)
  598         return (NULL);
  599       } while ((char)mytolower((unsigned char)sc) != c);
  600     } while (strncasecmp(s, find, len) != 0);
  601     s--;
  602   }
  603   return ((char *)s);
  604 }
  605 
  606 char * strncasestr(char *s, char *find, size_t n) {
  607   char *end = s + n;
  608   char c, sc;
  609   size_t len;
  610 
  611   if ((c = *find++) != 0) {
  612     c = mytolower((unsigned char)c);
  613     len = strlen(find);
  614     end -= (len - 1);
  615     do {
  616       do {
  617         if ((sc = *s++) == 0)
  618     return (NULL);
  619   if (s >= end)
  620     return (NULL);
  621       } while ((char)mytolower((unsigned char)sc) != c);
  622     } while (strncasecmp(s, find, len) != 0);
  623     s--;
  624   }
  625   return ((char *)s);
  626 }
  627 
  628 int get_decimal_from_hex(char hex) {
  629   if (isdigit(hex))
  630     return hex - '0';
  631   else
  632     return tolower(hex) - 'a' + 10;
  633 }
  634 
  635 
  636 /******************** Recv Poll Processing *********************/
  637 
  638 int                  pollnfds;
  639 unsigned int       call_sockets;
  640 struct pollfd        pollfiles[SIPP_MAXFDS];
  641 struct sipp_socket  *sockets[SIPP_MAXFDS];
  642 
  643 static int pending_messages = 0;
  644 
  645 map<string, struct sipp_socket *>     map_perip_fd;
  646 
  647 /***************** Check of the message received ***************/
  648 
  649 bool sipMsgCheck (const char *P_msg, int P_msgSize, struct sipp_socket *socket) {
  650   const char C_sipHeader[] = "SIP/2.0" ;
  651 
  652   if (socket == twinSippSocket || socket == localTwinSippSocket ||
  653       is_a_peer_socket(socket) || is_a_local_socket(socket))
  654   return true;
  655 
  656   if (strstr(P_msg, C_sipHeader) !=  NULL) {
  657     return true ;
  658   }
  659 
  660   return false ;
  661 }
  662 
  663 /************** Statistics display & User control *************/
  664 
  665 void print_stats_in_file(FILE * f, int last)
  666 {
  667   int index;
  668   static char temp_str[256];
  669   int divisor;
  670 
  671 #define SIPP_ENDL "\r\n"
  672 
  673   /* Optional timestamp line for files only */
  674   if(f != stdout) {
  675     time_t tim;
  676     time(&tim);
  677     fprintf(f, "  Timestamp: %s" SIPP_ENDL, ctime(&tim));
  678   }
  679 
  680   /* Header line with global parameters */
  681   sprintf(temp_str, "%3.1f(%d ms)/%5.3fs", rate, duration, (double)rate_period_ms / 1000.0);
  682   if( toolMode == MODE_SERVER) {
  683     fprintf
  684       (f,
  685        "  Port   Total-time  Total-calls  Transport"
  686        SIPP_ENDL
  687        "  %-5d %6d.%02d s     %8d  %s"
  688        SIPP_ENDL SIPP_ENDL,
  689        local_port,
  690        clock_tick / 1000, (clock_tick % 1000) / 10,
  691        total_calls,
  692        TRANSPORT_TO_STRING(transport));
  693   } else {
  694     fprintf
  695       (f,
  696        "  Call-rate(length)     Port   Total-time  Total-calls  Remote-host"
  697        SIPP_ENDL
  698        "%19s   %-5d %6d.%02d s     %8d  %s:%d(%s)"
  699        SIPP_ENDL SIPP_ENDL,
  700        temp_str,
  701        local_port,
  702        clock_tick / 1000, (clock_tick % 1000) / 10,
  703        total_calls,
  704        remote_ip,
  705        remote_port,
  706        TRANSPORT_TO_STRING(transport));
  707   }
  708 
  709   /* 1st line */
  710   if(total_calls < stop_after) {
  711     sprintf(temp_str, "%lu new calls during %lu.%03lu s period ",
  712             total_calls - last_report_calls,
  713             (clock_tick-last_report_time) / 1000,
  714             ((clock_tick-last_report_time) % 1000));
  715   } else {
  716     sprintf(temp_str, "Call limit reached (-m %lu), %lu.%03lu s period ",
  717             stop_after,
  718             (clock_tick-last_report_time) / 1000,
  719             ((clock_tick-last_report_time) % 1000));
  720   }
  721   divisor = scheduling_loops; if(!divisor) { divisor = 1; }
  722   fprintf(f,"  %-38s %d ms scheduler resolution"
  723          SIPP_ENDL,
  724          temp_str,
  725          (clock_tick-last_report_time) / divisor);
  726 
  727   /* 2nd line */
  728   if( toolMode == MODE_SERVER) {
  729     sprintf(temp_str, "%d calls", open_calls);
  730   } else {
  731     sprintf(temp_str, "%d calls (limit %d)", open_calls, open_calls_allowed);
  732   }
  733   fprintf(f,"  %-38s Peak was %d calls, after %d s" SIPP_ENDL,
  734          temp_str,
  735          open_calls_peak,
  736          open_calls_peak_time);
  737   fprintf(f,"  %d Running, %d Paused, %d Woken up" SIPP_ENDL,
  738    last_running_calls, last_paused_calls, last_woken_calls);
  739   last_woken_calls = 0;
  740 
  741   /* 3rd line (optional) */
  742   if( toolMode != MODE_SERVER) {
  743     sprintf(temp_str,"%d out-of-call msg (discarded)",
  744             nb_out_of_the_blue);
  745     fprintf(f,"  %-37s", temp_str);
  746   }
  747   if(compression) {
  748     fprintf(f,"  Comp resync: %d sent, %d recv" ,
  749            resynch_send, resynch_recv);
  750   }
  751   if(compression || (toolMode != MODE_SERVER)) {
  752     fprintf(f,SIPP_ENDL);
  753   }
  754 
  755   /* 4th line , sockets and optional errors */
  756   sprintf(temp_str,"%d open sockets",
  757           pollnfds);
  758   fprintf(f,"  %-38s", temp_str);
  759   if(nb_net_recv_errors || nb_net_send_errors || nb_net_cong) {
  760     fprintf(f,"  %d/%d/%d %s errors (send/recv/cong)" SIPP_ENDL,
  761            nb_net_send_errors,
  762            nb_net_recv_errors,
  763            nb_net_cong,
  764            TRANSPORT_TO_STRING(transport));
  765   } else {
  766     fprintf(f,SIPP_ENDL);
  767   }
  768 
  769 #ifdef PCAPPLAY
  770   /* if has media abilities */
  771   if (hasMedia != 0) {
  772     sprintf(temp_str, "%lu Total RTP pckts sent ",
  773             rtp_pckts_pcap);
  774     if (clock_tick-last_report_time) {
  775        fprintf(f,"  %-38s %d.%03d last period RTP rate (kB/s)" SIPP_ENDL,
  776               temp_str,
  777               (rtp_bytes_pcap)/(clock_tick-last_report_time),
  778               (rtp_bytes_pcap)%(clock_tick-last_report_time));
  779     }
  780     rtp_bytes_pcap = 0;
  781     rtp2_bytes_pcap = 0;
  782   }
  783 #endif
  784 
  785   /* 5th line, RTP echo statistics */
  786   if (rtp_echo_enabled && (media_socket > 0)) {
  787     sprintf(temp_str, "%lu Total echo RTP pckts 1st stream",
  788             rtp_pckts);
  789 
  790     // AComment: Fix for random coredump when using RTP echo
  791     if (clock_tick-last_report_time) {
  792        fprintf(f,"  %-38s %d.%03d last period RTP rate (kB/s)" SIPP_ENDL,
  793               temp_str,
  794               (rtp_bytes)/(clock_tick-last_report_time),
  795               (rtp_bytes)%(clock_tick-last_report_time));
  796     }
  797     /* second stream statitics: */
  798     sprintf(temp_str, "%lu Total echo RTP pckts 2nd stream",
  799             rtp2_pckts);
  800 
  801     // AComment: Fix for random coredump when using RTP echo
  802     if (clock_tick-last_report_time) {
  803       fprintf(f,"  %-38s %d.%03d last period RTP rate (kB/s)" SIPP_ENDL,
  804         temp_str,
  805         (rtp2_bytes)/(clock_tick-last_report_time),
  806         (rtp2_bytes)%(clock_tick-last_report_time));
  807     }
  808     rtp_bytes = 0;
  809     rtp2_bytes = 0;
  810   }
  811 
  812   /* Scenario counters */
  813   fprintf(f,SIPP_ENDL);
  814   if(!lose_packets) {
  815     fprintf(f,"                                 "
  816            "Messages  Retrans   Timeout   Unexpected-Msg"
  817            SIPP_ENDL);
  818   } else {
  819     fprintf(f,"                                 "
  820            "Messages  Retrans   Timeout   Unexp.    Lost"
  821            SIPP_ENDL);
  822   }
  823   for(index = 0;
  824       index < scenario_len;
  825       index ++) {
  826 
  827     if(SendingMessage *src = scenario[index] -> send_scheme) {
  828       if (src->isResponse()) {
  829   sprintf(temp_str, "%d", src->getCode());
  830       } else {
  831   sprintf(temp_str, "%s", src->getMethod());
  832       }
  833 
  834       if(toolMode == MODE_SERVER) {
  835         fprintf(f,"  <---------- %-10s ", temp_str);
  836       } else {
  837         fprintf(f,"  %10s ----------> ", temp_str);
  838       }
  839       if (scenario[index] -> start_rtd) {
  840   fprintf(f, " B-RTD%d ", scenario[index] -> start_rtd);
  841       } else if (scenario[index] -> stop_rtd) {
  842   fprintf(f, " E-RTD%d ", scenario[index] -> stop_rtd);
  843       } else {
  844   fprintf(f, "        ");
  845       }
  846 
  847       if(scenario[index] -> retrans_delay) {
  848         fprintf(f,"%-9d %-9d %-9d %-9s" ,
  849                scenario[index] -> nb_sent,
  850                scenario[index] -> nb_sent_retrans,
  851                scenario[index] -> nb_timeout,
  852                "" /* Unexpected */);
  853       } else {
  854         fprintf(f,"%-9d %-9d %-9s %-9s" ,
  855                scenario[index] -> nb_sent,
  856                scenario[index] -> nb_sent_retrans,
  857                "", /* Timeout. */
  858                "" /* Unexpected. */);
  859       }
  860     } else if(scenario[index] -> recv_response) {
  861       if(toolMode == MODE_SERVER) {
  862   fprintf(f,"  ----------> %-10d ", scenario[index] -> recv_response);
  863       } else {
  864   fprintf(f,"  %10d <---------- ", scenario[index] -> recv_response);
  865       }
  866 
  867       if (scenario[index] -> start_rtd) {
  868   fprintf(f, " B-RTD%d ", scenario[index] -> start_rtd);
  869       } else if (scenario[index] -> stop_rtd) {
  870   fprintf(f, " E-RTD%d ", scenario[index] -> stop_rtd);
  871       } else {
  872   fprintf(f, "        ");
  873       }
  874 
  875       if(scenario[index]->retrans_delay) {
  876         fprintf(f,"%-9ld %-9ld %-9ld %-9ld" ,
  877                scenario[index]->nb_recv,
  878                scenario[index]->nb_recv_retrans,
  879                scenario[index]->nb_timeout,
  880                scenario[index]->nb_unexp);
  881       } else {
  882         fprintf(f,"%-9ld %-9ld %-9ld %-9ld" ,
  883                scenario[index] -> nb_recv,
  884                scenario[index] -> nb_recv_retrans,
  885                scenario[index] -> nb_timeout,
  886                scenario[index] -> nb_unexp);
  887       }
  888     } else if (scenario[index] -> pause_distribution ||
  889          scenario[index] -> pause_variable) {
  890       char *desc = scenario[index]->pause_desc;
  891       if (!desc) {
  892   desc = (char *)malloc(24);
  893   if (scenario[index]->pause_distribution) {
  894     desc[0] = '\0';
  895     scenario[index]->pause_distribution->timeDescr(desc, 23);
  896   } else {
  897     snprintf(desc, 23, "$%d", scenario[index]->pause_variable);
  898   }
  899   desc[24] = '\0';
  900   scenario[index]->pause_desc = desc;
  901       }
  902       int len = strlen(desc) < 9 ? 9 : strlen(desc);
  903 
  904       if(toolMode == MODE_SERVER) {
  905   fprintf(f,"  [%9s] Pause%*s", desc, 23 - len > 0 ? 23 - len : 0, "");
  906       } else {
  907   fprintf(f,"       Pause [%9s]%*s", desc, 18 - len > 0 ? 18 - len : 0, "");
  908       }
  909 
  910       fprintf(f,"%-9d", scenario[index]->sessions);
  911       fprintf(f,"                     %-9d" , scenario[index]->nb_unexp);
  912     } else if(scenario[index] -> recv_request) {
  913       if(toolMode == MODE_SERVER) {
  914   fprintf(f,"  ----------> %-10s ", scenario[index] -> recv_request);
  915       } else {
  916   fprintf(f,"  %10s <---------- ", scenario[index] -> recv_request);
  917       }
  918 
  919       if (scenario[index] -> start_rtd) {
  920   fprintf(f, " B-RTD%d ", scenario[index] -> start_rtd);
  921       } else if (scenario[index] -> stop_rtd) {
  922   fprintf(f, " E-RTD%d ", scenario[index] -> stop_rtd);
  923       } else {
  924   fprintf(f, "        ");
  925       }
  926 
  927       fprintf(f,"%-9ld %-9ld %-9ld %-9ld" ,
  928     scenario[index] -> nb_recv,
  929     scenario[index] -> nb_recv_retrans,
  930     scenario[index] -> nb_timeout,
  931     scenario[index] -> nb_unexp);
  932     }
  933     else if(scenario[index] -> M_type == MSG_TYPE_NOP) {
  934       fprintf(f,"              [ NOP ]              ");
  935     }
  936 #ifdef __3PCC__
  937     else if(scenario[index] -> M_type == MSG_TYPE_RECVCMD) {
  938       fprintf(f,"    [ Received Command ]         ");
  939       if(scenario[index]->retrans_delay) {
  940         fprintf(f,"%-9ld %-9s %-9ld %-9s" ,
  941                 scenario[index]->M_nbCmdRecv,
  942                 "",
  943                 scenario[index]->nb_timeout,
  944                 "");
  945       } else {
  946          fprintf(f,"%-9ld %-9s           %-9s" ,
  947                 scenario[index] -> M_nbCmdRecv,
  948                 "",
  949                 "");
  950       }
  951     } else if(scenario[index] -> M_type == MSG_TYPE_SENDCMD) {
  952       fprintf(f,"        [ Sent Command ]         ");
  953       fprintf(f,"%-9d %-9s           %-9s" ,
  954              scenario[index] -> M_nbCmdSent,
  955              "",
  956              "");
  957     }
  958 #endif
  959     else {
  960       ERROR("Scenario command not implemented in display\n");
  961     }
  962 
  963     if(lose_packets && (scenario[index] -> nb_lost)) {
  964       fprintf(f," %-9d" SIPP_ENDL,
  965              scenario[index] -> nb_lost);
  966     } else {
  967       fprintf(f,SIPP_ENDL);
  968     }
  969 
  970     if(scenario[index] -> crlf) {
  971       fprintf(f,SIPP_ENDL);
  972     }
  973   }
  974 }
  975 
  976 void print_header_line(FILE *f, int last)
  977 {
  978   switch(currentScreenToDisplay)
  979     {
  980     case DISPLAY_STAT_SCREEN :
  981       fprintf(f,"----------------------------- Statistics Screen ------- [1-9]: Change Screen --" SIPP_ENDL);
  982       break;
  983     case DISPLAY_REPARTITION_SCREEN :
  984       fprintf(f,"---------------------------- Repartition Screen ------- [1-9]: Change Screen --" SIPP_ENDL);
  985       break;
  986     case DISPLAY_VARIABLE_SCREEN  :
  987       fprintf(f,"----------------------------- Variables Screen -------- [1-9]: Change Screen --" SIPP_ENDL);
  988       break;
  989     case DISPLAY_TDM_MAP_SCREEN  :
  990       fprintf(f,"------------------------------ TDM map Screen --------- [1-9]: Change Screen --" SIPP_ENDL);
  991       break;
  992     case DISPLAY_SECONDARY_REPARTITION_SCREEN :
  993       fprintf(f,"--------------------------- Repartition %d Screen ------ [1-9]: Change Screen --" SIPP_ENDL, currentRepartitionToDisplay);
  994       break;
  995     case DISPLAY_SCENARIO_SCREEN :
  996     default:
  997       fprintf(f,"------------------------------ Scenario Screen -------- [1-9]: Change Screen --" SIPP_ENDL);
  998       break;
  999     }
 1000 }
 1001 
 1002 void print_bottom_line(FILE *f, int last)
 1003 {
 1004   if(last) {
 1005     fprintf(f,"------------------------------ Test Terminated --------------------------------" SIPP_ENDL);
 1006   } else if(quitting) {
 1007     fprintf(f,"------- Waiting for active calls to end. Press [q] again to force exit. -------" SIPP_ENDL );
 1008   } else if(paused) {
 1009     fprintf(f,"----------------- Traffic Paused - Press [p] again to resume ------------------" SIPP_ENDL );
 1010   } else if(cpu_max) {
 1011     fprintf(f,"-------------------------------- CPU CONGESTED ---------------------------------" SIPP_ENDL);
 1012   } else if(outbound_congestion) {
 1013     fprintf(f,"------------------------------ OUTBOUND CONGESTION -----------------------------" SIPP_ENDL);
 1014   } else {
 1015     switch(toolMode)
 1016       {
 1017       case MODE_SERVER :
 1018         fprintf(f,"------------------------------ Sipp Server Mode -------------------------------" SIPP_ENDL);
 1019         break;
 1020 #ifdef __3PCC__
 1021       case MODE_3PCC_CONTROLLER_B :
 1022         fprintf(f,"----------------------- 3PCC Mode - Controller B side -------------------------" SIPP_ENDL);
 1023         break;
 1024       case MODE_3PCC_A_PASSIVE :
 1025         fprintf(f,"------------------ 3PCC Mode - Controller A side (passive) --------------------" SIPP_ENDL);
 1026         break;
 1027       case MODE_3PCC_CONTROLLER_A :
 1028         fprintf(f,"----------------------- 3PCC Mode - Controller A side -------------------------" SIPP_ENDL);
 1029         break;
 1030       case MODE_MASTER :
 1031         fprintf(f,"-----------------------3PCC extended mode - Master side -------------------------" SIPP_ENDL);
 1032         break;
 1033       case MODE_MASTER_PASSIVE :
 1034         fprintf(f,"------------------ 3PCC extended mode - Master side (passive) --------------------" SIPP_ENDL);
 1035         break;
 1036       case MODE_SLAVE :
 1037         fprintf(f,"----------------------- 3PCC extended mode - Slave side -------------------------" SIPP_ENDL);
 1038         break;
 1039 #endif
 1040       case MODE_CLIENT :
 1041       default:
 1042         fprintf(f,"------ [+|-|*|/]: Adjust rate ---- [q]: Soft exit ---- [p]: Pause traffic -----" SIPP_ENDL);
 1043         break;
 1044       }
 1045   }
 1046   fprintf(f,SIPP_ENDL);
 1047   fflush(stdout);
 1048 }
 1049 
 1050 void print_tdm_map()
 1051 {
 1052   int interval = 0;
 1053   int i = 0;
 1054   int in_use = 0;
 1055   interval = (tdm_map_a+1) * (tdm_map_b+1) * (tdm_map_c+1);
 1056 
 1057   printf("TDM Circuits in use:"  SIPP_ENDL);
 1058   while (i<interval) {
 1059     if (tdm_map[i]) {
 1060       printf("*");
 1061       in_use++;
 1062     } else {
 1063       printf(".");
 1064     }
 1065     i++;
 1066     if (i%(tdm_map_c+1) == 0) printf(SIPP_ENDL);
 1067   }
 1068   printf(SIPP_ENDL);
 1069   printf("%d/%d circuits (%d%%) in use", in_use, interval, int(100*in_use/interval));
 1070   printf(SIPP_ENDL);
 1071   for(int i=0; i<(scenario_len + 8 - int(interval/(tdm_map_c+1))); i++) {
 1072     printf(SIPP_ENDL);
 1073   }
 1074 }
 1075 
 1076 void print_variable_list()
 1077 {
 1078   CActions  * actions;
 1079   CAction   * action;
 1080   CVariable * variable;
 1081   int i,j;
 1082   bool found;
 1083 
 1084   printf("Action defined Per Message :" SIPP_ENDL);
 1085   found = false;
 1086   for(i=0; i<scenario_len; i++)
 1087     {
 1088       actions = scenario[i]->M_actions;
 1089       if(actions != NULL)
 1090         {
 1091           switch(scenario[i]->M_type)
 1092             {
 1093             case MSG_TYPE_RECV:
 1094               printf("=> Message[%d] (Receive Message) - "
 1095                      "[%d] action(s) defined :" SIPP_ENDL,
 1096                      i,
 1097                      actions->getActionSize());
 1098               break;
 1099 #ifdef __3PCC__
 1100             case MSG_TYPE_RECVCMD:
 1101               printf("=> Message[%d] (Receive Command Message) - "
 1102                      "[%d] action(s) defined :" SIPP_ENDL,
 1103                      i,
 1104                      actions->getActionSize());
 1105               break;
 1106 #endif
 1107             default:
 1108               printf("=> Message[%d] - [%d] action(s) defined :" SIPP_ENDL,
 1109                      i,
 1110                      actions->getActionSize());
 1111               break;
 1112             }
 1113 
 1114           for(int j=0; j<actions->getActionSize(); j++)
 1115             {
 1116               action = actions->getAction(j);
 1117               if(action != NULL)
 1118                 {
 1119                   printf("   --> action[%d] = ", j);
 1120                   action->afficheInfo();
 1121                   printf(SIPP_ENDL);
 1122                   found = true;
 1123                 }
 1124             }
 1125         }
 1126     }
 1127   if(!found) printf("=> No action found on any messages"SIPP_ENDL);
 1128 
 1129   printf(SIPP_ENDL);
 1130   printf("Setted Variable List:" SIPP_ENDL);
 1131   found = false;
 1132   j=0;
 1133   for(i=0; i<=maxVariableUsed; i++) {
 1134     for (int j=0;j<SCEN_MAX_MESSAGES;j++)
 1135     {
 1136       variable = scenVariableTable[i][j];
 1137       if(variable != NULL)
 1138         {
 1139           printf("=> Variable[%d] : setted regExp[%s]" SIPP_ENDL,
 1140                  i,
 1141                  variable->getRegularExpression());
 1142           found = true;
 1143           j++;
 1144         }
 1145     }
 1146   }
 1147   if(!found) printf("=> No variable found for this scenario"SIPP_ENDL);
 1148   for(i=0; i<(scenario_len + 5 - j); i++) {
 1149     printf(SIPP_ENDL);
 1150   }
 1151 
 1152 }
 1153 
 1154 /* Function to dump all available screens in a file */
 1155 void print_screens(void)
 1156 {
 1157   int oldScreen = currentScreenToDisplay;
 1158   int oldRepartition = currentRepartitionToDisplay;
 1159 
 1160   currentScreenToDisplay = DISPLAY_SCENARIO_SCREEN;
 1161   print_header_line(   screenf, 0);
 1162   print_stats_in_file( screenf, 0);
 1163   print_bottom_line(   screenf, 0);
 1164 
 1165   currentScreenToDisplay = DISPLAY_STAT_SCREEN;
 1166   print_header_line(   screenf, 0);
 1167   CStat::instance()->displayStat(screenf);
 1168   print_bottom_line(   screenf, 0);
 1169 
 1170   currentScreenToDisplay = DISPLAY_REPARTITION_SCREEN;
 1171   print_header_line(   screenf, 0);
 1172   CStat::instance()->displayRepartition(screenf);
 1173   print_bottom_line(   screenf, 0);
 1174 
 1175   currentScreenToDisplay = DISPLAY_SECONDARY_REPARTITION_SCREEN;
 1176   for (int i = 1; i <= MAX_RTD_INFO_LENGTH; i++) {
 1177     currentRepartitionToDisplay = i;
 1178     print_header_line(   screenf, 0);
 1179     CStat::instance()->displaySecondaryRepartition(screenf, i-1);
 1180     print_bottom_line(   screenf, 0);
 1181   }
 1182 
 1183   currentScreenToDisplay = oldScreen;
 1184   currentRepartitionToDisplay = oldRepartition;
 1185 }
 1186 
 1187 void print_statistics(int last)
 1188 {
 1189   static int first = 1;
 1190 
 1191   if(backgroundMode == false) {
 1192     if(!last) {
 1193       screen_clear();
 1194     }
 1195 
 1196     if(first) {
 1197       first = 0;
 1198       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"
 1199              "\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");
 1200     }
 1201     print_header_line(stdout,last);
 1202     switch(currentScreenToDisplay) {
 1203       case DISPLAY_STAT_SCREEN :
 1204         CStat::instance()->displayStat(stdout);
 1205         break;
 1206       case DISPLAY_REPARTITION_SCREEN :
 1207         CStat::instance()->displayRepartition(stdout);
 1208         break;
 1209       case DISPLAY_VARIABLE_SCREEN  :
 1210         print_variable_list();
 1211         break;
 1212       case DISPLAY_TDM_MAP_SCREEN  :
 1213         print_tdm_map();
 1214         break;
 1215       case DISPLAY_SECONDARY_REPARTITION_SCREEN :
 1216   CStat::instance()->displaySecondaryRepartition(stdout, currentRepartitionToDisplay - 1);
 1217   break;
 1218       case DISPLAY_SCENARIO_SCREEN :
 1219       default:
 1220         print_stats_in_file(stdout, last);
 1221         break;
 1222     }
 1223     print_bottom_line(stdout,last);
 1224 
 1225     if(last) { fprintf(stdout,"\n"); }
 1226   }
 1227 }
 1228 
 1229 void set_rate(double new_rate)
 1230 {
 1231   if(toolMode == MODE_SERVER) {
 1232     rate = 0;
 1233     open_calls_allowed = 0;
 1234   }
 1235 
 1236   rate = new_rate;
 1237   if(rate < 0) {
 1238     rate = 0;
 1239   }
 1240 
 1241   last_rate_change_time = clock_tick;
 1242   calls_since_last_rate_change = 0;
 1243 
 1244   if(!open_calls_user_setting) {
 1245 
 1246     int call_duration_min =  scenario_duration;
 1247 
 1248     if(duration > call_duration_min) call_duration_min = duration;
 1249 
 1250     if(call_duration_min < 1000) call_duration_min = 1000;
 1251 
 1252     open_calls_allowed = (int)((3.0 * rate * call_duration_min) / (double)rate_period_ms);
 1253     if(!open_calls_allowed) {
 1254       open_calls_allowed = 1;
 1255     }
 1256   }
 1257 }
 1258 
 1259 void sipp_sigusr1(int /* not used */)
 1260 {
 1261   /* Smooth exit: do not place any new calls and exit */
 1262   quitting+=10;
 1263 }
 1264 
 1265 void sipp_sigusr2(int /* not used */)
 1266 {
 1267   if (!signalDump) {
 1268      signalDump = true ;
 1269   }
 1270 }
 1271 
 1272 bool process_key(int c) {
 1273     switch (c) {
 1274     case '1':
 1275       currentScreenToDisplay = DISPLAY_SCENARIO_SCREEN;
 1276       print_statistics(0);
 1277       break;
 1278 
 1279     case '2':
 1280       currentScreenToDisplay = DISPLAY_STAT_SCREEN;
 1281       print_statistics(0);
 1282       break;
 1283 
 1284     case '3':
 1285       currentScreenToDisplay = DISPLAY_REPARTITION_SCREEN;
 1286       print_statistics(0);
 1287       break;
 1288 
 1289     case '4':
 1290       currentScreenToDisplay = DISPLAY_VARIABLE_SCREEN;
 1291       print_statistics(0);
 1292       break;
 1293 
 1294     case '5':
 1295       if (use_tdmmap) {
 1296         currentScreenToDisplay = DISPLAY_TDM_MAP_SCREEN;
 1297         print_statistics(0);
 1298       }
 1299       break;
 1300 
 1301     /* Screens 6, 7, 8, 9  are for the extra RTD repartitions. */
 1302     case '6':
 1303     case '7':
 1304     case '8':
 1305     case '9':
 1306       currentScreenToDisplay = DISPLAY_SECONDARY_REPARTITION_SCREEN;
 1307       currentRepartitionToDisplay = (c - '6') + 1;
 1308       print_statistics(0);
 1309       break;
 1310 
 1311     case '+':
 1312       set_rate(rate + 1);
 1313       print_statistics(0);
 1314       break;
 1315 
 1316     case '-':
 1317       set_rate(rate - 1);
 1318       print_statistics(0);
 1319       break;
 1320 
 1321     case '*':
 1322       set_rate(rate + 10);
 1323       print_statistics(0);
 1324       break;
 1325 
 1326     case '/':
 1327       set_rate(rate - 10);
 1328       print_statistics(0);
 1329       break;
 1330 
 1331     case 'p':
 1332       if(paused) {
 1333   paused = 0;
 1334   set_rate(rate);
 1335       } else {
 1336   paused = 1;
 1337       }
 1338       print_statistics(0);
 1339       break;
 1340 
 1341     case 's':
 1342       if (screenf) {
 1343   print_screens();
 1344       }
 1345       break;
 1346 
 1347     case 'q':
 1348       quitting+=10;
 1349       print_statistics(0);
 1350       break;
 1351 
 1352     case 'Q':
 1353       /* We are going to break, so we never have a chance to press q twice. */
 1354       quitting+=20;
 1355       print_statistics(0);
 1356       break;
 1357     }
 1358     return false;
 1359 }
 1360 
 1361 /* User interface threads */
 1362 /* Socket control thread */
 1363 void ctrl_thread (void * param)
 1364 {
 1365   int soc,ret;
 1366   short prt;
 1367   int port, firstport;
 1368   int try_counter = 60;
 1369   unsigned char bufrcv [20];
 1370   struct sockaddr_in sin;
 1371 
 1372   if (control_port) {
 1373     port = control_port;
 1374     /* If the user specified the control port, then we must assume they know
 1375      * what they want, and should not cycle. */
 1376     try_counter = 1;
 1377   } else {
 1378     /* Allow 60 control sockets on the same system */
 1379     /* (several SIPp instances)                   */
 1380     port = DEFAULT_CTRL_SOCKET_PORT;
 1381   }
 1382   firstport = port;
 1383   while (try_counter) {
 1384     prt = htons(port);
 1385     memset(&sin,0,sizeof(struct sockaddr_in));
 1386     soc = socket(AF_INET,SOCK_DGRAM,0);
 1387     sin.sin_port = prt;
 1388     sin.sin_family = AF_INET;
 1389     sin.sin_addr.s_addr = INADDR_ANY;
 1390     if (!bind(soc,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))) {
 1391       /* Bind successful */
 1392       break;
 1393     }
 1394     try_counter--;
 1395     port++;
 1396   }
 1397   if (try_counter == 0) {
 1398     if (control_port) {
 1399       ERROR_P2("Unable to bind remote control socket to UDP port %d: %s",
 1400                   control_port, strerror(errno));
 1401     } else {
 1402       WARNING_P3("Unable to bind remote control socket (tried UDP ports %d-%d): %s",
 1403                   firstport, port - 1, strerror(errno));
 1404     }
 1405     return;
 1406   }
 1407 
 1408   while(!feof(stdin)){
 1409     ret = recv(soc,bufrcv,20,0);
 1410     if ((ret > 0) && (process_key(bufrcv[0]))) {
 1411   return;
 1412     }
 1413   }
 1414 }
 1415 
 1416 /* KEYBOARD thread */
 1417 void keyb_thread (void * param)
 1418 {
 1419   int c;
 1420 
 1421   while(!feof(stdin)){
 1422     c = screen_readkey();
 1423     if (process_key(c)) {
 1424   return;
 1425     }
 1426   }
 1427 }
 1428 
 1429 /*************************** Mini SIP parser ***************************/
 1430 
 1431 char * get_peer_tag(char *msg)
 1432 {
 1433   char        * to_hdr;
 1434   char        * ptr;
 1435   char        * end_ptr;
 1436   static char   tag[MAX_HEADER_LEN];
 1437   int           tag_i = 0;
 1438 
 1439   to_hdr = strstr(msg, "\r\nTo:");
 1440   if(!to_hdr) to_hdr = strstr(msg, "\r\nto:");
 1441   if(!to_hdr) to_hdr = strstr(msg, "\r\nTO:");
 1442   if(!to_hdr) to_hdr = strstr(msg, "\r\nt:");
 1443   if(!to_hdr) {
 1444     ERROR("No valid To: header in reply");
 1445   }
 1446 
 1447   // Remove CRLF
 1448   to_hdr += 2;
 1449 
 1450   end_ptr = strchr(to_hdr,'\n');
 1451 
 1452   ptr = strchr(to_hdr, '>');
 1453   if (!ptr) {
 1454     return NULL;
 1455   }
 1456 
 1457   ptr = strchr(to_hdr, ';');
 1458 
 1459   if(!ptr) {
 1460     return NULL;
 1461   }
 1462 
 1463   to_hdr = ptr;
 1464 
 1465   ptr = strstr(to_hdr, "tag");
 1466   if(!ptr) { ptr = strstr(to_hdr, "TAG"); }
 1467   if(!ptr) { ptr = strstr(to_hdr, "Tag"); }
 1468 
 1469   if(!ptr) {
 1470     return NULL;
 1471   }
 1472 
 1473   if (ptr>end_ptr) {
 1474     return NULL ;
 1475   }
 1476 
 1477   ptr = strchr(ptr, '=');
 1478 
 1479   if(!ptr) {
 1480     ERROR("Invalid tag param in To: header");
 1481   }
 1482 
 1483   ptr ++;
 1484 
 1485   while((*ptr)         &&
 1486         (*ptr != ' ')  &&
 1487         (*ptr != ';')  &&
 1488         (*ptr != '\t') &&
 1489         (*ptr != '\t') &&
 1490         (*ptr != '\r') &&
 1491         (*ptr != '\n') &&
 1492         (*ptr)) {
 1493     tag[tag_i++] = *(ptr++);
 1494   }
 1495   tag[tag_i] = 0;
 1496 
 1497   return tag;
 1498 }
 1499 
 1500 char * get_incoming_header_content(char* message, char * name)
 1501 {
 1502   /* non reentrant. consider accepting char buffer as param */
 1503   static char last_header[MAX_HEADER_LEN * 10];
 1504   char * src, *dest, *ptr;
 1505 
 1506   /* returns empty string in case of error */
 1507   memset(last_header, 0, sizeof(last_header));
 1508 
 1509   if((!message) || (!strlen(message))) {
 1510     return last_header;
 1511   }
 1512 
 1513   src = message;
 1514   dest = last_header;
 1515 
 1516   /* for safety's sake */
 1517   if (NULL == name || NULL == strrchr(name, ':')) {
 1518       return last_header;
 1519   }
 1520 
 1521   while(src = strstr(src, name)) {
 1522 
 1523       /* just want the header's content */
 1524       src += strlen(name);
 1525 
 1526     ptr = strchr(src, '\n');
 1527 
 1528     /* Multiline headers always begin with a tab or a space
 1529      * on the subsequent lines */
 1530     while((ptr) &&
 1531           ((*(ptr+1) == ' ' ) ||
 1532            (*(ptr+1) == '\t')    )) {
 1533       ptr = strchr(ptr + 1, '\n');
 1534     }
 1535 
 1536     if(ptr) { *ptr = 0; }
 1537     // Add "," when several headers are present
 1538     if (dest != last_header) {
 1539       dest += sprintf(dest, ",");
 1540     }
 1541     dest += sprintf(dest, "%s", src);
 1542     if(ptr) { *ptr = '\n'; }
 1543 
 1544     src++;
 1545   }
 1546 
 1547   if(dest == last_header) {
 1548     return last_header;
 1549   }
 1550 
 1551   *(dest--) = 0;
 1552 
 1553   /* Remove trailing whitespaces, tabs, and CRs */
 1554   while ((dest > last_header) &&
 1555          ((*dest == ' ') || (*dest == '\r')|| (*dest == '\t'))) {
 1556     *(dest--) = 0;
 1557   }
 1558 
 1559   /* remove enclosed CRs in multilines */
 1560   while(ptr = strchr(last_header, '\r')) {
 1561     /* Use strlen(ptr) to include trailing zero */
 1562     memmove(ptr, ptr+1, strlen(ptr));
 1563   }
 1564 
 1565   return last_header;
 1566 }
 1567 
 1568 char * get_incoming_first_line(char * message)
 1569 {
 1570   /* non reentrant. consider accepting char buffer as param */
 1571   static char last_header[MAX_HEADER_LEN * 10];
 1572   char * src, *dest, *ptr;
 1573 
 1574   /* returns empty string in case of error */
 1575   memset(last_header, 0, sizeof(last_header));
 1576 
 1577   if((!message) || (!strlen(message))) {
 1578     return last_header;
 1579   }
 1580 
 1581   src = message;
 1582   dest = last_header;
 1583 
 1584   int i=0;
 1585   while (*src){
 1586     if((*src=='\n')||(*src=='\r')){
 1587       break;
 1588     }
 1589     else
 1590     {
 1591       last_header[i]=*src;
 1592     }
 1593     i++;
 1594     src++;
 1595   }
 1596 
 1597   return last_header;
 1598 }
 1599 
 1600 
 1601 char * get_call_id(char *msg)
 1602 {
 1603   static char call_id[MAX_HEADER_LEN];
 1604   char * ptr1, * ptr2, * ptr3, backup;
 1605   bool short_form;
 1606 
 1607   call_id[0] = '\0';
 1608 
 1609   short_form = false;
 1610 
 1611   ptr1 = strstr(msg, "Call-ID:");
 1612   if(!ptr1) { ptr1 = strstr(msg, "Call-Id:"); }
 1613   if(!ptr1) { ptr1 = strstr(msg, "Call-id:"); }
 1614   if(!ptr1) { ptr1 = strstr(msg, "call-Id:"); }
 1615   if(!ptr1) { ptr1 = strstr(msg, "call-id:"); }
 1616   if(!ptr1) { ptr1 = strstr(msg, "CALL-ID:"); }
 1617   // For short form, we need to make sure we start from beginning of line
 1618   // For others, no need to
 1619   if(!ptr1) { ptr1 = strstr(msg, "\r\ni:"); short_form = true;}
 1620   if(!ptr1) {
 1621     WARNING_P1("(1) No valid Call-ID: header in reply '%s'", msg);
 1622     return call_id;
 1623   }
 1624 
 1625   if (short_form) {
 1626     ptr1 += 4;
 1627   } else {
 1628     ptr1 += 8;
 1629   }
 1630 
 1631   while((*ptr1 == ' ') || (*ptr1 == '\t')) { ptr1++; }
 1632 
 1633   if(!(*ptr1)) {
 1634     WARNING("(2) No valid Call-ID: header in reply");
 1635     return call_id;
 1636   }
 1637 
 1638   ptr2 = ptr1;
 1639 
 1640   while((*ptr2) &&
 1641         (*ptr2 != ' ') &&
 1642         (*ptr2 != '\t') &&
 1643         (*ptr2 != '\r') &&
 1644         (*ptr2 != '\n')) {
 1645     ptr2 ++;
 1646   }
 1647 
 1648   if(!*ptr2) {
 1649     WARNING("(3) No valid Call-ID: header in reply");
 1650     return call_id;
 1651   }
 1652 
 1653   backup = *ptr2;
 1654   *ptr2 = 0;
 1655   if ((ptr3 = strstr(ptr1, "///")) != 0) ptr1 = ptr3+3;
 1656   strcpy(call_id, ptr1);
 1657   *ptr2 = backup;
 1658   return (char *) call_id;
 1659 }
 1660 
 1661 unsigned long int get_cseq_value(char *msg) {
 1662   char *ptr1;
 1663 
 1664 
 1665   // no short form for CSeq:
 1666   ptr1 = strstr(msg, "\r\nCSeq:");
 1667   if(!ptr1) { ptr1 = strstr(msg, "\r\nCSEQ:"); }
 1668   if(!ptr1) { ptr1 = strstr(msg, "\r\ncseq:"); }
 1669   if(!ptr1) { ptr1 = strstr(msg, "\r\nCseq:"); }
 1670   if(!ptr1) { WARNING_P1("No valid Cseq header in request %s", msg); return 0;}
 1671 
 1672   ptr1 += 7;
 1673 
 1674   while((*ptr1 == ' ') || (*ptr1 == '\t')) {++ptr1;}
 1675 
 1676   if(!(*ptr1)) { WARNING("No valid Cseq data in header"); return 0;}
 1677 
 1678   return strtoul(ptr1, NULL, 10);
 1679 }
 1680 
 1681 unsigned long get_reply_code(char *msg)
 1682 {
 1683   while((msg) && (*msg != ' ') && (*msg != '\t')) msg ++;
 1684   while((msg) && ((*msg == ' ') || (*msg == '\t'))) msg ++;
 1685 
 1686   if ((msg) && (strlen(msg)>0)) {
 1687     return atol(msg);
 1688   } else {
 1689     return 0;
 1690   }
 1691 }
 1692 
 1693 /*************************** I/O functions ***************************/
 1694 
 1695 /* Allocate a socket buffer. */
 1696 struct socketbuf *alloc_socketbuf(char *buffer, size_t size, int copy) {
 1697   struct socketbuf *socketbuf;
 1698 
 1699   socketbuf = (struct socketbuf *)malloc(sizeof(struct socketbuf));
 1700   if (!socketbuf) {
 1701   ERROR("Could not allocate socket buffer!\n");
 1702   }
 1703   if (copy) {
 1704     socketbuf->buf = (char *)malloc(size);
 1705     if (!socketbuf->buf) {
 1706       ERROR("Could not allocate socket buffer data!\n");
 1707     }
 1708     memcpy(socketbuf->buf, buffer, size);
 1709   } else {
 1710     socketbuf->buf = buffer;
 1711   }
 1712   socketbuf->len = size;
 1713   socketbuf->offset = 0;
 1714   socketbuf->next = NULL;
 1715 
 1716   return socketbuf;
 1717 }
 1718 
 1719 /* Free a poll buffer. */
 1720 void free_socketbuf(struct socketbuf *socketbuf) {
 1721   free(socketbuf->buf);
 1722   free(socketbuf);
 1723 }
 1724 
 1725 size_t decompress_if_needed(int sock, char *buff,  size_t len, void **st)
 1726 {
 1727   if(compression && len) {
 1728     if (useMessagef == 1) {
 1729     struct timeval currentTime;
 1730     GET_TIME (&currentTime);
 1731     TRACE_MSG((s,
 1732                "----------------------------------------------- %s\n"
 1733                "Compressed message received, header :\n"
 1734                "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x "
 1735                "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
 1736                CStat::instance()->formatTime(&currentTime, true),
 1737                buff[0] , buff[1] , buff[2] , buff[3],
 1738                buff[4] , buff[5] , buff[6] , buff[7],
 1739                buff[8] , buff[9] , buff[10], buff[11],
 1740                buff[12], buff[13], buff[14], buff[15]));
 1741     }
 1742 
 1743     int rc = comp_uncompress(st,
 1744                              buff,
 1745                              (unsigned int *) &len);
 1746 
 1747     switch(rc) {
 1748     case COMP_OK:
 1749       TRACE_MSG((s,"Compressed message decompressed properly.\n"));
 1750       break;
 1751 
 1752     case COMP_REPLY:
 1753       TRACE_MSG((s,
 1754                  "Compressed message KO, sending a reply (resynch).\n"));
 1755       sendto(sock,
 1756              buff,
 1757              len,
 1758              0,
 1759              (sockaddr *)(void *)&remote_sockaddr,
 1760              SOCK_ADDR_SIZE(&remote_sockaddr));
 1761       resynch_send++;
 1762       return 0;
 1763 
 1764     case COMP_DISCARD:
 1765       TRACE_MSG((s, "Compressed message discarded by pluggin.\n"));
 1766       resynch_recv++;
 1767       return 0;
 1768 
 1769     default:
 1770     case COMP_KO:
 1771       ERROR("Compression pluggin error");
 1772       return 0;
 1773     }
 1774   }
 1775   return len;
 1776 }
 1777 
 1778 void sipp_customize_socket(struct sipp_socket *socket)
 1779 {
 1780   unsigned int buffsize = buff_size;
 1781 
 1782   /* Allows fast TCP reuse of the socket */
 1783   if (socket->ss_transport == T_TCP || socket->ss_transport == T_TLS ) {
 1784     int sock_opt = 1;
 1785 
 1786     if (setsockopt(socket->ss_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&sock_opt,
 1787                    sizeof (sock_opt)) == -1) {
 1788       ERROR_NO("setsockopt(SO_REUSEADDR) failed");
 1789     }
 1790 
 1791 #ifndef SOL_TCP
 1792 #define SOL_TCP 6
 1793 #endif
 1794     if (setsockopt(socket->ss_fd, SOL_TCP, TCP_NODELAY, (void *)&sock_opt,
 1795                     sizeof (sock_opt)) == -1) {
 1796       {
 1797         ERROR_NO("setsockopt(TCP_NODELAY) failed");
 1798       }
 1799     }
 1800 
 1801     {
 1802       struct linger linger;
 1803 
 1804       linger.l_onoff = 1;
 1805       linger.l_linger = 1;
 1806       if (setsockopt (socket->ss_fd, SOL_SOCKET, SO_LINGER,
 1807                       &linger, sizeof (linger)) < 0) {
 1808         ERROR_NO("Unable to set SO_LINGER option");
 1809       }
 1810     }
 1811   }
 1812 
 1813     /* Increase buffer sizes for this sockets */
 1814   if(setsockopt(socket->ss_fd,
 1815                 SOL_SOCKET,
 1816                 SO_SNDBUF,
 1817                 &buffsize,
 1818                 sizeof(buffsize))) {
 1819     ERROR_NO("Unable to set socket sndbuf");
 1820   }
 1821 
 1822   buffsize = buff_size;
 1823   if(setsockopt(socket->ss_fd,
 1824                 SOL_SOCKET,
 1825                 SO_RCVBUF,
 1826                 &buffsize,
 1827                 sizeof(buffsize))) {
 1828     ERROR_NO("Unable to set socket rcvbuf");
 1829   }
 1830 }
 1831 
 1832 static ssize_t socket_write_primitive(struct sipp_socket *socket, char *buffer, size_t len) {
 1833   ssize_t rc;
 1834 
 1835   /* Refuse to write to invalid sockets. */
 1836   if (socket->ss_invalid) {
 1837     errno = EPIPE;
 1838     return -1;
 1839   }
 1840 
 1841   /* Always check congestion before sending. */
 1842   if (socket->ss_congested) {
 1843     errno = EWOULDBLOCK;
 1844     return -1;
 1845   }
 1846 
 1847   switch(socket->ss_transport) {
 1848     case T_TLS:
 1849 #ifdef _USE_OPENSSL
 1850       rc = send_nowait_tls(socket->ss_ssl, buffer, len, 0);
 1851 #else
 1852       errno = EOPNOTSUPP;
 1853       rc = -1;
 1854 #endif
 1855       break;
 1856     case T_TCP:
 1857       rc = send_nowait(socket->ss_fd, buffer, len, 0);
 1858       break;
 1859     case T_UDP:
 1860       if(compression) {
 1861   static char comp_msg[SIPP_MAX_MSG_SIZE];
 1862   strcpy(comp_msg, buffer);
 1863   if(comp_compress(&socket->ss_comp_state,
 1864         comp_msg,
 1865         (unsigned int *) &len) != COMP_OK) {
 1866     ERROR("Compression pluggin error");
 1867   }
 1868   buffer = (char *)comp_msg;
 1869 
 1870   TRACE_MSG((s, "---\nCompressed message len: %d\n", len));
 1871       }
 1872 
 1873       {
 1874   // different remote sending address from received
 1875   struct sockaddr_storage *L_dest = &socket->ss_remote_sockaddr;
 1876   if (use_remote_sending_addr) {
 1877     L_dest = &remote_sending_sockaddr ;
 1878   }
 1879 
 1880   rc = sendto(socket->ss_fd, buffer, len, 0, (struct sockaddr *)L_dest, SOCK_ADDR_SIZE(L_dest));
 1881       }
 1882       break;
 1883     default:
 1884       ERROR_P1("Internal error, unknown transport type %d\n", socket->ss_transport);
 1885   }
 1886 
 1887   return rc;
 1888 }
 1889 
 1890 /* This socket is congestion, mark its as such and add it to the poll files. */
 1891 int enter_congestion(struct sipp_socket *socket, int again) {
 1892   socket->ss_congested = true;
 1893 
 1894   TRACE_MSG((s,"Problem %s on socket  %d and poll_idx  is %d \n",
 1895   again == EWOULDBLOCK ? "EWOULDBLOCK" : "EAGAIN",
 1896   socket->ss_fd, socket->ss_pollidx));
 1897 
 1898   pollfiles[socket->ss_pollidx].events |= POLLOUT;
 1899 
 1900   nb_net_cong++;
 1901   return -1;
 1902 }
 1903 
 1904 
 1905 static int write_error(struct sipp_socket *socket, int ret) {
 1906   const char *errstring = strerror(errno);
 1907 
 1908 #ifndef EAGAIN
 1909   int again = (errno == EWOULDBLOCK) ? errno : 0;
 1910 #else
 1911   int again = ((errno == EAGAIN) || (errno == EWOULDBLOCK)) ? errno : 0;
 1912 
 1913   /* Scrub away EAGAIN from the rest of the code. */
 1914   if (errno == EAGAIN) {
 1915   errno = EWOULDBLOCK;
 1916   }
 1917 #endif
 1918 
 1919   if(again) {
 1920     return enter_congestion(socket, again);
 1921   }
 1922 
 1923   if (socket->ss_transport == T_TCP && errno == EPIPE) {
 1924     nb_net_send_errors++;
 1925     start_calls = 1;
 1926     if (reset_number > 0) {
 1927       WARNING("Broken pipe on TCP connection, remote peer "
 1928     "probably closed the socket");
 1929     } else {
 1930       ERROR("Broken pipe on TCP connection, remote peer "
 1931     "probably closed the socket");
 1932     }
 1933     return -1;
 1934   }
 1935 
 1936 #ifdef _USE_OPENSSL
 1937   if (socket->ss_transport == T_TLS) {
 1938     errstring = sip_tls_error_string(socket->ss_ssl, ret);
 1939   }
 1940 #endif
 1941 
 1942   WARNING_P2("Unable to send %s message: %s", TRANSPORT_TO_STRING(socket->ss_transport), errstring);
 1943   nb_net_send_errors++;
 1944   return -1;
 1945 }
 1946 
 1947 static int read_error(struct sipp_socket *socket, int ret) {
 1948   const char *errstring = strerror(errno);
 1949 #ifdef _USE_OPENSSL
 1950   if (socket->ss_transport == T_TLS) {
 1951     errstring = sip_tls_error_string(socket->ss_ssl, ret);
 1952   }
 1953 #endif
 1954 
 1955   assert(ret <= 0);
 1956 
 1957 #ifdef EAGAIN
 1958   /* Scrub away EAGAIN from the rest of the code. */
 1959   if (errno == EAGAIN) {
 1960     errno = EWOULDBLOCK;
 1961   }
 1962 #endif
 1963 
 1964   /* We have only non-blocking reads, so this should not occur. */
 1965   assert(errno != EAGAIN);
 1966 
 1967   if (socket->ss_transport == T_TCP || socket->ss_transport == T_TLS) {
 1968     if (ret == 0) {
 1969       /* The remote side closed the connection. */
 1970       if(socket->ss_control) {
 1971         if(localTwinSippSocket) sipp_close_socket(localTwinSippSocket);
 1972         if (extendedTwinSippMode) {
 1973           close_peer_sockets();
 1974           close_local_sockets();
 1975           free_peer_addr_map();
 1976           WARNING("One of the twin instances has ended -> exiting");
 1977           quitting += 20;
 1978           }else if(twinSippMode) {
 1979            if(twinSippSocket) sipp_close_socket(twinSippSocket);
 1980            if(toolMode == MODE_3PCC_CONTROLLER_B) {
 1981              WARNING("3PCC controller A has ended -> exiting");
 1982              quitting += 20;
 1983            }else {
 1984              quitting = 1;
 1985            }
 1986         }
 1987       }else {
 1988         sipp_socket_invalidate(socket);
 1989         if (reset_close) {
 1990         close_calls(socket);
 1991         }
 1992       }
 1993       return 0;
 1994     }
 1995 
 1996     nb_net_recv_errors++;
 1997     start_calls = 1;
 1998     if (reset_number > 0) {
 1999       WARNING_P1("Error on TCP connection, remote peer probably closed the socket: %s", errstring);
 2000     } else {
 2001       ERROR_P1("Error on TCP connection, remote peer probably closed the socket: %s", errstring);
 2002     }
 2003     return -1;
 2004   }
 2005 
 2006   WARNING_P2("Unable to receive %s message: %s", TRANSPORT_TO_STRING(socket->ss_transport), errstring);
 2007   nb_net_recv_errors++;
 2008   return -1;
 2009 }
 2010 
 2011 /* Flush any output buffers for this socket. */
 2012 static int flush_socket(struct sipp_socket *socket) {
 2013   struct socketbuf *buf;
 2014   int ret;
 2015 
 2016   while ((buf = socket->ss_out)) {
 2017     ssize_t size = buf->len - buf->offset;
 2018     ret = socket_write_primitive(socket, buf->buf + buf->offset, size);
 2019     TRACE_MSG((s, "Wrote %d of %d bytes in an output buffer.", ret, size));
 2020     if (ret == size) {
 2021       /* Everything is great, throw away this buffer. */
 2022       socket->ss_out = buf->next;
 2023       free_socketbuf(buf);
 2024     } else if (ret <= 0) {
 2025       /* Handle connection closes and errors. */
 2026       return write_error(socket, ret);
 2027     } else {
 2028       /* We have written more of the partial buffer. */
 2029       buf->offset += ret;
 2030       errno = EWOULDBLOCK;
 2031       enter_congestion(socket, EWOULDBLOCK);
 2032       return -1;
 2033     }
 2034   }
 2035 
 2036   return 0;
 2037 }
 2038 
 2039 void buffer_write(struct sipp_socket *socket, char *buffer, size_t len) {
 2040   struct socketbuf *buf = socket->ss_out;
 2041   struct socketbuf *prev = buf;
 2042 
 2043   if (!buf) {
 2044   socket->ss_out = alloc_socketbuf(buffer, len, DO_COPY);
 2045   TRACE_MSG((s, "Added first buffered message to socket %d\n", socket->ss_fd));
 2046   return;
 2047   }
 2048 
 2049   while(buf->next) {
 2050   prev = buf;
 2051   buf = buf->next;
 2052   }
 2053 
 2054   prev->next = alloc_socketbuf(buffer, len, DO_COPY);
 2055   TRACE_MSG((s, "Appended buffered message to socket %d\n", socket->ss_fd));
 2056 }
 2057 
 2058 void buffer_read(struct sipp_socket *socket, struct socketbuf *newbuf) {
 2059   struct socketbuf *buf = socket->ss_in;
 2060   struct socketbuf *prev = buf;
 2061 
 2062   if (!buf) {
 2063   socket->ss_in = newbuf;
 2064   return;
 2065   }
 2066 
 2067   while(buf->next) {
 2068   prev = buf;
 2069   buf = buf->next;
 2070   }
 2071 
 2072   prev->next = newbuf;
 2073 }
 2074 
 2075 /* Write data to a socket. */
 2076 int write_socket(struct sipp_socket *socket, char *buffer, ssize_t len, int flags) {
 2077   int rc;
 2078 
 2079   if (socket->ss_out) {
 2080     rc = flush_socket(socket);
 2081     TRACE_MSG((s, "Attempted socket flush returned %d\r\n", rc));
 2082     if (rc < 0) {
 2083       if ((errno == EWOULDBLOCK) && (flags & WS_BUFFER)) {
 2084   buffer_write(socket, buffer, len);
 2085   return len;
 2086       } else {
 2087   return rc;
 2088       }
 2089     }
 2090   }
 2091 
 2092   rc = socket_write_primitive(socket, buffer, len);
 2093 
 2094   if (rc == len) {
 2095     /* Everything is great. */
 2096     if (useMessagef == 1) {
 2097       struct timeval currentTime;
 2098       GET_TIME (&currentTime);
 2099       TRACE_MSG((s, "----------------------------------------------- %s\n"
 2100       "%s %smessage sent (%d bytes):\n\n%.*s\n",
 2101       CStat::instance()->formatTime(&currentTime, true),
 2102       TRANSPORT_TO_STRING(socket->ss_transport),
 2103       socket->ss_control ? "control " : "",
 2104       len, len, buffer));
 2105     }
 2106   } else if (rc <= 0) {
 2107     if ((errno == EWOULDBLOCK) && (flags & WS_BUFFER)) {
 2108       buffer_write(socket, buffer, len);
 2109       return len;
 2110     }
 2111     if (useMessagef == 1) {
 2112       struct timeval currentTime;
 2113       GET_TIME (&currentTime);
 2114       TRACE_MSG((s, "----------------------------------------------- %s\n"
 2115       "Error sending %s message:\n\n%.*s\n",
 2116       CStat::instance()->formatTime(&currentTime, true),
 2117       TRANSPORT_TO_STRING(socket->ss_transport),
 2118       len, buffer));
 2119     }
 2120     return write_error(socket, errno);
 2121   } else {
 2122     /* We have a truncated message, which must be handled internally to the write function. */
 2123     if (useMessagef == 1) {
 2124       struct timeval currentTime;
 2125       GET_TIME (&currentTime);
 2126       TRACE_MSG((s, "----------------------------------------------- %s\n"
 2127       "Truncation sending %s message (%d of %d sent):\n\n%.*s\n",
 2128       CStat::instance()->formatTime(&currentTime, true),
 2129       TRANSPORT_TO_STRING(socket->ss_transport),
 2130       rc, len, len, buffer));
 2131     }
 2132     buffer_write(socket, buffer + rc, len - rc);
 2133   }
 2134 
 2135   return rc;
 2136 }
 2137 
 2138 /****************************** Network Interface *******************/
 2139 
 2140 /* Our message detection states: */
 2141 #define CFM_NORMAL 0 /* No CR Found, searchign for \r\n\r\n. */
 2142 #define CFM_CONTROL 1 /* Searching for 27 */
 2143 #define CFM_CR 2 /* CR Found, Searching for \n\r\n */
 2144 #define CFM_CRLF 3 /* CRLF Found, Searching for \r\n */
 2145 #define CFM_CRLFCR 4 /* CRLFCR Found, Searching for \n */
 2146 #define CFM_CRLFCRLF 5 /* We've found the end of the headers! */
 2147 
 2148 void merge_socketbufs(struct socketbuf *socketbuf) {
 2149   struct socketbuf *next = socketbuf->next;
 2150   int newsize;
 2151   char *newbuf;
 2152 
 2153   if (!next) {
 2154     return;
 2155   }
 2156 
 2157   if (next->offset) {
 2158     ERROR("Internal error: can not merge a socketbuf with a non-zero offset.");
 2159   }
 2160 
 2161   if (socketbuf->offset) {
 2162     memmove(socketbuf->buf, socketbuf->buf + socketbuf->offset, socketbuf->len - socketbuf->offset);
 2163     socketbuf->len -= socketbuf->offset;
 2164     socketbuf->offset = 0;
 2165   }
 2166 
 2167   newsize = socketbuf->len + next->len;
 2168 
 2169   newbuf = (char *)realloc(socketbuf->buf, newsize);
 2170   if (!newbuf) {
 2171     ERROR("Could not allocate memory to merge socket buffers!");
 2172   }
 2173   memcpy(newbuf + socketbuf->len, next->buf, next->len);
 2174   socketbuf->buf = newbuf;
 2175   socketbuf->len = newsize;
 2176   socketbuf->next = next->next;
 2177   free_socketbuf(next);
 2178 }
 2179 
 2180 /* Check for a message in the socket and return the length of the first
 2181  * message.  If this is UDP, the only check is if we have buffers.  If this is
 2182  * TCP or TLS we need to parse out the content-length. */
 2183 static int check_for_message(struct sipp_socket *socket) {
 2184   struct socketbuf *socketbuf = socket->ss_in;
 2185   int state = socket->ss_control ? CFM_CONTROL : CFM_NORMAL;
 2186   const char *l;
 2187 
 2188   if (!socketbuf)
 2189     return 0;
 2190 
 2191   if (socket->ss_transport == T_UDP) {
 2192     return socketbuf->len;
 2193   }
 2194 
 2195   int len = 0;
 2196 
 2197   while (socketbuf->offset + len < socketbuf->len) {
 2198     char c = socketbuf->buf[socketbuf->offset + len];
 2199 
 2200     switch(state) {
 2201       case CFM_CONTROL:
 2202   /* For CMD Message the escape char is the end of message */
 2203   if (c == 27) {
 2204     return len + 1; /* The plus one includes the control character. */
 2205   }
 2206   break;
 2207       case CFM_NORMAL:
 2208   if (c == '\r') {
 2209     state = CFM_CR;
 2210   }
 2211   break;
 2212       case CFM_CR:
 2213   if (c == '\n') {
 2214     state = CFM_CRLF;
 2215   } else {
 2216     state = CFM_NORMAL;
 2217   }
 2218   break;
 2219       case CFM_CRLF:
 2220   if (c == '\r') {
 2221     state = CFM_CRLFCR;
 2222   } else {
 2223     state = CFM_NORMAL;
 2224   }
 2225   break;
 2226       case CFM_CRLFCR:
 2227   if (c == '\n') {
 2228     state = CFM_CRLFCRLF;
 2229   } else {
 2230     state = CFM_NORMAL;
 2231   }
 2232   break;
 2233     }
 2234 
 2235     /* Head off failing because the buffer does not contain the whole header. */
 2236     if (socketbuf->offset + len == socketbuf->len - 1) {
 2237       merge_socketbufs(socketbuf);
 2238     }
 2239 
 2240     if (state == CFM_CRLFCRLF) {
 2241       break;
 2242     }
 2243 
 2244     len++;
 2245   }
 2246 
 2247   /* We did not find the end-of-header marker. */
 2248   if (state != CFM_CRLFCRLF) {
 2249     return 0;
 2250   }
 2251 
 2252   /* Find the content-length header. */
 2253   if ((l = strncasestr(socketbuf->buf + socketbuf->offset, "\r\nContent-Length:", len))) {
 2254     l += strlen("\r\nContent-Length:");
 2255   } else if ((l = strncasestr(socketbuf->buf + socketbuf->offset, "\r\nl:", len))) {
 2256     l += strlen("\r\nl:");
 2257   } else {
 2258     /* There is no header, so the content-length is zero. */
 2259     return len + 1;
 2260   }
 2261 
 2262   /* Skip spaces. */
 2263   while(isspace(*l)) {
 2264     if (*l == '\r' || *l == '\n') {
 2265       /* We ran into an end-of-line, so there is no content-length. */
 2266       return len + 1;
 2267     }
 2268     l++;
 2269   }
 2270 
 2271   /* Do the integer conversion, we only allow '\r' or spaces after the integer. */
 2272   char *endptr;
 2273   int content_length = strtol(l, &endptr, 10);
 2274   if (*endptr != '\r' && !isspace(*endptr)) {
 2275     content_length = 0;
 2276   }
 2277 
 2278   /* Now that we know how large this message is, we make sure we have the whole thing. */
 2279   do
 2280   {
 2281     /* It is in this buffer. */
 2282     if (socketbuf->offset + len + content_length < socketbuf->len) {
 2283       return len + content_length + 1;
 2284     }
 2285     if (socketbuf->next == NULL) {
 2286       /* There is no buffer to merge, so we fail. */
 2287       return 0;
 2288     }
 2289     /* We merge ourself with the next buffer. */
 2290     merge_socketbufs(socketbuf);
 2291   }
 2292   while (1);
 2293 }
 2294 
 2295 /* Pull up to tcp_readsize data bytes out of the socket into our local buffer. */
 2296 static int empty_socket(struct sipp_socket *socket) {
 2297   int readsize = socket->ss_transport == T_UDP ? SIPP_MAX_MSG_SIZE : tcp_readsize;
 2298   struct socketbuf *socketbuf;
 2299   char *buffer;
 2300   int ret;
 2301   /* Where should we start sending packets to, ideally we should begin to parse
 2302    * the Via, Contact, and Route headers.  But for now SIPp always sends to the
 2303    * host specified on the command line; or for UAS mode to the address that
 2304    * sent the last message. */
 2305   struct sockaddr *new_destination = NULL;
 2306   sipp_socklen_t addrlen = 0;
 2307 
 2308   if (toolMode == MODE_SERVER && socket->ss_transport == T_UDP) {
 2309     new_destination = (struct sockaddr *) &socket->ss_remote_sockaddr;
 2310     addrlen = sizeof(socket->ss_remote_sockaddr);
 2311   }
 2312 
 2313   buffer = (char *)malloc(readsize);
 2314   if (!buffer) {
 2315     ERROR("Could not allocate memory for read!");
 2316   }
 2317   socketbuf = alloc_socketbuf(buffer, readsize, NO_COPY);
 2318 
 2319   switch(socket->ss_transport) {
 2320     case T_TCP:
 2321     case T_UDP:
 2322       ret = recvfrom(socket->ss_fd, buffer, readsize, 0, new_destination,  &addrlen);
 2323       break;
 2324     case T_TLS:
 2325 #ifdef _USE_OPENSSL
 2326       ret = SSL_read(socket->ss_ssl, buffer, readsize);
 2327       /* XXX: Check for clean shutdown. */
 2328 #else
 2329       ERROR("TLS support is not enabled!");
 2330 #endif
 2331       break;
 2332   }
 2333   if (ret <= 0) {
 2334     free_socketbuf(socketbuf);
 2335     return ret;
 2336   }
 2337 
 2338   socketbuf->len = ret;
 2339 
 2340   buffer_read(socket, socketbuf);
 2341 
 2342   /* Do we have a complete SIP message? */
 2343   if (!socket->ss_msglen) {
 2344     if (int msg_len = check_for_message(socket)) {
 2345       socket->ss_msglen = msg_len;
 2346       pending_messages++;
 2347     }
 2348   }
 2349 
 2350   return ret;
 2351 }
 2352 
 2353 void sipp_socket_invalidate(struct sipp_socket *socket) {
 2354   int pollidx;
 2355 
 2356   if (socket->ss_invalid) {
 2357     return;
 2358   }
 2359 
 2360 #ifdef _USE_OPENSSL
 2361   if (SSL *ssl = socket->ss_ssl) {
 2362     SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
 2363     SSL_free(ssl);
 2364   }
 2365 #endif
 2366 
 2367   shutdown(socket->ss_fd, SHUT_RDWR);
 2368   close(socket->ss_fd);
 2369 
 2370   if((pollidx = socket->ss_pollidx) >= pollnfds) {
 2371     ERROR_P2("Pollset error: index %d is greater than number of fds %d!", pollidx, pollnfds);
 2372   }
 2373 
 2374   if (socket->ss_call_socket) {
 2375     call_sockets--;
 2376   }
 2377 
 2378   socket->ss_invalid = true;
 2379   socket->ss_pollidx = -1;
 2380 
 2381   /* Adds call sockets in the array */
 2382   assert(pollnfds > 0);
 2383 
 2384   pollnfds--;
 2385   pollfiles[pollidx] = pollfiles[pollnfds];
 2386   sockets[pollidx] = sockets[pollnfds];
 2387   sockets[pollidx]->ss_pollidx = pollidx;
 2388 }
 2389 
 2390 void sipp_close_socket (struct sipp_socket *socket) {
 2391   int count = --socket->ss_count;
 2392 
 2393   if (count > 0) {
 2394     return;
 2395   }
 2396 
 2397   sipp_socket_invalidate(socket);
 2398   free(socket);
 2399 }
 2400 
 2401 static ssize_t read_message(struct sipp_socket *socket, char *buf, size_t len) {
 2402   size_t avail;
 2403 
 2404   if (!socket->ss_msglen)
 2405     return 0;
 2406   if (socket->ss_msglen > len)
 2407     ERROR_P1("There is a message waiting in a socket that is bigger (%zd bytes) than the read size.", socket->ss_msglen);
 2408 
 2409   len = socket->ss_msglen;
 2410 
 2411   avail = socket->ss_in->len - socket->ss_in->offset;
 2412   if (avail > len) {
 2413     avail = len;
 2414   }
 2415 
 2416   memcpy(buf, socket->ss_in->buf + socket->ss_in->offset, avail);
 2417 
 2418   /* Update our buffer and return value. */
 2419   buf[avail] = '\0';
 2420   /* For CMD Message the escape char is the end of message */
 2421   if((socket->ss_control) && buf[avail-1] == 27 ) buf[avail-1] = '\0';
 2422 
 2423   socket->ss_in->offset += avail;
 2424 
 2425   /* Have we emptied the buffer? */
 2426   if (socket->ss_in->offset == socket->ss_in->len) {
 2427     struct socketbuf *next = socket->ss_in->next;
 2428     free_socketbuf(socket->ss_in);
 2429     socket->ss_in = next;
 2430   }
 2431 
 2432   if (int msg_len = check_for_message(socket)) {
 2433     socket->ss_msglen = msg_len;
 2434   } else {
 2435     socket->ss_msglen = 0;
 2436     pending_messages--;
 2437   }
 2438 
 2439   if (useMessagef == 1) {
 2440     struct timeval currentTime;
 2441     GET_TIME (&currentTime);
 2442     TRACE_MSG((s, "----------------------------------------------- %s\n"
 2443     "%s %smessage received [%d] bytes :\n\n%s\n",
 2444     CStat::instance()->formatTime(&currentTime, true),
 2445     TRANSPORT_TO_STRING(socket->ss_transport),
 2446     socket->ss_control ? "control " : "",
 2447     avail, buf));
 2448   }
 2449 
 2450   return avail;
 2451 }
 2452 
 2453 void process_message(struct sipp_socket *socket, char *msg, ssize_t msg_size) {
 2454   // TRACE_MSG((s," msg_size %d and pollset_index is %d \n", msg_size, pollset_index));
 2455   if(msg_size <= 0) {
 2456     return;
 2457   }
 2458   if (sipMsgCheck(msg, msg_size, socket) == false) {
 2459     WARNING("non SIP message discarded");
 2460     return;
 2461   }
 2462 
 2463   char *call_id = get_call_id(msg);
 2464   if (call_id[0] == '\0') {
 2465     WARNING("SIP message without Call-ID discarded");
 2466     return;
 2467   }
 2468   call *call_ptr = get_call(call_id);
 2469 
 2470   if (useShortMessagef == 1) {
 2471               struct timeval currentTime;
 2472               GET_TIME (&currentTime);
 2473               TRACE_SHORTMSG((s, "%s\tS\t%s\tCSeq:%s\t%s\n",
 2474               CStat::instance()->formatTime(&currentTime),call_id, get_incoming_header_content(msg,"CSeq:"), get_incoming_first_line(msg)));
 2475           }
 2476 
 2477   if(!call_ptr)
 2478   {
 2479     if(toolMode == MODE_SERVER)
 2480     {
 2481       if (quitting >= 1) {
 2482   nb_out_of_the_blue++;
 2483   CStat::instance()->computeStat(CStat::E_OUT_OF_CALL_MSGS);
 2484   TRACE_MSG((s,"Discarded message for new calls while quitting\n"));
 2485   return;
 2486       }
 2487 
 2488       // Adding a new INCOMING call !
 2489       CStat::instance()->computeStat(CStat::E_CREATE_INCOMING_CALL);
 2490 
 2491       call_ptr = add_call(call_id, socket);
 2492       if(!call_ptr) {
 2493   outbound_congestion = true;
 2494   CStat::instance()->computeStat(CStat::E_CALL_FAILED);
 2495   CStat::instance()->computeStat(CStat::E_FAILED_OUTBOUND_CONGESTION);
 2496       } else {
 2497   outbound_congestion = false;
 2498   socket->ss_count++;
 2499       }
 2500     }
 2501     else if(toolMode == MODE_3PCC_CONTROLLER_B || toolMode == MODE_3PCC_A_PASSIVE
 2502   || toolMode == MODE_MASTER_PASSIVE || toolMode == MODE_SLAVE)
 2503     {
 2504       // Adding a new OUTGOING call !
 2505       CStat::instance()->computeStat
 2506   (CStat::E_CREATE_OUTGOING_CALL);
 2507       call_ptr = add_call(call_id, is_ipv6, 0);
 2508       if(!call_ptr) {
 2509   outbound_congestion = true;
 2510   CStat::instance()->computeStat(CStat::E_CALL_FAILED);
 2511   CStat::instance()->computeStat(CStat::E_FAILED_OUTBOUND_CONGESTION);
 2512       } else {
 2513   outbound_congestion = false;
 2514   if((socket != main_socket) &&
 2515       (socket != tcp_multiplex) &&
 2516       (socket != localTwinSippSocket) &&
 2517       (socket != twinSippSocket) &&
 2518       (!is_a_local_socket(socket))) {
 2519     call_ptr->associate_socket(socket);
 2520     socket->ss_count++;
 2521   } else {
 2522     /* We need to hook this call up to a real *call* socket. */
 2523     if (!multisocket) {
 2524       switch(transport) {
 2525         case T_UDP:
 2526     call_ptr->associate_socket(main_socket);
 2527     main_socket->ss_count++;
 2528     break;
 2529         case T_TCP:
 2530         case T_TLS:
 2531     call_ptr->associate_socket(tcp_multiplex);
 2532     tcp_multiplex->ss_count++;
 2533     break;
 2534       }
 2535     }
 2536   }
 2537       }
 2538     }
 2539     else // mode != from SERVER and 3PCC Controller B
 2540     {
 2541       // This is a message that is not relating to any known call
 2542      if (auto_answer == true) {
 2543   // If auto answer mode, try to answer the incoming message
 2544   // with automaticResponseMode
 2545   // call is discarded before exiting the block
 2546       if(!get_reply_code(msg)){
 2547       call_ptr = add_call(call_id, socket, true);
 2548       if (call_ptr) {
 2549           socket->ss_count++;
 2550           call_ptr->last_recv_msg = (char *) realloc(call_ptr->last_recv_msg, strlen(msg) + 1);
 2551           strcpy(call_ptr->last_recv_msg, msg);
 2552           call_ptr->automaticResponseMode(5, msg);
 2553           delete_call(call_id);
 2554           call_ptr = NULL;
 2555           total_calls--;
 2556          }
 2557         } else{
 2558           /* We received a response not relating to any known call */
 2559           /* Do nothing, even if in auto answer mode */
 2560          }
 2561       } else {
 2562   nb_out_of_the_blue++;
 2563   CStat::instance()->computeStat
 2564     (CStat::E_OUT_OF_CALL_MSGS);
 2565   WARNING_P1("Discarding message which can't be mapped to a known SIPp call:\n%s", msg);
 2566       }
 2567     }
 2568   }
 2569 
 2570   /* If the call was not created above, we just drop this message. */
 2571   if (!call_ptr) {
 2572     return;
 2573   }
 2574 
 2575   if((socket == localTwinSippSocket) || (socket == twinSippSocket) || (is_a_local_socket(socket)))
 2576   {
 2577     call_ptr -> process_twinSippCom(msg);
 2578   }
 2579   else
 2580   {
 2581     call_ptr -> process_incoming(msg);
 2582   }
 2583 }
 2584 
 2585 void pollset_process()
 2586 {
 2587   int rs; /* Number of times to execute recv().
 2588        For TCP with 1 socket per call:
 2589            no. of events returned by poll
 2590        For UDP and TCP with 1 global socket:
 2591            recv_count is a flag that stays up as
 2592            long as there's data to read */
 2593 
 2594   int loops = max_recv_loops;
 2595 
 2596   /* What index should we try reading from? */
 2597   static int read_index;
 2598 
 2599   /* We need to process any messages that we have left over. */
 2600   while (pending_messages && (loops-- > 0)) {
 2601     clock_tick = getmilliseconds();
 2602     if (sockets[read_index]->ss_msglen) {
 2603   char msg[SIPP_MAX_MSG_SIZE];
 2604   ssize_t len = read_message(sockets[read_index], msg, sizeof(msg));
 2605   if (len > 0) {
 2606     process_message(sockets[read_index], msg, len);
 2607   } else {
 2608     assert(0);
 2609   }
 2610       }
 2611     read_index = (read_index + 1) % pollnfds;
 2612   }
 2613 
 2614   /* Don't read more data if we still have some left over. */
 2615   if (pending_messages) {
 2616     return;
 2617   }
 2618 
 2619   /* Get socket events. */
 2620   rs = poll(pollfiles, pollnfds,  1);
 2621   if((rs < 0) && (errno == EINTR)) {
 2622     return;
 2623   }
 2624 
 2625   /* We need to flush all sockets and pull data into all of our buffers. */
 2626   for(int poll_idx = 0; rs > 0 && poll_idx < pollnfds; poll_idx++) {
 2627     struct sipp_socket *sock = sockets[poll_idx];
 2628     int events = 0;
 2629     int ret = 0;
 2630 
 2631     assert(sock);
 2632 
 2633     if(pollfiles[poll_idx].revents & POLLOUT) {
 2634       /* We can flush this socket. */
 2635       TRACE_MSG((s, "Exit problem event on socket %d \n", sock->ss_fd));
 2636       pollfiles[poll_idx].events &= ~POLLOUT;
 2637       sock->ss_congested = false;
 2638 
 2639       flush_socket(sock);
 2640       events++;
 2641     }
 2642 
 2643     if(pollfiles[poll_idx].revents & POLLIN) {
 2644       /* We can empty this socket. */
 2645       if ((transport == T_TCP || transport == T_TLS) && sock == main_socket) {
 2646   struct sipp_socket *new_sock = sipp_accept_socket(sock);
 2647   if (!new_sock) {
 2648     ERROR_NO("Accepting new TCP connection.\n");
 2649   }
 2650       } else if (sock == localTwinSippSocket) {
 2651   if (toolMode == MODE_3PCC_CONTROLLER_B) {
 2652     twinSippSocket = sipp_accept_socket(sock);
 2653     if (!twinSippMode) {
 2654       ERROR_NO("Accepting new TCP connection on Twin SIPp Socket.\n");
 2655     }
 2656     twinSippSocket->ss_control = 1;
 2657   } else {
 2658     /*3pcc extended mode: open a local socket
 2659       which will be used for reading the infos sent by this remote
 2660       twin sipp instance (slave or master) */
 2661     if(local_nb == MAX_LOCAL_TWIN_SOCKETS) {
 2662       ERROR("Max number of twin instances reached\n");
 2663     }
 2664 
 2665     struct sipp_socket *localSocket = sipp_accept_socket(sock);
 2666      localSocket->ss_control = 1;
 2667     local_sockets[local_nb] = localSocket;
 2668     local_nb++;
 2669     if(!peers_connected){
 2670       connect_to_all_peers();
 2671     }
 2672   }
 2673       } else {
 2674   if ((ret = empty_socket(sock)) <= 0) {
 2675     read_error(sock, ret);
 2676   }
 2677       }
 2678       events++;
 2679     }
 2680 
 2681     pollfiles[poll_idx].revents = 0;
 2682     if (events) {
 2683       rs--;
 2684     }
 2685   }
 2686 
 2687   /* We need to process any new messages that we read. */
 2688   while (pending_messages && (loops-- > 0)) {
 2689     clock_tick = getmilliseconds();
 2690 
 2691     if (sockets[read_index]->ss_msglen) {
 2692       char msg[SIPP_MAX_MSG_SIZE];
 2693       ssize_t len;
 2694 
 2695       len = read_message(sockets[read_index], msg, sizeof(msg));
 2696       if (len > 0) {
 2697   process_message(sockets[read_index], msg, len);
 2698       } else {
 2699   assert(0);
 2700       }
 2701     }
 2702     read_index = (read_index + 1) % pollnfds;
 2703   }
 2704 
 2705   cpu_max = loops <= 0;
 2706 }
 2707 
 2708 void timeout_alarm(int param){
 2709   quitting = 1;
 2710   timeout_exit = true;
 2711 }
 2712 
 2713 /* Send loop & trafic generation*/
 2714 
 2715 void traffic_thread()
 2716 {
 2717   unsigned int calls_to_open = 0;
 2718   unsigned int new_time;
 2719   unsigned int last_time;
 2720   bool         firstPass;
 2721 
 2722   /* create the file */
 2723   char         L_file_name [MAX_PATH];
 2724   sprintf (L_file_name, "%s_%d_screen.log", scenario_file, getpid());
 2725 
 2726 
 2727   firstPass = true;
 2728   last_time = getmilliseconds();
 2729 
 2730   /* Arm the global timer if needed */
 2731   if (global_timeout > 0) {
 2732     signal(SIGALRM, timeout_alarm);
 2733     alarm(global_timeout / 1000);
 2734   }
 2735 
 2736   while(1) {
 2737     scheduling_loops ++;
 2738 
 2739     /* update local time, except if resetted*/
 2740     new_time = getmilliseconds();
 2741 
 2742     clock_tick = new_time;
 2743     last_time = new_time;
 2744 
 2745     if (start_calls == 1) {
 2746       reset_connections();
 2747     }
 2748 
 2749     if (signalDump) {
 2750        /* Screen dumping in a file */
 2751        if (screenf) {
 2752           print_screens();
 2753        } else {
 2754          /* If the -trace_screen option has not been set, */
 2755          /* create the file at this occasion              */
 2756          screenf = fopen(L_file_name, "a");
 2757    if (!screenf) {
 2758             WARNING_P1("Unable to create '%s'", L_file_name);
 2759          }
 2760    print_screens();
 2761    fclose(screenf);
 2762    screenf = 0;
 2763        }
 2764 
 2765        if(dumpInRtt) {
 2766           CStat::instance()->dumpDataRtt ();
 2767        }
 2768 
 2769        signalDump = false ;
 2770     }
 2771 
 2772     if ((!quitting) && (!paused) && (!start_calls)) {
 2773       long l=0;
 2774 
 2775       if (users) {
 2776   calls_to_open = ((l = (users - open_calls)) > 0) ? l : 0;
 2777       } else {
 2778   calls_to_open = (unsigned int)
 2779               ((l=(long)floor(((clock_tick - last_rate_change_time) * rate/rate_period_ms)
 2780               - calls_since_last_rate_change))>0?l:0);
 2781       }
 2782 
 2783 
 2784       if( (toolMode == MODE_CLIENT)
 2785 #ifdef __3PCC__
 2786           || (toolMode == MODE_3PCC_CONTROLLER_A)
 2787           || (toolMode == MODE_MASTER)
 2788 #endif
 2789           )
 2790         {
 2791     int first_open_tick = clock_tick;
 2792           while((calls_to_open--) &&
 2793                 (!open_calls_allowed || open_calls < open_calls_allowed) &&
 2794                 (total_calls < stop_after))
 2795             {
 2796         /* Associate a user with this call, if we are in users mode. */
 2797         int userid = 0;
 2798         if (users) {
 2799     userid = freeUsers.back();
 2800     freeUsers.pop_back();
 2801         }
 2802 
 2803               // adding a new OUTGOING CALL
 2804               CStat::instance()->computeStat(CStat::E_CREATE_OUTGOING_CALL);
 2805               call * call_ptr = add_call(userid, is_ipv6);
 2806               if(!call_ptr) {
 2807                 outbound_congestion = true;
 2808                 CStat::instance()->computeStat(CStat::E_CALL_FAILED);
 2809                 CStat::instance()->computeStat(CStat::E_FAILED_OUTBOUND_CONGESTION);
 2810               } else {
 2811                  outbound_congestion = false;
 2812 
 2813      if (!multisocket) {
 2814        switch(transport) {
 2815          case T_UDP:
 2816            call_ptr->associate_socket(main_socket);
 2817            main_socket->ss_count++;
 2818            break;
 2819          case T_TCP:
 2820          case T_TLS:
 2821            call_ptr->associate_socket(tcp_multiplex);
 2822            tcp_multiplex->ss_count++;
 2823            break;
 2824        }
 2825      }
 2826 
 2827                  call_ptr -> run();
 2828         }
 2829 
 2830         new_time = getmilliseconds();
 2831         /* Never spend more than half of our time processing new call requests. */
 2832         if (new_time > (first_open_tick + (timer_resolution < 2 ? 1 : (timer_resolution / 2)))) {
 2833     break;
 2834         }
 2835             }
 2836 
 2837           if(open_calls_allowed && (open_calls >= open_calls_allowed)) {
 2838             set_rate(rate);
 2839           }
 2840         }
 2841 
 2842         // Quit after asked number of calls is reached
 2843         if(total_calls >= stop_after) {
 2844           quitting = 1;
 2845         }
 2846     } else if (quitting) {
 2847       if (quitting > 11) {
 2848         /* Force exit: abort all calls */
 2849         delete_calls();
 2850       }
 2851       /* Quitting and no more openned calls, close all */
 2852       if(!open_calls) {
 2853   print_statistics(0);
 2854 
 2855         // Dump the latest statistics if necessary
 2856         if(dumpInFile) {
 2857           CStat::instance()->dumpData();
 2858         }
 2859 
 2860         if(dumpInRtt) {
 2861           CStat::instance()->dumpDataRtt();
 2862         }
 2863 
 2864         /* Screen dumping in a file if asked */
 2865         if(screenf) {
 2866           print_screens();
 2867         }
 2868 
 2869   for (int i = 0; i < pollnfds; i++) {
 2870     sipp_close_socket(sockets[i]);
 2871   }
 2872 
 2873         screen_exit(EXIT_TEST_RES_UNKNOWN);
 2874       }
 2875     }
 2876 
 2877     new_time = getmilliseconds();
 2878     clock_tick = new_time;
 2879     last_time = new_time;
 2880 
 2881     /* Schedule all pending calls and process their timers */
 2882     call_list *running_calls;
 2883     if((clock_tick - last_timer_cycle) > timer_resolution) {
 2884 
 2885       /* Just for the count. */
 2886       running_calls = get_running_calls();
 2887       last_running_calls = running_calls->size();
 2888 
 2889       /* If we have expired paused calls, move them to the run queue. */
 2890       last_woken_calls += expire_paused_calls();
 2891 
 2892       last_paused_calls = paused_calls_count();
 2893 
 2894       last_timer_cycle = clock_tick;
 2895     }
 2896 
 2897     /* We should never get so busy with running calls that we can't process some messages. */
 2898     int loops = max_sched_loops;
 2899 
 2900     /* Now we process calls that are on the run queue. */
 2901     running_calls = get_running_calls();
 2902 
 2903     /* Workaround hpux problem with iterators. Deleting the
 2904      * current object when iterating breaks the iterator and
 2905      * leads to iterate again on the destroyed (deleted)
 2906      * object. Thus, we have to wait ont step befere actual
 2907      * deletion of the object*/
 2908     call * last = NULL;
 2909 
 2910     call_list::iterator iter;
 2911     for(iter = running_calls->begin(); iter != running_calls->end(); iter++) {
 2912       if(last) { last -> run(); }
 2913       last = *iter;
 2914       if (--loops <= 0) {
 2915   break;
 2916       }
 2917     }
 2918     if(last) { last -> run(); }
 2919 
 2920     /* Update the clock. */
 2921     new_time = getmilliseconds();
 2922     clock_tick = new_time ;
 2923     last_time = new_time;
 2924 
 2925     /* Receive incoming messages */
 2926     pollset_process();
 2927     new_time = getmilliseconds();
 2928     clock_tick = new_time ;
 2929     last_time = new_time;
 2930 
 2931     if(firstPass)
 2932       {
 2933         // dumping (to create file on disk) and showing
 2934         // screen at the beginning even if the report
 2935         // period is not reach
 2936         firstPass = false;
 2937   if (report_freq > 0) {
 2938     print_statistics(0);
 2939   }
 2940         /* Dumping once to create the file on disk */
 2941         if(dumpInFile)
 2942           {
 2943             CStat::instance()->dumpData();
 2944           }
 2945         if(dumpInRtt)
 2946           {
 2947             CStat::instance()->dumpDataRtt();
 2948           }
 2949 
 2950       }
 2951 
 2952     if(report_freq && ((clock_tick - last_report_time) >= report_freq))
 2953       {
 2954         print_statistics(0);
 2955         CStat::instance()->computeStat(CStat::E_RESET_PD_COUNTERS);
 2956         last_report_time  = clock_tick;
 2957         last_report_calls = total_calls;
 2958         scheduling_loops = 0;
 2959       }
 2960 
 2961     // FIXME - Should we recompute time ? print stat take
 2962     // a lot of time, so the clock_time is no more
 2963     // the current time !
 2964     if((clock_tick - last_dump_time) >= report_freq_dumpLog)  {
 2965       if(dumpInFile) {
 2966   CStat::instance()->dumpData();
 2967   CStat::instance()->computeStat(CStat::E_RESET_PL_COUNTERS);
 2968       }
 2969       last_dump_time  = clock_tick;
 2970       if (rate_increase) {
 2971   set_rate(rate + rate_increase);
 2972   if (rate_max && (rate > rate_max)) {
 2973     quitting += 10;
 2974   }
 2975       }
 2976     }
 2977   }
 2978 }
 2979 
 2980 /*************** RTP ECHO THREAD ***********************/
 2981 /* param is a pointer to RTP socket */
 2982 
 2983 void rtp_echo_thread (void * param)
 2984 {
 2985   char *msg = (char*)alloca(media_bufsize);
 2986   size_t nr, ns;
 2987   sipp_socklen_t len;
 2988   struct sockaddr_storage remote_rtp_addr;
 2989 
 2990 
 2991    int                   rc;
 2992    sigset_t              mask;
 2993    sigfillset(&mask); /* Mask all allowed signals */
 2994    rc = pthread_sigmask(SIG_BLOCK, &mask, NULL);
 2995 
 2996   for (;;) {
 2997     len = sizeof(remote_rtp_addr);
 2998     nr = recvfrom(*(int *)param,
 2999                   msg,
 3000                   media_bufsize, 0,
 3001                   (sockaddr *)(void *) &remote_rtp_addr,
 3002                   &len);
 3003 
 3004     if (((long)nr) < 0) {
 3005       WARNING_P2("%s %i",
 3006                  "Error on RTP echo reception - stopping echo - errno=",
 3007                  errno);
 3008       return;
 3009     }
 3010     ns = sendto(*(int *)param, msg, nr,
 3011                 0, (sockaddr *)(void *) &remote_rtp_addr,
 3012                 len);
 3013 
 3014     if (ns != nr) {
 3015       WARNING_P2("%s %i",
 3016                  "Error on RTP echo transmission - stopping echo - errno=",
 3017                  errno);
 3018       return;
 3019     }
 3020 
 3021     if (*(int *)param==media_socket) {
 3022     rtp_pckts++;
 3023     rtp_bytes += ns;
 3024   }
 3025     else {
 3026       /* packets on the second RTP stream */
 3027       rtp2_pckts++;
 3028       rtp2_bytes += ns;
 3029     }
 3030   }
 3031 }
 3032 
 3033 /* Wrap the help text. */
 3034 char *wrap(const char *in, int offset, int size) {
 3035   int pos = 0;
 3036   int i, j;
 3037   int l = strlen(in);
 3038   int alloced = l + 1;
 3039   char *out = (char *)malloc(alloced);
 3040   int indent = 0;
 3041 
 3042   if (!out) {
 3043     ERROR_NO("malloc");
 3044   }
 3045 
 3046   for (i = j = 0; i < l; i++) {
 3047     out[j++] = in[i];
 3048     if (in[i] == '\n') {
 3049       out = (char *)realloc(out, alloced += offset);
 3050       if (!out) {
 3051         ERROR_NO("realloc");
 3052       }
 3053       pos = 0;
 3054       for (int k = 0; k < offset; k++) {
 3055         out[j++] = ' ';
 3056       }
 3057       if (indent) {
 3058         indent = 0;
 3059       }
 3060     }
 3061     if (in[i] == '-' && i > 0 && in[i - 1] == '\n') {
 3062       indent = 1;
 3063     }
 3064     if (++pos > size) {
 3065       int k;
 3066       for (k = j - 1; k > 0 && !isspace(out[k]); k--);
 3067       int useoffset = offset;
 3068 
 3069       if (indent) {
 3070         useoffset += 2;
 3071       }
 3072 
 3073       if (k == 0 || out[k] == '\n') {
 3074         pos = 0;
 3075         out[j++] = '\n';
 3076         out = (char *)realloc(out, alloced += useoffset);
 3077         if (!out) {
 3078           ERROR_NO("realloc");
 3079         }
 3080         for (k = 0; k < useoffset; k++) {
 3081           out[j++] = ' ';
 3082         }
 3083       } else {
 3084         int m;
 3085 
 3086         out[j] = '\0';
 3087         //printf("Before wrapping (pos = %d, k = %d, j = %d):\n%-*s%s\n", pos, k, j, offset, "", out);
 3088 
 3089         out[k] = '\n';
 3090         pos = j - k;
 3091         k++;
 3092         out[j] = '\0';
 3093         out = (char *)realloc(out, alloced += useoffset);
 3094         if (!out) {
 3095           ERROR_NO("realloc");
 3096         }
 3097         for (m = 0; m < useoffset; m++) {
 3098           if (k + useoffset + m < alloced) {
 3099             out[k + useoffset + m] = out[k + m];
 3100           }
 3101           out[k + m] = ' ';
 3102         }
 3103         j += useoffset;
 3104         out[j] = '\0';
 3105         //printf("After wrapping (pos = %d, k = %d):\n%-*s%s\n", pos, k, offset, "", out);
 3106       }
 3107     }
 3108   }
 3109   out[j] = '\0';
 3110 
 3111   return out;
 3112 }
 3113 
 3114 /* Help screen */
 3115 void help()
 3116 {
 3117   int i, max;
 3118 
 3119   printf
 3120     ("\n"
 3121      "Usage:\n"
 3122      "\n"
 3123      "  sipp remote_host[:remote_port] [options]\n"
 3124      "\n"
 3125      "  Available options:\n"
 3126      "\n");
 3127 
 3128   /* We automatically generate the help messages based on the options array.
 3129    * This should hopefully encourage people to write help text when they
 3130    * introduce a new option and keep the code a bit cleaner. */
 3131     max = sizeof(options_table)/sizeof(options_table[0]);
 3132     for (i = 0; i < max; i++) {
 3133       char *formatted;
 3134       if (!options_table[i].help) {
 3135         continue;
 3136       }
 3137       formatted = wrap(options_table[i].help, 22, 57);
 3138       printf("   -%-16s: %s\n\n", options_table[i].option, formatted);
 3139       free(formatted);
 3140     }
 3141 
 3142     printf
 3143     (
 3144      "Signal handling:\n"
 3145      "\n"
 3146      "   SIPp can be controlled using posix signals. The following signals\n"
 3147      "   are handled:\n"
 3148      "   USR1: Similar to press 'q' keyboard key. It triggers a soft exit\n"
 3149      "         of SIPp. No more new calls are placed and all ongoing calls\n"
 3150      "         are finished before SIPp exits.\n"
 3151      "         Example: kill -SIGUSR1 732\n"
 3152      "   USR2: Triggers a dump of all statistics screens in\n"
 3153      "         <scenario_name>_<pid>_screens.log file. Especially useful \n"
 3154      "         in background mode to know what the current status is.\n"
 3155      "         Example: kill -SIGUSR2 732\n"
 3156      "\n"
 3157      "Exit code:\n"
 3158      "\n"
 3159      "   Upon exit (on fatal error or when the number of asked calls (-m\n"
 3160      "   option) is reached, sipp exits with one of the following exit\n"
 3161      "   code:\n"
 3162      "    0: All calls were successful\n"
 3163      "    1: At least one call failed\n"
 3164      "   97: exit on internal command. Calls may have been processed\n"
 3165      "   99: Normal exit without calls processed\n"
 3166      "   -1: Fatal error\n"
 3167      "\n"
 3168      "\n"
 3169      "Example:\n"
 3170      "\n"
 3171      "   Run sipp with embedded server (uas) scenario:\n"
 3172      "     ./sipp -sn uas\n"
 3173      "   On the same host, run sipp with embedded client (uac) scenario\n"
 3174      "     ./sipp -sn uac 127.0.0.1\n"
 3175      "\n");
 3176 }
 3177 
 3178 
 3179 void help_stats()
 3180 {
 3181   printf(
 3182 "\n"
 3183 "  The  -trace_stat option dumps all statistics in the\n"
 3184 "  <scenario_name.csv> file. The dump starts with one header\n"
 3185 "  line with all counters. All following lines are 'snapshots' of \n"
 3186 "  statistics counter given the statistics report frequency\n"
 3187 "  (-fd option). This file can be easily imported in any\n"
 3188 "  spreadsheet application, like Excel.\n"
 3189 "\n"
 3190 "  In counter names, (P) means 'Periodic' - since last\n"
 3191 "  statistic row and (C) means 'Cumulated' - since sipp was\n"
 3192 "  started.\n"
 3193 "\n"
 3194 "  Available statistics are:\n"
 3195 "\n"
 3196 "  - StartTime: \n"
 3197 "    Date and time when the test has started.\n"
 3198 "\n"
 3199 "  - LastResetTime:\n"
 3200 "    Date and time when periodic counters where last reseted.\n"
 3201 "\n"
 3202 "  - CurrentTime:\n"
 3203 "    Date and time of the statistic row.\n"
 3204 "\n"
 3205 "  - ElapsedTime:\n"
 3206 "    Elapsed time.\n"
 3207 "\n"
 3208 "  - CallRate:\n"
 3209 "    Call rate (calls per seconds).\n"
 3210 "\n"
 3211 "  - IncomingCall:\n"
 3212 "    Number of incoming calls.\n"
 3213 "\n"
 3214 "  - OutgoingCall:\n"
 3215 "    Number of outgoing calls.\n"
 3216 "\n"
 3217 "  - TotalCallCreated:\n"
 3218 "    Number of calls created.\n"
 3219 "\n"
 3220 "  - CurrentCall:\n"
 3221 "    Number of calls currently ongoing.\n"
 3222 "\n"
 3223 "  - SuccessfulCall:\n"
 3224 "    Number of successful calls.\n"
 3225 "\n"
 3226 "  - FailedCall:\n"
 3227 "    Number of failed calls (all reasons).\n"
 3228 "\n"
 3229 "  - FailedCannotSendMessage:\n"
 3230 "    Number of failed calls because Sipp cannot send the\n"
 3231 "    message (transport issue).\n"
 3232 "\n"
 3233 "  - FailedMaxUDPRetrans:\n"
 3234 "    Number of failed calls because the maximum number of\n"
 3235 "    UDP retransmission attempts has been reached.\n"
 3236 "\n"
 3237 "  - FailedUnexpectedMessage:\n"
 3238 "    Number of failed calls because the SIP message received\n"
 3239 "    is not expected in the scenario.\n"
 3240 "\n"
 3241 "  - FailedCallRejected:\n"
 3242 "    Number of failed calls because of Sipp internal error.\n"
 3243 "    (a scenario sync command is not recognized or a scenario\n"
 3244 "    action failed or a scenario variable assignment failed).\n"
 3245 "\n"
 3246 "  - FailedCmdNotSent:\n"
 3247 "    Number of failed calls because of inter-Sipp\n"
 3248 "    communication error (a scenario sync command failed to\n"
 3249 "    be sent).\n"
 3250 "\n"
 3251 "  - FailedRegexpDoesntMatch:\n"
 3252 "    Number of failed calls because of regexp that doesn't\n"
 3253 "    match (there might be several regexp that don't match\n"
 3254 "    during the call but the counter is increased only by\n"
 3255 "    one).\n"
 3256 "\n"
 3257 "  - FailedRegexpHdrNotFound:\n"
 3258 "    Number of failed calls because of regexp with hdr    \n"
 3259 "    option but no matching header found.\n"
 3260 "\n"
 3261 "  - OutOfCallMsgs:\n"
 3262 "    Number of SIP messages received that cannot be associated\n"
 3263 "    to an existing call.\n"
 3264 "\n"
 3265 "  - AutoAnswered:\n"
 3266 "    Number of unexpected specific messages received for new Call-ID.\n"
 3267 "    The message has been automatically answered by a 200 OK\n"
 3268 "    Currently, implemented for 'PING' message only.\n"
 3269 "\n");
 3270 }
 3271 
 3272 /************* exit handler *****************/
 3273 
 3274 void print_last_stats()
 3275 {
 3276   interrupt = 1;
 3277   // print last current screen
 3278   print_statistics(1);
 3279   // and print statistics screen
 3280   currentScreenToDisplay = DISPLAY_STAT_SCREEN;
 3281   print_statistics(1);
 3282 }
 3283 
 3284 void releaseGlobalAllocations()
 3285 {
 3286   int i,j;
 3287   message * L_ptMsg = NULL;
 3288 
 3289   CStat::instance()->close();
 3290 
 3291   for(i=0; i<=maxVariableUsed; i++) {
 3292     for (j=0; j<SCEN_MAX_MESSAGES;j++)
 3293     {
 3294       if (scenVariableTable[i][j] != NULL)
 3295         delete(scenVariableTable[i][j]);
 3296       scenVariableTable[i][j] = NULL;
 3297     }
 3298       delete scenVariableTable[i];
 3299       scenVariableTable[i] = NULL;
 3300     }
 3301   for(i=0; i<scenario_len; i++)
 3302   {
 3303     L_ptMsg = scenario[i];
 3304     if (L_ptMsg != NULL)
 3305     {
 3306       delete(L_ptMsg);
 3307       scenario[i] = NULL;
 3308     }
 3309   }
 3310 }
 3311 
 3312 void stop_all_traces()
 3313 {
 3314   if(messagef) messagef = NULL;
 3315   if(logfile) logfile = NULL;
 3316  // if(timeoutf) timeoutf = NULL; TODO: finish the -trace_timeout option implementation
 3317   if(dumpInRtt) dumpInRtt = 0;
 3318   if(dumpInFile) dumpInFile = 0;
 3319 
 3320 }
 3321 
 3322 char* remove_pattern(char* P_buffer, char* P_extensionPattern) {
 3323 
 3324   char *L_ptr = P_buffer;
 3325 
 3326   if (P_extensionPattern == NULL) {
 3327     return P_buffer ;
 3328   }
 3329 
 3330   if (P_buffer == NULL) {
 3331     return P_buffer ;
 3332   }
 3333 
 3334   L_ptr = strstr(P_buffer, P_extensionPattern) ;
 3335   if (L_ptr != NULL) {
 3336     *L_ptr = '\0' ;
 3337   }
 3338 
 3339   return P_buffer ;
 3340 }
 3341 
 3342 static struct sipp_socket *sipp_allocate_socket(bool use_ipv6, int transport, int fd, int accepting) {
 3343   struct sipp_socket *ret = NULL;
 3344 
 3345   ret = (struct sipp_socket *)malloc(sizeof(struct sipp_socket));
 3346   if (!ret) {
 3347     ERROR("Could not allocate a sipp_socket structure.");
 3348   }
 3349   memset(ret, 0, sizeof(struct sipp_socket));
 3350 
 3351 
 3352   ret->ss_transport = transport;
 3353   ret->ss_control = false;
 3354   ret->ss_ipv6 = use_ipv6;
 3355   ret->ss_fd = fd;
 3356   ret->ss_comp_state = NULL;
 3357   ret->ss_count = 1;
 3358 
 3359   /* Initialize all sockets with our destination address. */
 3360   memcpy(&ret->ss_remote_sockaddr, &remote_sockaddr, sizeof(ret->ss_remote_sockaddr));
 3361 
 3362 #ifdef _USE_OPENSSL
 3363   ret->ss_ssl = NULL;
 3364 
 3365   if ( transport == T_TLS ) {
 3366     if ((ret->ss_bio = BIO_new_socket(fd,BIO_NOCLOSE)) == NULL) {
 3367       ERROR("Unable to create BIO object:Problem with BIO_new_socket()\n");
 3368     }
 3369 
 3370     if (!(ret->ss_ssl = SSL_new(accepting ? sip_trp_ssl_ctx : sip_trp_ssl_ctx_client))) {
 3371       ERROR("Unable to create SSL object : Problem with SSL_new() \n");
 3372     }
 3373 
 3374     SSL_set_bio(ret->ss_ssl,ret->ss_bio,ret->ss_bio);
 3375   }
 3376 #endif
 3377 
 3378   ret->ss_in = NULL;
 3379   ret->ss_out = NULL;
 3380   ret->ss_msglen = 0;
 3381   ret->ss_congested = false;
 3382   ret->ss_invalid = false;
 3383 
 3384   /* Store this socket in the tables. */
 3385   ret->ss_pollidx = pollnfds++;
 3386   sockets[ret->ss_pollidx] = ret;
 3387   pollfiles[ret->ss_pollidx].fd      = ret->ss_fd;
 3388   pollfiles[ret->ss_pollidx].events  = POLLIN | POLLERR;
 3389   pollfiles[ret->ss_pollidx].revents = 0;
 3390 
 3391   return ret;
 3392 }
 3393 
 3394 static struct sipp_socket *sipp_allocate_socket(bool use_ipv6, int transport, int fd) {
 3395   return sipp_allocate_socket(use_ipv6, transport, fd, 0);
 3396 }
 3397 
 3398 struct sipp_socket *new_sipp_socket(bool use_ipv6, int transport) {
 3399   int socket_type;
 3400   struct sipp_socket *ret;
 3401   int fd;
 3402 
 3403   switch(transport) {
 3404     case T_UDP:
 3405       socket_type = SOCK_DGRAM;
 3406       break;
 3407     case T_TLS:
 3408 #ifndef _USE_OPENSSL
 3409       ERROR("You do not have TLS support enabled!\n");
 3410 #endif
 3411     case T_TCP:
 3412       socket_type = SOCK_STREAM;
 3413       break;
 3414   }
 3415 
 3416   if((fd = socket(use_ipv6 ? AF_INET6 : AF_INET, socket_type, 0))== -1) {
 3417     ERROR_P1("Unable to get a %s socket", TRANSPORT_TO_STRING(transport));
 3418   }
 3419 
 3420   ret  = sipp_allocate_socket(use_ipv6, transport, fd);
 3421   if (!ret) {
 3422     close(fd);
 3423     ERROR("Could not allocate new socket structure!");
 3424   }
 3425   return ret;
 3426 }
 3427 
 3428 struct sipp_socket *new_sipp_call_socket(bool use_ipv6, int transport, bool *existing) {
 3429   struct sipp_socket *sock = NULL;
 3430   static int next_socket;
 3431   if (call_sockets >= max_multi_socket - 1) {  // we must take the main socket into account
 3432     /* Find an existing socket that matches transport and ipv6 parameters. */
 3433     int first = next_socket;
 3434     do
 3435     {
 3436       int test_socket = next_socket;
 3437       next_socket = (next_socket + 1) % pollnfds;
 3438 
 3439       assert(sockets[test_socket]->ss_call_socket >= 0);
 3440       if (sockets[test_socket]->ss_call_socket) {
 3441   sock = sockets[test_socket];
 3442   sock->ss_count++;
 3443   *existing = true;
 3444   break;
 3445       }
 3446     }
 3447     while (next_socket != first);
 3448     if (next_socket == first) {
 3449       ERROR("Could not find an existing call socket to re-use!");
 3450     }
 3451   } else {
 3452     sock = new_sipp_socket(use_ipv6, transport);
 3453     sock->ss_call_socket = true;
 3454     call_sockets++;
 3455     *existing = false;
 3456   }
 3457   return sock;
 3458 }
 3459 
 3460 struct sipp_socket *sipp_accept_socket(struct sipp_socket *accept_socket) {
 3461   struct sipp_socket *ret;
 3462   struct sockaddr_storage remote_sockaddr;
 3463   int fd;
 3464   sipp_socklen_t addrlen = sizeof(remote_sockaddr);
 3465 
 3466   if((fd = accept(accept_socket->ss_fd, (struct sockaddr *)&remote_sockaddr, &addrlen))== -1) {
 3467     ERROR_P2("Unable to accept on a %s socket: %s", TRANSPORT_TO_STRING(transport), strerror(errno));
 3468   }
 3469 
 3470   ret  = sipp_allocate_socket(accept_socket->ss_ipv6, accept_socket->ss_transport, fd, 1);
 3471   if (!ret) {
 3472   close(fd);
 3473   ERROR_NO("Could not allocate new socket!");
 3474   }
 3475 
 3476   memcpy(&ret->ss_remote_sockaddr, &remote_sockaddr, sizeof(ret->ss_remote_sockaddr));
 3477 
 3478   if (ret->ss_transport == T_TLS) {
 3479 #ifdef _USE_OPENSSL
 3480     int err;
 3481     if ((err = SSL_accept(ret->ss_ssl)) < 0) {
 3482       ERROR_P1("Error in SSL_accept: %s\n", sip_tls_error_string(accept_socket->ss_ssl, err));
 3483     }
 3484 #else
 3485     ERROR("You need to compile SIPp with TLS support");
 3486 #endif
 3487   }
 3488 
 3489   return ret;
 3490 }
 3491 
 3492 int sipp_bind_socket(struct sipp_socket *socket, struct sockaddr_storage *saddr, int *port) {
 3493   int ret;
 3494   int len;
 3495 
 3496   if (socket->ss_ipv6) {
 3497     len = sizeof(struct sockaddr_in6);
 3498   } else {
 3499     len = sizeof(struct sockaddr_in);
 3500   }
 3501 
 3502   if((ret = bind(socket->ss_fd, (sockaddr *)saddr, len))) {
 3503     return ret;
 3504   }
 3505 
 3506   if (!port) {
 3507     return 0;
 3508   }
 3509 
 3510   if ((ret = getsockname(socket->ss_fd, (sockaddr *)saddr, (sipp_socklen_t *) &len))) {
 3511     return ret;
 3512   }
 3513 
 3514   if (socket->ss_ipv6) {
 3515     *port = ntohs((short)((_RCAST(struct sockaddr_in6 *, saddr))->sin6_port));
 3516   } else {
 3517     *port = ntohs((short)((_RCAST(struct sockaddr_in *, saddr))->sin_port));
 3518   }
 3519 
 3520   return 0;
 3521 }
 3522 
 3523 int sipp_connect_socket(struct sipp_socket *socket, struct sockaddr_storage *dest) {
 3524   int fd;
 3525 
 3526   assert(socket->ss_transport == T_TCP || socket->ss_transport == T_TLS);
 3527 
 3528   fd = connect(socket->ss_fd, (struct sockaddr *)dest, SOCK_ADDR_SIZE(dest));
 3529   if (fd < 0) {
 3530     return fd;
 3531   }
 3532 
 3533   if (socket->ss_transport == T_TLS) {
 3534 #ifdef _USE_OPENSSL
 3535     int err;
 3536     if ((err = SSL_connect(socket->ss_ssl)) < 0) {
 3537       ERROR_P1("Error in SSL connection: %s\n", sip_tls_error_string(socket->ss_ssl, err));
 3538     }
 3539 #else
 3540     ERROR("You need to compile SIPp with TLS support");
 3541 #endif
 3542   }
 3543 
 3544   return 0;
 3545 }
 3546 
 3547 /* Main */
 3548 int main(int argc, char *argv[])
 3549 {
 3550   int                  argi = 0;
 3551   struct sockaddr_storage   media_sockaddr;
 3552   pthread_t            pthread_id, pthread2_id,  pthread3_id;
 3553   int                  L_maxSocketPresent = 0;
 3554   unsigned int         generic_count = 0;
 3555   bool                 slave_masterSet = false;
 3556 
 3557   generic[0] = NULL;
 3558 
 3559   /* At least one argument is needed */
 3560   if(argc < 2) {
 3561     help();
 3562     exit(EXIT_OTHER);
 3563   }
 3564   {
 3565     /* Ignore the SIGPIPE signal */
 3566     struct sigaction action_pipe;
 3567     memset(&action_pipe, 0, sizeof(action_pipe));
 3568     action_pipe.sa_handler=SIG_IGN;
 3569     sigaction(SIGPIPE, &action_pipe, NULL);
 3570 
 3571     /* The Window Size change Signal is also useless, and causes failures. */
 3572 #ifdef SIGWINCH
 3573     sigaction(SIGWINCH, &action_pipe, NULL);
 3574 #endif
 3575 
 3576     /* sig usr1 management */
 3577     struct sigaction action_usr1;
 3578     memset(&action_usr1, 0, sizeof(action_usr1));
 3579     action_usr1.sa_handler = sipp_sigusr1;
 3580     sigaction(SIGUSR1, &action_usr1, NULL);
 3581 
 3582     /* sig usr2 management */
 3583     struct sigaction action_usr2;
 3584     memset(&action_usr2, 0, sizeof(action_usr2));
 3585     action_usr2.sa_handler = sipp_sigusr2;
 3586     sigaction(SIGUSR2, &action_usr2, NULL);
 3587   }
 3588 
 3589   screen_set_exename((char *)"sipp");
 3590 
 3591   pid = getpid();
 3592   memset(local_ip, 0, 40);
 3593   memset(media_ip,0, 40);
 3594   memset(media_ip_escaped,0, 42);
 3595 
 3596   /* Load compression pluggin if available */
 3597   comp_load();
 3598 
 3599   /* Initialize the tolower table. */
 3600   init_tolower_table();
 3601 
 3602   /* Command line parsing */
 3603 #define REQUIRE_ARG() if((++argi) >= argc) { ERROR_P1("Missing argument for param '%s'.\n" \
 3604              "Use 'sipp -h' for details",  argv[argi - 1]); }
 3605 #define CHECK_PASS() if (option->pass != pass) { break; }
 3606 
 3607   for (int pass = 0; pass <= 2; pass++) {
 3608     for(argi = 1; argi < argc; argi++) {
 3609       struct sipp_option *option = find_option(argv[argi]);
 3610       if (!option) {
 3611   if((argv[argi])[0] != '-') {
 3612     strcpy(remote_host, argv[argi]);
 3613     continue;
 3614   }
 3615   help();
 3616   ERROR_P1("Invalid argument: '%s'.\n"
 3617       "Use 'sipp -h' for details", argv[argi]);
 3618       }
 3619 
 3620       switch(option->type)
 3621       {
 3622   case SIPP_OPTION_HELP:
 3623     if(((argi+1) < argc) && (!strcmp(argv[argi+1], "stat"))) {
 3624       help_stats();
 3625     } else {
 3626       help();
 3627     }
 3628     exit(EXIT_OTHER);
 3629   case SIPP_OPTION_VERSION:
 3630     printf("\n SIPp v2.0"
 3631 #ifdef _USE_OPENSSL
 3632         "-TLS"
 3633 #endif
 3634 #ifdef PCAPPLAY
 3635         "-PCAP"
 3636 #endif
 3637         ", version %d, built %s, %s.\n\n",
 3638         SIPP_VERSION, __DATE__, __TIME__);
 3639 
 3640     printf
 3641       (" This program is free software; you can redistribute it and/or\n"
 3642        " modify it under the terms of the GNU General Public License as\n"
 3643        " published by the Free Software Foundation; either version 2 of\n"
 3644        " the License, or (at your option) any later version.\n"
 3645        "\n"
 3646        " This program is distributed in the hope that it will be useful,\n"
 3647        " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
 3648        " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
 3649        " GNU General Public License for more details.\n"
 3650        "\n"
 3651        " You should have received a copy of the GNU General Public\n"
 3652        " License along with this program; if not, write to the\n"
 3653        " Free Software Foundation, Inc.,\n"
 3654        " 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA\n"
 3655        "\n"
 3656        " Author: see source files.\n\n");
 3657     exit(EXIT_OTHER);
 3658   case SIPP_OPTION_INT:
 3659     REQUIRE_ARG();
 3660     CHECK_PASS();
 3661     *((int *)option->data) = get_long(argv[argi], argv[argi-1]);
 3662     break;
 3663         case SIPP_OPTION_LONG:
 3664           REQUIRE_ARG();
 3665           CHECK_PASS();
 3666           *((long *)option->data) = get_long(argv[argi], argv[argi-1]);
 3667           break;
 3668   case SIPP_OPTION_TIME_SEC:
 3669     REQUIRE_ARG();
 3670     CHECK_PASS();
 3671     *((long *)option->data) = get_time(argv[argi], argv[argi-1], 1000);
 3672     break;
 3673   case SIPP_OPTION_TIME_MS:
 3674     REQUIRE_ARG();
 3675     CHECK_PASS();
 3676     *((int *)option->data) = get_time(argv[argi], argv[argi-1], 1);
 3677     break;
 3678         case SIPP_OPTION_TIME_MS_LONG:
 3679           REQUIRE_ARG();
 3680           CHECK_PASS();
 3681           *((long *)option->data) = get_time(argv[argi], argv[argi-1], 1);
 3682           break;
 3683   case SIPP_OPTION_BOOL:
 3684     REQUIRE_ARG();
 3685     CHECK_PASS();
 3686     *((bool *)option->data) = get_bool(argv[argi], argv[argi-1]);
 3687     break;
 3688   case SIPP_OPTION_FLOAT:
 3689     REQUIRE_ARG();
 3690     CHECK_PASS();
 3691     *((double *)option->data) = get_double(argv[argi], argv[argi-1]);
 3692     break;
 3693   case SIPP_OPTION_STRING:
 3694     REQUIRE_ARG();
 3695     CHECK_PASS();
 3696     *((char **)option->data) = argv[argi];
 3697     break;
 3698   case SIPP_OPTION_ARGI:
 3699     REQUIRE_ARG();
 3700     CHECK_PASS();
 3701     *((int *)option->data) = argi;
 3702     break;
 3703   case SIPP_OPTION_INPUT_FILE:
 3704     REQUIRE_ARG();
 3705     CHECK_PASS();
 3706     inFiles[argv[argi]] = new FileContents(argv[argi]);
 3707     /* By default, the first file is used for IP address input. */
 3708     if (!ip_file) {
 3709       ip_file = argv[argi];
 3710     }
 3711     if (!default_file) {
 3712       default_file = argv[argi];
 3713     }
 3714     break;
 3715   case SIPP_OPTION_SETFLAG:
 3716     CHECK_PASS();
 3717     *((bool *)option->data) = true;
 3718     break;
 3719   case SIPP_OPTION_UNSETFLAG:
 3720     CHECK_PASS();
 3721     *((bool *)option->data) = false;
 3722     break;
 3723   case SIPP_OPTION_TRANSPORT:
 3724     REQUIRE_ARG();
 3725     CHECK_PASS();
 3726 
 3727     if (strlen(argv[argi]) != 2) {
 3728       ERROR_P1("Invalid argument for -t param : '%s'.\n"
 3729     "Use 'sipp -h' for details",  argv[argi]);
 3730     }
 3731 
 3732     switch(argv[argi][0]) {
 3733       case 'u':
 3734         transport = T_UDP;
 3735         break;
 3736       case 't':
 3737         transport = T_TCP;
 3738         break;
 3739       case 'l':
 3740 #ifdef _USE_OPENSSL
 3741         transport = T_TLS;
 3742         if ( init_OpenSSL() != 1) {
 3743     printf("OpenSSL Initialization problem\n");
 3744     exit ( -1);
 3745         }
 3746 #else
 3747         ERROR("To use a TLS transport you must compile SIPp with OpenSSL");
 3748 #endif
 3749         break;
 3750       case 'c':
 3751         if(strlen(comp_error)) {
 3752     ERROR_P1("No " COMP_PLUGGIN " pluggin available:\n%s", comp_error);
 3753         }
 3754         transport = T_UDP;
 3755         compression = 1;
 3756     }
 3757     switch(argv[argi][1]) {
 3758       case '1':
 3759         multisocket = 0;
 3760         peripsocket = 0;
 3761         break;
 3762       case 'n':
 3763         multisocket = 1;
 3764         peripsocket = 0;
 3765         break;
 3766       case 'i':
 3767         multisocket = 1;
 3768         peripsocket = 1;
 3769         socket_close = false;
 3770         break;
 3771     }
 3772 
 3773     if (peripsocket && transport != T_UDP) {
 3774       ERROR("You can only use a perip socket with UDP!\n");
 3775     }
 3776     break;
 3777   case SIPP_OPTION_NEED_SSL:
 3778     CHECK_PASS();
 3779     ERROR_P1("OpenSSL is required for the %s option.", argv[argi]);
 3780     break;
 3781   case SIPP_OPTION_MAX_SOCKET:
 3782     REQUIRE_ARG();
 3783     CHECK_PASS();
 3784     max_multi_socket = get_long(argv[argi], argv[argi - 1]);
 3785     maxSocketPresent = true ;
 3786     break;
 3787   case SIPP_OPTION_CSEQ:
 3788     REQUIRE_ARG();
 3789     CHECK_PASS();
 3790     base_cseq = get_long(argv[argi], argv[argi - 1]);
 3791     base_cseq--;
 3792     break;
 3793   case SIPP_OPTION_IP:
 3794     {
 3795       int dummy_port;
 3796       char *ptr = (char *)option->data;
 3797       REQUIRE_ARG();
 3798       CHECK_PASS();
 3799 
 3800       strcpy(ptr, argv[argi]);
 3801       get_host_and_port(ptr, ptr, &dummy_port);
 3802     }
 3803     break;
 3804   case SIPP_OPTION_LIMIT:
 3805     REQUIRE_ARG();
 3806     CHECK_PASS();
 3807     open_calls_allowed = get_long(argv[argi], argv[argi - 1]);
 3808     open_calls_user_setting = 1;
 3809     break;
 3810   case SIPP_OPTION_USERS:
 3811     REQUIRE_ARG();
 3812     CHECK_PASS();
 3813     users = open_calls_allowed = get_long(argv[argi], argv[argi - 1]);
 3814     open_calls_user_setting = 1;
 3815     for (int i = 1; i <= users; i++) {
 3816       freeUsers.push_back(i);
 3817     }
 3818     break;
 3819   case SIPP_OPTION_KEY:
 3820     REQUIRE_ARG();
 3821     REQUIRE_ARG();
 3822     CHECK_PASS();
 3823 
 3824     if (generic_count+1 >= sizeof(generic)/sizeof(generic[0])) {
 3825       ERROR_P1("Too many generic parameters %d",generic_count+1);
 3826     }
 3827     generic[generic_count++] = &argv[argi - 1];
 3828     generic[generic_count] = NULL;
 3829     break;
 3830   case SIPP_OPTION_3PCC:
 3831 #ifdef __3PCC__
 3832     if(slave_masterSet){
 3833       ERROR("-3PCC option is not compatible with -master and -slave options\n");
 3834     }
 3835     if(extendedTwinSippMode){
 3836       ERROR("-3pcc and -slave_cfg options are not compatible\n");
 3837     }
 3838     REQUIRE_ARG();
 3839     CHECK_PASS();
 3840     twinSippMode = true;
 3841     strcpy(twinSippHost, argv[argi]);
 3842      get_host_and_port(twinSippHost, twinSippHost, &twinSippPort);
 3843 #else
 3844     ERROR("SIPp was not compiled with 3PCC enabled!");
 3845 #endif
 3846     break;
 3847   case SIPP_OPTION_SCENARIO:
 3848     REQUIRE_ARG();
 3849     CHECK_PASS();
 3850     if (!strcmp(argv[argi - 1], "-sf")) {
 3851       load_scenario(argv[argi], 0);
 3852       scenario_file = new char [strlen(argv[argi])+1] ;
 3853       sprintf(scenario_file,"%s", argv[argi]);
 3854       CStat::instance()->setFileName(argv[argi], (char*)".csv");
 3855     } else if (!strcmp(argv[argi - 1], "-sn")) {
 3856       int i = find_scenario(argv[argi]);
 3857 
 3858       if (i < 0) {
 3859         ERROR_P1("Invalid default scenario name '%s'.\n", argv[argi]);
 3860       }
 3861 
 3862       CStat::instance()->setFileName(argv[argi], (char*)".csv");
 3863       load_scenario(0, i);
 3864       scenario_file = new char [strlen(argv[argi])+1] ;
 3865       sprintf(scenario_file,"%s", argv[argi]);
 3866     } else if (!strcmp(argv[argi - 1], "-sd")) {
 3867       int i = find_scenario(argv[argi]);
 3868 
 3869       if (i < 0) {
 3870         ERROR_P1("Invalid default scenario name '%s'.\n", argv[argi]);
 3871       }
 3872 
 3873       fprintf(stdout, "%s", default_scenario[i]);
 3874       exit(EXIT_OTHER);
 3875     } else {
 3876       ERROR_P1("Internal error, I don't recognize %s as a scenario option\n", argv[argi] - 1);
 3877     }
 3878     break;
 3879   case SIPP_OPTION_SLAVE_CFG:
 3880     REQUIRE_ARG();
 3881     CHECK_PASS();
 3882     if(twinSippMode){
 3883       ERROR("-slave_cfg and -3pcc options are not compatible\n");
 3884     }
 3885     extendedTwinSippMode = true;
 3886     slave_cfg_file = new char [strlen(argv[argi])+1] ;
 3887     sprintf(slave_cfg_file,"%s", argv[argi]);
 3888     parse_slave_cfg();
 3889     break;
 3890   case SIPP_OPTION_3PCC_EXTENDED:
 3891      REQUIRE_ARG();
 3892      CHECK_PASS();
 3893     if(slave_masterSet){
 3894       ERROR("-slave and -master options are not compatible\n");
 3895     }
 3896     if(twinSippMode){
 3897       ERROR("-master and -slave options are not compatible with -3PCC option\n");
 3898     }
 3899     *((char **)option->data) = argv[argi];
 3900     slave_masterSet = true;
 3901     break;
 3902   case SIPP_OPTION_RSA: {
 3903     REQUIRE_ARG();
 3904     CHECK_PASS();
 3905     char *remote_s_address ;
 3906     int   remote_s_p = DEFAULT_PORT;
 3907     int   temp_remote_s_p;
 3908 
 3909     temp_remote_s_p = 0;
 3910     remote_s_address = argv[argi] ;
 3911     get_host_and_port(remote_s_address, remote_s_address, &temp_remote_s_p);
 3912     if (temp_remote_s_p != 0) {
 3913       remote_s_p = temp_remote_s_p;
 3914     }
 3915     struct addrinfo   hints;
 3916     struct addrinfo * local_addr;
 3917 
 3918     printf("Resolving remote sending address %s...\n", remote_s_address);
 3919 
 3920     memset((char*)&hints, 0, sizeof(hints));
 3921     hints.ai_flags  = AI_PASSIVE;
 3922     hints.ai_family = PF_UNSPEC;
 3923 
 3924     /* FIXME: add DNS SRV support using liburli? */
 3925     if (getaddrinfo(remote_s_address,
 3926     NULL,
 3927     &hints,
 3928     &local_addr) != 0) {
 3929       ERROR_P1("Unknown remote host '%s'.\n"
 3930     "Use 'sipp -h' for details", remote_s_address);
 3931     }
 3932 
 3933     memcpy(&remote_sending_sockaddr,
 3934         local_addr->ai_addr,
 3935         SOCK_ADDR_SIZE(
 3936     _RCAST(struct sockaddr_storage *, local_addr->ai_addr)));
 3937 
 3938     if (remote_sending_sockaddr.ss_family == AF_INET) {
 3939       (_RCAST(struct sockaddr_in *, &remote_sending_sockaddr))->sin_port =
 3940         htons((short)remote_s_p);
 3941     } else {
 3942       (_RCAST(struct sockaddr_in6 *, &remote_sending_sockaddr))->sin6_port =
 3943         htons((short)remote_s_p);
 3944     }
 3945     use_remote_sending_addr = 1 ;
 3946 
 3947     freeaddrinfo(local_addr);
 3948     break;
 3949   }
 3950   case SIPP_OPTION_TDMMAP: {
 3951           REQUIRE_ARG();
 3952     CHECK_PASS();
 3953     int i1, i2, i3, i4, i5, i6, i7;
 3954 
 3955     if (sscanf(argv[argi], "{%d-%d}{%d}{%d-%d}{%d-%d}", &i1, &i2, &i3, &i4, &i5, &i6, &i7) == 7) {
 3956       use_tdmmap = true;
 3957       tdm_map_a = i2 - i1;
 3958       tdm_map_x = i1;
 3959       tdm_map_h = i3;
 3960       tdm_map_b = i5 - i4;
 3961       tdm_map_y = i4;
 3962       tdm_map_c = i7 - i6;
 3963       tdm_map_z = i6;
 3964     } else {
 3965       ERROR("Parameter -tdmmap must be of form {%%d-%%d}{%%d}{%%d-%%d}{%%d-%%d}");
 3966     }
 3967     break;
 3968   }
 3969   default:
 3970     ERROR_P1("Internal error: I don't recognize the option type for %s\n", argv[argi]);
 3971       }
 3972     }
 3973   }
 3974 
 3975   if((extendedTwinSippMode && !slave_masterSet) || (!extendedTwinSippMode && slave_masterSet)){
 3976     ERROR("-slave_cfg option must be used with -slave or -master option\n");
 3977   }
 3978 
 3979   if (peripsocket) {
 3980     if (!ip_file) {
 3981       ERROR("You must use the -inf option when using -t ui.\n"
 3982                "Use 'sipp -h' for details");
 3983     }
 3984   }
 3985 
 3986   if (global_lost) {
 3987     lose_packets = 1;
 3988   }
 3989 
 3990   /* trace file setting */
 3991   if (scenario_file == NULL) {
 3992     scenario_file = new char [ 5 ] ;
 3993     sprintf(scenario_file, "%s", "sipp");
 3994   } else {
 3995     scenario_file = remove_pattern (scenario_file, (char*)".xml");
 3996   }
 3997 
 3998    if (print_all_responses) {
 3999       char L_file_name [MAX_PATH];
 4000       sprintf (L_file_name, "%s_%d_errors.log", scenario_file, getpid());
 4001       screen_init(L_file_name, print_last_stats);
 4002     } else {
 4003       screen_init(NULL, print_last_stats);
 4004     }
 4005 
 4006 #ifdef _USE_OPENSSL
 4007     if ((transport == T_TLS) && (FI_init_ssl_context() != SSL_INIT_NORMAL))
 4008     {
 4009       ERROR("FI_init_ssl_context() failed");
 4010     }
 4011 #endif
 4012 
 4013   if (useMessagef == 1) {
 4014     char L_file_name [MAX_PATH];
 4015     sprintf (L_file_name, "%s_%d_messages.log", scenario_file, getpid());
 4016     messagef = fopen(L_file_name, "w");
 4017     if(!messagef) {
 4018       ERROR_P1("Unable to create '%s'", L_file_name);
 4019     }
 4020   }
 4021 
 4022   if (useShortMessagef == 1) {
 4023     char L_file_name [MAX_PATH];
 4024     sprintf (L_file_name, "%s_%d_shortmessages.log", scenario_file, getpid());
 4025     shortmessagef = fopen(L_file_name, "w");
 4026     if(!shortmessagef) {
 4027       ERROR_P1("Unable to create '%s'", L_file_name);
 4028     }
 4029   }
 4030 
 4031   if (useScreenf == 1) {
 4032     char L_file_name [MAX_PATH];
 4033     sprintf (L_file_name, "%s_%d_screen.log", scenario_file, getpid());
 4034     screenf = fopen(L_file_name, "w");
 4035     if(!screenf) {
 4036       ERROR_P1("Unable to create '%s'", L_file_name);
 4037     }
 4038   }
 4039 
 4040    // TODO: finish the -trace_timeout option implementation
 4041 
 4042  /* if (useTimeoutf == 1) {
 4043     char L_file_name [MAX_PATH];
 4044     sprintf (L_file_name, "%s_%d_timeout.log", scenario_file, getpid());
 4045     timeoutf = fopen(L_file_name, "w");
 4046     if(!timeoutf) {
 4047       ERROR_P1("Unable to create '%s'", L_file_name);
 4048     }
 4049   } */
 4050 
 4051   if (useLogf == 1) {
 4052     char L_file_name [MAX_PATH];
 4053     sprintf (L_file_name, "%s_%d_logs.log", scenario_file, getpid());
 4054     logfile = fopen(L_file_name, "w");
 4055     if(!logfile) {
 4056       ERROR_P1("Unable to create '%s'", L_file_name);
 4057     }
 4058   }
 4059 
 4060   if (dumpInRtt == 1) {
 4061      CStat::instance()->initRtt((char*)scenario_file, (char*)".csv",
 4062                                 report_freq_dumpRtt);
 4063   }
 4064 
 4065   if ((maxSocketPresent) && (max_multi_socket > FD_SETSIZE) ) {
 4066      L_maxSocketPresent = 1;
 4067   }
 4068 
 4069   /* Initialization:  boost open file limit to the max (AgM)*/
 4070   {
 4071     struct rlimit rlimit;
 4072 
 4073     if (getrlimit (RLIMIT_NOFILE, &rlimit) < 0) {
 4074       ERROR_NO("getrlimit error");
 4075     }
 4076 
 4077     if (rlimit.rlim_max >
 4078 #ifndef __CYGWIN
 4079        ((L_maxSocketPresent) ?  max_multi_socket : FD_SETSIZE)
 4080 #else
 4081        FD_SETSIZE
 4082 #endif
 4083        ) {
 4084       fprintf (stderr, "Warning: open file limit > FD_SETSIZE; "
 4085                "limiting max. # of open files to FD_SETSIZE = %d\n",
 4086                FD_SETSIZE);
 4087 
 4088       rlimit.rlim_max =
 4089 #ifndef __CYGWIN
 4090           (L_maxSocketPresent) ?  max_multi_socket+min_socket : FD_SETSIZE ;
 4091 #else
 4092 
 4093     FD_SETSIZE;
 4094 #endif
 4095     }
 4096 
 4097     rlimit.rlim_cur = rlimit.rlim_max;
 4098     if (setrlimit (RLIMIT_NOFILE, &rlimit) < 0) {
 4099       ERROR_P1("Unable to increase the open file limit to FD_SETSIZE = %d",
 4100                FD_SETSIZE);
 4101     }
 4102   }
 4103 
 4104   /* Load default scenario in case nothing was loaded */
 4105   if(!scenario_len) {
 4106     load_scenario(0, 0);
 4107     CStat::instance()->setFileName((char*)"uac", (char*)".csv");
 4108     sprintf(scenario_file,"uac");
 4109   }
 4110 
 4111   if(argiFileName) {
 4112     CStat::instance()->setFileName(argv[argiFileName]);
 4113   }
 4114 
 4115   /* In which mode the tool is launched ? */
 4116   computeSippMode();
 4117 
 4118   /* checking if we need to launch the tool in background mode */
 4119   if(backgroundMode == true)
 4120     {
 4121       pid_t l_pid;
 4122       switch(l_pid = fork())
 4123         {
 4124         case -1:
 4125           // error when forking !
 4126           ERROR_NO("Forking error");
 4127           exit(EXIT_FATAL_ERROR);
 4128         case 0:
 4129           // child process - poursuing the execution
 4130     // close all of our file descriptors
 4131     {
 4132       int nullfd = open("/dev/null", O_RDWR);
 4133 
 4134       dup2(nullfd, fileno(stdin));
 4135       dup2(nullfd, fileno(stdout));
 4136       dup2(nullfd, fileno(stderr));
 4137 
 4138       close(nullfd);
 4139     }
 4140           break;
 4141         default:
 4142           // parent process - killing the parent - the child get the parent pid
 4143           printf("Background mode - PID=[%d]\n", l_pid);
 4144           exit(EXIT_OTHER);
 4145         }
 4146     }
 4147 
 4148   /* Setting the rate and its dependant params (open_calls_allowed) */
 4149   set_rate(rate);
 4150 
 4151   if (toolMode == MODE_SERVER) {
 4152     reset_number = 0;
 4153   }
 4154 
 4155   open_connections();
 4156 
 4157 
 4158   /* Defaults for media sockets */
 4159   if (media_ip[0] == '\0') {
 4160       strcpy(media_ip, local_ip);
 4161     }
 4162   if (media_ip_escaped[0] == '\0') {
 4163     strcpy(media_ip_escaped, local_ip);
 4164   }
 4165   if (local_ip_is_ipv6) {
 4166     media_ip_is_ipv6 = true;
 4167   } else {
 4168     media_ip_is_ipv6 = false;
 4169   }
 4170 
 4171   /* Always create and Bind RTP socket */
 4172   /* to avoid ICMP                     */
 4173   if (1) {
 4174     /* retrieve RTP local addr */
 4175     struct addrinfo   hints;
 4176     struct addrinfo * local_addr;
 4177 
 4178     memset((char*)&hints, 0, sizeof(hints));
 4179     hints.ai_flags  = AI_PASSIVE;
 4180     hints.ai_family = PF_UNSPEC;
 4181 
 4182     /* Resolving local IP */
 4183     if (getaddrinfo(media_ip,
 4184                     NULL,
 4185                     &hints,
 4186                     &local_addr) != 0) {
 4187       ERROR_P1("Unknown RTP address '%s'.\n"
 4188                "Use 'sipp -h' for details", media_ip);
 4189     }
 4190 
 4191     memcpy(&media_sockaddr,
 4192            local_addr->ai_addr,
 4193            SOCK_ADDR_SIZE(
 4194              _RCAST(struct sockaddr_storage *,local_addr->ai_addr)));
 4195     freeaddrinfo(local_addr);
 4196 
 4197     if((media_socket = socket(media_ip_is_ipv6 ? AF_INET6 : AF_INET,
 4198                               SOCK_DGRAM, 0)) == -1) {
 4199       char msg[512];
 4200       sprintf(msg, "Unable to get the audio RTP socket (IP=%s, port=%d)", media_ip, media_port);
 4201       ERROR_NO(msg);
 4202     }
 4203     /* create a second socket for video */
 4204     if((media_socket_video = socket(media_ip_is_ipv6 ? AF_INET6 : AF_INET,
 4205                                     SOCK_DGRAM, 0)) == -1) {
 4206       char msg[512];
 4207       sprintf(msg, "Unable to get the video RTP socket (IP=%s, port=%d)", media_ip, media_port+2);
 4208       ERROR_NO(msg);
 4209     }
 4210 
 4211     int try_counter;
 4212     int max_tries = user_media_port ? 1 : 10;
 4213     media_port = user_media_port ? user_media_port : DEFAULT_MEDIA_PORT;
 4214     for (try_counter = 0; try_counter < max_tries; try_counter++) {
 4215 
 4216       if (media_sockaddr.ss_family == AF_INET) {
 4217   (_RCAST(struct sockaddr_in *,&media_sockaddr))->sin_port =
 4218     htons((short)media_port);
 4219       } else {
 4220   (_RCAST(struct sockaddr_in6 *,&media_sockaddr))->sin6_port =
 4221     htons((short)media_port);
 4222   media_ip_is_ipv6 = true;
 4223       }
 4224       strcpy(media_ip_escaped, media_ip);
 4225 
 4226       if(bind(media_socket,
 4227       (sockaddr *)(void *)&media_sockaddr,
 4228       SOCK_ADDR_SIZE(&media_sockaddr)) == 0) {
 4229   break;
 4230       }
 4231 
 4232       media_port++;
 4233     }
 4234 
 4235     if (try_counter >= max_tries) {
 4236       char msg[512];
 4237       sprintf(msg, "Unable to bind audio RTP socket (IP=%s, port=%d)", media_ip, media_port);
 4238       ERROR_NO(msg);
 4239     }
 4240 
 4241     /*---------------------------------------------------------
 4242        Bind the second socket to media_port+2
 4243        (+1 is reserved for RTCP)
 4244     ----------------------------------------------------------*/
 4245 
 4246     if (media_sockaddr.ss_family == AF_INET) {
 4247      (_RCAST(struct sockaddr_in *,&media_sockaddr))->sin_port =
 4248        htons((short)media_port+2);
 4249      strcpy(media_ip_escaped, media_ip);
 4250     } else {
 4251       (_RCAST(struct sockaddr_in6 *,&media_sockaddr))->sin6_port =
 4252         htons((short)media_port+2);
 4253       media_ip_is_ipv6 = true;
 4254       strcpy(media_ip_escaped, media_ip);
 4255     }
 4256 
 4257     if(bind(media_socket_video,
 4258             (sockaddr *)(void *)&media_sockaddr,
 4259             SOCK_ADDR_SIZE(&media_sockaddr))) {
 4260       char msg[512];
 4261       sprintf(msg, "Unable to bind video RTP socket (IP=%s, port=%d)", media_ip, media_port+2);
 4262       ERROR_NO(msg);
 4263     }
 4264     /* Second socket bound */
 4265   }
 4266 
 4267   /* Creating the remote control socket thread */
 4268   if (pthread_create
 4269       (&pthread_id,
 4270        NULL,
 4271        (void *(*)(void *)) ctrl_thread,
 4272        (void*)NULL)
 4273       == -1) {
 4274     ERROR_NO("Unable to create remote control socket thread");
 4275   }
 4276 
 4277   if( backgroundMode == false ) {
 4278     /* Creating the keyb thread */
 4279     if (pthread_create
 4280         (&pthread_id,
 4281          NULL,
 4282          (void *(*)(void *)) keyb_thread,
 4283          (void*)NULL)
 4284         == -1) {
 4285       ERROR_NO("Unable to create recv thread");
 4286     }
 4287   }
 4288 
 4289   if ((media_socket > 0) && (rtp_echo_enabled)) {
 4290     if (pthread_create
 4291         (&pthread2_id,
 4292          NULL,
 4293          (void *(*)(void *)) rtp_echo_thread,
 4294          (void*)&media_socket)
 4295         == -1) {
 4296       ERROR_NO("Unable to create RTP echo thread");
 4297     }
 4298   }
 4299 
 4300 
 4301   /* Creating second RTP echo thread for video */
 4302   if ((media_socket_video > 0) && (rtp_echo_enabled)) {
 4303     if (pthread_create
 4304         (&pthread3_id,
 4305          NULL,
 4306          (void *(*)(void *)) rtp_echo_thread,
 4307          (void*)&media_socket_video)
 4308         == -1) {
 4309       ERROR_NO("Unable to create second RTP echo thread");
 4310       }
 4311     }
 4312 
 4313   traffic_thread();
 4314 
 4315   if (scenario_file != NULL) {
 4316     delete [] scenario_file ;
 4317     scenario_file = NULL ;
 4318   }
 4319 
 4320 }
 4321 
 4322 void sipp_usleep(unsigned long usec) {
 4323   if (usec >= 1000000) {
 4324     sleep(usec / 1000000);
 4325   }
 4326   usec %= 1000000;
 4327   usleep(usec);
 4328 }
 4329 
 4330 int reset_connections() {
 4331   int status=0;
 4332 
 4333   start_calls = 1;
 4334   reset_number--;
 4335 
 4336   if (reset_number < 0) {
 4337     ERROR_NO("Max number of reconnections reached");
 4338   }
 4339   if (reset_close) {
 4340     status = close_calls();
 4341   }
 4342   if (status==0) {
 4343     status = close_connections();
 4344     if (status==0) {
 4345       do{
 4346           sipp_usleep(reset_sleep * 1000);
 4347           status = open_connections();
 4348       }while(status == 1);
 4349       start_calls = 0;
 4350       WARNING("Re-connection for connections");
 4351     }
 4352   }
 4353 
 4354   return status;
 4355 }
 4356 
 4357 /* Close *all* of the calls. */
 4358 int close_calls() {
 4359   int status=0;
 4360   call_map * calls = get_calls();
 4361   call_map::iterator call_it;
 4362   call * call_ptr = NULL;
 4363 
 4364   while (calls->begin() != calls->end()) {
 4365     call_ptr = (calls->begin() != calls->end()) ? (calls->begin())->second : NULL ;
 4366     if(call_ptr) {
 4367       calls->erase(calls->begin());
 4368       if (call_ptr->running) {
 4369   if (!remove_running_call(call_ptr)) {
 4370     ERROR("Internal error: A running call is not in the list.\n");
 4371   }
 4372       } else {
 4373   remove_paused_call(call_ptr);
 4374       }
 4375       delete call_ptr;
 4376       open_calls--;
 4377     }
 4378   }
 4379   return status;
 4380 }
 4381 
 4382 /* Close just those calls for a given socket (e.g., if the remote end closes
 4383  * the connection. */
 4384 int close_calls(struct sipp_socket *socket) {
 4385   int status=0;
 4386   call_list * calls = get_calls_for_socket(socket);
 4387   call_list::iterator call_it;
 4388   call * call_ptr = NULL;
 4389 
 4390   for (call_it = calls->begin(); call_it != calls->end(); call_it++) {
 4391     call_ptr = *call_it;
 4392     if (call_ptr->running) {
 4393       if (!remove_running_call(call_ptr)) {
 4394   ERROR("Internal error: A running call is not in the list.\n");
 4395       }
 4396     } else {
 4397       remove_paused_call(call_ptr);
 4398     }
 4399     delete call_ptr;
 4400     open_calls--;
 4401   }
 4402 
 4403   delete calls;
 4404 
 4405   return status;
 4406 }
 4407 
 4408 int close_connections() {
 4409   int status=0;
 4410 
 4411   if (toolMode != MODE_SERVER)   {
 4412     sipp_close_socket(main_socket);
 4413     main_socket = NULL;
 4414   }
 4415   return status;
 4416 }
 4417 
 4418 int open_connections() {
 4419   int status=0;
 4420   local_port = 0;
 4421 
 4422   if(!strlen(remote_host)) {
 4423     if((toolMode != MODE_SERVER)) {
 4424       ERROR("Missing remote host parameter. This scenario requires it");
 4425     }
 4426   } else {
 4427     int temp_remote_port;
 4428     get_host_and_port(remote_host, remote_host, &temp_remote_port);
 4429     if (temp_remote_port != 0) {
 4430       remote_port = temp_remote_port;
 4431     }
 4432 
 4433     /* Resolving the remote IP */
 4434     {
 4435       struct addrinfo   hints;
 4436       struct addrinfo * local_addr;
 4437 
 4438       fprintf(stderr,"Resolving remote host '%s'... ", remote_host);
 4439 
 4440       memset((char*)&hints, 0, sizeof(hints));
 4441       hints.ai_flags  = AI_PASSIVE;
 4442       hints.ai_family = PF_UNSPEC;
 4443 
 4444       /* FIXME: add DNS SRV support using liburli? */
 4445       if (getaddrinfo(remote_host,
 4446                       NULL,
 4447                       &hints,
 4448                       &local_addr) != 0) {
 4449         ERROR_P1("Unknown remote host '%s'.\n"
 4450                  "Use 'sipp -h' for details", remote_host);
 4451       }
 4452 
 4453       memset(&remote_sockaddr, 0, sizeof( remote_sockaddr ));
 4454       memcpy(&remote_sockaddr,
 4455              local_addr->ai_addr,
 4456              SOCK_ADDR_SIZE(
 4457                _RCAST(struct sockaddr_storage *,local_addr->ai_addr)));
 4458 
 4459       freeaddrinfo(local_addr);
 4460 
 4461       strcpy(remote_ip, get_inet_address(&remote_sockaddr));
 4462       if (remote_sockaddr.ss_family == AF_INET) {
 4463         (_RCAST(struct sockaddr_in *, &remote_sockaddr))->sin_port =
 4464           htons((short)remote_port);
 4465         strcpy(remote_ip_escaped, remote_ip);
 4466       } else {
 4467         (_RCAST(struct sockaddr_in6 *, &remote_sockaddr))->sin6_port =
 4468           htons((short)remote_port);
 4469         sprintf(remote_ip_escaped, "[%s]", remote_ip);
 4470       }
 4471       fprintf(stderr,"Done.\n");
 4472     }
 4473    }
 4474 
 4475   if(gethostname(hostname,64) != 0) {
 4476     ERROR_NO("Can't get local hostname in 'gethostname(hostname,64)'");
 4477   }
 4478 
 4479   {
 4480     char            * local_host = NULL;
 4481     struct addrinfo * local_addr;
 4482     struct addrinfo   hints;
 4483 
 4484     if (!strlen(local_ip)) {
 4485       local_host = (char *)hostname;
 4486     } else {
 4487       local_host = (char *)local_ip;
 4488     }
 4489 
 4490     memset((char*)&hints, 0, sizeof(hints));
 4491     hints.ai_flags  = AI_PASSIVE;
 4492     hints.ai_family = PF_UNSPEC;
 4493 
 4494     /* Resolving local IP */
 4495     if (getaddrinfo(local_host, NULL, &hints, &local_addr) != 0) {
 4496       ERROR_P2("Can't get local IP address in getaddrinfo, local_host='%s', local_ip='%s'",
 4497     local_host,
 4498     local_ip);
 4499     }
 4500     // store local addr info for rsa option
 4501     getaddrinfo(local_host, NULL, &hints, &local_addr_storage);
 4502 
 4503     memset(&local_sockaddr,0,sizeof(struct sockaddr_storage));
 4504     local_sockaddr.ss_family = local_addr->ai_addr->sa_family;
 4505 
 4506     if (!strlen(local_ip)) {
 4507       strcpy(local_ip,
 4508     get_inet_address(
 4509       _RCAST(struct sockaddr_storage *, local_addr->ai_addr)));
 4510     } else {
 4511       if (!(local_sockaddr.ss_family == AF_INET6)) {
 4512   memcpy(&local_sockaddr,
 4513       local_addr->ai_addr,
 4514       SOCK_ADDR_SIZE(
 4515         _RCAST(struct sockaddr_storage *,local_addr->ai_addr)));
 4516       }
 4517     }
 4518     freeaddrinfo(local_addr);
 4519 
 4520     if (local_sockaddr.ss_family == AF_INET6) {
 4521       local_ip_is_ipv6 = true;
 4522       sprintf(local_ip_escaped, "[%s]", local_ip);
 4523     } else {
 4524       strcpy(local_ip_escaped, local_ip);
 4525     }
 4526   }
 4527 
 4528   /* Creating and binding the local socket */
 4529   if ((main_socket = new_sipp_socket(local_ip_is_ipv6, transport)) == NULL) {
 4530     ERROR_NO("Unable to get the local socket");
 4531   }
 4532 
 4533   sipp_customize_socket(main_socket);
 4534 
 4535   /* Trying to bind local port */
 4536   char peripaddr[256];
 4537   if(!user_port) {
 4538     unsigned short l_port;
 4539     for(l_port = DEFAULT_PORT;
 4540         l_port < (DEFAULT_PORT + 60);
 4541         l_port++) {
 4542 
 4543       // Bind socket to local_ip
 4544       if (bind_local || peripsocket) {
 4545   struct addrinfo * local_addr;
 4546   struct addrinfo   hints;
 4547   memset((char*)&hints, 0, sizeof(hints));
 4548   hints.ai_flags  = AI_PASSIVE;
 4549   hints.ai_family = PF_UNSPEC;
 4550 
 4551   if (peripsocket) {
 4552     // On some machines it fails to bind to the self computed local
 4553     // IP address.
 4554     // For the socket per IP mode, bind the main socket to the
 4555     // first IP address specified in the inject file.
 4556     inFiles[ip_file]->getField(0, peripfield, peripaddr, sizeof(peripaddr));
 4557     if (getaddrinfo(peripaddr,
 4558     NULL,
 4559     &hints,
 4560     &local_addr) != 0) {
 4561       ERROR_P1("Unknown host '%s'.\n"
 4562     "Use 'sipp -h' for details", peripaddr);
 4563     }
 4564   } else {
 4565     if (getaddrinfo(local_ip,
 4566     NULL,
 4567     &hints,
 4568     &local_addr) != 0) {
 4569       ERROR_P1("Unknown host '%s'.\n"
 4570     "Use 'sipp -h' for details", peripaddr);
 4571     }
 4572   }
 4573   memcpy(&local_sockaddr,
 4574       local_addr->ai_addr,
 4575       SOCK_ADDR_SIZE(
 4576         _RCAST(struct sockaddr_storage *, local_addr->ai_addr)));
 4577   freeaddrinfo(local_addr);
 4578       }
 4579       if (local_ip_is_ipv6) {
 4580   (_RCAST(struct sockaddr_in6 *, &local_sockaddr))->sin6_port
 4581     = htons((short)l_port);
 4582       } else {
 4583   (_RCAST(struct sockaddr_in *, &local_sockaddr))->sin_port
 4584     = htons((short)l_port);
 4585       }
 4586       if(sipp_bind_socket(main_socket, &local_sockaddr, &local_port) == 0) {
 4587   break;
 4588       }
 4589     }
 4590   }
 4591 
 4592   if(!local_port) {
 4593     /* Not already binded, use user_port of 0 to leave
 4594      * the system choose a port. */
 4595 
 4596     if (bind_local || peripsocket) {
 4597       struct addrinfo * local_addr;
 4598       struct addrinfo   hints;
 4599       memset((char*)&hints, 0, sizeof(hints));
 4600       hints.ai_flags  = AI_PASSIVE;
 4601       hints.ai_family = PF_UNSPEC;
 4602 
 4603       if (peripsocket) {
 4604         // On some machines it fails to bind to the self computed local
 4605         // IP address.
 4606         // For the socket per IP mode, bind the main socket to the
 4607         // first IP address specified in the inject file.
 4608   inFiles[ip_file]->getField(0, peripfield, peripaddr, sizeof(peripaddr));
 4609         if (getaddrinfo(peripaddr,
 4610                          NULL,
 4611                          &hints,
 4612                          &local_addr) != 0) {
 4613            ERROR_P1("Unknown host '%s'.\n"
 4614                     "Use 'sipp -h' for details", peripaddr);
 4615         }
 4616       } else {
 4617         if (getaddrinfo(local_ip,
 4618                         NULL,
 4619                         &hints,
 4620                         &local_addr) != 0) {
 4621            ERROR_P1("Unknown host '%s'.\n"
 4622                    "Use 'sipp -h' for details", peripaddr);
 4623         }
 4624       }
 4625       memcpy(&local_sockaddr,
 4626              local_addr->ai_addr,
 4627              SOCK_ADDR_SIZE(
 4628                _RCAST(struct sockaddr_storage *, local_addr->ai_addr)));
 4629       freeaddrinfo(local_addr);
 4630     }
 4631 
 4632     if (local_ip_is_ipv6) {
 4633       (_RCAST(struct sockaddr_in6 *, &local_sockaddr))->sin6_port
 4634           = htons((short)user_port);
 4635     } else {
 4636       (_RCAST(struct sockaddr_in *, &local_sockaddr))->sin_port
 4637           = htons((short)user_port);
 4638     }
 4639     if(sipp_bind_socket(main_socket, &local_sockaddr, &local_port)) {
 4640       ERROR_NO("Unable to bind main socket");
 4641     }
 4642   }
 4643 
 4644   if (peripsocket) {
 4645     // Add the main socket to the socket per subscriber map
 4646     map_perip_fd[peripaddr] = main_socket;
 4647   }
 4648 
 4649   // Create additional server sockets when running in socket per
 4650   // IP address mode.
 4651   if (peripsocket && toolMode == MODE_SERVER) {
 4652     struct sockaddr_storage server_sockaddr;
 4653     struct addrinfo * local_addr;
 4654     struct addrinfo   hints;
 4655     memset((char*)&hints, 0, sizeof(hints));
 4656     hints.ai_flags  = AI_PASSIVE;
 4657     hints.ai_family = PF_UNSPEC;
 4658 
 4659     char peripaddr[256];
 4660     struct sipp_socket *sock;
 4661     unsigned int lines = inFiles[ip_file]->numLines();
 4662     for (unsigned int i = 0; i < lines; i++) {
 4663       inFiles[ip_file]->getField(i, peripfield, peripaddr, sizeof(peripaddr));
 4664       map<string, struct sipp_socket *>::iterator j;
 4665       j = map_perip_fd.find(peripaddr);
 4666 
 4667       if (j == map_perip_fd.end()) {
 4668         if((sock = new_sipp_socket(is_ipv6, transport)) == NULL) {
 4669           ERROR_NO("Unable to get server socket");
 4670         }
 4671 
 4672         if (getaddrinfo(peripaddr,
 4673                         NULL,
 4674                         &hints,
 4675                         &local_addr) != 0) {
 4676             ERROR_P1("Unknown remote host '%s'.\n"
 4677                      "Use 'sipp -h' for details", peripaddr);
 4678           }
 4679 
 4680         memcpy(&server_sockaddr,
 4681               local_addr->ai_addr,
 4682               SOCK_ADDR_SIZE(
 4683                  _RCAST(struct sockaddr_storage *, local_addr->ai_addr)));
 4684         freeaddrinfo(local_addr);
 4685 
 4686         if (is_ipv6) {
 4687           (_RCAST(struct sockaddr_in6 *, &server_sockaddr))->sin6_port
 4688               = htons((short)local_port);
 4689         } else {
 4690           (_RCAST(struct sockaddr_in *, &server_sockaddr))->sin_port
 4691               = htons((short)local_port);
 4692         }
 4693 
 4694         sipp_customize_socket(sock);
 4695         if(sipp_bind_socket(sock, &server_sockaddr, NULL)) {
 4696           ERROR_NO("Unable to bind server socket");
 4697         }
 4698 
 4699         map_perip_fd[peripaddr] = sock;
 4700       }
 4701     }
 4702   }
 4703 
 4704   if((!multisocket) && (transport == T_TCP || transport == T_TLS) &&
 4705    (toolMode != MODE_SERVER)) {
 4706     if((tcp_multiplex = new_sipp_socket(local_ip_is_ipv6, transport)) == NULL) {
 4707       ERROR_NO("Unable to get a TCP socket");
 4708     }
 4709 
 4710     /* OJA FIXME: is it correct? */
 4711     if (use_remote_sending_addr) {
 4712         remote_sockaddr = remote_sending_sockaddr ;
 4713     }
 4714 
 4715     if(sipp_connect_socket(tcp_multiplex, &remote_sockaddr)) {
 4716       if(reset_number >0){
 4717         WARNING("Failed to reconnect\n");
 4718         sipp_close_socket(main_socket);
 4719         reset_number--;
 4720         return 1;
 4721      }else{
 4722       if(errno == EINVAL){
 4723         /* This occurs sometime on HPUX but is not a true INVAL */
 4724         ERROR_NO("Unable to connect a TCP socket, remote peer error.\n"
 4725               "Use 'sipp -h' for details");
 4726       } else {
 4727         ERROR_NO("Unable to connect a TCP socket.\n"
 4728                  "Use 'sipp -h' for details");
 4729       }
 4730     }
 4731     }
 4732 
 4733     sipp_customize_socket(tcp_multiplex);
 4734   }
 4735 
 4736 
 4737   if(transport == T_TCP || transport == T_TLS) {
 4738     if(listen(main_socket->ss_fd, 100)) {
 4739       ERROR_NO("Unable to listen main socket");
 4740     }
 4741   }
 4742 
 4743 #ifdef __3PCC__
 4744   /* Trying to connect to Twin Sipp in 3PCC mode */
 4745   if(twinSippMode) {
 4746     if(toolMode == MODE_3PCC_CONTROLLER_A || toolMode == MODE_3PCC_A_PASSIVE) {
 4747        connect_to_peer(twinSippHost, twinSippPort, &twinSipp_sockaddr, twinSippIp, &twinSippSocket);
 4748      }else if(toolMode == MODE_3PCC_CONTROLLER_B){
 4749        connect_local_twin_socket(twinSippHost);
 4750       }else{
 4751        ERROR("TwinSipp Mode enabled but toolMode is different "
 4752               "from 3PCC_CONTROLLER_B and 3PCC_CONTROLLER_A\n");
 4753       }
 4754    }else if (extendedTwinSippMode){
 4755      if (toolMode == MODE_MASTER || toolMode == MODE_MASTER_PASSIVE) {
 4756        strcpy(twinSippHost,get_peer_addr(master_name));
 4757        get_host_and_port(twinSippHost, twinSippHost, &twinSippPort);
 4758        connect_local_twin_socket(twinSippHost);
 4759        connect_to_all_peers();
 4760      }else if(toolMode == MODE_SLAVE) {
 4761        strcpy(twinSippHost,get_peer_addr(slave_number));
 4762        get_host_and_port(twinSippHost, twinSippHost, &twinSippPort);
 4763        connect_local_twin_socket(twinSippHost);
 4764      }else{
 4765         ERROR("extendedTwinSipp Mode enabled but toolMode is different "
 4766               "from MASTER and SLAVE\n");
 4767      }
 4768     }
 4769 #endif
 4770 
 4771   return status;
 4772             }
 4773 
 4774 
 4775 void connect_to_peer(char *peer_host, int peer_port, struct sockaddr_storage *peer_sockaddr, char *peer_ip, struct sipp_socket **peer_socket) {
 4776 
 4777           /* Resolving the  peer IP */
 4778       printf("Resolving peer address : %s...\n",peer_host);
 4779       struct addrinfo   hints;
 4780       struct addrinfo * local_addr;
 4781       memset((char*)&hints, 0, sizeof(hints));
 4782       hints.ai_flags  = AI_PASSIVE;
 4783       hints.ai_family = PF_UNSPEC;
 4784       is_ipv6 = false;
 4785       /* Resolving twin IP */
 4786       if (getaddrinfo(peer_host,
 4787                       NULL,
 4788                       &hints,
 4789                       &local_addr) != 0) {
 4790 
 4791 ERROR_P1("Unknown peer host '%s'.\n"
 4792                        "Use 'sipp -h' for details", peer_host);
 4793             }
 4794 
 4795       memcpy(peer_sockaddr,
 4796              local_addr->ai_addr,
 4797              SOCK_ADDR_SIZE(
 4798                _RCAST(struct sockaddr_storage *,local_addr->ai_addr)));
 4799 
 4800       freeaddrinfo(local_addr);
 4801 
 4802       if (peer_sockaddr->ss_family == AF_INET) {
 4803        (_RCAST(struct sockaddr_in *,peer_sockaddr))->sin_port =
 4804          htons((short)peer_port);
 4805       } else {
 4806         (_RCAST(struct sockaddr_in6 *,peer_sockaddr))->sin6_port =
 4807           htons((short)peer_port);
 4808         is_ipv6 = true;
 4809       }
 4810       strcpy(peer_ip, get_inet_address(peer_sockaddr));
 4811       if((*peer_socket = new_sipp_socket(is_ipv6, T_TCP)) == NULL) {
 4812   ERROR_NO("Unable to get a twin sipp TCP socket");
 4813       }
 4814 
 4815       /* Mark this as a control socket. */
 4816       (*peer_socket)->ss_control = 1;
 4817 
 4818       if(sipp_connect_socket(*peer_socket, peer_sockaddr)) {
 4819   if(errno == EINVAL) {
 4820     /* This occurs sometime on HPUX but is not a true INVAL */
 4821     ERROR_NO("Unable to connect a twin sipp TCP socket\n "
 4822         ", remote peer error.\n"
 4823         "Use 'sipp -h' for details");
 4824   } else {
 4825     ERROR_NO("Unable to connect a twin sipp socket "
 4826         "\n"
 4827         "Use 'sipp -h' for details");
 4828   }
 4829       }
 4830 
 4831       sipp_customize_socket(*peer_socket);
 4832 }
 4833 
 4834 struct sipp_socket **get_peer_socket(char * peer)
 4835 {
 4836     struct sipp_socket **peer_socket;
 4837     T_peer_infos infos;
 4838     peer_map::iterator peer_it;
 4839     peer_it = peers.find(peer_map::key_type(peer));
 4840     if(peer_it != peers.end()) {
 4841       infos = peer_it->second;
 4842       peer_socket = &(infos.peer_socket);
 4843       return peer_socket;
 4844      }
 4845      else {
 4846        ERROR_P1("get_peer_socket: Peer %s not found\n", peer);
 4847     }
 4848    return NULL;
 4849 }
 4850 
 4851 char * get_peer_addr(char * peer)
 4852 {
 4853     char * addr;
 4854     peer_addr_map::iterator peer_addr_it;
 4855     peer_addr_it = peer_addrs.find(peer_addr_map::key_type(peer));
 4856     if(peer_addr_it != peer_addrs.end()){
 4857        addr =  peer_addr_it->second;
 4858        return addr;
 4859        }
 4860      else{
 4861        ERROR_P1("get_peer_addr: Peer %s not found\n", peer);
 4862        }
 4863    return NULL;
 4864 }
 4865 
 4866 bool is_a_peer_socket(struct sipp_socket *peer_socket)
 4867 {
 4868     peer_socket_map::iterator peer_socket_it;
 4869     peer_socket_it = peer_sockets.find(peer_socket_map::key_type(peer_socket));
 4870     if(peer_socket_it == peer_sockets.end()){
 4871        return false;
 4872       }else{
 4873        return true;
 4874       }
 4875 }
 4876 
 4877 void connect_local_twin_socket(char * twinSippHost)
 4878 {
 4879           /* Resolving the listener IP */
 4880             printf("Resolving listener address : %s...\n", twinSippHost);
 4881             struct addrinfo   hints;
 4882             struct addrinfo * local_addr;
 4883             memset((char*)&hints, 0, sizeof(hints));
 4884             hints.ai_flags  = AI_PASSIVE;
 4885             hints.ai_family = PF_UNSPEC;
 4886             is_ipv6 = false;
 4887 
 4888             /* Resolving twin IP */
 4889             if (getaddrinfo(twinSippHost,
 4890                            NULL,
 4891                            &hints,
 4892                            &local_addr) != 0) {
 4893                ERROR_P1("Unknown twin host '%s'.\n"
 4894                         "Use 'sipp -h' for details", twinSippHost);
 4895                 }
 4896              memcpy(&twinSipp_sockaddr,
 4897                     local_addr->ai_addr,
 4898                     SOCK_ADDR_SIZE(
 4899                       _RCAST(struct sockaddr_storage *,local_addr->ai_addr)));
 4900 
 4901              if (twinSipp_sockaddr.ss_family == AF_INET) {
 4902               (_RCAST(struct sockaddr_in *,&twinSipp_sockaddr))->sin_port =
 4903                 htons((short)twinSippPort);
 4904              } else {
 4905                (_RCAST(struct sockaddr_in6 *,&twinSipp_sockaddr))->sin6_port =
 4906                  htons((short)twinSippPort);
 4907                is_ipv6 = true;
 4908              }
 4909              strcpy(twinSippIp, get_inet_address(&twinSipp_sockaddr));
 4910 
 4911        if((localTwinSippSocket = new_sipp_socket(is_ipv6, T_TCP)) == NULL) {
 4912          ERROR_NO("Unable to get a listener TCP socket ");
 4913        }
 4914 
 4915            memset(&localTwin_sockaddr, 0, sizeof(struct sockaddr_storage));
 4916            if (!is_ipv6) {
 4917                localTwin_sockaddr.ss_family = AF_INET;
 4918             (_RCAST(struct sockaddr_in *,&localTwin_sockaddr))->sin_port =
 4919              htons((short)twinSippPort);
 4920            } else {
 4921              localTwin_sockaddr.ss_family = AF_INET6;
 4922              (_RCAST(struct sockaddr_in6 *,&localTwin_sockaddr))->sin6_port =
 4923                htons((short)twinSippPort);
 4924            }
 4925 
 4926            // add socket option to allow the use of it without the TCP timeout
 4927            // This allows to re-start the controller B (or slave) without timeout after its exit
 4928            int reuse = 1;
 4929            setsockopt(localTwinSippSocket->ss_fd,SOL_SOCKET,SO_REUSEADDR,(int *)&reuse,sizeof(reuse));
 4930            sipp_customize_socket(localTwinSippSocket);
 4931 
 4932      if(sipp_bind_socket(localTwinSippSocket, &localTwin_sockaddr, 0)) {
 4933        ERROR_NO("Unable to bind twin sipp socket ");
 4934      }
 4935 
 4936      if(listen(localTwinSippSocket->ss_fd, 100)) {
 4937        ERROR_NO("Unable to listen twin sipp socket in ");
 4938      }
 4939 }
 4940 
 4941 void close_peer_sockets()
 4942 {
 4943  peer_map::iterator peer_it;
 4944  T_peer_infos infos;
 4945 
 4946  for(peer_it = peers.begin(); peer_it != peers.end(); peer_it++){
 4947      infos = peer_it->second;
 4948      sipp_close_socket(infos.peer_socket);
 4949      infos.peer_socket = NULL ;
 4950      peers[std::string(peer_it->first)] = infos;
 4951  }
 4952 
 4953  peers_connected = 0;
 4954 }
 4955 
 4956 void close_local_sockets(){
 4957    for (int i = 0; i< local_nb; i++){
 4958      sipp_close_socket(local_sockets[i]);
 4959      local_sockets[i] = NULL;
 4960    }
 4961 }
 4962 
 4963 void connect_to_all_peers(){
 4964      peer_map::iterator peer_it;
 4965      T_peer_infos infos;
 4966      for (peer_it = peers.begin(); peer_it != peers.end(); peer_it++){
 4967          infos = peer_it->second;
 4968          get_host_and_port(infos.peer_host, infos.peer_host, &infos.peer_port);
 4969          connect_to_peer(infos.peer_host, infos.peer_port,&(infos.peer_sockaddr), infos.peer_ip, &(infos.peer_socket));
 4970          peer_sockets[infos.peer_socket] = peer_it->first;
 4971          peers[std::string(peer_it->first)] = infos;
 4972      }
 4973      peers_connected = 1;
 4974 }
 4975 
 4976 bool is_a_local_socket(struct sipp_socket *s){
 4977   for (int i = 0; i< local_nb + 1; i++){
 4978     if(local_sockets[i] == s) return true;
 4979   }
 4980   return (false);
 4981 }
 4982 
 4983 void free_peer_addr_map() {
 4984   peer_addr_map::iterator peer_addr_it;
 4985   for (peer_addr_it = peer_addrs.begin(); peer_addr_it != peer_addrs.end(); peer_addr_it++){
 4986        free(peer_addr_it->second);
 4987   }
 4988 }

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.8