From f5f3de27bf31adbd2d07ce8a1a42fc28a48cbaf4 Mon Sep 17 00:00:00 2001 From: Saikrishna Edupuganti <6157640+krsna1729@users.noreply.github.com> Date: Thu, 18 Jun 2026 07:48:40 +0530 Subject: [PATCH 1/2] feat: add ListenerControl callback to Config Go's net.ListenConfig exposes a Control callback so callers can set arbitrary socket options on the raw fd before bind. gosrt hardcodes its own ListenControl() inside Listen() but provides no way for the caller to hook into the same mechanism. Add a ListenerControl field to Config, following the same signature as net.ListenConfig.Control. If set, it runs after gosrt's built-in socket options (SO_REUSEADDR, IP_TOS, IP_TTL) but before the socket is bound. This lets callers set SO_RCVBUF (or any other socket option) without gosrt needing to know about application-specific details: conf.ListenerControl = func(network, address string, c syscall.RawConn) error { return c.Control(func(fd uintptr) { syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_RCVBUF, 26214400) }) } --- config.go | 6 ++++++ listen.go | 11 ++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/config.go b/config.go index be70bc0b..95f48500 100644 --- a/config.go +++ b/config.go @@ -4,6 +4,7 @@ import ( "fmt" "net/url" "strconv" + "syscall" "time" ) @@ -170,6 +171,11 @@ type Config struct { // An implementation of the Logger interface Logger Logger + // ListenerControl is called on the raw socket file descriptor after + // gosrt's built-in options (SO_REUSEADDR, IP_TOS, IP_TTL) are set + // but before the socket is bound. Same signature as net.ListenConfig.Control. + ListenerControl func(network, address string, c syscall.RawConn) error + // if a new IP starts sending data on an existing socket id, allow it AllowPeerIpChange bool } diff --git a/listen.go b/listen.go index 1d53b001..2872f1f0 100644 --- a/listen.go +++ b/listen.go @@ -9,6 +9,7 @@ import ( "net/netip" "os" "sync" + "syscall" "time" srtnet "github.com/datarhei/gosrt/net" @@ -175,7 +176,15 @@ func Listen(network, address string, config Config) (Listener, error) { } lc := net.ListenConfig{ - Control: ListenControl(config), + Control: func(network, address string, c syscall.RawConn) error { + if err := ListenControl(config)(network, address, c); err != nil { + return err + } + if config.ListenerControl != nil { + return config.ListenerControl(network, address, c) + } + return nil + }, } network = "udp" From 6101829f5397a704df0561ab57628802135bdc82 Mon Sep 17 00:00:00 2001 From: Saikrishna Edupuganti <6157640+krsna1729@users.noreply.github.com> Date: Thu, 18 Jun 2026 07:58:39 +0530 Subject: [PATCH 2/2] test: add TestListenerControl Verify that the ListenerControl callback is invoked during Listen(). --- listen_test.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/listen_test.go b/listen_test.go index bae7b400..e292bda0 100644 --- a/listen_test.go +++ b/listen_test.go @@ -6,6 +6,7 @@ import ( "net" "strconv" "sync" + "syscall" "testing" "time" @@ -27,6 +28,22 @@ func TestListenReuse(t *testing.T) { ln.Close() } +func TestListenerControl(t *testing.T) { + called := false + + config := DefaultConfig() + config.ListenerControl = func(network, address string, c syscall.RawConn) error { + called = true + return nil + } + + ln, err := Listen("srt", "127.0.0.1:6003", config) + require.NoError(t, err) + defer ln.Close() + + require.True(t, called, "ListenerControl callback was not invoked") +} + func TestListen(t *testing.T) { ln, err := Listen("srt", "127.0.0.1:6003", DefaultConfig()) require.NoError(t, err)