From: <cha...@us...> - 2008-01-08 22:00:25
|
Revision: 405 http://sipp.svn.sourceforge.net/sipp/?rev=405&view=rev Author: charlespwright Date: 2008-01-08 14:00:22 -0800 (Tue, 08 Jan 2008) Log Message: ----------- Enh: Allow multiple simultaneous scenarios. Modified Paths: -------------- sipp/trunk/actions.cpp sipp/trunk/actions.hpp sipp/trunk/call.cpp sipp/trunk/call.hpp sipp/trunk/message.cpp sipp/trunk/message.hpp sipp/trunk/scenario.cpp sipp/trunk/scenario.hpp sipp/trunk/sipp.cpp sipp/trunk/stat.cpp Modified: sipp/trunk/actions.cpp =================================================================== --- sipp/trunk/actions.cpp 2008-01-08 21:59:55 UTC (rev 404) +++ sipp/trunk/actions.cpp 2008-01-08 22:00:22 UTC (rev 405) @@ -95,14 +95,14 @@ M_action, "Full Msg", M_checkIt, - variableRevMap[M_varId]); + display_scenario->variableRevMap[M_varId]); } else { printf("Type[%d] - where[%s-%s] - checkIt[%d] - $%d", M_action, "Header", M_lookingChar, M_checkIt, - variableRevMap[M_varId]); + display_scenario->variableRevMap[M_varId]); } } else if (M_action == E_AT_EXECUTE_CMD) { if (M_cmdLine) { @@ -115,23 +115,23 @@ } else if (M_action == E_AT_ASSIGN_FROM_SAMPLE) { char tmp[40]; M_distribution->textDescr(tmp, sizeof(tmp)); - printf("Type[%d] - sample varId[%d] %s", M_action, variableRevMap[M_varId], tmp); + printf("Type[%d] - sample varId[%d] %s", M_action, display_scenario->variableRevMap[M_varId], tmp); } else if (M_action == E_AT_ASSIGN_FROM_VALUE) { - printf("Type[%d] - assign varId[%d] %lf", M_action, variableRevMap[M_varId], M_doubleValue); + printf("Type[%d] - assign varId[%d] %lf", M_action, display_scenario->variableRevMap[M_varId], M_doubleValue); } else if (M_action == E_AT_ASSIGN_FROM_STRING) { - printf("Type[%d] - string assign varId[%d] [%-32.32s]", M_action, variableRevMap[M_varId], M_message); + printf("Type[%d] - string assign varId[%d] [%-32.32s]", M_action, display_scenario->variableRevMap[M_varId], M_message); } else if (M_action == E_AT_VAR_ADD) { - printf("Type[%d] - add varId[%d] %lf", M_action, variableRevMap[M_varId], M_doubleValue); + printf("Type[%d] - add varId[%d] %lf", M_action, display_scenario->variableRevMap[M_varId], M_doubleValue); } else if (M_action == E_AT_VAR_MULTIPLY) { - printf("Type[%d] - multiply varId[%d] %lf", M_action, variableRevMap[M_varId], M_doubleValue); + printf("Type[%d] - multiply varId[%d] %lf", M_action, display_scenario->variableRevMap[M_varId], M_doubleValue); } else if (M_action == E_AT_VAR_DIVIDE) { - printf("Type[%d] - divide varId[%d] %lf", M_action, variableRevMap[M_varId], M_doubleValue); + printf("Type[%d] - divide varId[%d] %lf", M_action, display_scenario->variableRevMap[M_varId], M_doubleValue); } else if (M_action == E_AT_VAR_TRIM) { - printf("Type[%d] - trim varId[%d]", M_action, variableRevMap[M_varId]); + printf("Type[%d] - trim varId[%d]", M_action, display_scenario->variableRevMap[M_varId]); } else if (M_action == E_AT_VAR_TEST) { - printf("Type[%d] - divide varId[%d] varInId[%d] %s %lf", M_action, variableRevMap[M_varId], variableRevMap[M_varInId], comparatorToString(M_comp), M_doubleValue); + printf("Type[%d] - divide varId[%d] varInId[%d] %s %lf", M_action, display_scenario->variableRevMap[M_varId], display_scenario->variableRevMap[M_varInId], comparatorToString(M_comp), M_doubleValue); } else if (M_action == E_AT_VAR_TO_DOUBLE) { - printf("Type[%d] - toDouble varId[%d]", M_action, variableRevMap[M_varId]); + printf("Type[%d] - toDouble varId[%d]", M_action, display_scenario->variableRevMap[M_varId]); #ifdef PCAPPLAY } else if ((M_action == E_AT_PLAY_PCAP_AUDIO) || (M_action == E_AT_PLAY_PCAP_VIDEO)) { printf("Type[%d] - file[%s]", M_action, M_pcapArgs->file); @@ -248,7 +248,7 @@ if(P_value != NULL) { M_message_str = strdup(P_value); - M_message = new SendingMessage(P_value, true /* skip sanity */); + M_message = new SendingMessage(M_scenario, P_value, true /* skip sanity */); } } @@ -263,7 +263,7 @@ if(P_value != NULL) { M_cmdLine_str = strdup(P_value); - M_cmdLine = new SendingMessage(P_value, true /* skip sanity */); + M_cmdLine = new SendingMessage(M_scenario, P_value, true /* skip sanity */); } } @@ -305,6 +305,10 @@ } #endif +void CAction::setScenario(scenario * P_scenario) { + M_scenario = P_scenario; +} + void CAction::setAction(CAction P_action) { if (P_action.getActionType() == CAction::E_AT_ASSIGN_FROM_SAMPLE) { @@ -317,6 +321,7 @@ setVarInId ( P_action.getVarInId() ); setDoubleValue ( P_action.getDoubleValue() ); setDistribution ( P_action.getDistribution() ); + setScenario ( P_action.M_scenario ); setNbSubVarId ( P_action.getNbSubVarId() ); for (L_i = 0; L_i < P_action.getNbSubVarId() ; L_i++ ) { @@ -336,7 +341,7 @@ #endif } -CAction::CAction() +CAction::CAction(scenario *scenario) { M_action = E_AT_NO_ACTION; M_varId = 0; @@ -364,6 +369,7 @@ M_message = NULL; M_message_str = NULL; M_cmdLine_str = NULL; + M_scenario = scenario; } CAction::~CAction() Modified: sipp/trunk/actions.hpp =================================================================== --- sipp/trunk/actions.hpp 2008-01-08 21:59:55 UTC (rev 404) +++ sipp/trunk/actions.hpp 2008-01-08 22:00:22 UTC (rev 405) @@ -123,6 +123,7 @@ void setCaseIndep (bool P_action); void setOccurence (int P_value); void setHeadersOnly (bool P_value); + void setScenario (scenario * P_scenario); void setMessage (char* P_value); /* log specific function */ void setCmdLine (char* P_value); /* exec specific function */ void setIntCmd (T_IntCmdType P_type ); /* exec specific function */ @@ -143,7 +144,7 @@ double getDoubleValue (); /* assign value specific function */ char * getStringValue (); /* strcmp specific function */ - CAction(); + CAction(scenario *scenario); ~CAction(); private: @@ -174,6 +175,8 @@ double M_doubleValue; /* strcmp specific member. */ char * M_stringValue; + /* what scenario we belong to. */ + scenario * M_scenario; #ifdef PCAPPLAY /* pcap specific member */ pcap_pkts * M_pcapArgs; Modified: sipp/trunk/call.cpp =================================================================== --- sipp/trunk/call.cpp 2008-01-08 21:59:55 UTC (rev 404) +++ sipp/trunk/call.cpp 2008-01-08 22:00:22 UTC (rev 405) @@ -363,6 +363,7 @@ call::call(char * p_id, int userId, int tdmMap, bool ipv6, bool isAutomatic) : listener(p_id, true) { + call_scenario = main_scenario; msg_index = 0; last_send_index = 0; last_send_msg = NULL; @@ -416,12 +417,12 @@ // initialising the CallVariable with the Scenario variable int i; - if (maxVariableUsed >= 0) { - M_callVariableTable = new CCallVariable *[maxVariableUsed + 1]; + if (call_scenario->maxVariableUsed >= 0) { + M_callVariableTable = new CCallVariable *[call_scenario->maxVariableUsed + 1]; } else { M_callVariableTable = NULL; } - for(i=0; i<=maxVariableUsed; i++) + for(i=0; i<=call_scenario->maxVariableUsed; i++) { M_callVariableTable[i] = new CCallVariable(); if (M_callVariableTable[i] == NULL) { @@ -429,9 +430,9 @@ } } - if (maxTxnUsed > 0) { - txnID = (char **)malloc(sizeof(char *) * maxTxnUsed); - memset(txnID, 0, sizeof(char *) * maxTxnUsed); + if (call_scenario->maxTxnUsed > 0) { + txnID = (char **)malloc(sizeof(char *) * call_scenario->maxTxnUsed); + memset(txnID, 0, sizeof(char *) * call_scenario->maxTxnUsed); } else { txnID = NULL; } @@ -510,7 +511,7 @@ } /* Deletion of the call variable */ - for(int i=0; i<=maxVariableUsed; i++) { + for(int i=0; i<=call_scenario->maxVariableUsed; i++) { if(M_callVariableTable[i] != NULL) { delete M_callVariableTable[i] ; M_callVariableTable[i] = NULL; @@ -522,7 +523,7 @@ freeUsers.push_front(userId); } - for (int i = 0; i < maxTxnUsed; i++) { + for (int i = 0; i < call_scenario->maxTxnUsed; i++) { free(txnID[i]); } free(txnID); @@ -689,15 +690,15 @@ return true; } -bool lost(int index) +bool call::lost(int index) { static int inited = 0; double percent = global_lost; if(!lose_packets) return false; - if (scenario[index]->lost >= 0) { - percent = scenario[index]->lost; + if (call_scenario->messages[index]->lost >= 0) { + percent = call_scenario->messages[index]->lost; } if (percent == 0) { @@ -729,7 +730,7 @@ TRACE_MSG("%s message voluntary lost (while sending).", TRANSPORT_TO_STRING(transport)); if(comp_state) { comp_free(&comp_state); } - scenario[index] -> nb_lost++; + call_scenario->messages[index] -> nb_lost++; return 0; } @@ -1083,9 +1084,9 @@ return NULL; } - if(scenario[index] -> send_scheme) { + if(call_scenario->messages[index] -> send_scheme) { char * dest; - dest = createSendingMessage(scenario[index] -> send_scheme, index); + dest = createSendingMessage(call_scenario->messages[index] -> send_scheme, index); strcpy(msg_buffer, dest); if (dest) { @@ -1118,16 +1119,16 @@ void call::do_bookkeeping(int index) { /* If this message increments a counter, do it now. */ - if(int counter = scenario[index] -> counter) { + if(int counter = call_scenario->messages[index] -> counter) { CStat::instance()->computeStat(CStat::E_ADD_GENERIC_COUNTER, 1, counter - 1); } /* If this message can be used to compute RTD, do it now */ - if(int rtd = scenario[index] -> start_rtd) { + if(int rtd = call_scenario->messages[index] -> start_rtd) { start_time_rtd[rtd - 1] = getmicroseconds(); } - if(int rtd = scenario[index] -> stop_rtd) { + if(int rtd = call_scenario->messages[index] -> stop_rtd) { if (!rtd_done[rtd - 1]) { unsigned long long start = start_time_rtd[rtd - 1]; unsigned long long end = getmicroseconds(); @@ -1139,7 +1140,7 @@ CStat::instance()->computeStat(CStat::E_ADD_RESPONSE_TIME_DURATION, (end - start) / 1000, rtd - 1); - if (!scenario[index] -> repeat_rtd) { + if (!call_scenario->messages[index] -> repeat_rtd) { rtd_done[rtd - 1] = true; } } @@ -1201,25 +1202,25 @@ bool call::next() { - int test = scenario[msg_index]->test; + int test = call_scenario->messages[msg_index]->test; /* What is the next message index? */ /* Default without branching: use the next message */ int new_msg_index = msg_index+1; /* If branch needed, overwrite this default */ - if ( (scenario[msg_index]->next >= 0) && + if ( (call_scenario->messages[msg_index]->next >= 0) && ((test == -1) || - (test <= maxVariableUsed && M_callVariableTable[test] != NULL && M_callVariableTable[test]->isSet())) + (test <= call_scenario->maxVariableUsed && M_callVariableTable[test] != NULL && M_callVariableTable[test]->isSet())) ) { /* Branching possible, check the probability */ - int chance = scenario[msg_index]->chance; + int chance = call_scenario->messages[msg_index]->chance; if ((chance <= 0) || (rand() > chance )) { /* Branch == overwrite with the 'next' attribute value */ - new_msg_index = scenario[msg_index]->next; + new_msg_index = call_scenario->messages[msg_index]->next; } } msg_index=new_msg_index; recv_timeout = 0; - if(msg_index >= scenario_len) { + if(msg_index >= call_scenario->length) { terminate(CStat::E_CALL_SUCCESSFULLY_ENDED); return false; } @@ -1236,11 +1237,13 @@ clock_tick = getmilliseconds(); - if(msg_index >= scenario_len) { + if(msg_index >= call_scenario->length) { ERROR("Scenario overrun for call %s (%p) (index = %d)\n", id, this, msg_index); } + message *curmsg = call_scenario->messages[msg_index]; + /* Manages retransmissions or delete if max retrans reached */ if(next_retrans && (next_retrans < clock_tick)) { nb_retrans++; @@ -1252,14 +1255,14 @@ if((nb_retrans > (bInviteTransaction ? max_invite_retrans : max_non_invite_retrans)) || (nb_retrans > max_udp_retrans)) { - scenario[last_send_index] -> nb_timeout ++; - if (scenario[last_send_index]->on_timeout >= 0) { // action on timeout + call_scenario->messages[last_send_index] -> nb_timeout ++; + if (call_scenario->messages[last_send_index]->on_timeout >= 0) { // action on timeout WARNING("Call-Id: %s, timeout on max UDP retrans for message %d, jumping to label %d ", - id, msg_index, scenario[last_send_index]->on_timeout); - msg_index = scenario[last_send_index]->on_timeout; + id, msg_index, call_scenario->messages[last_send_index]->on_timeout); + msg_index = call_scenario->messages[last_send_index]->on_timeout; next_retrans = 0; recv_timeout = 0; - if (msg_index < scenario_len) { + if (msg_index < call_scenario->length) { return true; } @@ -1298,7 +1301,7 @@ if(send_raw(last_send_msg, last_send_index) < -1) { return false; } - scenario[last_send_index] -> nb_sent_retrans++; + call_scenario->messages[last_send_index] -> nb_sent_retrans++; CStat::instance()->computeStat(CStat::E_RETRANSMISSION); next_retrans = clock_tick + nb_last_delay; } @@ -1313,13 +1316,13 @@ /* Our pause is over. */ paused_until = 0; return next(); - } else if(scenario[msg_index] -> pause_distribution || scenario[msg_index]->pause_variable) { + } else if(curmsg -> pause_distribution || curmsg->pause_variable) { unsigned int pause; - if (scenario[msg_index]->pause_distribution) { - pause = (int)(scenario[msg_index] -> pause_distribution -> sample()); + if (curmsg->pause_distribution) { + pause = (int)(curmsg -> pause_distribution -> sample()); } else { - int varId = scenario[msg_index]->pause_variable; - if(varId <= maxVariableUsed && M_callVariableTable[varId]) { + int varId = curmsg->pause_variable; + if(varId <= call_scenario->maxVariableUsed && M_callVariableTable[varId]) { pause = (int) M_callVariableTable[varId]->getDouble(); } else { pause = 0; @@ -1336,13 +1339,15 @@ /* This state is used as the last message of a scenario, just for handling * final retransmissions. If the connection closes, we do not mark it is * failed. */ - this->timewait = scenario[msg_index]->timewait; + this->timewait = curmsg->timewait; /* Increment the number of sessions in pause state */ - ++scenario[msg_index]->sessions; + curmsg->sessions++; + do_bookkeeping(msg_index); + actionResult = executeAction(NULL, msg_index); return run(); /* In case delay is 0 */ } - else if(scenario[msg_index] -> M_type == MSG_TYPE_SENDCMD) { + else if(curmsg -> M_type == MSG_TYPE_SENDCMD) { int send_status; if(next_retrans) { @@ -1354,17 +1359,20 @@ if(send_status != 0) { /* Send error */ return false; /* call deleted */ } - scenario[msg_index] -> M_nbCmdSent++; + curmsg -> M_nbCmdSent++; next_retrans = 0; + + do_bookkeeping(msg_index); + actionResult = executeAction(NULL, msg_index); return(next()); } - else if(scenario[msg_index] -> M_type == MSG_TYPE_NOP) { + else if(curmsg -> M_type == MSG_TYPE_NOP) { do_bookkeeping(msg_index); actionResult = executeAction(NULL, msg_index); return(next()); } - else if(scenario[msg_index] -> send_scheme) { + else if(curmsg -> send_scheme) { char * msg_snd; int send_status; @@ -1386,9 +1394,9 @@ */ int incr_cseq = 0; - if (!scenario[msg_index]->send_scheme->isAck() && - !scenario[msg_index]->send_scheme->isCancel() && - !scenario[msg_index]->send_scheme->isResponse()) { + if (!curmsg->send_scheme->isAck() && + !curmsg->send_scheme->isCancel() && + !curmsg->send_scheme->isResponse()) { ++cseq; incr_cseq = 1; } @@ -1411,9 +1419,9 @@ return false; } } - } else if (scenario[msg_index]->timeout) { + } else if (curmsg->timeout) { /* Initialize the send timeout to the per message timeout. */ - send_timeout = clock_tick + scenario[msg_index]->timeout; + send_timeout = clock_tick + curmsg->timeout; } else if (defl_send_timeout) { /* Initialize the send timeout to the global timeout. */ send_timeout = clock_tick + defl_send_timeout; @@ -1432,9 +1440,9 @@ last_send_msg = (char *) realloc(last_send_msg, strlen(msg_snd) + 1); strcpy(last_send_msg, msg_snd); - if (scenario[msg_index]->start_txn) { - txnID[scenario[msg_index]->start_txn - 1] = (char *)realloc(txnID[scenario[msg_index]->start_txn - 1], MAX_HEADER_LEN); - extract_transaction(txnID[scenario[msg_index]->start_txn - 1], last_send_msg); + if (curmsg->start_txn) { + txnID[curmsg->start_txn - 1] = (char *)realloc(txnID[curmsg->start_txn - 1], MAX_HEADER_LEN); + extract_transaction(txnID[curmsg->start_txn - 1], last_send_msg); } if(last_recv_hash) { @@ -1450,26 +1458,24 @@ } /* Update retransmission information */ - if(scenario[msg_index] -> retrans_delay) { + if(curmsg -> retrans_delay) { if((transport == T_UDP) && (retrans_enabled)) { - next_retrans = clock_tick + scenario[msg_index] -> retrans_delay; + next_retrans = clock_tick + curmsg -> retrans_delay; nb_retrans = 0; - nb_last_delay = scenario[msg_index]->retrans_delay; + nb_last_delay = curmsg->retrans_delay; } } else { next_retrans = 0; } - -#ifdef PCAPPLAY + actionResult = executeAction(msg_snd, msg_index); -#endif - + /* Update scenario statistics */ - scenario[msg_index] -> nb_sent++; + curmsg -> nb_sent++; return next(); - } else if (scenario[msg_index]->M_type == MSG_TYPE_RECV - || scenario[msg_index]->M_type == MSG_TYPE_RECVCMD + } else if (curmsg->M_type == MSG_TYPE_RECV + || curmsg->M_type == MSG_TYPE_RECVCMD ) { if (recv_timeout) { if(recv_timeout > clock_tick || recv_timeout > getmilliseconds()) { @@ -1477,8 +1483,8 @@ return true; } recv_timeout = 0; - ++scenario[msg_index]->nb_timeout; - if (scenario[msg_index]->on_timeout < 0) { + curmsg->nb_timeout++; + if (curmsg->on_timeout < 0) { // if you set a timeout but not a label, the call is aborted WARNING("Call-Id: %s, receive timeout on message %d without label to jump to (ontimeout attribute): aborting call", id, msg_index); @@ -1492,10 +1498,10 @@ } } WARNING("Call-Id: %s, receive timeout on message %d, jumping to label %d", - id, msg_index, scenario[msg_index]->on_timeout); - msg_index = scenario[msg_index]->on_timeout; + id, msg_index, curmsg->on_timeout); + msg_index = curmsg->on_timeout; recv_timeout = 0; - if (msg_index < scenario_len) return true; + if (msg_index < call_scenario->length) return true; // special case - the label points to the end - finish the call CStat::instance()->computeStat(CStat::E_CALL_FAILED); CStat::instance()->computeStat(CStat::E_FAILED_TIMEOUT_ON_RECV); @@ -1505,10 +1511,10 @@ delete this; return false; } - } else if ((scenario[msg_index]->timeout) || (defl_recv_timeout)) { - if (scenario[msg_index]->timeout) + } else if (curmsg->timeout || defl_recv_timeout) { + if (curmsg->timeout) // If timeout is specified on message receive, use it - recv_timeout = getmilliseconds() + scenario[msg_index]->timeout; + recv_timeout = getmilliseconds() + curmsg->timeout; else // Else use the default timeout if specified recv_timeout = getmilliseconds() + defl_recv_timeout; @@ -1591,10 +1597,18 @@ int messages = sizeof(default_message_strings)/sizeof(default_message_strings[0]); default_messages = new SendingMessage* [messages]; for (int i = 0; i < messages; i++) { - default_messages[i] = new SendingMessage(default_message_strings[i]); + default_messages[i] = new SendingMessage(main_scenario, default_message_strings[i]); } } +void free_default_messages() { + int messages = sizeof(default_message_strings)/sizeof(default_message_strings[0]); + for (int i = 0; i < messages; i++) { + delete default_messages[i]; + } + delete [] default_messages; +} + SendingMessage *get_default_message(const char *which) { int messages = sizeof(default_message_names)/sizeof(default_message_names[0]); for (int i = 0; i < messages; i++) { @@ -1621,8 +1635,10 @@ char buffer[MAX_HEADER_LEN]; char *desc = buffer; - scenario[msg_index] -> nb_unexp++; + message *curmsg = call_scenario->messages[msg_index]; + curmsg->nb_unexp++; + if (default_behaviors & DEFAULT_BEHAVIOR_ABORTUNEXP) { desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "Aborting "); } else { @@ -1630,22 +1646,22 @@ } desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "call on unexpected message for Call-Id '%s': ", id); - if (scenario[msg_index] -> M_type == MSG_TYPE_RECV) { - if (scenario[msg_index] -> recv_request) { - desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%s' ", scenario[msg_index] -> recv_request); + if (curmsg -> M_type == MSG_TYPE_RECV) { + if (curmsg -> recv_request) { + desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%s' ", curmsg -> recv_request); } else { - desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%d' ", scenario[msg_index] -> recv_response); + desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%d' ", curmsg -> recv_response); } - } else if (scenario[msg_index] -> M_type == MSG_TYPE_SEND) { + } else if (curmsg -> M_type == MSG_TYPE_SEND) { desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while sending "); - } else if (scenario[msg_index] -> M_type == MSG_TYPE_PAUSE) { + } else if (curmsg -> M_type == MSG_TYPE_PAUSE) { desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while pausing "); - } else if (scenario[msg_index] -> M_type == MSG_TYPE_SENDCMD) { + } else if (curmsg -> M_type == MSG_TYPE_SENDCMD) { desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while sending command "); - } else if (scenario[msg_index] -> M_type == MSG_TYPE_RECVCMD) { + } else if (curmsg -> M_type == MSG_TYPE_RECVCMD) { desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting command "); } else { - desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while in message type %d ", scenario[msg_index]->M_type); + desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while in message type %d ", curmsg->M_type); } desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "(index %d)", msg_index); @@ -1778,16 +1794,18 @@ char * peer_dest; struct sipp_socket **peer_socket; - if(scenario[index] -> M_sendCmdData) { + message *curmsg = call_scenario->messages[index]; + + if(curmsg -> M_sendCmdData) { // WARNING("---PREPARING_TWIN_CMD---%s---", scenario[index] -> M_sendCmdData); - dest = createSendingMessage(scenario[index] -> M_sendCmdData, -1); + dest = createSendingMessage(curmsg -> M_sendCmdData, -1); strcat(dest, delimitor); //WARNING("---SEND_TWIN_CMD---%s---", dest); int rc; /* 3pcc extended mode */ - peer_dest = scenario[index]->peer_dest; + peer_dest = curmsg->peer_dest; if(peer_dest){ peer_socket = get_peer_socket(peer_dest); rc = write_socket(*peer_socket, dest, strlen(dest), WS_BUFFER); @@ -2024,7 +2042,7 @@ break; case E_Message_Variable: { int varId = comp->varId; - if(varId <= maxVariableUsed) { + if(varId <= call_scenario->maxVariableUsed) { if(M_callVariableTable[varId] != NULL) { if(M_callVariableTable[varId]->isSet()) { if (M_callVariableTable[varId]->isRegExp()) { @@ -2046,7 +2064,7 @@ case E_Message_Fill: { int varId = comp->varId; int length = 0; - if(varId <= maxVariableUsed && M_callVariableTable[varId]) { + if(varId <= call_scenario->maxVariableUsed && M_callVariableTable[varId]) { length = (int) M_callVariableTable[varId]->getDouble(); if (length < 0) { length = 0; @@ -2079,7 +2097,7 @@ tmp = strchr(auth_marker, ']'); char c = *tmp; *tmp = '\0'; - SendingMessage::parseAuthenticationKeyword(auth_comp, auth_marker); + SendingMessage::parseAuthenticationKeyword(call_scenario, auth_comp, auth_marker); *tmp = c; } if (*(dest - 1) == '\n') { @@ -2240,35 +2258,36 @@ if (checkInternalCmd(msg) == false) { for(search_index = msg_index; - search_index < scenario_len; + search_index < call_scenario->length; search_index++) { - if(scenario[search_index] -> M_type != MSG_TYPE_RECVCMD) { - if(scenario[search_index] -> optional) { - continue; - } - /* The received message is different from the expected one */ + if(call_scenario->messages[search_index] -> M_type != MSG_TYPE_RECVCMD) { + if(call_scenario->messages[search_index] -> optional) { + continue; + } + /* The received message is different from the expected one */ TRACE_MSG("Unexpected control message received (I was expecting a different type of message):\n%s\n", msg); - return rejectCall(); + return rejectCall(); } else { - if(extendedTwinSippMode){ // 3pcc extended mode + if(extendedTwinSippMode){ // 3pcc extended mode if(check_peer_src(msg, search_index)){ - found = true; - break; + found = true; + break; } else{ WARNING("Unexpected sender for the received peer message \n%s\n", msg); return rejectCall(); - } - } - else { - found = true; - break; + } + } + else { + found = true; + break; + } } } - } - + if (found) { - scenario[search_index]->M_nbCmdRecv ++; - + call_scenario->messages[search_index]->M_nbCmdRecv ++; + do_bookkeeping(search_index); + // variable treatment // Remove \r, \n at the end of a received command // (necessary for transport, to be removed for usage) @@ -2277,7 +2296,7 @@ msg[strlen(msg)-2] = 0; } actionResult = executeAction(msg, search_index); - + if(actionResult != call::E_AR_NO_ERROR) { // Store last action result if it is an error // and go on with the scenario @@ -2292,7 +2311,6 @@ } msg_index = search_index; //update the state machine return(next()); - } else { return (false); } @@ -2351,7 +2369,7 @@ if(!*L_ptr2) { return (false); } L_backup = *L_ptr2; *L_ptr2 = 0; - if (strcmp(L_ptr1, scenario[search_index] -> peer_src) == 0) { + if (strcmp(L_ptr1, call_scenario->messages[search_index] -> peer_src) == 0) { *L_ptr2 = L_backup; return(true); } @@ -2555,24 +2573,25 @@ bool call::matches_scenario(unsigned int index, int reply_code, char * request, char * responsecseqmethod, char *txn) { int result; + message *curmsg = call_scenario->messages[index]; - if ((scenario[index] -> recv_request)) { - if (scenario[index]->regexp_match) { - if (scenario[index] -> regexp_compile == NULL) { + if ((curmsg -> recv_request)) { + if (curmsg->regexp_match) { + if (curmsg -> regexp_compile == NULL) { regex_t *re = new regex_t; - if (regcomp(re, scenario[index] -> recv_request, REG_EXTENDED|REG_NOSUB)) { - ERROR("Invalid regular expression for index %d: %s", scenario[index]->recv_request); + if (regcomp(re, curmsg -> recv_request, REG_EXTENDED|REG_NOSUB)) { + ERROR("Invalid regular expression for index %d: %s", curmsg->recv_request); } - scenario[index] -> regexp_compile = re; + curmsg -> regexp_compile = re; } - return !regexec(scenario[index] -> regexp_compile, request, (size_t)0, NULL, 0); + return !regexec(curmsg -> regexp_compile, request, (size_t)0, NULL, 0); } else { - return !strcmp(scenario[index] -> recv_request, request); + return !strcmp(curmsg -> recv_request, request); } - } else if (scenario[index]->recv_response && (scenario[index]->recv_response == reply_code)) { + } else if (curmsg->recv_response && (curmsg->recv_response == reply_code)) { /* This is a potential candidate, we need to match transactions. */ - if (scenario[index]->response_txn) { - if (txnID[scenario[index]->response_txn - 1] && !strcmp(txnID[scenario[index]->response_txn - 1], txn)) { + if (curmsg->response_txn) { + if (txnID[curmsg->response_txn - 1] && !strcmp(txnID[curmsg->response_txn - 1], txn)) { return true; } else { return false; @@ -2580,8 +2599,8 @@ } else if (index == 0) { /* Always true for the first message. */ return true; - } else if (scenario[index]->recv_response_for_cseq_method_list && - strstr(scenario[index]->recv_response_for_cseq_method_list, responsecseqmethod)) { + } else if (curmsg->recv_response_for_cseq_method_list && + strstr(curmsg->recv_response_for_cseq_method_list, responsecseqmethod)) { /* If we do not have a transaction defined, we just check the CSEQ method. */ return true; } else { @@ -2607,10 +2626,10 @@ setRunning(); /* Ignore the messages received during a pause if -pause_msg_ign is set */ - if(scenario[msg_index] -> M_type == MSG_TYPE_PAUSE && pause_msg_ign) return(true); + if(call_scenario->messages[msg_index] -> M_type == MSG_TYPE_PAUSE && pause_msg_ign) return(true); /* Authorize nop as a first command, even in server mode */ - if((msg_index == 0) && (scenario[msg_index] -> M_type == MSG_TYPE_NOP)) { + if((msg_index == 0) && (call_scenario->messages[msg_index] -> M_type == MSG_TYPE_NOP)) { actionResult = executeAction(NULL, msg_index); return next(); } @@ -2630,16 +2649,16 @@ TRANSPORT_TO_STRING(transport)); if(comp_state) { comp_free(&comp_state); } - scenario[recv_retrans_recv_index] -> nb_lost++; + call_scenario->messages[recv_retrans_recv_index] -> nb_lost++; return true; } - scenario[recv_retrans_recv_index] -> nb_recv_retrans++; + call_scenario->messages[recv_retrans_recv_index] -> nb_recv_retrans++; send_scene(recv_retrans_send_index, &status); if(status == 0) { - scenario[recv_retrans_send_index] -> nb_sent_retrans++; + call_scenario->messages[recv_retrans_send_index] -> nb_sent_retrans++; CStat::instance()->computeStat(CStat::E_RETRANSMISSION); } else if(status < 0) { return false; @@ -2662,7 +2681,7 @@ * This case can also appear in case of message duplication by * the network. This should not be considered as an unexpected. */ - scenario[last_recv_index]->nb_recv_retrans++; + call_scenario->messages[last_recv_index]->nb_recv_retrans++; return true; } } @@ -2735,10 +2754,10 @@ /* Try to find it in the expected non mandatory responses * until the first mandatory response in the scenario */ for(search_index = msg_index; - search_index < scenario_len; + search_index < call_scenario->length; search_index++) { if(!matches_scenario(search_index, reply_code, request, responsecseqmethod, txn)) { - if(scenario[search_index] -> optional) { + if(call_scenario->messages[search_index] -> optional) { continue; } /* The received message is different for the expected one */ @@ -2759,25 +2778,25 @@ for(search_index = msg_index - 1; search_index >= 0; search_index--) { - if (scenario[search_index]->optional == OPTIONAL_FALSE) contig = false; + if (call_scenario->messages[search_index]->optional == OPTIONAL_FALSE) contig = false; if(matches_scenario(search_index, reply_code, request, responsecseqmethod, txn)) { - if (contig || scenario[search_index]->optional == OPTIONAL_GLOBAL) { + if (contig || call_scenario->messages[search_index]->optional == OPTIONAL_GLOBAL) { found = true; break; } else { - if (int checkTxn = scenario[search_index]->response_txn) { + if (int checkTxn = call_scenario->messages[search_index]->response_txn) { /* This is a reply to an old transaction. */ if (!strcmp(txnID[checkTxn - 1], txn)) { /* This reply is provisional, so it should have no effect if we recieve it out-of-order. */ if (reply_code >= 100 && reply_code <= 199) { TRACE_MSG("-----------------------------------------------\n" "Ignoring provisional %s message for transaction %s:\n\n%s\n", - TRANSPORT_TO_STRING(transport), txnRevMap[checkTxn - 1], msg); + TRANSPORT_TO_STRING(transport), call_scenario->txnRevMap[checkTxn - 1], msg); return true; - } else if (scenario[search_index + 1]->M_type == MSG_TYPE_SEND && scenario[search_index + 1]->send_scheme->isAck()) { + } else if (call_scenario->messages[search_index + 1]->M_type == MSG_TYPE_SEND && call_scenario->messages[search_index + 1]->send_scheme->isAck()) { /* This is the message before an ACK, so verify that this is an invite transaction. */ if (!strcmp(responsecseqmethod, "INVITE")) { - sendBuffer(createSendingMessage(scenario[search_index+1] -> send_scheme, (search_index+1))); + sendBuffer(createSendingMessage(call_scenario->messages[search_index+1] -> send_scheme, (search_index+1))); return true; } } @@ -2791,9 +2810,9 @@ */ if ( (reply_code) && (0 == strncmp (responsecseqmethod, "INVITE", strlen(responsecseqmethod)) ) && - (scenario[search_index+1]->M_type == MSG_TYPE_SEND) && - (scenario[search_index+1]->send_scheme->isAck()) ) { - sendBuffer(createSendingMessage(scenario[search_index+1] -> send_scheme, (search_index+1))); + (call_scenario->messages[search_index+1]->M_type == MSG_TYPE_SEND) && + (call_scenario->messages[search_index+1]->send_scheme->isAck()) ) { + sendBuffer(createSendingMessage(call_scenario->messages[search_index+1] -> send_scheme, (search_index+1))); return true; } } @@ -2815,7 +2834,7 @@ } } - int test = (!found) ? -1 : scenario[search_index]->test; + int test = (!found) ? -1 : call_scenario->messages[search_index]->test; /* test==0: No branching" * test==-1 branching without testing" * test>0 branching with testing @@ -2826,7 +2845,7 @@ TRACE_MSG("%s message lost (recv).", TRANSPORT_TO_STRING(transport)); if(comp_state) { comp_free(&comp_state); } - scenario[search_index] -> nb_lost++; + call_scenario->messages[search_index] -> nb_lost++; return true; } @@ -2835,7 +2854,7 @@ do_bookkeeping(search_index); /* Increment the recv counter */ - scenario[search_index] -> nb_recv++; + call_scenario->messages[search_index] -> nb_recv++; // Action treatment if (found) { @@ -2896,7 +2915,7 @@ } /* store the route set only once. TODO: does not support target refreshes!! */ - if (scenario[search_index] -> bShouldRecordRoutes && + if (call_scenario->messages[search_index] -> bShouldRecordRoutes && NULL == dialog_route_set ) { next_req_url = (char*) calloc(1, MAX_HEADER_LEN); @@ -2930,7 +2949,7 @@ #ifdef _USE_OPENSSL /* store the authentication info */ - if ((scenario[search_index] -> bShouldAuthenticate) && + if ((call_scenario->messages[search_index] -> bShouldAuthenticate) && (reply_code == 401 || reply_code == 407)) { /* is a challenge */ @@ -2953,7 +2972,7 @@ #endif /* If we are not advancing state, we should quite before we change this stuff. */ - if (!scenario[search_index]->advance_state) { + if (!call_scenario->messages[search_index]->advance_state) { return true; } @@ -2967,10 +2986,10 @@ /* If this was a mandatory message, or if there is an explicit next label set * we must update our state machine. */ - if (!(scenario[search_index] -> optional) || - scenario[search_index]->next && + if (!(call_scenario->messages[search_index] -> optional) || + call_scenario->messages[search_index]->next && ((test == -1) || - (test <= maxVariableUsed && M_callVariableTable[test] != NULL && M_callVariableTable[test]->isSet())) + (test <= call_scenario->maxVariableUsed && M_callVariableTable[test] != NULL && M_callVariableTable[test]->isSet())) ) { /* If we are paused, then we need to wake up so that we properly go through the state machine. */ paused_until = 0; @@ -2980,7 +2999,7 @@ unsigned int timeout = wake(); unsigned int candidate; - if (scenario[search_index]->next && test <= maxVariableUsed && + if (call_scenario->messages[search_index]->next && test <= call_scenario->maxVariableUsed && M_callVariableTable[test] != NULL && M_callVariableTable[test]->isSet()) { WARNING("Last message generates an error and will not be used for next sends (for last_ variables):\r\n%s",msg); } @@ -2988,11 +3007,11 @@ /* We are just waiting for a message to be received, if any of the * potential messages have a timeout we set it as our timeout. We * start from the next message and go until any non-receives. */ - for(search_index++; search_index < scenario_len; search_index++) { - if(scenario[search_index] -> M_type != MSG_TYPE_RECV) { + for(search_index++; search_index < call_scenario->length; search_index++) { + if(call_scenario->messages[search_index] -> M_type != MSG_TYPE_RECV) { break; } - candidate = scenario[search_index] -> timeout; + candidate = call_scenario->messages[search_index] -> timeout; if (candidate == 0) { if (defl_recv_timeout == 0) { continue; @@ -3025,7 +3044,7 @@ char msgPart[MAX_SUB_MESSAGE_LENGTH]; int currentId; - actions = scenario[scenarioIndex]->M_actions; + actions = call_scenario->messages[scenarioIndex]->M_actions; // looking for action to do on this message if(actions != NULL) { for(int i=0; i<actions->getActionSize(); i++) { @@ -3033,7 +3052,7 @@ if(currentAction != NULL) { if(currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_REGEXP) { currentId = currentAction->getVarId(); - scenVariable = scenVariableTable[currentId][scenarioIndex]; + scenVariable = call_scenario->scenVariableTable[currentId][scenarioIndex]; if(scenVariable != NULL) { if(currentAction->getLookingPlace() == CAction::E_LP_HDR) { extractSubMessage @@ -3369,7 +3388,7 @@ strcpy(last_recv_msg, P_recv); // The BYE is unexpected, count it - scenario[msg_index] -> nb_unexp++; + call_scenario->messages[msg_index] -> nb_unexp++; if (default_behaviors & DEFAULT_BEHAVIOR_ABORTUNEXP) { WARNING("Aborting call on an unexpected BYE for call: %s", (id==NULL)?"none":id); if (default_behaviors & DEFAULT_BEHAVIOR_BYE) { @@ -3394,7 +3413,7 @@ strcpy(last_recv_msg, P_recv); // The CANCEL is unexpected, count it - scenario[msg_index] -> nb_unexp++; + call_scenario->messages[msg_index] -> nb_unexp++; if (default_behaviors & DEFAULT_BEHAVIOR_ABORTUNEXP) { WARNING("Aborting call on an unexpected CANCEL for call: %s", (id==NULL)?"none":id); if (default_behaviors & DEFAULT_BEHAVIOR_BYE) { Modified: sipp/trunk/call.hpp =================================================================== --- sipp/trunk/call.hpp 2008-01-08 21:59:55 UTC (rev 404) +++ sipp/trunk/call.hpp 2008-01-08 22:00:22 UTC (rev 405) @@ -88,6 +88,7 @@ bool automaticResponseMode(T_AutoMode P_case, char* P_recv); private: + scenario *call_scenario; unsigned int number; unsigned int tdm_map_number; @@ -266,6 +267,8 @@ void get_remote_media_addr(char * message); + bool lost(int index); + #ifdef _USE_OPENSSL SSL_CTX *m_ctx_ssl ; BIO *m_bio ; @@ -282,6 +285,7 @@ /* Default Message Functions. */ void init_default_messages(); +void free_default_messages(); SendingMessage *get_default_message(const char *which); void set_default_message(const char *which, char *message); Modified: sipp/trunk/message.cpp =================================================================== --- sipp/trunk/message.cpp 2008-01-08 21:59:55 UTC (rev 404) +++ sipp/trunk/message.cpp 2008-01-08 22:00:22 UTC (rev 405) @@ -79,7 +79,7 @@ #define KEYWORD_SIZE 256 -SendingMessage::SendingMessage(char *src, bool skip_sanity) { +SendingMessage::SendingMessage(scenario *msg_scenario, char *src, bool skip_sanity) { char *osrc = src; char * literal; char * dest; @@ -91,6 +91,8 @@ char * line_mark = NULL; char * tsrc; int num_cr = get_cr_number(src); + + this->msg_scenario = msg_scenario; dest = literal = (char *)malloc(strlen(src) + num_cr + 1); @@ -235,7 +237,10 @@ } } else if(*keyword == '$') { newcomp->type = E_Message_Variable; - newcomp->varId = get_var(keyword + 1, "Variable keyword"); + if (!msg_scenario) { + ERROR("SendingMessage with variable usage outside of scenario!"); + } + newcomp->varId = msg_scenario->get_var(keyword + 1, "Variable keyword"); } else if(!strncmp(keyword, "fill", strlen("fill"))) { newcomp->type = E_Message_Fill; char filltext[KEYWORD_SIZE]; @@ -248,7 +253,10 @@ getKeywordParam(keyword, "variable=", varName); newcomp->literal = strdup(filltext); - newcomp->varId = get_var(varName, "Fill Variable"); + if (!msg_scenario) { + ERROR("SendingMessage with variable usage outside of scenario!"); + } + newcomp->varId = msg_scenario->get_var(varName, "Fill Variable"); } else if(!strncmp(keyword, "last_", strlen("last_"))) { if(!strncmp(keyword, "last_Request_URI", strlen("last_Request_URI"))){ newcomp->type = E_Message_Last_Request_URI; @@ -259,7 +267,7 @@ } newcomp->literal = strdup(keyword + strlen("last_")); } else if(!strncmp(keyword, "authentication", strlen("authentication"))) { - parseAuthenticationKeyword(newcomp, keyword); + parseAuthenticationKeyword(msg_scenario, newcomp, keyword); } #ifndef PCAPPLAY else if(!strcmp(keyword, "auto_media_port") || @@ -451,7 +459,7 @@ } } -void SendingMessage::parseAuthenticationKeyword(struct MessageComponent *dst, char *keyword) { +void SendingMessage::parseAuthenticationKeyword(scenario *msg_scenario, struct MessageComponent *dst, char *keyword) { char my_auth_user[KEYWORD_SIZE + 1]; char my_auth_pass[KEYWORD_SIZE + 1]; char my_aka[KEYWORD_SIZE + 1]; @@ -472,8 +480,8 @@ } - dst->comp_param.auth_param.auth_user = new SendingMessage(my_auth_user, true /* skip sanity */); - dst->comp_param.auth_param.auth_pass = new SendingMessage(my_auth_pass, true); + dst->comp_param.auth_param.auth_user = new SendingMessage(msg_scenario, my_auth_user, true /* skip sanity */); + dst->comp_param.auth_param.auth_pass = new SendingMessage(msg_scenario, my_auth_pass, true); /* add aka_OP, aka_AMF, aka_K */ getKeywordParam(keyword, "aka_K=", my_aka); @@ -481,12 +489,12 @@ memcpy(my_aka,my_auth_pass,16); my_aka[16]=0; } - dst->comp_param.auth_param.aka_K = new SendingMessage(my_aka, true); + dst->comp_param.auth_param.aka_K = new SendingMessage(msg_scenario, my_aka, true); getKeywordParam(keyword, "aka_OP=", my_aka); - dst->comp_param.auth_param.aka_OP = new SendingMessage(my_aka, true); + dst->comp_param.auth_param.aka_OP = new SendingMessage(msg_scenario, my_aka, true); getKeywordParam(keyword, "aka_AMF=", my_aka); - dst->comp_param.auth_param.aka_AMF = new SendingMessage(my_aka, true); + dst->comp_param.auth_param.aka_AMF = new SendingMessage(msg_scenario, my_aka, true); } void SendingMessage::freeMessageComponent(struct MessageComponent *comp) { Modified: sipp/trunk/message.hpp =================================================================== --- sipp/trunk/message.hpp 2008-01-08 21:59:55 UTC (rev 404) +++ sipp/trunk/message.hpp 2008-01-08 22:00:22 UTC (rev 405) @@ -39,6 +39,8 @@ #include <vector> +class scenario; + struct MessageComponent; typedef enum { @@ -82,7 +84,7 @@ class SendingMessage { public: - SendingMessage(char *msg, bool skip_sanity = false); + SendingMessage(scenario *msg_scenario, char *msg, bool skip_sanity = false); ~SendingMessage(); struct MessageComponent *getComponent(int); @@ -95,7 +97,7 @@ bool isAck(); bool isCancel(); - static void parseAuthenticationKeyword(struct MessageComponent *dst, char *keyword); + static void parseAuthenticationKeyword(scenario *msg_scenario, struct MessageComponent *dst, char *keyword); static void freeMessageComponent(struct MessageComponent *comp); private: std::vector <struct MessageComponent *> messageComponents; @@ -107,6 +109,8 @@ bool cancel; bool response; + scenario *msg_scenario; + // Get parameters from a [keyword] static void getQuotedParam(char * dest, char * src, int * len); static void getHexStringParam(char * dest, char * src, int * len); Modified: sipp/trunk/scenario.cpp =================================================================== --- sipp/trunk/scenario.cpp 2008-01-08 21:59:55 UTC (rev 404) +++ sipp/trunk/scenario.cpp 2008-01-08 22:00:22 UTC (rev 405) @@ -145,35 +145,31 @@ free(recv_response_for_cseq_method_list); } +void scenario::expand(int length) { + assert(length >= this->length); + if (length == this->length) { + return; + } + + messages = (message **)realloc(messages, sizeof(message *) * length); + if (!messages) { + ERROR("Out of memory allocating scenario messages."); + } + + for (int i = this->length; i < length; i++) { + messages[i] = NULL; + } +} + /******** Global variables which compose the scenario file **********/ -message* scenario[SCEN_MAX_MESSAGES]; -CVariable*** scenVariableTable; -int maxVariableUsed = -1; -typedef std::map<std::string, int> var_map; -var_map variableMap; -char **variableRevMap; -int *variableReferences; -int scenario_len = 0; -char scenario_name[255]; +scenario *main_scenario; +scenario *display_scenario; + int toolMode = MODE_CLIENT; -unsigned long scenario_duration = 0; bool rtd_stopped[MAX_RTD_INFO_LENGTH]; bool rtd_started[MAX_RTD_INFO_LENGTH]; -/* The mapping of labels to IDs. */ -var_map labelMap; -/* The string label representations. */ -char *nextLabels[SCEN_MAX_MESSAGES]; -char *ontimeoutLabels[SCEN_MAX_MESSAGES]; -/* The mapping of transactions to IDs. */ -int maxTxnUsed = 0; -typedef std::map<std::string, int> txn_map; -txn_map txnMap; -char **txnRevMap; -int *txnStarted; -int *txnResponses; - /*************** Helper functions for various types *****************/ long get_long(const char *ptr, const char *what) { char *endptr; @@ -337,7 +333,7 @@ return xp_get_bool(name, what); } -int get_txn(const char *txnName, const char *what, bool start) { +int scenario::get_txn(const char *txnName, const char *what, bool start) { /* Check the name's validity. */ if (txnName[0] == '\0') { ERROR("Variable names may not be empty for %s\n", what); @@ -347,12 +343,12 @@ } /* If this transaction has already been used, then we have nothing to do. */ - txn_map::iterator txn_it = txnMap.find(txnName); + str_int_map::iterator txn_it = txnMap.find(txnName); if (txn_it != txnMap.end()) { if (start) { - txnStarted[txn_it->second - 1]++; + txnStarted[txn_it->second]++; } else { - txnResponses[txn_it->second - 1]++; + txnResponses[txn_it->second]++; } return txn_it->second; } @@ -360,38 +356,20 @@ /* Assign this variable the next slot. */ int txnNum = ++maxTxnUsed; - char **tmpTxnRevMap = new char *[txnNum]; - int *tmpTxnStarted = new int[txnNum]; - int *tmpTxnResponses = new int[txnNum]; - int i; - for (i = 0; i < txnNum - 1; i++) { - tmpTxnRevMap[i] = txnRevMap[i]; - tmpTxnStarted[i] = txnStarted[i]; - tmpTxnResponses[i] = txnResponses[i]; - } - if (txnRevMap) { - delete [] txnRevMap; - delete [] txnStarted; - delete [] txnResponses; - } - txnRevMap = tmpTxnRevMap; - txnStarted = tmpTxnStarted; - txnResponses = tmpTxnResponses; - txnMap[txnName] = txnNum; - txnRevMap[txnNum - 1] = strdup(txnName); + txnRevMap[txnNum] = strdup(txnName); if (start) { - txnStarted[txnNum - 1] = 1; - txnResponses[txnNum - 1] = 0; + txnStarted[txnNum] = 1; + txnResponses[txnNum] = 0; } else { - txnStarted[txnNum - 1] = 0; - txnResponses[txnNum - 1] = 1; + txnStarted[txnNum] = 0; + txnResponses[txnNum] = 1; } return txnNum; } -int get_var(const char *varName, const char *what) { +int scenario::get_var(const char *varName, const char *what) { /* Check the name's validity. */ if (varName[0] == '\0') { ERROR("Transaction names may not be empty for %s\n", what); @@ -401,7 +379,7 @@ } /* If this variable has already been used, then we have nothing to do. */ - var_map::iterator var_it = variableMap.find(varName); + str_int_map::iterator var_it = variableMap.find(varName); if (var_it != variableMap.end()) { variableReferences[var_it->second]++; return var_it->second; @@ -411,8 +389,6 @@ int varNum = maxVariableUsed > 0 ? maxVariableUsed + 1 : 1; CVariable ***tmpScenVars = new CVariable **[varNum + 1]; - char **tmpVariableRevMap = new char *[varNum + 1]; - int *tmpVariableReferences = new int[varNum + 1]; int i; for (i = 0; i <= maxVariableUsed; i++) { tmpScenVars[i] = new CVariable * [SCEN_MAX_MESSAGES]; @@ -420,17 +396,11 @@ tmpScenVars[i][j] = scenVariableTable[i][j]; } delete scenVariableTable[i]; - tmpVariableRevMap[i] = variableRevMap[i]; - tmpVariableReferences[i] = variableReferences[i]; } if (scenVariableTable) { delete [] scenVariableTable; - delete [] variableRevMap; - delete [] variableReferences; } scenVariableTable = tmpScenVars; - variableRevMap = tmpVariableRevMap; - variableReferences = tmpVariableReferences; for (; i <= varNum; i++) { scenVariableTable[i] = new CVariable * [SCEN_MAX_MESSAGES]; @@ -447,7 +417,7 @@ return varNum; } -int xp_get_var(const char *name, const char *what) { +int scenario::xp_get_var(const char *name, const char *what) { char *ptr; char *helptext; @@ -458,7 +428,7 @@ return get_var(ptr, what); } -int xp_get_var(const char *name, const char *what, int defval) { +int scenario::xp_get_var(const char *name, const char *what, int defval) { char *ptr; char *helptext; @@ -589,7 +559,7 @@ /* Some validation functions. */ /* If you start an RTD, then you should be interested in collecting statistics for it. */ -void validate_rtds() { +void scenario::validate_rtds() { for (int i = 0; i < MAX_RTD_INFO_LENGTH; i++) { if (rtd_started[i] && !rtd_stopped[i]) { ERROR("You have started Response Time Duration %d, but have never stopped it!", i + 1); @@ -597,7 +567,7 @@ } } -void validate_variable_usage() { +void scenario::validate_variable_usage() { for (int i = 1; i <= maxVariableUsed; i++) { if(variableReferences[i] == 1) { ERROR("Variable $%s is referenced only once!\n", variableRevMap[i]); @@ -605,8 +575,8 @@ } } -void validate_txn_usage() { - for (int i = 0; i < maxTxnUsed; i++) { +void scenario::validate_txn_usage() { + for (int i = 1; i <= maxTxnUsed; i++) { if(txnStarted[i] == 0) { ERROR("Transaction %s is never started!\n", variableRevMap[i]); } else if(txnResponses[i] == 0) { @@ -616,26 +586,27 @@ } /* Apply the next and ontimeout labels according to our map. */ -void apply_labels() { - for (int i = 0; i <= scenario_len; i++) { - if (nextLabels[i]) { - var_map::iterator label_it = labelMap.find(nextLabels[i]); +void scenario::apply_labels() { + for (int i = 0; i <= length; i++) { + int_str_map::iterator it; + if ((it = nextLabels.find(i)) != nextLabels.end()) { + str_int_map::iterator label_it = labelMap.find(it->second); if (label_it == labelMap.end()) { - ERROR("The label '%s' was not defined (index %d, next attribute)\n", nextLabels[i], i); + ERROR("The label '%s' was not defined (index %d, next attribute)\n", it->second, i); } - scenario[i]->next = label_it->second; + messages[i]->next = label_it->second; } - if (ontimeoutLabels[i]) { - var_map::iterator label_it = labelMap.find(ontimeoutLabels[i]); + if ((it = ontimeoutLabels.find(i)) != ontimeoutLabels.end()) { + str_int_map::iterator label_it = labelMap.find(it->second); if (label_it == labelMap.end()) { - ERROR("The label '%s' was not defined (index %d, ontimeout attribute)\n", ontimeoutLabels[i], i); + ERROR("The label '%s' was not defined (index %d, ontimeout attribute)\n", it->second, i); } - scenario[i]->on_timeout = label_it->second; + messages[i]->on_timeout = label_it->second; } } } -void init_rtds() +void scenario::init_rtds() { for (int i = 0; i < MAX_RTD_INFO_LENGTH; i++) { rtd_started[i] = rtd_stopped[i] = false; @@ -702,9 +673,8 @@ /********************** Scenario File analyser **********************/ -void load_scenario(char * filename, int deflt) +scenario::scenario(char * filename, int deflt) { - static int loaded = 0; char * elem; char *method_list = NULL; unsigned int scenario_file_cursor = 0; @@ -712,13 +682,7 @@ unsigned int recv_count = 0; unsigned int recv_opt_count = 0; char * peer; - bool found_timewait = false; - if (loaded) { - ERROR("You may only specify a single scenario!\n"); - } - loaded++; - if(filename) { if(!xp_set_xml_buffer_from_file(filename)) { ERROR("Unable to load or parse '%s' xml scenario file", filename); @@ -729,7 +693,8 @@ } } - init_rtds(); + init_rtds(); + elem = xp_open_element(0); if (!elem) { ERROR("No element in xml scenario file"); @@ -738,13 +703,19 @@ ERROR("No 'scenario' section in xml scenario file"); } - if(xp_get_value((char *)"name")) { - strcpy(scenario_name, xp_get_value((char *)"name")); + if(char *ptr = xp_get_value((char *)"name")) { + name = strdup(ptr); } else { - scenario_name[0] = 0; + name = strdup(""); } - scenario_len = 0; + length = 0; + messages = NULL; + duration = 0; + maxVariableUsed = -1; + maxTxnUsed = 0; + found_timewait = false; + scenario_file_cursor = 0; while(elem = xp_open_element(scenario_file_cursor)) { @@ -754,10 +725,11 @@ if(!strcmp(elem, "CallLengthRepartition")) { ptr = xp_get_value((char *)"value"); CStat::instance()->setRepartitionCallLength(ptr); - + /* XXX: This should really be per scenario. */ } else if(!strcmp(elem, "ResponseTimeRepartition")) { ptr = xp_get_value((char *)"value"); CStat::instance()->setRepartitionResponseTime(ptr); + /* XXX: This should really be per RTD. */ } else if(!strcmp(elem, "DefaultMessage")) { char *id = xp_get_string("id", "DefaultMessage"); if(!(ptr = xp_get_cdata())) { @@ -766,18 +738,19 @@ char *msg = clean_cdata(ptr); set_default_message(id, msg); free(id); + /* XXX: This should really be per scenario. */ } else if(!strcmp(elem, "label")) { ptr = xp_get_value((char *)"id"); if (labelMap.find(ptr) != labelMap.end()) { ERROR("The label name '%s' is used twice.", ptr); } - labelMap[ptr] = ::scenario_len; + labelMap[ptr] = length; } else { /** Message Case */ if (found_timewait) { ERROR("<timewait> can only be the last message in a scenario!\n"); } - scenario[scenario_len] = new message(); - scenario[scenario_len] -> content_length_flag = message::ContentLengthNoPresent; // Initialize to No present + expand(length + 1); + messages[length] = new message(); if(!strcmp(elem, "send")) { if (recv_count) { @@ -789,7 +762,7 @@ } } - scenario[scenario_len]->M_type = MSG_TYPE_SEND; + messages[length]->M_type = MSG_TYPE_SEND; /* Sent messages descriptions */ if(!(ptr = xp_get_cdata())) { ERROR("No CDATA in 'send' section of xml scenario file"); @@ -804,11 +777,11 @@ // the msg does not contain content-length field break ; case 0 : - scenario[scenario_len] -> content_length_flag = + messages[length] -> content_length_flag = message::ContentLengthValueZero; // Initialize to No present break ; default : - scenario[scenario_len] -> content_length_flag = + messages[length] -> content_length_flag = message::ContentLengthValueNoZero; // Initialize to No present break ; } @@ -816,15 +789,15 @@ if((msg[strlen(msg) - 1] != '\n') && (removed_clrf)) { strcat(msg, "\n"); } - scenario[scenario_len] -> send_scheme = new SendingMessage(msg); + messages[length] -> send_scheme = new SendingMessage(this, msg); free(msg); // If this is a request we are sending, then store our transaction/method matching information. - if (!scenario[scenario_len]->send_scheme->isResponse()) { + if (!messages[length]->send_scheme->isResponse()) { if (ptr = xp_get_value("start_txn")) { - scenario[scenario_len]->start_txn = get_txn(ptr, "start transaction", true); + messages[length]->start_txn = get_txn(ptr, "start transaction", true); } else { - char *method = scenario[scenario_len]->send_scheme->getMethod(); + char *method = messages[length]->send_scheme->getMethod(); int len = method_list ? strlen(method_list) : 0; method_list = (char *)realloc(method_list, len + strlen(method) + 1); if (!method_list) { @@ -842,119 +815,72 @@ ERROR("response_txn can only be used for recieved messages."); } - scenario[scenario_len] -> retrans_delay = xp_get_long("retrans", "retransmission timer", 0); - scenario[scenario_len] -> timeout = xp_get_long("timeout", "message send timeout", 0); - - if(ptr = xp_get_value((char *)"rtd")) { - scenario[scenario_len] -> stop_rtd = get_rtd(ptr); - rtd_stopped[scenario[scenario_len]->stop_rtd - 1] = true; - } - - if(ptr = xp_get_value((char *)"start_rtd")) { - scenario[scenario_len] -> start_rtd = get_rtd(ptr); - rtd_started[scenario[scenario_len]->start_rtd - 1] = true; - } - - if (ptr = xp_get_value((char *)"repeat_rtd")) { - if (scenario[scenario_len] -> stop_rtd) { - scenario[scenario_len] -> repeat_rtd = get_bool(ptr, "repeat_rtd"); - } else { - ERROR("There is a repeat_rtd element without an rtd element"); - } - } - - if(ptr = xp_get_value((char *)"counter")) { - scenario[scenario_len] -> counter = get_counter(ptr, "counter"); - } - - getActionForThisMessage(); + messages[length] -> retrans_delay = xp_get_long("retrans", "retransmission timer", 0); + messages[length] -> timeout = xp_get_long("timeout", "message send timeout", 0); } else if(!strcmp(elem, (char *)"recv")) { recv_count++; - scenario[scenario_len]->M_type = MSG_TYPE_RECV; + messages[length]->M_type = MSG_TYPE_RECV; /* Received messages descriptions */ if(ptr = xp_get_value((char *)"response")) { - scenario[scenario_len] ->recv_response = get_long(ptr, "response code"); + messages[length] ->recv_response = get_long(ptr, "response code"); if (method_list) { - scenario[scenario_len]->recv_response_for_cseq_method_list = strdup(method_list); + messages[length]->recv_response_for_cseq_method_list = strdup(method_list); } if (ptr = xp_get_value("response_txn"))... [truncated message content] |