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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we could just run the read loop on creation

That would have been ideal, and was my first go-to approach. But sure to how things are structured right now, we can one of the following:

  1. This PR or a variation (no reopen, just straight up close and immediately open on the same port).
  2. Start a "custom" rtp loop - just read & discard function until told to stop. Not reusing the Session type.
  3. Start a dummy Session type, have it run the normal, then, when we receive the answer SDP (and thus have *MediaConf), we can determine whether its srtp.NewSession(p.log, p.port, c.Crypto) or rtp.NewSession(p.log, p.port) and drop the old session.
  4. Ideally, I'd like to be able to start the normal session without knowing the selected codecs/crypto just yet, but that requires quite a lot of changes that I'm not sure need to be taken on today.
    All these aren't great to some extent. I think option 2 is easy enough as well, but I'd like to avoid 3.

Do you have any specific preferences on this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

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