Skip to content

Conversation

@alexlivekit
Copy link
Contributor

@alexlivekit alexlivekit commented Jan 27, 2026

From initial PR, timeline:

  • Start outbound call.
    • This causes us first create a local UDP socket to reserve the port.
    • rtpLoop is not yet started, only after accepting call (meaning we're not reading from socket at all)
    • This is a good behavior, since we want media to be ready asap.
    • Send RTP offer.
  • Remote side receives RTP offer, generates RTP answer and sends back.
    • This can be with either SIP-183 or SIP-200.
    • On a 200, there is no issue.
    • On a 183 code, the remote media stack starts sending RTP to local cloud-sip right away.
  • As long as the call is not answered
    • Remote end is sending RTP.
    • Local end not reading RTP from OS socket.
    • UDP buffer accumulates packets.
    • If UDP buffer is maxed, new packets arriving to the machine will be dropped.
  • Call is accepted
    • Only now do we start rtpLoop
    • OS UDP buffer has data, and if it was full can potentially have bot a lot of it, and the moment we start reading, it will suddenly accept new RTP packets creating a discontinuity. Data shows it can be in the range of 0.5 to 1 seconds.

This PR is here to address that issue.

// Creates a new underlying UDP connection on the same port.
// The practical use of this function is to discard the assicuated OS-level read buffer of the old socket.
func (c *udpConn) Reopen() error {
lc := &net.ListenConfig{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is possible to enable SO_REUSEADDR here, instead of on creation, but would require an entire rework of these interface chains. Avoiding that for now.

@alexlivekit alexlivekit marked this pull request as ready for review January 27, 2026 08:01
@alexlivekit alexlivekit requested a review from a team as a code owner January 27, 2026 08:01
lc := &net.ListenConfig{
Control: func(network, address string, c syscall.RawConn) error {
return c.Control(func(fd uintptr) {
syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, anything that has to do with syscall should be in a separate file, under a build flag. This also implies that there should be a file that provides a fallback if these syscalls are not available.

So maybe we could solve it a bit more naively to avoid these portability issues? For example, we could just run the read loop on creation, but do not pass packets down until the port is explicitly enabled.

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.

3 participants