Skip to content

fix: Normalize bare LF to CRLF for non-compliant SIP devices#31

Merged
loreste merged 1 commit intomainfrom
fix/crlf-normalizer-sipgo-292
Mar 28, 2026
Merged

fix: Normalize bare LF to CRLF for non-compliant SIP devices#31
loreste merged 1 commit intomainfrom
fix/crlf-normalizer-sipgo-292

Conversation

@loreste
Copy link
Copy Markdown
Owner

@loreste loreste commented Mar 28, 2026

Summary

  • Adds a transport-layer CRLF normalizer to handle non-compliant SIP devices that send bare \n instead of \r\n (ref: sipgo#292)
  • Wraps net.PacketConn (UDP) and net.Listener/net.Conn (TCP) to normalize line endings before sipgo's parser processes them
  • Zero-alloc fast path (~25ns/op) when messages already have correct CRLF

Details

Some PBX devices terminate SIP headers with only \n instead of the \r\n required by RFC 3261 Section 7. Since sipgo's parser strictly requires CRLF, these messages fail to parse. Rather than forking sipgo, this fix intercepts raw bytes at the transport layer and normalizes bare \n to \r\n before they reach the parser.

Files changed:

  • pkg/sip/crlf_normalizer.go — normalizer function + crlfPacketConn, crlfListener, crlfConn wrappers
  • pkg/sip/crlf_normalizer_test.go — unit tests, integration tests over real sockets, benchmarks
  • pkg/sip/custom_server.goListenAndServeUDP and ListenAndServeTCP now use wrapped connections via ServeUDP/ServeTCP

Test plan

  • Unit tests for normalizeCRLF covering: correct CRLF, bare LF, mixed, empty, leading LF, full SIP message
  • Integration test over real UDP socket (TestCRLFPacketConn)
  • Integration test over real TCP socket (TestCRLFConn)
  • Benchmarks confirm zero-alloc fast path for compliant messages
  • Manual testing with a non-compliant PBX device

Summary by CodeRabbit

  • Bug Fixes

    • Improved SIP protocol interoperability by implementing automatic line ending normalization for non-compliant devices that send bare newline characters instead of proper CRLF sequences.
  • Tests

    • Added comprehensive test coverage for CRLF normalization functionality, including unit tests, transport-level integration tests for both UDP and TCP protocols, and performance benchmarks.

Some PBX devices send SIP headers terminated with bare \n instead of
\r\n as required by RFC 3261. This causes sipgo's parser to fail.
Add a transport-layer CRLF normalizer that wraps UDP/TCP connections
to fix bare LF before sipgo processes the data.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 28, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR introduces CRLF normalization for SIP traffic handling non-compliant devices. A new normalizer detects and converts bare \n characters to \r\n in UDP and TCP packet payloads. The custom SIP server is updated to wrap UDP and TCP listeners with these normalization wrappers before passing them to the SIP server.

Changes

Cohort / File(s) Summary
CRLF Normalization Implementation
pkg/sip/crlf_normalizer.go
Added normalizeCRLF() function that replaces bare \n with \r\n. Introduced crlfPacketConn wrapper for UDP packets and crlfListener/crlfConn wrappers for TCP streams. Includes buffer overflow handling for TCP when normalization expands data beyond read buffer capacity.
CRLF Normalization Tests
pkg/sip/crlf_normalizer_test.go
Added comprehensive table-driven tests for normalizeCRLF() covering edge cases (mixed line endings, leading newlines, empty input). Implemented transport-level integration tests for crlfPacketConn and crlfConn. Included benchmarks for normalized and already-compliant payloads.
Custom Server Integration
pkg/sip/custom_server.go
Modified ListenAndServeUDP() and ListenAndServeTCP() to explicitly create listeners and wrap them with crlfPacketConn and crlfListener before passing to SIP server. Added context-based cleanup and improved error messages.

Sequence Diagram

sequenceDiagram
    participant Client
    participant crlfPacketConn
    participant SIPServer as SIP Server
    
    Client->>crlfPacketConn: SendData (with bare \n)
    crlfPacketConn->>crlfPacketConn: ReadFrom (receive packet)
    crlfPacketConn->>crlfPacketConn: normalizeCRLF (convert \n to \r\n)
    crlfPacketConn->>SIPServer: ReadFrom (normalized data)
    SIPServer->>SIPServer: Parse SIP message
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 Bare newlines hop no more,
\r\n normalizes the score!
TCP and UDP unite,
Wrapping streams, setting things right—
Compliant SIP takes flight! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'fix: Normalize bare LF to CRLF for non-compliant SIP devices' clearly and concisely summarizes the main change: adding CRLF normalization for SIP devices that use bare newlines. It accurately reflects the core purpose of the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/crlf-normalizer-sipgo-292

Comment @coderabbitai help to get the list of available commands and usage tips.

}
go func() {
<-ctx.Done()
conn.Close()

Check warning

Code scanning / gosec

Errors unhandled Warning

Errors unhandled
}
go func() {
<-ctx.Done()
listener.Close()

Check warning

Code scanning / gosec

Errors unhandled Warning

Errors unhandled
@loreste loreste merged commit 04e64ff into main Mar 28, 2026
13 of 14 checks passed
@loreste loreste deleted the fix/crlf-normalizer-sipgo-292 branch March 28, 2026 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant