Skip to content

Commit 5c11564

Browse files
authored
Improve SIP packet detection using heuristic parsing (#2024)
* add initial heuristic detection for SIP packets * add comment * refactor move helper methods to private, keep public API minimal * use function dissectSipHeuristic * Remove unused #include <iostream> * move the implementation to SipLayer.cpp * refactor: use SipRequestFirstLine and SipResponseFirstLine static parsers in heuristic SIP detection * Remove unused helper functions * Revert add-sip-heuristic to match dev * Add heuristic SIP message type detection in dissectSipHeuristic * Resolve conflict * add parameter and return descriptions to SIP parsing functions * fix(spelling): correct "heristic" → "heuristic" * remove unnecessary blank line in SipLayer heuristic check * Change data parameter to const uint8_t* in dissectSipHeuristic * style: trim trailing whitespace (fix CI) * Fix doxygen fails for CI * style: apply clang-format for CI * refactor SIP layer detection logic * Fix SIP version parsing bug and correctly extract version from request line * Rename lineEnd to firstLineEnd * Oops, fix mistake * replace c-style cast with reinterpret_cast for pointer conversion * refactor * style: apply clang-format for CI * Add SipContentBasedDetectionTest for SIP detection by content on non-standard ports * Add sip_non_default_port.pcap * Unify SIP first line parsing into single method * Return std::pair from parseFirstLine to separate validation from data * Use std::move to optimize string assignment * fix typo * Refactor code * Fixed mistake * refactor code * refactor code * remove SipMethodShortMap * refactor code
1 parent 50b55f1 commit 5c11564

File tree

9 files changed

+278
-9
lines changed

9 files changed

+278
-9
lines changed

Packet++/header/SipLayer.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,28 @@ namespace pcpp
114114
return port == 5060 || port == 5061;
115115
}
116116

117+
/// A static factory method that attempts to create a SIP layer from existing packet raw data
118+
/// The method first checks whether the source or destination port matches the SIP protocol.
119+
/// @param[in] data A pointer to the raw data
120+
/// @param[in] dataLen Size of the data in bytes
121+
/// @param[in] prevLayer A pointer to the previous layer
122+
/// @param[in] packet A pointer to the Packet instance where layer will be stored in
123+
/// @param[in] srcPort Source port number to check
124+
/// @param[in] dstPort Dest port number to check
125+
/// @return A newly allocated SIP layer of type request or response, or nullptr if parsing fails
126+
static SipLayer* parseSipLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet,
127+
uint16_t srcPort, uint16_t dstPort);
128+
129+
/// A static factory method that attempts to create a SIP layer from existing packet raw data
130+
/// This method does not check source or destination ports. Instead, it uses heuristics
131+
/// to determine whether the data represents a SIP request or response.
132+
/// @param[in] data A pointer to the raw data
133+
/// @param[in] dataLen Size of the data in bytes
134+
/// @param[in] prevLayer A pointer to the previous layer
135+
/// @param[in] packet A pointer to the Packet instance where layer will be stored in
136+
/// @return A newly allocated SIP layer of type request or response, or nullptr if parsing fails
137+
static SipLayer* parseSipLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
138+
117139
protected:
118140
SipLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ProtocolType protocol)
119141
: TextBasedProtocolMessage(data, dataLen, prevLayer, packet, protocol)
@@ -137,6 +159,16 @@ namespace pcpp
137159
{
138160
return true;
139161
}
162+
163+
private:
164+
enum class SipParseResult
165+
{
166+
Unknown = 0,
167+
Request = 1,
168+
Response = 2,
169+
};
170+
171+
static SipParseResult detectSipMessageType(const uint8_t* data, size_t dataLen);
140172
};
141173

142174
class SipRequestFirstLine;
@@ -498,6 +530,15 @@ namespace pcpp
498530
friend class SipRequestLayer;
499531

500532
public:
533+
/// A structure containing parsed components from a SIP request first line.
534+
/// All string fields are empty if parsing fails
535+
struct SipFirstLineData
536+
{
537+
std::string method; ///< The SIP method (e.g., INVITE, REGISTER, BYE)
538+
std::string uri; ///< The Request-URI destination
539+
std::string version; ///< The SIP protocol version (e.g., SIP/2.0)
540+
};
541+
501542
/// @return The SIP request method
502543
SipRequestLayer::SipMethod getMethod() const
503544
{
@@ -531,6 +572,13 @@ namespace pcpp
531572
/// @return The parsed SIP method
532573
static SipRequestLayer::SipMethod parseMethod(const char* data, size_t dataLen);
533574

575+
/// A static method for parsing the complete SIP request first line from raw data
576+
/// @param[in] data The raw data containing the SIP request line
577+
/// @param[in] dataLen The raw data length
578+
/// @return A pair where first indicates success/failure, and second contains the parsed data.
579+
/// If parsing fails, first is false and second contains empty strings
580+
static std::pair<bool, SipFirstLineData> parseFirstLine(const char* data, size_t dataLen);
581+
534582
/// @return The size in bytes of the SIP request first line
535583
int getSize() const
536584
{

Packet++/src/SipLayer.cpp

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@
1212

1313
namespace pcpp
1414
{
15+
constexpr uint32_t pack4(const char* data, size_t len)
16+
{
17+
return ((len > 0 ? static_cast<uint32_t>(data[0]) << 24 : 0) |
18+
(len > 1 ? static_cast<uint32_t>(data[1]) << 16 : 0) |
19+
(len > 2 ? static_cast<uint32_t>(data[2]) << 8 : 0) | (len > 3 ? static_cast<uint32_t>(data[3]) : 0));
20+
}
21+
22+
constexpr uint32_t operator""_packed4(const char* str, size_t len)
23+
{
24+
return pack4(str, len);
25+
}
1526

1627
const std::string SipMethodEnumToString[14] = { "INVITE", "ACK", "BYE", "CANCEL", "REGISTER",
1728
"PRACK", "OPTIONS", "SUBSCRIBE", "NOTIFY", "PUBLISH",
@@ -103,6 +114,92 @@ namespace pcpp
103114
}
104115
}
105116

117+
SipLayer::SipParseResult SipLayer::detectSipMessageType(const uint8_t* data, size_t dataLen)
118+
{
119+
if (!data || dataLen < 3)
120+
{
121+
return SipLayer::SipParseResult::Unknown;
122+
}
123+
124+
uint32_t key = pack4(reinterpret_cast<const char*>(data), dataLen);
125+
126+
switch (key)
127+
{
128+
case "INVI"_packed4: // INVITE
129+
case "ACK "_packed4: // ACK
130+
case "BYE "_packed4: // BYE
131+
case "CANC"_packed4: // CANCEL
132+
case "REGI"_packed4: // REGISTER
133+
case "PRAC"_packed4: // PRACK
134+
case "OPTI"_packed4: // OPTIONS
135+
case "SUBS"_packed4: // SUBSCRIBE
136+
case "NOTI"_packed4: // NOTIFY
137+
case "PUBL"_packed4: // PUBLISH
138+
case "INFO"_packed4: // INFO
139+
case "REFE"_packed4: // REFER
140+
case "MESS"_packed4: // MESSAGE
141+
case "UPDA"_packed4: // UPDATE
142+
return SipLayer::SipParseResult::Request;
143+
144+
case "SIP/"_packed4:
145+
return SipLayer::SipParseResult::Response;
146+
147+
default:
148+
return SipLayer::SipParseResult::Unknown;
149+
}
150+
}
151+
152+
SipLayer* SipLayer::parseSipLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, uint16_t srcPort,
153+
uint16_t dstPort)
154+
{
155+
if (!(SipLayer::isSipPort(srcPort) || SipLayer::isSipPort(dstPort)))
156+
{
157+
return nullptr;
158+
}
159+
160+
if (SipRequestFirstLine::parseMethod(reinterpret_cast<char*>(data), dataLen) !=
161+
SipRequestLayer::SipMethodUnknown)
162+
{
163+
return new SipRequestLayer(data, dataLen, prevLayer, packet);
164+
}
165+
166+
if (SipResponseFirstLine::parseStatusCode(reinterpret_cast<char*>(data), dataLen) !=
167+
SipResponseLayer::SipStatusCodeUnknown &&
168+
!SipResponseFirstLine::parseVersion(reinterpret_cast<char*>(data), dataLen).empty())
169+
{
170+
return new SipResponseLayer(data, dataLen, prevLayer, packet);
171+
}
172+
173+
return nullptr;
174+
}
175+
176+
SipLayer* SipLayer::parseSipLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
177+
{
178+
SipLayer::SipParseResult sipParseResult = detectSipMessageType(data, dataLen);
179+
180+
if (sipParseResult == SipLayer::SipParseResult::Unknown)
181+
{
182+
return nullptr;
183+
}
184+
185+
if (sipParseResult == SipLayer::SipParseResult::Request)
186+
{
187+
if (SipRequestFirstLine::parseFirstLine(reinterpret_cast<char*>(data), dataLen).first)
188+
{
189+
return new SipRequestLayer(data, dataLen, prevLayer, packet);
190+
}
191+
return nullptr;
192+
}
193+
194+
if (SipResponseFirstLine::parseStatusCode(reinterpret_cast<char*>(data), dataLen) !=
195+
SipResponseLayer::SipStatusCodeUnknown &&
196+
!SipResponseFirstLine::parseVersion(reinterpret_cast<char*>(data), dataLen).empty())
197+
{
198+
return new SipResponseLayer(data, dataLen, prevLayer, packet);
199+
}
200+
return nullptr;
201+
}
202+
106203
// -------- Class SipRequestFirstLine -----------------
107204

108205
SipRequestFirstLine::SipRequestFirstLine(SipRequestLayer* sipRequest) : m_SipRequest(sipRequest)
@@ -208,6 +305,84 @@ namespace pcpp
208305
return methodAdEnum->second;
209306
}
210307

308+
std::pair<bool, SipRequestFirstLine::SipFirstLineData> SipRequestFirstLine::parseFirstLine(const char* data,
309+
size_t dataLen)
310+
{
311+
SipFirstLineData result = { "", "", "" };
312+
313+
if (data == nullptr || dataLen == 0)
314+
{
315+
PCPP_LOG_DEBUG("Empty data in SIP request line");
316+
return { false, result };
317+
}
318+
319+
// Find first space (end of METHOD)
320+
size_t firstSpaceIndex = 0;
321+
while (firstSpaceIndex < dataLen && data[firstSpaceIndex] != ' ')
322+
{
323+
firstSpaceIndex++;
324+
}
325+
326+
if (firstSpaceIndex == 0 || firstSpaceIndex == dataLen)
327+
{
328+
PCPP_LOG_DEBUG("Invalid METHOD in SIP request line");
329+
return { false, result };
330+
}
331+
332+
// Validate method exists in SipMethodStringToEnum
333+
std::string methodStr{ data, firstSpaceIndex };
334+
if (SipMethodStringToEnum.find(methodStr) == SipMethodStringToEnum.end())
335+
{
336+
PCPP_LOG_DEBUG("Unknown SIP method");
337+
return { false, result };
338+
}
339+
340+
// Find second space (end of URI)
341+
size_t secondSpaceIndex = firstSpaceIndex + 1;
342+
while (secondSpaceIndex < dataLen && data[secondSpaceIndex] != ' ')
343+
secondSpaceIndex++;
344+
345+
if (secondSpaceIndex == dataLen)
346+
{
347+
PCPP_LOG_DEBUG("No space before version");
348+
return { false, result };
349+
}
350+
351+
size_t uriLen = secondSpaceIndex - firstSpaceIndex - 1;
352+
if (uriLen == 0)
353+
{
354+
PCPP_LOG_DEBUG("Empty URI");
355+
return { false, result };
356+
}
357+
358+
// Find end of line
359+
size_t lineEnd = secondSpaceIndex + 1;
360+
while (lineEnd < dataLen && data[lineEnd] != '\r' && data[lineEnd] != '\n')
361+
lineEnd++;
362+
363+
// Minimum length for "SIP/x.y"
364+
size_t versionLen = lineEnd - secondSpaceIndex - 1;
365+
if (versionLen < 7)
366+
{
367+
PCPP_LOG_DEBUG("Version too short");
368+
return { false, result };
369+
}
370+
371+
const char* versionStart = data + secondSpaceIndex + 1;
372+
if (versionStart[0] != 'S' || versionStart[1] != 'I' || versionStart[2] != 'P' || versionStart[3] != '/')
373+
{
374+
PCPP_LOG_DEBUG("Invalid SIP version format");
375+
return { false, result };
376+
}
377+
378+
// All validations passed
379+
result.method = std::move(methodStr);
380+
result.uri = std::string{ data + firstSpaceIndex + 1, uriLen };
381+
result.version = std::string{ versionStart, versionLen };
382+
383+
return { true, result };
384+
}
385+
211386
void SipRequestFirstLine::parseVersion()
212387
{
213388
if (m_SipRequest->getDataLen() < static_cast<size_t>(m_UriOffset))

Packet++/src/UdpLayer.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,11 @@ namespace pcpp
110110
m_NextLayer = new DnsLayer(udpData, udpDataLen, this, getAttachedPacket());
111111
else if (SipLayer::isSipPort(portDst) || SipLayer::isSipPort(portSrc))
112112
{
113-
if (SipRequestFirstLine::parseMethod((char*)udpData, udpDataLen) != SipRequestLayer::SipMethodUnknown)
114-
m_NextLayer = new SipRequestLayer(udpData, udpDataLen, this, getAttachedPacket());
115-
else if (SipResponseFirstLine::parseStatusCode((char*)udpData, udpDataLen) !=
116-
SipResponseLayer::SipStatusCodeUnknown &&
117-
SipResponseFirstLine::parseVersion((char*)udpData, udpDataLen) != "")
118-
m_NextLayer = new SipResponseLayer(udpData, udpDataLen, this, getAttachedPacket());
119-
else
120-
m_NextLayer = new PayloadLayer(udpData, udpDataLen, this, getAttachedPacket());
113+
m_NextLayer = SipLayer::parseSipLayer(udpData, udpDataLen, this, getAttachedPacket(), portSrc, portDst);
114+
if (!m_NextLayer)
115+
{
116+
constructNextLayer<PayloadLayer>(udpData, udpDataLen, getAttachedPacket());
117+
}
121118
}
122119
else if ((RadiusLayer::isRadiusPort(portDst) || RadiusLayer::isRadiusPort(portSrc)) &&
123120
RadiusLayer::isDataValid(udpData, udpDataLen))
@@ -152,8 +149,20 @@ namespace pcpp
152149
if (!m_NextLayer)
153150
m_NextLayer = new PayloadLayer(udpData, udpDataLen, this, getAttachedPacket());
154151
}
155-
else
152+
153+
// If a valid layer was found, return immediately
154+
if (m_NextLayer)
155+
{
156+
return;
157+
}
158+
159+
// Here, heuristics for all protocols should be invoked to determine the correct layer
160+
m_NextLayer = SipLayer::parseSipLayer(udpData, udpDataLen, this, getAttachedPacket());
161+
162+
if (!m_NextLayer)
163+
{
156164
m_NextLayer = new PayloadLayer(udpData, udpDataLen, this, getAttachedPacket());
165+
}
157166
}
158167

159168
void UdpLayer::computeCalculateFields()
1.95 KB
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
5056c2a5e282ac49c3b41e570800450003e60000400040118c1fc0a81444c0a81553d03dcc9c03d20000494e56495445207369703a31303036403139322e3136382e32312e38333a3532333830205349502f322e300d0a5669613a205349502f322e302f554450203139322e3136382e32302e36383a35333330393b72706f72743b6272616e63683d7a39684734624b506a39336161623839353831623034623239383762353561353332303331643731320d0a4d61782d466f7277617264733a2037300d0a46726f6d3a203c7369703a31303035403139322e3136382e32312e38333e3b7461673d61353062666662356464643334323665386638343865636537643064333839620d0a546f3a203c7369703a31303036403139322e3136382e32312e38333e0d0a436f6e746163743a203c7369703a31303035403139322e3136382e32302e36383a35333330393b6f623e0d0a43616c6c2d49443a2030633362616232636562653334656339393761383064616134333436623339330d0a435365713a20313230303320494e564954450d0a416c6c6f773a20505241434b2c20494e564954452c2041434b2c204259452c2043414e43454c2c205550444154452c20494e464f2c205355425343524942452c204e4f544946592c2052454645522c204d4553534147452c204f5054494f4e530d0a537570706f727465643a207265706c616365732c2031303072656c2c2074696d65722c206e6f72656665727375620d0a53657373696f6e2d457870697265733a20313830300d0a4d696e2d53453a2039300d0a557365722d4167656e743a204d6963726f5349502f332e32322e330d0a436f6e74656e742d547970653a206170706c69636174696f6e2f7364700d0a436f6e74656e742d4c656e6774683a2020203334320d0a0d0a763d300d0a6f3d2d2033393735343231383631203339373534323138363120494e20495034203139322e3136382e32302e36380d0a733d706a6d656469610d0a623d41533a38340d0a743d3020300d0a613d582d6e61743a300d0a6d3d617564696f2034303034205254502f41565020382030203130310d0a633d494e20495034203139322e3136382e32302e36380d0a623d544941533a36343030300d0a613d727463703a3430303520494e20495034203139322e3136382e32302e36380d0a613d73656e64726563760d0a613d7274706d61703a382050434d412f383030300d0a613d7274706d61703a302050434d552f383030300d0a613d7274706d61703a3130312074656c6570686f6e652d6576656e742f383030300d0a613d666d74703a31303120302d31360d0a613d737372633a31333038393936333420636e616d653a343938653434356430336530346262360d0a
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
5056c2a5e282ac49c3b41e570800450003960000400040118c6fc0a81444c0a81553e0f2cc9c038200005349502f322e3020323030204f4b0d0a5669613a205349502f322e302f554450203139322e3136382e32312e38333a35323338303b72706f72743d35323338303b72656365697665643d3139322e3136382e32312e38333b6272616e63683d7a39684734624b396a6a676536483430356335610d0a43616c6c2d49443a2030633166623163352d353966352d313233662d316162302d3030353035366135383034390d0a46726f6d3a2022457874656e73696f6e203130303522203c7369703a31303035403139322e3136382e32312e38333e3b7461673d3963745174324e355a6d3546440d0a546f3a203c7369703a31303036403139322e3136382e32302e36383b6f623e3b7461673d35323065343635313963653934333532626566323630366161616436333333630d0a435365713a2031303836353634333820494e564954450d0a416c6c6f773a20505241434b2c20494e564954452c2041434b2c204259452c2043414e43454c2c205550444154452c20494e464f2c205355425343524942452c204e4f544946592c2052454645522c204d4553534147452c204f5054494f4e530d0a436f6e746163743a203c7369703a31303036403139322e3136382e32302e36383a35373538363b6f623e0d0a537570706f727465643a207265706c616365732c2031303072656c2c2074696d65722c206e6f72656665727375620d0a436f6e74656e742d547970653a206170706c69636174696f6e2f7364700d0a436f6e74656e742d4c656e6774683a2020203331390d0a0d0a763d300d0a6f3d2d2033393735343231383631203339373534323138363220494e20495034203139322e3136382e32302e36380d0a733d706a6d656469610d0a623d41533a38340d0a743d3020300d0a613d582d6e61743a300d0a6d3d617564696f2034303036205254502f4156502038203130310d0a633d494e20495034203139322e3136382e32302e36380d0a623d544941533a36343030300d0a613d727463703a3430303720494e20495034203139322e3136382e32302e36380d0a613d73656e64726563760d0a613d7274706d61703a382050434d412f383030300d0a613d7274706d61703a3130312074656c6570686f6e652d6576656e742f383030300d0a613d666d74703a31303120302d31360d0a613d737372633a3134393431323030333120636e616d653a313739363565373334373065373364390d0a

Tests/Packet++Test/TestDefinition.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ PTF_TEST_CASE(Igmpv3ReportCreateAndEditTest);
181181
// Implemented in SipSdpTests.cpp
182182
PTF_TEST_CASE(SipRequestParseMethodTest);
183183
PTF_TEST_CASE(SipRequestLayerParsingTest);
184+
PTF_TEST_CASE(SipDetectionByContentOnNonStandardPort);
184185
PTF_TEST_CASE(SipRequestLayerCreationTest);
185186
PTF_TEST_CASE(SipRequestLayerEditTest);
186187
PTF_TEST_CASE(SipResponseParseStatusCodeTest);

Tests/Packet++Test/Tests/SipSdpTests.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,39 @@ PTF_TEST_CASE(SipRequestLayerParsingTest)
166166

167167
} // SipRequestLayerParsingTest
168168

169+
PTF_TEST_CASE(SipDetectionByContentOnNonStandardPort)
170+
{
171+
timeval time;
172+
gettimeofday(&time, nullptr);
173+
174+
// Load SIP Request packet with non-standard ports: UDP src=53309, dst=52380
175+
auto rawPacket1 = createPacketFromHexResource("PacketExamples/sip_non_default_port1.dat");
176+
pcpp::Packet sipReqNonStandardPort(rawPacket1.get());
177+
178+
PTF_ASSERT_TRUE(sipReqNonStandardPort.isPacketOfType(pcpp::SIPRequest));
179+
180+
auto sipReqLayer = sipReqNonStandardPort.getLayerOfType<pcpp::SipRequestLayer>();
181+
PTF_ASSERT_NOT_NULL(sipReqLayer);
182+
183+
PTF_ASSERT_EQUAL(sipReqLayer->getFirstLine()->getMethod(), pcpp::SipRequestLayer::SipINVITE, enum);
184+
PTF_ASSERT_EQUAL(sipReqLayer->getFirstLine()->getUri(), "sip:1006@192.168.21.83:52380");
185+
PTF_ASSERT_EQUAL(sipReqLayer->getFirstLine()->getVersion(), "SIP/2.0");
186+
187+
// Load SIP Response packet with non-standard ports: UDP src=53309, dst=52380
188+
auto rawPacket2 = createPacketFromHexResource("PacketExamples/sip_non_default_port2.dat");
189+
pcpp::Packet sipResNonStandardPort(rawPacket2.get());
190+
191+
PTF_ASSERT_TRUE(sipResNonStandardPort.isPacketOfType(pcpp::SIPResponse));
192+
193+
auto sipRespLayer = sipResNonStandardPort.getLayerOfType<pcpp::SipResponseLayer>();
194+
PTF_ASSERT_NOT_NULL(sipRespLayer);
195+
196+
PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCode(), pcpp::SipResponseLayer::Sip200OK, enum);
197+
PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCodeAsInt(), 200);
198+
PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCodeString(), "OK");
199+
PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getVersion(), "SIP/2.0");
200+
} // SipDetectionByContentOnNonStandardPort
201+
169202
PTF_TEST_CASE(SipRequestLayerCreationTest)
170203
{
171204
auto rawPacketAndBuf1 = createPacketAndBufferFromHexResource("PacketExamples/sip_req1.dat");

Tests/Packet++Test/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ int main(int argc, char* argv[])
278278

279279
PTF_RUN_TEST(SipRequestParseMethodTest, "sip");
280280
PTF_RUN_TEST(SipRequestLayerParsingTest, "sip");
281+
PTF_RUN_TEST(SipDetectionByContentOnNonStandardPort, "sip");
281282
PTF_RUN_TEST(SipRequestLayerCreationTest, "sip");
282283
PTF_RUN_TEST(SipRequestLayerEditTest, "sip");
283284
PTF_RUN_TEST(SipResponseParseStatusCodeTest, "sip");

0 commit comments

Comments
 (0)