📄 call.cpp
字号:
/* This is an ACK or a response, and its index is greater than the * current active retransmission message, so we stop the retrans timer. */ if(((reply_code) || (!strcmp(request, "ACK"))) && (search_index > last_send_index)) { next_retrans = 0; } /* This is a response with 200 so set the flag indicating that an * ACK is pending (used to prevent from release a call with CANCEL * when an ACK+BYE should be sent instead) */ if (reply_code == 200) { ack_is_pending = true; } /* If this message can be used to compute RTD, do it now */ if(!rtd_done) { if(scenario[search_index] -> start_rtd) { start_time_rtd = clock_tick; } if(scenario[search_index] -> stop_rtd) { rtd_sum += clock_tick - start_time_rtd; CStat::instance()-> computeStat(CStat::E_ADD_RESPONSE_TIME_DURATION, clock_tick - start_time_rtd); rtd_nb ++; rtd_done = true; } } /* Increment the recv counter */ scenario[search_index] -> nb_recv++; /* store the route set only once. TODO: does not support target refreshes!! */ if (scenario[search_index] -> bShouldRecordRoutes && NULL == dialog_route_set ) { /* should cache the route set */ if (reply_code) { /* is a reply. */ char rr[MAX_HEADER_LEN]; strcpy(rr, get_header_content(msg, (char*)"Record-Route:")); char actual_rr[MAX_HEADER_LEN]; memset(actual_rr, 0, sizeof(actual_rr)); bool isFirst(true); while (1) { char* pointer = strrchr(rr, ','); if (pointer) { if (!isFirst) { strcat(actual_rr, pointer + 1); } else { isFirst = false; } } else { if (!isFirst) { strcat(actual_rr, rr); } break; } *pointer = '\0'; } /* lose the bottom most record route -- that is the SUT */ char ch[MAX_HEADER_LEN]; strcpy(ch, get_header_content(msg, (char*)"Contact:")); if (strlen(actual_rr)) { dialog_route_set = (char *) calloc(1, strlen(actual_rr) + strlen(ch) + 2); sprintf(dialog_route_set, "%s,%s", actual_rr, ch); } else { dialog_route_set = (char *) calloc(1, strlen(ch) + 2); sprintf(dialog_route_set, "%s", ch); } } else { /* is a request. */ char rr[MAX_HEADER_LEN]; strcpy(rr, get_header_content(msg, (char*)"Record-Route:")); /* toss the first RR, it is going to be the SUT */ char* actual_rr = strchr(rr, ','); if (actual_rr) { actual_rr += 1; } char ch[MAX_HEADER_LEN]; strcpy(ch, get_header_content(msg, (char*)"Contact:")); if (actual_rr) { dialog_route_set = (char *) calloc(1, strlen(actual_rr) + strlen(ch) + 2); sprintf(dialog_route_set, "%s,%s", actual_rr, ch); } else { dialog_route_set = (char *) calloc(1, strlen(ch) + 2); sprintf(dialog_route_set, "%s", ch); } } } /* If this was a mandatory message, and keeps its cookie for * future retransmissions, and its body for fields inclusion * in our messages. */ if(!(scenario[search_index] -> optional)) { msg_index = search_index; /* Store last recv msg information */ last_recv_index = search_index; last_recv_hash = cookie; last_recv_msg = (char *) realloc(last_recv_msg, strlen(msg) + 1); strcpy(last_recv_msg, msg); return next(); } return true;} call::T_ActionResult call::executeAction(char * msg, int scenarioIndex){ CActions* actions; CAction* currentAction; CVariable* scenVariable; char msgPart[MAX_SUB_MESSAGE_LENGTH]; int currentId; actions = scenario[scenarioIndex]->M_actions; // looking for action to do on this message if(actions != NULL) { for(int i=0; i<actions->getUsedAction(); i++) { currentAction = actions->getAction(i); if(currentAction != NULL) { if(currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_REGEXP) { currentId = currentAction->getVarId(); scenVariable = scenVariableTable[currentId]; if(scenVariable != NULL) { if(currentAction->getLookingPlace() == CAction::E_LP_HDR) { extractSubMessage (msg, currentAction->getLookingChar(), msgPart); if(strlen(msgPart) > 0) { scenVariable->extractOneMatchedExpression (msgPart, M_callVariableTable[currentId]); if( (!(M_callVariableTable[currentId]->isSet())) && (currentAction->getCheckIt() == true) ) { // the message doesn't match and the checkit // action say it MUST match // Allow easier regexp debugging WARNING_P2("Failed regexp match: looking " "in '%s', with regexp '%s'", msgPart, scenVariable-> getRegularExpression()); // --> Call will be marked as failed return(call::E_AR_REGEXP_DOESNT_MATCH); } } else {// sub part of message not found if( currentAction->getCheckIt() == true ) { // the sub message is not found and the // checking action say it MUST match // --> Call will be marked as failed but // will go on return(call::E_AR_HDR_NOT_FOUND); } } } else {// we must look in the entire message // WARNING_P1("LOOKING IN MSG -%s-", msg); scenVariable->extractOneMatchedExpression (msg, M_callVariableTable[currentId]); if((!(M_callVariableTable[currentId]->isSet())) && (currentAction->getCheckIt() == true) ) { // the message doesn't match and the checkit // action say it MUST match // Allow easier regexp debugging WARNING_P2("Failed regexp match: looking in '%s'" ", with regexp '%s'", msg, scenVariable->getRegularExpression()); // --> rejecting the call return(call::E_AR_REGEXP_DOESNT_MATCH); } } } // end if scen variable != null } else {// end action == ASSIGN_FROM_REG_EXP ERROR("call::executeAction unknown action"); } } // end if current action != null } // end for } return(call::E_AR_NO_ERROR);}void call::extractSubMessage(char * msg, char * matchingString, char* result){ char * ptr; int sizeOf; int i = 0; int len; ptr = strstr(msg, matchingString); if(ptr != NULL) { len = strlen(matchingString); strcpy(result, ptr+len); sizeOf = strlen(result); if(sizeOf >= MAX_SUB_MESSAGE_LENGTH) sizeOf = MAX_SUB_MESSAGE_LENGTH-1; while((i<sizeOf) && (result[i] != '\n') && (result[i] != '\r')) i++; result[i] = '\0'; } else { result[0] = '\0'; }}void call::dumpFileContents(void){ WARNING_P3("Line choosing strategy is [%s]. m_counter [%d] numLinesInFile [%d]", m_usage == InputFileSequentialOrder ? "SEQUENTIAL" : "RANDOM", m_counter, numLinesInFile); for (int i(0); i < numLinesInFile && fileContents[i][0]; ++i) { WARNING_P2("%dth line reads [%s]", i, fileContents[i].c_str()); }}/* Read MAX_CHAR_BUFFER_SIZE size lines from the * "fileName" and populate it in the fileContents * vector. The file should not be more than * MAX_LINES_IN_FILE lines long and each line * should be terminated with a '\n' */void call::readInputFileContents(const char* fileName){ ifstream *inFile = new ifstream(fileName); ifstream &inFileObj = *inFile; char line[MAX_CHAR_BUFFER_SIZE]; if (!inFile->good()) { ERROR_P1("Unable to open file %s", fileName); return ; } numLinesInFile = 0; call::m_counter = 0; line[0] = '\0'; inFileObj.getline(line, MAX_CHAR_BUFFER_SIZE); if (NULL != strstr(line, "RANDOM")) { call::m_usage = InputFileRandomOrder; } else if (NULL != strstr(line, "SEQUENTIAL")) { call::m_usage = InputFileSequentialOrder; } else { // default call::m_usage = InputFileSequentialOrder; } while (!inFileObj.eof()) { line[0] = '\0'; inFileObj.getline(line, MAX_CHAR_BUFFER_SIZE); if (line[0]) { if ('#' != line[0]) { fileContents.push_back(line); } numLinesInFile++; } else { break; } } // call::dumpFileContents(); delete inFile;} void call::getFieldFromInputFile(const char* keyword, int lineNum, char*& dest){ int nthField = atoi(keyword+5 /*strlen("field")*/); if (fileContents.size() > lineNum) { const string& line = fileContents[lineNum]; // WARNING_P3("lineNum [%d] nthField [%d] line [%s]", // lineNum, nthField, line.c_str()); int pos(0), oldpos(0); do { oldpos = pos; int localint = line.find(';', oldpos); if (localint != string::npos) { pos = localint + 1; } else { pos = localint; break; } string x = line.substr(oldpos, pos - oldpos); // WARNING_P3("pos [%d] oldpos [%d] is [%s]", pos, oldpos, x.c_str()); if (nthField) { --nthField; } else { break; } } while (oldpos != string::npos); if (nthField) { WARNING_P1("Field %d not found in the file", nthField+2); // field not found in line } else { if (string::npos != oldpos) { if (line[oldpos] == ';') { ++oldpos; // should not be incremeneted for field0 } if (string::npos != pos) { // should not be decremented for fieldN pos -= (oldpos + 1); } string x = line.substr(oldpos, pos); dest += sprintf(dest, "%s", x.c_str()); // WARNING_P2("nthField [%d] is [%s]", nthField, x.c_str()); } } } else { WARNING_P1("Field %d definition not found", nthField); }}int call::checkAutomaticResponseMode(char * P_recv) { int L_res = 0 ; if (strcmp(P_recv, "BYE")==0) { L_res = 1 ; } else if (strcmp(P_recv, "CANCEL") == 0) { L_res = 2 ; } else if (strcmp(P_recv, "PING") == 0) { L_res = 3 ; } return (L_res) ; }void call::automaticResponseMode(int P_case, char * P_recv){ int res ; // usage of last_ keywords last_recv_msg = (char *) realloc(last_recv_msg, strlen(P_recv) + 1); strcpy(last_recv_msg, P_recv); switch (P_case) { case 1: // response for an unexpected BYE WARNING_P1("Automatic response mode for an unexpected BYE for call: %s", (id==NULL)?"none":id); res = sendBuffer(createSendingMessage( (char*)"SIP/2.0 200 OK\n" "[last_Via:]\n" "[last_From:]\n" "[last_To:]\n" "[last_Call-ID:]\n" "[last_CSeq:]\n" "Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n" "Content-Length: 0\n" , -1)) ;#ifdef __3PCC__ // if twin socket call => reset the other part here if (twinSippSocket && (msg_index > 0)) { res = sendCmdBuffer (createSendingMessage((char*)"call-id: [call_id]\ninternal-cmd: abort_call\n", -1)); }#endif /* __3PCC__ */ CStat::instance()->computeStat(CStat::E_CALL_FAILED); CStat::instance()->computeStat(CStat::E_FAILED_UNEXPECTED_MSG); delete_call(id); break ; case 2: // response for an unexpected cancel WARNING_P1("Automatic response mode for an unexpected CANCEL for call: %s", (id==NULL)?"none":id); res = sendBuffer(createSendingMessage( (char*)"SIP/2.0 200 OK\n" "[last_Via:]\n" "[last_From:]\n" "[last_To:]\n" "[last_Call-ID:]\n" "[last_CSeq:]\n" "Contact: sip:sipp@[local_ip]:[local_port]\n" "Content-Length: 0" , -1)) ; #ifdef __3PCC__ // if twin socket call => reset the other part here if (twinSippSocket && (msg_index > 0)) { res = sendCmdBuffer (createSendingMessage((char*)"call-id: [call_id]\ninternal-cmd: abort_call\n", -1)); }#endif /* __3PCC__ */ CStat::instance()->computeStat(CStat::E_CALL_FAILED); CStat::instance()->computeStat(CStat::E_FAILED_UNEXPECTED_MSG); delete_call(id); break ; case 3: // response for a random ping WARNING_P1("Automatic response mode for an unexpected PING for call: %s", (id==NULL)?"none":id); count_in_stats = false; // Call must not be counted in statistics res = sendBuffer(createSendingMessage( (char*)"SIP/2.0 200 OK\n" "[last_Via:]\n" "[last_Call-ID:]\n" "[last_To:]\n" "[last_From:]\n" "[last_CSeq:]\n" "Contact: sip:sipp@[local_ip]:[local_port]\n" "Content-Length: 0" , -1)) ; // Note: the call ends here but it is not marked as bad. PING is a // normal message.#ifdef __3PCC__ // if twin socket call => reset the other part here if (twinSippSocket && (msg_index > 0)) { res = sendCmdBuffer (createSendingMessage((char*)"call-id: [call_id]\ninternal-cmd: abort_call\n",-1)); }#endif /* __3PCC__ */ CStat::instance()->computeStat(CStat::E_AUTO_ANSWERED); delete_call(id); break ; default: ERROR_P1("Internal error for automaticResponseMode %d", P_case); break ; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -