fix: Robust parsing of SIP messages from tcpdump output containing raw header artifacts

This commit is contained in:
Jose Luis Montañes Ojados
2026-01-19 15:35:13 +01:00
parent 4fa44fb9c7
commit 2d99d8ddc4
3 changed files with 36 additions and 14 deletions

View File

@@ -115,7 +115,10 @@ func (c *Capturer) processStream(r io.Reader) {
line := scanner.Text()
// Detect start of SIP message
if isSIPStart(line) {
if idx := findSIPStart(line); idx != -1 {
// Clean the line (remove prefix garbage)
line = line[idx:]
// If we were building a message, parse it
if buffer.Len() > 0 {
c.parseAndEmit(buffer.String())
@@ -161,21 +164,37 @@ func (c *Capturer) parseAndEmit(raw string) {
}
}
// isSIPStart checks if a line looks like the start of a SIP message
func isSIPStart(line string) bool {
// findSIPStart returns the index of the start of a SIP message, or -1 if not found
func findSIPStart(line string) int {
sipMethods := []string{"INVITE", "ACK", "BYE", "CANCEL", "REGISTER", "OPTIONS", "PRACK", "SUBSCRIBE", "NOTIFY", "PUBLISH", "INFO", "REFER", "MESSAGE", "UPDATE"}
// Response
if strings.HasPrefix(line, "SIP/2.0") {
return true
}
// Request
for _, m := range sipMethods {
if strings.HasPrefix(line, m+" ") {
return true
// Check for Response "SIP/2.0"
if idx := strings.Index(line, "SIP/2.0 "); idx != -1 {
// Verify it's not part of a header like Via or Record-Route
// We look at what comes before. If it's the start of the line or preceded by garbage (nulls etc), it's likely a start.
// If it is preceded by "Via: " or "Route: ", it is a header.
prefix := strings.ToUpper(line[:idx])
if !strings.HasSuffix(prefix, "VIA: ") &&
!strings.HasSuffix(prefix, "ROUTE: ") &&
!strings.HasSuffix(prefix, "VIA:") { // Handle varying spacing
return idx
}
}
return false
// Check for Request "METHOD "
for _, m := range sipMethods {
target := m + " "
if idx := strings.Index(line, target); idx != -1 {
// Verify it's not CSeq, Allow, Rack, etc.
prefix := strings.ToUpper(line[:idx])
if !strings.HasSuffix(prefix, "CSEQ: ") &&
!strings.HasSuffix(prefix, "ALLOW: ") &&
!strings.HasSuffix(prefix, "RACK: ") &&
!strings.HasSuffix(prefix, "SUPPORTED: ") {
return idx
}
}
}
return -1
}