From aab495b0f01e63bc6ad6b59a237cf4a75fe38a2a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 30 Jul 2025 17:00:55 +0000 Subject: [PATCH 1/7] Initial plan From 325da62716f7c3e8b9432016eebfd37ff014e241 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 30 Jul 2025 17:16:49 +0000 Subject: [PATCH 2/7] Implement support for CSV field and variable substitution in recv timeout parameter Co-authored-by: orgads <1246544+orgads@users.noreply.github.com> --- include/scenario.hpp | 2 ++ src/call.cpp | 47 +++++++++++++++++++++++++++++++++++++++----- src/scenario.cpp | 28 ++++++++++++++++++++++++-- 3 files changed, 70 insertions(+), 7 deletions(-) diff --git a/include/scenario.hpp b/include/scenario.hpp index 0ae347bd..37b20a72 100644 --- a/include/scenario.hpp +++ b/include/scenario.hpp @@ -85,6 +85,8 @@ class message unsigned int retrans_delay; /* The receive/send timeout. */ unsigned int timeout; + /* The timeout string for variable substitution */ + char * timeout_str; /* 3pcc extended mode: if this is a sendCmd */ char * peer_dest; diff --git a/src/call.cpp b/src/call.cpp index 6da83483..cfc2160f 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -1967,9 +1967,27 @@ bool call::executeMessage(message *curmsg) return false; } } - } else if (curmsg->timeout) { + } else if (curmsg->timeout || curmsg->timeout_str) { /* Initialize the send timeout to the per message timeout. */ - send_timeout = clock_tick + curmsg->timeout; + unsigned int resolved_timeout = 0; + if (curmsg->timeout_str) { + // Resolve variables in timeout string at runtime + char timeout_buffer[256]; + SendingMessage timeout_msg(call_scenario, curmsg->timeout_str); + char* resolved_str = createSendingMessage(&timeout_msg, msg_index, timeout_buffer, sizeof(timeout_buffer)); + if (resolved_str) { + char* endptr; + resolved_timeout = strtoul(resolved_str, &endptr, 0); + if (*endptr) { + ERROR("Invalid timeout value after variable substitution: '%s'", resolved_str); + } + } else { + ERROR("Failed to resolve timeout variables"); + } + } else { + resolved_timeout = curmsg->timeout; + } + send_timeout = clock_tick + resolved_timeout; } else if (defl_send_timeout) { /* Initialize the send timeout to the global timeout. */ send_timeout = clock_tick + defl_send_timeout; @@ -2081,10 +2099,29 @@ bool call::executeMessage(message *curmsg) delete this; return false; } - } else if (curmsg->timeout || defl_recv_timeout) { - if (curmsg->timeout) + } else if (curmsg->timeout || curmsg->timeout_str || defl_recv_timeout) { + unsigned int resolved_timeout = 0; + if (curmsg->timeout_str) { + // Resolve variables in timeout string at runtime + char timeout_buffer[256]; + SendingMessage timeout_msg(call_scenario, curmsg->timeout_str); + char* resolved_str = createSendingMessage(&timeout_msg, msg_index, timeout_buffer, sizeof(timeout_buffer)); + if (resolved_str) { + char* endptr; + resolved_timeout = strtoul(resolved_str, &endptr, 0); + if (*endptr) { + ERROR("Invalid timeout value after variable substitution: '%s'", resolved_str); + } + } else { + ERROR("Failed to resolve timeout variables"); + } + } else if (curmsg->timeout) { + resolved_timeout = curmsg->timeout; + } + + if (resolved_timeout) // If timeout is specified on message receive, use it - recv_timeout = getmilliseconds() + curmsg->timeout; + recv_timeout = getmilliseconds() + resolved_timeout; else // Else use the default timeout if specified recv_timeout = getmilliseconds() + defl_recv_timeout; diff --git a/src/scenario.cpp b/src/scenario.cpp index a47324dc..4edfc0f0 100644 --- a/src/scenario.cpp +++ b/src/scenario.cpp @@ -52,6 +52,7 @@ message::message(int index, const char *desc) send_scheme = nullptr; // delete on exit retrans_delay = 0; timeout = 0; + timeout_str = nullptr; // free on exit recv_response = nullptr; // free on exit recv_request = nullptr; // free on exit @@ -125,6 +126,7 @@ message::~message() free(display_str); free(nextLabel); free(onTimeoutLabel); + free(timeout_str); free(peer_dest); free(peer_src); @@ -887,7 +889,18 @@ scenario::scenario(char * filename, int deflt) } curmsg -> retrans_delay = xp_get_long("retrans", "retransmission timer", 0); - curmsg -> timeout = xp_get_long("timeout", "message send timeout", 0); + if ((cptr = xp_get_value("timeout"))) { + curmsg->timeout_str = strdup(cptr); + // If the timeout string contains no variables, parse it as integer now + if (strchr(cptr, '[') == nullptr && strchr(cptr, '$') == nullptr) { + curmsg->timeout = get_long(cptr, "message send timeout"); + } else { + curmsg->timeout = 0; // Will be resolved at runtime + } + } else { + curmsg->timeout = 0; + curmsg->timeout_str = nullptr; + } } else if (!strcmp(elem, "recv")) { curmsg->M_type = MSG_TYPE_RECV; /* Received messages descriptions */ @@ -921,7 +934,18 @@ scenario::scenario(char * filename, int deflt) } } - curmsg->timeout = xp_get_long("timeout", "message timeout", 0); + if ((cptr = xp_get_value("timeout"))) { + curmsg->timeout_str = strdup(cptr); + // If the timeout string contains no variables, parse it as integer now + if (strchr(cptr, '[') == nullptr && strchr(cptr, '$') == nullptr) { + curmsg->timeout = get_long(cptr, "message timeout"); + } else { + curmsg->timeout = 0; // Will be resolved at runtime + } + } else { + curmsg->timeout = 0; + curmsg->timeout_str = nullptr; + } /* record the route set */ /* TODO disallow optional and rrs to coexist? */ From c7e15f082e4d91c6a9a2f40598948f49a408690f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 30 Jul 2025 17:33:31 +0000 Subject: [PATCH 3/7] Fix timeout variable resolution and add comprehensive regression test Co-authored-by: orgads <1246544+orgads@users.noreply.github.com> --- include/call.hpp | 3 + regress/github-#0801/run | 18 ++++++ regress/github-#0801/uac_csv.xml | 65 +++++++++++++++++++ regress/github-#0801/uac_variable.xml | 72 +++++++++++++++++++++ regress/github-#0801/uas_csv.xml | 65 +++++++++++++++++++ regress/github-#0801/uas_variable.xml | 65 +++++++++++++++++++ src/call.cpp | 91 ++++++++++++++++++++------- 7 files changed, 355 insertions(+), 24 deletions(-) create mode 100755 regress/github-#0801/run create mode 100644 regress/github-#0801/uac_csv.xml create mode 100644 regress/github-#0801/uac_variable.xml create mode 100644 regress/github-#0801/uas_csv.xml create mode 100644 regress/github-#0801/uas_variable.xml diff --git a/include/call.hpp b/include/call.hpp index f5fa0728..c9ff5943 100644 --- a/include/call.hpp +++ b/include/call.hpp @@ -277,6 +277,9 @@ class call : virtual public task, virtual public listener, public virtual socket char* createSendingMessage(char* src, int P_index, bool skip_sanity=false); char* createSendingMessage(SendingMessage*src, int P_index, char *msg_buffer, int buflen, int *msgLen=nullptr); + // Helper method to resolve timeout values with variables + unsigned int resolveTimeoutValue(const char* timeout_str); + // method for the management of unexpected messages bool checkInternalCmd(char* cmd); // check of specific internal command // received from the twin socket diff --git a/regress/github-#0801/run b/regress/github-#0801/run new file mode 100755 index 00000000..9208f274 --- /dev/null +++ b/regress/github-#0801/run @@ -0,0 +1,18 @@ +#!/bin/sh +# Simple test to demonstrate timeout variable functionality works +. "`dirname "$0"`/../functions"; init + +# Test that scenarios with timeout variables can be parsed without errors +echo "SEQUENTIAL" > test_data.csv +echo "call1;user1;100;1000" >> test_data.csv + +# Test 1: Parse scenario with CSV field timeout - should not produce parsing errors +timeout 3 "`get_sipp`" -sf uac_csv.xml -inf test_data.csv -p 5070 -m 0 127.0.0.1 2>&1 | grep -q "timeout.*field" && fail "parsing error with CSV field timeout" + +# Test 2: Parse scenario with variable timeout - should not produce parsing errors +timeout 3 "`get_sipp`" -sf uac_variable.xml -inf test_data.csv -p 5071 -m 0 127.0.0.1 2>&1 | grep -q "timeout.*variable" && fail "parsing error with variable timeout" + +# Clean up +rm -f test_data.csv + +ok \ No newline at end of file diff --git a/regress/github-#0801/uac_csv.xml b/regress/github-#0801/uac_csv.xml new file mode 100644 index 00000000..227129d3 --- /dev/null +++ b/regress/github-#0801/uac_csv.xml @@ -0,0 +1,65 @@ + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: [field1] + Call-ID: [call_id] + CSeq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test - [field0] + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[local_ip_type] [local_ip] + t=0 0 + m=audio [media_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + ]]> + + + + + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: [field1] [peer_tag_param] + Call-ID: [call_id] + CSeq: 1 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + ]]> + + + + + + + + [peer_tag_param] + To: sipp ;tag=[pid]SIPpTag00[call_number] + Call-ID: [call_id] + CSeq: [cseq] BYE + Content-Length: 0 + ]]> + + + \ No newline at end of file diff --git a/regress/github-#0801/uac_variable.xml b/regress/github-#0801/uac_variable.xml new file mode 100644 index 00000000..df912522 --- /dev/null +++ b/regress/github-#0801/uac_variable.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: [field1] + Call-ID: [call_id] + CSeq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test - [field0] + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[local_ip_type] [local_ip] + t=0 0 + m=audio [media_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + ]]> + + + + + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: [field1] [peer_tag_param] + Call-ID: [call_id] + CSeq: 1 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + ]]> + + + + + + + + [peer_tag_param] + To: sipp ;tag=[pid]SIPpTag00[call_number] + Call-ID: [call_id] + CSeq: [cseq] BYE + Content-Length: 0 + ]]> + + + \ No newline at end of file diff --git a/regress/github-#0801/uas_csv.xml b/regress/github-#0801/uas_csv.xml new file mode 100644 index 00000000..345818d4 --- /dev/null +++ b/regress/github-#0801/uas_csv.xml @@ -0,0 +1,65 @@ + + + + + + + + + + Content-Length: 0 + ]]> + + + + + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=uas 1 1 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[local_ip_type] [local_ip] + t=0 0 + m=audio [media_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + ]]> + + + + + + + + + + + Content-Length: 0 + ]]> + + + + + + \ No newline at end of file diff --git a/regress/github-#0801/uas_variable.xml b/regress/github-#0801/uas_variable.xml new file mode 100644 index 00000000..f8c22d76 --- /dev/null +++ b/regress/github-#0801/uas_variable.xml @@ -0,0 +1,65 @@ + + + + + + + + + + Content-Length: 0 + ]]> + + + + + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=uas 1 1 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[local_ip_type] [local_ip] + t=0 0 + m=audio [media_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + ]]> + + + + + + + + + + + Content-Length: 0 + ]]> + + + + + + \ No newline at end of file diff --git a/src/call.cpp b/src/call.cpp index cfc2160f..74d5846f 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -1972,18 +1972,7 @@ bool call::executeMessage(message *curmsg) unsigned int resolved_timeout = 0; if (curmsg->timeout_str) { // Resolve variables in timeout string at runtime - char timeout_buffer[256]; - SendingMessage timeout_msg(call_scenario, curmsg->timeout_str); - char* resolved_str = createSendingMessage(&timeout_msg, msg_index, timeout_buffer, sizeof(timeout_buffer)); - if (resolved_str) { - char* endptr; - resolved_timeout = strtoul(resolved_str, &endptr, 0); - if (*endptr) { - ERROR("Invalid timeout value after variable substitution: '%s'", resolved_str); - } - } else { - ERROR("Failed to resolve timeout variables"); - } + resolved_timeout = resolveTimeoutValue(curmsg->timeout_str); } else { resolved_timeout = curmsg->timeout; } @@ -2103,18 +2092,7 @@ bool call::executeMessage(message *curmsg) unsigned int resolved_timeout = 0; if (curmsg->timeout_str) { // Resolve variables in timeout string at runtime - char timeout_buffer[256]; - SendingMessage timeout_msg(call_scenario, curmsg->timeout_str); - char* resolved_str = createSendingMessage(&timeout_msg, msg_index, timeout_buffer, sizeof(timeout_buffer)); - if (resolved_str) { - char* endptr; - resolved_timeout = strtoul(resolved_str, &endptr, 0); - if (*endptr) { - ERROR("Invalid timeout value after variable substitution: '%s'", resolved_str); - } - } else { - ERROR("Failed to resolve timeout variables"); - } + resolved_timeout = resolveTimeoutValue(curmsg->timeout_str); } else if (curmsg->timeout) { resolved_timeout = curmsg->timeout; } @@ -6875,6 +6853,71 @@ SessionState call::getSessionStateOld() return _sessionStateOld; } +unsigned int call::resolveTimeoutValue(const char* timeout_str) { + if (!timeout_str) return 0; + + char resolved_str[256]; + strcpy(resolved_str, timeout_str); + + // Handle CSV field variables like [field0], [field1], etc. + char* field_start = strstr(resolved_str, "[field"); + if (field_start) { + char* field_end = strchr(field_start, ']'); + if (field_end) { + char* field_num_str = field_start + 6; // Skip "[field" + *field_end = '\0'; + int field_num = atoi(field_num_str); + + // Get the field value from CSV data directly + char field_value[256] = ""; + if (m_lineNumber && !inFiles.empty()) { + // Use the first available input file (default behavior) + auto file_it = inFiles.begin(); + const char* fileName = file_it->first.c_str(); + int line = (*m_lineNumber)[fileName]; + if (line >= 0) { + file_it->second->getField(line, field_num, field_value, sizeof(field_value)); + } + } + + // Replace [fieldN] with the actual value + strcpy(field_start, field_value); + strcat(field_start, field_end + 1); + } + } + + // Handle computed variables like [$varname] + char* var_start = strstr(resolved_str, "[$"); + if (var_start) { + char* var_end = strchr(var_start, ']'); + if (var_end) { + char* var_name = var_start + 2; // Skip "[$" + *var_end = '\0'; + + // Get the variable value + int varId = call_scenario->get_var(var_name, "timeout variable"); + CCallVariable *var = M_callVariableTable->getVar(varId); + if (var && var->isSet()) { + if (var->isDouble()) { + sprintf(var_start, "%.0lf", var->getDouble()); + strcat(var_start, var_end + 1); + } else if (var->isString()) { + strcpy(var_start, var->getString()); + strcat(var_start, var_end + 1); + } + } + } + } + + // Convert the resolved string to unsigned int + char* endptr; + unsigned int result = strtoul(resolved_str, &endptr, 0); + if (*endptr) { + ERROR("Invalid timeout value after variable substitution: '%s'", resolved_str); + } + return result; +} + #ifdef PCAPPLAY void *send_wrapper(void *arg) { From 03a2f3f55b61ff49f6ed99ea97d5db405ed857b2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 30 Jul 2025 17:36:56 +0000 Subject: [PATCH 4/7] Enable CSV field and computed variable substitution in recv timeout parameters Co-authored-by: orgads <1246544+orgads@users.noreply.github.com> --- regress/github-#0544/debuglsrtpafile_uac | 9 +++++++ regress/github-#0544/debuglsrtpvfile_uac | 9 +++++++ regress/github-#0544/srtpctxdebugfile_uac | 29 +++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 regress/github-#0544/debuglsrtpafile_uac create mode 100644 regress/github-#0544/debuglsrtpvfile_uac create mode 100644 regress/github-#0544/srtpctxdebugfile_uac diff --git a/regress/github-#0544/debuglsrtpafile_uac b/regress/github-#0544/debuglsrtpafile_uac new file mode 100644 index 00000000..820e02f8 --- /dev/null +++ b/regress/github-#0544/debuglsrtpafile_uac @@ -0,0 +1,9 @@ +audio_found : 1 +primary_audio_cryptotag : 1 +secondary_audio_cryptotag : 2 +primary_audio_cryptosuite : AES_CM_128_HMAC_SHA1_80 +secondary_audio_cryptosuite : AES_CM_128_HMAC_SHA1_32 +primary_audio_cryptokeyparams : Ijmgrr3jQU/Z2HKBVPj4SNgR0QHH64i4KOCkeyA3 +secondary_audio_cryptokeyparams : UKUBHcjWoG0prpbzZrDleoWhWgRJG98Dlw0TZ4cZ +primary_unencrypted_audio_srtp : 0 +secondary_unencrypted_audio_srtp: 0 diff --git a/regress/github-#0544/debuglsrtpvfile_uac b/regress/github-#0544/debuglsrtpvfile_uac new file mode 100644 index 00000000..5e342691 --- /dev/null +++ b/regress/github-#0544/debuglsrtpvfile_uac @@ -0,0 +1,9 @@ +video_found : 1 +primary_video_cryptotag : 1 +secondary_video_cryptotag : 2 +primary_video_cryptosuite : AES_CM_128_HMAC_SHA1_80 +secondary_video_cryptosuite : AES_CM_128_HMAC_SHA1_32 +primary_video_cryptokeyparams : W2bmaZ2IKPX+JSEu91+A9a3ImZKjt9II46MqQg7+ +secondary_video_cryptokeyparams : 1Mh4k9bF8y/NiK813haiLO0ZnvXdG9mEy9YyLG+V +primary_unencrypted_video_srtp : 0 +secondary_unencrypted_video_srtp: 0 diff --git a/regress/github-#0544/srtpctxdebugfile_uac b/regress/github-#0544/srtpctxdebugfile_uac new file mode 100644 index 00000000..3ba2fc8f --- /dev/null +++ b/regress/github-#0544/srtpctxdebugfile_uac @@ -0,0 +1,29 @@ +call::init(): (a) TX-UAC-AUDIO SRTP context - CLIENT setting SRTP header size to 12 +call::init(): (a) TX-UAC-VIDEO SRTP context - CLIENT setting SRTP header size to 12 +call::init(): (b) RX-UAC-AUDIO SRTP context - CLIENT setting SRTP header size to 12 +call::init(): (b) RX-UAC-VIDEO SRTP context - CLIENT setting SRTP header size to 12 +call::createSendingMessage(): E_Message_RTPStream_Audio_Port: 6000 +call::createSendingMessage(): E_Message_CryptoTag1Audio() - PRIMARY - CLIENT: 1 +call::createSendingMessage(): E_Message_CryptoSuiteAesCm128Sha1801Audio() - PRIMARY - CLIENT +call::createSendingMessage(): Marking preferred OFFER cryptosuite... +call::createSendingMessage(): E_Message_CryptoKeyParams1Audio() - PRIMARY - CLIENT - component offset:0 +call::createSendingMessage(): E_Message_CryptoKeyParams1Audio() - PRIMARY - CLIENT - generating new concatenated base64-encoded master key/salt:Ijmgrr3jQU/Z2HKBVPj4SNgR0QHH64i4KOCkeyA3 +call::createSendingMessage(): E_Message_CryptoTag2Audio() - SECONDARY - CLIENT: 2 +call::createSendingMessage(): E_Message_CryptoSuiteAesCm128Sha1322Audio() - SECONDARY - CLIENT +call::createSendingMessage(): E_Message_CryptoKeyParams2Audio() - SECONDARY - CLIENT - component offset:0 +call::createSendingMessage(): E_Message_CryptoKeyParams2Audio() - SECONDARY - CLIENT - generating new concatenated base64-encoded master key/salt:UKUBHcjWoG0prpbzZrDleoWhWgRJG98Dlw0TZ4cZ +call::createSendingMessage(): E_Message_RTPStream_Audio_Port: 6001 +call::createSendingMessage(): E_Message_RTPStream_Video_Port: 6002 +call::createSendingMessage(): E_Message_CryptoTag1Video() - PRIMARY - CLIENT: 1 +call::createSendingMessage(): E_Message_CryptoSuiteAesCm128Sha1801Video() - PRIMARY - CLIENT +call::createSendingMessage(): Marking preferred OFFER cryptosuite... +call::createSendingMessage(): E_Message_CryptoKeyParams1Video() - PRIMARY - CLIENT - component offset:0 +call::createSendingMessage(): E_Message_CryptoKeyParams1Video() - PRIMARY - CLIENT - generating new concatenated base64-encoded master key/salt:W2bmaZ2IKPX+JSEu91+A9a3ImZKjt9II46MqQg7+ +call::createSendingMessage(): E_Message_CryptoTag2Video() - SECONDARY - CLIENT: 2 +call::createSendingMessage(): E_Message_CryptoSuiteAesCm128Sha1322Video() - SECONDARY - CLIENT +call::createSendingMessage(): E_Message_CryptoKeyParams2Video() - SECONDARY - CLIENT - component offset:0 +call::createSendingMessage(): E_Message_CryptoKeyParams2Video() - SECONDARY - CLIENT - generating new concatenated base64-encoded master key/salt:1Mh4k9bF8y/NiK813haiLO0ZnvXdG9mEy9YyLG+V +call::createSendingMessage(): E_Message_RTPStream_Video_Port: 6003 +call::createSendingMessage(): (b) RX-UAC-AUDIO SRTP context - ssrc:0x6b8b4567 address:127.0.0.2 port:6000 +call::createSendingMessage(): (b) RX-UAC-VIDEO SRTP context - ssrc:0x6b8b4568 address:127.0.0.2 port:6002 +call::createSendingMessage(): Switching session state: eNoSession --> eOfferSent From 7dba0f07eee50afe4c3e6504d39d7c22babd974f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 30 Jul 2025 18:16:30 +0000 Subject: [PATCH 5/7] Address PR review comments: fix linting, remove debug files, deduplicate code, add newlines Co-authored-by: orgads <1246544+orgads@users.noreply.github.com> --- .gitignore | 5 +++ regress/github-#0544/debuglsrtpafile_uac | 9 ----- regress/github-#0544/debuglsrtpvfile_uac | 9 ----- regress/github-#0544/srtpctxdebugfile_uac | 29 --------------- regress/github-#0801/uac_csv.xml | 2 +- regress/github-#0801/uac_variable.xml | 2 +- regress/github-#0801/uas_csv.xml | 2 +- regress/github-#0801/uas_variable.xml | 2 +- src/call.cpp | 16 ++++----- src/scenario.cpp | 43 ++++++++++------------- 10 files changed, 36 insertions(+), 83 deletions(-) delete mode 100644 regress/github-#0544/debuglsrtpafile_uac delete mode 100644 regress/github-#0544/debuglsrtpvfile_uac delete mode 100644 regress/github-#0544/srtpctxdebugfile_uac diff --git a/.gitignore b/.gitignore index a75ffaef..5184b5d0 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ compile_commands.json CMakeCache.txt CMakeFiles/ cmake_install.cmake +build/ # Ignore *.xml in root dir, but not in regression tests dir. /*.xml @@ -54,3 +55,7 @@ cmake_install.cmake # Ignore autogenerated version.h. /include/version.cmake /version.h + +# Ignore debug files from regression tests +regress/*/debug*_* +regress/*/srtpctx* diff --git a/regress/github-#0544/debuglsrtpafile_uac b/regress/github-#0544/debuglsrtpafile_uac deleted file mode 100644 index 820e02f8..00000000 --- a/regress/github-#0544/debuglsrtpafile_uac +++ /dev/null @@ -1,9 +0,0 @@ -audio_found : 1 -primary_audio_cryptotag : 1 -secondary_audio_cryptotag : 2 -primary_audio_cryptosuite : AES_CM_128_HMAC_SHA1_80 -secondary_audio_cryptosuite : AES_CM_128_HMAC_SHA1_32 -primary_audio_cryptokeyparams : Ijmgrr3jQU/Z2HKBVPj4SNgR0QHH64i4KOCkeyA3 -secondary_audio_cryptokeyparams : UKUBHcjWoG0prpbzZrDleoWhWgRJG98Dlw0TZ4cZ -primary_unencrypted_audio_srtp : 0 -secondary_unencrypted_audio_srtp: 0 diff --git a/regress/github-#0544/debuglsrtpvfile_uac b/regress/github-#0544/debuglsrtpvfile_uac deleted file mode 100644 index 5e342691..00000000 --- a/regress/github-#0544/debuglsrtpvfile_uac +++ /dev/null @@ -1,9 +0,0 @@ -video_found : 1 -primary_video_cryptotag : 1 -secondary_video_cryptotag : 2 -primary_video_cryptosuite : AES_CM_128_HMAC_SHA1_80 -secondary_video_cryptosuite : AES_CM_128_HMAC_SHA1_32 -primary_video_cryptokeyparams : W2bmaZ2IKPX+JSEu91+A9a3ImZKjt9II46MqQg7+ -secondary_video_cryptokeyparams : 1Mh4k9bF8y/NiK813haiLO0ZnvXdG9mEy9YyLG+V -primary_unencrypted_video_srtp : 0 -secondary_unencrypted_video_srtp: 0 diff --git a/regress/github-#0544/srtpctxdebugfile_uac b/regress/github-#0544/srtpctxdebugfile_uac deleted file mode 100644 index 3ba2fc8f..00000000 --- a/regress/github-#0544/srtpctxdebugfile_uac +++ /dev/null @@ -1,29 +0,0 @@ -call::init(): (a) TX-UAC-AUDIO SRTP context - CLIENT setting SRTP header size to 12 -call::init(): (a) TX-UAC-VIDEO SRTP context - CLIENT setting SRTP header size to 12 -call::init(): (b) RX-UAC-AUDIO SRTP context - CLIENT setting SRTP header size to 12 -call::init(): (b) RX-UAC-VIDEO SRTP context - CLIENT setting SRTP header size to 12 -call::createSendingMessage(): E_Message_RTPStream_Audio_Port: 6000 -call::createSendingMessage(): E_Message_CryptoTag1Audio() - PRIMARY - CLIENT: 1 -call::createSendingMessage(): E_Message_CryptoSuiteAesCm128Sha1801Audio() - PRIMARY - CLIENT -call::createSendingMessage(): Marking preferred OFFER cryptosuite... -call::createSendingMessage(): E_Message_CryptoKeyParams1Audio() - PRIMARY - CLIENT - component offset:0 -call::createSendingMessage(): E_Message_CryptoKeyParams1Audio() - PRIMARY - CLIENT - generating new concatenated base64-encoded master key/salt:Ijmgrr3jQU/Z2HKBVPj4SNgR0QHH64i4KOCkeyA3 -call::createSendingMessage(): E_Message_CryptoTag2Audio() - SECONDARY - CLIENT: 2 -call::createSendingMessage(): E_Message_CryptoSuiteAesCm128Sha1322Audio() - SECONDARY - CLIENT -call::createSendingMessage(): E_Message_CryptoKeyParams2Audio() - SECONDARY - CLIENT - component offset:0 -call::createSendingMessage(): E_Message_CryptoKeyParams2Audio() - SECONDARY - CLIENT - generating new concatenated base64-encoded master key/salt:UKUBHcjWoG0prpbzZrDleoWhWgRJG98Dlw0TZ4cZ -call::createSendingMessage(): E_Message_RTPStream_Audio_Port: 6001 -call::createSendingMessage(): E_Message_RTPStream_Video_Port: 6002 -call::createSendingMessage(): E_Message_CryptoTag1Video() - PRIMARY - CLIENT: 1 -call::createSendingMessage(): E_Message_CryptoSuiteAesCm128Sha1801Video() - PRIMARY - CLIENT -call::createSendingMessage(): Marking preferred OFFER cryptosuite... -call::createSendingMessage(): E_Message_CryptoKeyParams1Video() - PRIMARY - CLIENT - component offset:0 -call::createSendingMessage(): E_Message_CryptoKeyParams1Video() - PRIMARY - CLIENT - generating new concatenated base64-encoded master key/salt:W2bmaZ2IKPX+JSEu91+A9a3ImZKjt9II46MqQg7+ -call::createSendingMessage(): E_Message_CryptoTag2Video() - SECONDARY - CLIENT: 2 -call::createSendingMessage(): E_Message_CryptoSuiteAesCm128Sha1322Video() - SECONDARY - CLIENT -call::createSendingMessage(): E_Message_CryptoKeyParams2Video() - SECONDARY - CLIENT - component offset:0 -call::createSendingMessage(): E_Message_CryptoKeyParams2Video() - SECONDARY - CLIENT - generating new concatenated base64-encoded master key/salt:1Mh4k9bF8y/NiK813haiLO0ZnvXdG9mEy9YyLG+V -call::createSendingMessage(): E_Message_RTPStream_Video_Port: 6003 -call::createSendingMessage(): (b) RX-UAC-AUDIO SRTP context - ssrc:0x6b8b4567 address:127.0.0.2 port:6000 -call::createSendingMessage(): (b) RX-UAC-VIDEO SRTP context - ssrc:0x6b8b4568 address:127.0.0.2 port:6002 -call::createSendingMessage(): Switching session state: eNoSession --> eOfferSent diff --git a/regress/github-#0801/uac_csv.xml b/regress/github-#0801/uac_csv.xml index 227129d3..40f37959 100644 --- a/regress/github-#0801/uac_csv.xml +++ b/regress/github-#0801/uac_csv.xml @@ -62,4 +62,4 @@ ]]> - \ No newline at end of file + diff --git a/regress/github-#0801/uac_variable.xml b/regress/github-#0801/uac_variable.xml index df912522..80a74ac1 100644 --- a/regress/github-#0801/uac_variable.xml +++ b/regress/github-#0801/uac_variable.xml @@ -69,4 +69,4 @@ ]]> - \ No newline at end of file + diff --git a/regress/github-#0801/uas_csv.xml b/regress/github-#0801/uas_csv.xml index 345818d4..c2526c85 100644 --- a/regress/github-#0801/uas_csv.xml +++ b/regress/github-#0801/uas_csv.xml @@ -62,4 +62,4 @@ - \ No newline at end of file + diff --git a/regress/github-#0801/uas_variable.xml b/regress/github-#0801/uas_variable.xml index f8c22d76..fd9caa05 100644 --- a/regress/github-#0801/uas_variable.xml +++ b/regress/github-#0801/uas_variable.xml @@ -62,4 +62,4 @@ - \ No newline at end of file + diff --git a/src/call.cpp b/src/call.cpp index 74d5846f..42ce8a9c 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -2096,7 +2096,7 @@ bool call::executeMessage(message *curmsg) } else if (curmsg->timeout) { resolved_timeout = curmsg->timeout; } - + if (resolved_timeout) // If timeout is specified on message receive, use it recv_timeout = getmilliseconds() + resolved_timeout; @@ -6855,10 +6855,10 @@ SessionState call::getSessionStateOld() unsigned int call::resolveTimeoutValue(const char* timeout_str) { if (!timeout_str) return 0; - + char resolved_str[256]; strcpy(resolved_str, timeout_str); - + // Handle CSV field variables like [field0], [field1], etc. char* field_start = strstr(resolved_str, "[field"); if (field_start) { @@ -6867,7 +6867,7 @@ unsigned int call::resolveTimeoutValue(const char* timeout_str) { char* field_num_str = field_start + 6; // Skip "[field" *field_end = '\0'; int field_num = atoi(field_num_str); - + // Get the field value from CSV data directly char field_value[256] = ""; if (m_lineNumber && !inFiles.empty()) { @@ -6879,13 +6879,13 @@ unsigned int call::resolveTimeoutValue(const char* timeout_str) { file_it->second->getField(line, field_num, field_value, sizeof(field_value)); } } - + // Replace [fieldN] with the actual value strcpy(field_start, field_value); strcat(field_start, field_end + 1); } } - + // Handle computed variables like [$varname] char* var_start = strstr(resolved_str, "[$"); if (var_start) { @@ -6893,7 +6893,7 @@ unsigned int call::resolveTimeoutValue(const char* timeout_str) { if (var_end) { char* var_name = var_start + 2; // Skip "[$" *var_end = '\0'; - + // Get the variable value int varId = call_scenario->get_var(var_name, "timeout variable"); CCallVariable *var = M_callVariableTable->getVar(varId); @@ -6908,7 +6908,7 @@ unsigned int call::resolveTimeoutValue(const char* timeout_str) { } } } - + // Convert the resolved string to unsigned int char* endptr; unsigned int result = strtoul(resolved_str, &endptr, 0); diff --git a/src/scenario.cpp b/src/scenario.cpp index 4edfc0f0..80cc8be5 100644 --- a/src/scenario.cpp +++ b/src/scenario.cpp @@ -467,6 +467,23 @@ static int xp_get_optional(const char *name, const char *what) return OPTIONAL_FALSE; } +static void xp_set_timeout(message* curmsg, const char* context_name) +{ + const char* cptr = xp_get_value("timeout"); + if (cptr) { + curmsg->timeout_str = strdup(cptr); + // If the timeout string contains no variables, parse it as integer now + if (strchr(cptr, '[') == nullptr && strchr(cptr, '$') == nullptr) { + curmsg->timeout = get_long(cptr, context_name); + } else { + curmsg->timeout = 0; // Will be resolved at runtime + } + } else { + curmsg->timeout = 0; + curmsg->timeout_str = nullptr; + } +} + int scenario::xp_get_var(const char *name, const char *what, int defval) { @@ -889,18 +906,7 @@ scenario::scenario(char * filename, int deflt) } curmsg -> retrans_delay = xp_get_long("retrans", "retransmission timer", 0); - if ((cptr = xp_get_value("timeout"))) { - curmsg->timeout_str = strdup(cptr); - // If the timeout string contains no variables, parse it as integer now - if (strchr(cptr, '[') == nullptr && strchr(cptr, '$') == nullptr) { - curmsg->timeout = get_long(cptr, "message send timeout"); - } else { - curmsg->timeout = 0; // Will be resolved at runtime - } - } else { - curmsg->timeout = 0; - curmsg->timeout_str = nullptr; - } + xp_set_timeout(curmsg, "message send timeout"); } else if (!strcmp(elem, "recv")) { curmsg->M_type = MSG_TYPE_RECV; /* Received messages descriptions */ @@ -934,18 +940,7 @@ scenario::scenario(char * filename, int deflt) } } - if ((cptr = xp_get_value("timeout"))) { - curmsg->timeout_str = strdup(cptr); - // If the timeout string contains no variables, parse it as integer now - if (strchr(cptr, '[') == nullptr && strchr(cptr, '$') == nullptr) { - curmsg->timeout = get_long(cptr, "message timeout"); - } else { - curmsg->timeout = 0; // Will be resolved at runtime - } - } else { - curmsg->timeout = 0; - curmsg->timeout_str = nullptr; - } + xp_set_timeout(curmsg, "message timeout"); /* record the route set */ /* TODO disallow optional and rrs to coexist? */ From 138cd4c0d4fdf8ec19982214f51f1fc51ea3cddd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 30 Jul 2025 19:34:38 +0000 Subject: [PATCH 6/7] Improve timeout variable testing and fix newline issue Co-authored-by: orgads <1246544+orgads@users.noreply.github.com> --- regress/github-#0801/run | 22 ++++++-- regress/github-#0801/uac_timeout_test.xml | 56 ++++++++++++++++++++ regress/github-#0801/uas_timeout_test.xml | 63 +++++++++++++++++++++++ 3 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 regress/github-#0801/uac_timeout_test.xml create mode 100644 regress/github-#0801/uas_timeout_test.xml diff --git a/regress/github-#0801/run b/regress/github-#0801/run index 9208f274..c46ea663 100755 --- a/regress/github-#0801/run +++ b/regress/github-#0801/run @@ -1,10 +1,11 @@ #!/bin/sh -# Simple test to demonstrate timeout variable functionality works +# Test to verify timeout variable functionality works correctly . "`dirname "$0"`/../functions"; init -# Test that scenarios with timeout variables can be parsed without errors +# Create test data with different timeout values echo "SEQUENTIAL" > test_data.csv -echo "call1;user1;100;1000" >> test_data.csv +echo "call1;user1;100;1000" >> test_data.csv # 1000ms timeout +echo "call2;user2;200;500" >> test_data.csv # 500ms timeout # Test 1: Parse scenario with CSV field timeout - should not produce parsing errors timeout 3 "`get_sipp`" -sf uac_csv.xml -inf test_data.csv -p 5070 -m 0 127.0.0.1 2>&1 | grep -q "timeout.*field" && fail "parsing error with CSV field timeout" @@ -12,7 +13,18 @@ timeout 3 "`get_sipp`" -sf uac_csv.xml -inf test_data.csv -p 5070 -m 0 127.0.0.1 # Test 2: Parse scenario with variable timeout - should not produce parsing errors timeout 3 "`get_sipp`" -sf uac_variable.xml -inf test_data.csv -p 5071 -m 0 127.0.0.1 2>&1 | grep -q "timeout.*variable" && fail "parsing error with variable timeout" +# Test 3: Verify timeout variable resolution doesn't cause parse errors +# Run with very short timeout to minimize test time, looking for variable resolution errors +echo "SEQUENTIAL" > timeout_test.csv +echo "call1;user1;100;100" >> timeout_test.csv # 100ms timeout for quick test +timeout 5 "`get_sipp`" -sf uac_csv.xml -inf timeout_test.csv -p 5072 -m 1 127.0.0.1 -nostdin -timeout 2 2>&1 | grep -iE "(invalid.*timeout|timeout.*not.*valid|variable.*error)" && fail "timeout variable resolution failed" + +# Test 4: Verify computed variable timeout doesn't cause parse errors +echo "SEQUENTIAL" > var_test.csv +echo "call1;user1;100;150" >> var_test.csv # 150ms timeout for quick test +timeout 5 "`get_sipp`" -sf uac_variable.xml -inf var_test.csv -p 5073 -m 1 127.0.0.1 -nostdin -timeout 2 2>&1 | grep -iE "(invalid.*timeout|timeout.*not.*valid|variable.*error)" && fail "variable timeout resolution failed" + # Clean up -rm -f test_data.csv +rm -f test_data.csv timeout_test.csv var_test.csv -ok \ No newline at end of file +ok diff --git a/regress/github-#0801/uac_timeout_test.xml b/regress/github-#0801/uac_timeout_test.xml new file mode 100644 index 00000000..6fb8ac7b --- /dev/null +++ b/regress/github-#0801/uac_timeout_test.xml @@ -0,0 +1,56 @@ + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: [field1] + Call-ID: [call_id] + CSeq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test - [field0] + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[local_ip_type] [local_ip] + t=0 0 + m=audio [media_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + ]]> + + + + + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: [field1] [peer_tag_param] + Call-ID: [call_id] + CSeq: 1 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + ]]> + + + + + + + + + + \ No newline at end of file diff --git a/regress/github-#0801/uas_timeout_test.xml b/regress/github-#0801/uas_timeout_test.xml new file mode 100644 index 00000000..d05befa0 --- /dev/null +++ b/regress/github-#0801/uas_timeout_test.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[local_ip_type] [local_ip] + t=0 0 + m=audio [media_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + ]]> + + + + + + + + + + + + + + + + \ No newline at end of file From e49bc843898fe83df3d1b7dda50514094732d371 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 30 Jul 2025 19:35:47 +0000 Subject: [PATCH 7/7] Remove unused test files and finalize regression test suite Co-authored-by: orgads <1246544+orgads@users.noreply.github.com> --- regress/github-#0801/uac_timeout_test.xml | 56 -------------------- regress/github-#0801/uas_timeout_test.xml | 63 ----------------------- 2 files changed, 119 deletions(-) delete mode 100644 regress/github-#0801/uac_timeout_test.xml delete mode 100644 regress/github-#0801/uas_timeout_test.xml diff --git a/regress/github-#0801/uac_timeout_test.xml b/regress/github-#0801/uac_timeout_test.xml deleted file mode 100644 index 6fb8ac7b..00000000 --- a/regress/github-#0801/uac_timeout_test.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - ;tag=[pid]SIPpTag00[call_number] - To: [field1] - Call-ID: [call_id] - CSeq: 1 INVITE - Contact: sip:sipp@[local_ip]:[local_port] - Max-Forwards: 70 - Subject: Performance Test - [field0] - Content-Type: application/sdp - Content-Length: [len] - - v=0 - o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] - s=- - c=IN IP[local_ip_type] [local_ip] - t=0 0 - m=audio [media_port] RTP/AVP 0 - a=rtpmap:0 PCMU/8000 - ]]> - - - - - - - - - - ;tag=[pid]SIPpTag00[call_number] - To: [field1] [peer_tag_param] - Call-ID: [call_id] - CSeq: 1 ACK - Contact: sip:sipp@[local_ip]:[local_port] - Max-Forwards: 70 - Content-Length: 0 - ]]> - - - - - - - - - - \ No newline at end of file diff --git a/regress/github-#0801/uas_timeout_test.xml b/regress/github-#0801/uas_timeout_test.xml deleted file mode 100644 index d05befa0..00000000 --- a/regress/github-#0801/uas_timeout_test.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - Content-Type: application/sdp - Content-Length: [len] - - v=0 - o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] - s=- - c=IN IP[local_ip_type] [local_ip] - t=0 0 - m=audio [media_port] RTP/AVP 0 - a=rtpmap:0 PCMU/8000 - ]]> - - - - - - - - - - - - - - - - \ No newline at end of file