Parent Directory
|
Revision Log
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 (¤tTime); 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(¤tTime, 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 (¤tTime); 2099 TRACE_MSG((s, "----------------------------------------------- %s\n" 2100 "%s %smessage sent (%d bytes):\n\n%.*s\n", 2101 CStat::instance()->formatTime(¤tTime, 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 (¤tTime); 2114 TRACE_MSG((s, "----------------------------------------------- %s\n" 2115 "Error sending %s message:\n\n%.*s\n", 2116 CStat::instance()->formatTime(¤tTime, 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 (¤tTime); 2126 TRACE_MSG((s, "----------------------------------------------- %s\n" 2127 "Truncation sending %s message (%d of %d sent):\n\n%.*s\n", 2128 CStat::instance()->formatTime(¤tTime, 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 (¤tTime); 2442 TRACE_MSG((s, "----------------------------------------------- %s\n" 2443 "%s %smessage received [%d] bytes :\n\n%s\n", 2444 CStat::instance()->formatTime(¤tTime, 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 (¤tTime); 2473 TRACE_SHORTMSG((s, "%s\tS\t%s\tCSeq:%s\t%s\n", 2474 CStat::instance()->formatTime(¤tTime),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 |