From 6f0faa49d189b97b51c3f83bc1aade47de0a267f Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Fri, 7 Aug 2026 10:05:05 +0200 Subject: [PATCH] webrtc: fix warning when IPv6 is disabled (#5733) (#6048) --- internal/core/core.go | 16 ++++++++ internal/core/path.go | 2 + internal/core/path_manager.go | 2 + internal/protocols/webrtc/peer_connection.go | 12 ++++-- .../protocols/webrtc/peer_connection_test.go | 40 +++++++++++++++++++ internal/protocols/whip/client.go | 2 + internal/servers/webrtc/server.go | 2 + internal/servers/webrtc/session.go | 3 ++ internal/staticsources/handler.go | 2 + internal/staticsources/webrtc/source.go | 2 + 10 files changed, 79 insertions(+), 4 deletions(-) diff --git a/internal/core/core.go b/internal/core/core.go index b6be1441..1f7a2473 100644 --- a/internal/core/core.go +++ b/internal/core/core.go @@ -5,6 +5,7 @@ import ( "context" _ "embed" "fmt" + "net" "os" "os/signal" "path/filepath" @@ -98,6 +99,16 @@ func getRTPMaxPayloadSize(udpMaxPayloadSize int, rtspEncryption conf.Encryption) return v } +func supportsIPv6() bool { + ln, err := net.ListenUDP("udp6", &net.UDPAddr{IP: net.IPv6unspecified, Port: 0}) + if err != nil { + return false + } + defer ln.Close() //nolint:errcheck + + return true +} + var cli struct { Confpath string `arg:"" default:""` Version bool `help:"print version"` @@ -111,6 +122,7 @@ type Core struct { ctxCancel func() confPath string conf *conf.Conf + supportsIPv6 bool logger *logger.Logger externalCmdPool *externalcmd.Pool authManager *auth.Manager @@ -345,6 +357,8 @@ func (p *Core) createResources(initial bool) error { gin.SetMode(gin.ReleaseMode) + p.supportsIPv6 = supportsIPv6() + p.externalCmdPool = &externalcmd.Pool{} p.externalCmdPool.Initialize() } @@ -456,6 +470,7 @@ func (p *Core) createResources(initial bool) error { udpReadBufferSize: p.conf.UDPReadBufferSize, udpMaxPayloadSize: p.conf.UDPMaxPayloadSize, rtpMaxPayloadSize: rtpMaxPayloadSize, + supportsIPv6: p.supportsIPv6, pathConfs: p.conf.Paths, authManager: p.authManager, externalCmdPool: p.externalCmdPool, @@ -659,6 +674,7 @@ func (p *Core) createResources(initial bool) error { UDPReadBufferSize: p.conf.UDPReadBufferSize, LocalUDPAddress: p.conf.WebRTCLocalUDPAddress, LocalTCPAddress: p.conf.WebRTCLocalTCPAddress, + SupportsIPv6: p.supportsIPv6, IPsFromInterfaces: p.conf.WebRTCIPsFromInterfaces, IPsFromInterfacesList: p.conf.WebRTCIPsFromInterfacesList, AdditionalHosts: p.conf.WebRTCAdditionalHosts, diff --git a/internal/core/path.go b/internal/core/path.go index 1bba5f0a..611a5ca9 100644 --- a/internal/core/path.go +++ b/internal/core/path.go @@ -101,6 +101,7 @@ type path struct { udpReadBufferSize uint udpMaxPayloadSize int rtpMaxPayloadSize int + supportsIPv6 bool conf *conf.Path name string matches []string @@ -237,6 +238,7 @@ func (pa *path) run() { WriteQueueSize: pa.writeQueueSize, UDPReadBufferSize: pa.udpReadBufferSize, RTPMaxPayloadSize: pa.rtpMaxPayloadSize, + SupportsIPv6: pa.supportsIPv6, Matches: pa.matches, PathManager: pa.parent, Parent: pa, diff --git a/internal/core/path_manager.go b/internal/core/path_manager.go index b65259c5..366a4f95 100644 --- a/internal/core/path_manager.go +++ b/internal/core/path_manager.go @@ -83,6 +83,7 @@ type pathManager struct { udpReadBufferSize uint udpMaxPayloadSize int rtpMaxPayloadSize int + supportsIPv6 bool pathConfs map[string]*conf.Path authManager pathManagerAuthManager externalCmdPool *externalcmd.Pool @@ -504,6 +505,7 @@ func (pm *pathManager) createPath( udpReadBufferSize: pm.udpReadBufferSize, udpMaxPayloadSize: pm.udpMaxPayloadSize, rtpMaxPayloadSize: pm.rtpMaxPayloadSize, + supportsIPv6: pm.supportsIPv6, conf: pathConf, name: name, matches: matches, diff --git a/internal/protocols/webrtc/peer_connection.go b/internal/protocols/webrtc/peer_connection.go index 516cb795..9f0c3bb5 100644 --- a/internal/protocols/webrtc/peer_connection.go +++ b/internal/protocols/webrtc/peer_connection.go @@ -180,6 +180,7 @@ type PeerConnection struct { IPsFromInterfacesList []string AdditionalHosts []string STUNGatherTimeout time.Duration + SupportsIPv6 bool Publish bool OutboundTracks []*OutboundTrack OutboundDataChannels []*OutboundDataChannel @@ -217,13 +218,16 @@ func (co *PeerConnection) Start() error { settingsEngine.SetIncludeLoopbackCandidate(true) // always enable TCP since we might be the client of a remote TCP listener - networkTypes := []webrtc.NetworkType{ - webrtc.NetworkTypeTCP4, - webrtc.NetworkTypeTCP6, + networkTypes := []webrtc.NetworkType{webrtc.NetworkTypeTCP4} + if co.SupportsIPv6 { + networkTypes = append(networkTypes, webrtc.NetworkTypeTCP6) } if co.LocalRandomUDP || co.ICEUDPMux != nil || len(co.ICEServers) != 0 { - networkTypes = append(networkTypes, webrtc.NetworkTypeUDP4, webrtc.NetworkTypeUDP6) + networkTypes = append(networkTypes, webrtc.NetworkTypeUDP4) + if co.SupportsIPv6 { + networkTypes = append(networkTypes, webrtc.NetworkTypeUDP6) + } } settingsEngine.SetNetworkTypes(networkTypes) diff --git a/internal/protocols/webrtc/peer_connection_test.go b/internal/protocols/webrtc/peer_connection_test.go index b2ebf0e2..6cda3aec 100644 --- a/internal/protocols/webrtc/peer_connection_test.go +++ b/internal/protocols/webrtc/peer_connection_test.go @@ -161,6 +161,7 @@ func TestPeerConnectionCandidates(t *testing.T) { LocalRandomUDP: (ca == "udp random" || ca == "udp random+stun"), ICEUDPMux: udpMux, ICETCPMux: tcpMux, + SupportsIPv6: true, IPsFromInterfaces: true, IPsFromInterfacesList: []string{"lo"}, Log: test.NilLogger, @@ -203,6 +204,45 @@ func TestPeerConnectionCandidates(t *testing.T) { } } +func TestPeerConnectionCandidatesIPv6Disabled(t *testing.T) { + pc2, err := webrtc.NewPeerConnection(webrtc.Configuration{}) + require.NoError(t, err) + defer pc2.Close() //nolint:errcheck + + track, err := webrtc.NewTrackLocalStaticRTP( + webrtc.RTPCodecCapability{ + MimeType: webrtc.MimeTypeVP8, + ClockRate: 90000, + }, + "video", + "publisher", + ) + require.NoError(t, err) + + _, err = pc2.AddTrack(track) + require.NoError(t, err) + + offer, err := pc2.CreateOffer(nil) + require.NoError(t, err) + + pc := &PeerConnection{ + SupportsIPv6: false, + IPsFromInterfaces: true, + IPsFromInterfacesList: []string{"lo"}, + Log: test.NilLogger, + } + + err = pc.Start() + require.NoError(t, err) + defer pc.Close() + + answer, err := pc.CreateFullAnswer(&offer, false) + require.NoError(t, err) + + require.NotContains(t, answer.SDP, " udp6 ") + require.NotContains(t, answer.SDP, " tcp6 ") +} + func TestPeerConnectionConnectivity(t *testing.T) { for _, mode := range []string{ "passive udp", diff --git a/internal/protocols/whip/client.go b/internal/protocols/whip/client.go index 388d8328..ab9f2e03 100644 --- a/internal/protocols/whip/client.go +++ b/internal/protocols/whip/client.go @@ -81,6 +81,7 @@ type Client struct { HTTPClient *http.Client BearerToken string UDPReadBufferSize uint + SupportsIPv6 bool STUNGatherTimeout time.Duration HandshakeTimeout time.Duration TrackGatherTimeout time.Duration @@ -110,6 +111,7 @@ func (c *Client) Initialize(ctx context.Context) error { c.pc = &webrtc.PeerConnection{ Net: &webrtc.Net{UDPReadBufferSize: int(c.UDPReadBufferSize)}, LocalRandomUDP: true, + SupportsIPv6: c.SupportsIPv6, ICEServers: iceServers, IPsFromInterfaces: true, Publish: c.Publish, diff --git a/internal/servers/webrtc/server.go b/internal/servers/webrtc/server.go index 72a1292c..4aa53a14 100644 --- a/internal/servers/webrtc/server.go +++ b/internal/servers/webrtc/server.go @@ -197,6 +197,7 @@ type Server struct { UDPReadBufferSize uint LocalUDPAddress string LocalTCPAddress string + SupportsIPv6 bool IPsFromInterfaces bool IPsFromInterfacesList []string AdditionalHosts []string @@ -370,6 +371,7 @@ outer: additionalHosts: s.AdditionalHosts, iceUDPMux: s.iceUDPMux, iceTCPMux: s.iceTCPMux, + supportsIPv6: s.SupportsIPv6, stunGatherTimeout: s.STUNGatherTimeout, handshakeTimeout: s.HandshakeTimeout, trackGatherTimeout: s.TrackGatherTimeout, diff --git a/internal/servers/webrtc/session.go b/internal/servers/webrtc/session.go index 441eadb5..05f98e53 100644 --- a/internal/servers/webrtc/session.go +++ b/internal/servers/webrtc/session.go @@ -243,6 +243,7 @@ type session struct { additionalHosts []string iceUDPMux ice.UDPMux iceTCPMux *webrtc.TCPMuxWrapper + supportsIPv6 bool stunGatherTimeout conf.Duration handshakeTimeout conf.Duration trackGatherTimeout conf.Duration @@ -368,6 +369,7 @@ func (s *session) runPublish(req *initialRequestReq) (int, error) { Net: s.net, ICEUDPMux: s.iceUDPMux, ICETCPMux: s.iceTCPMux, + SupportsIPv6: s.supportsIPv6, ICEServers: iceServers, IPsFromInterfaces: s.ipsFromInterfaces, IPsFromInterfacesList: s.ipsFromInterfacesList, @@ -518,6 +520,7 @@ func (s *session) runRead(req *initialRequestReq) (int, error) { Net: s.net, ICEUDPMux: s.iceUDPMux, ICETCPMux: s.iceTCPMux, + SupportsIPv6: s.supportsIPv6, ICEServers: iceServers, IPsFromInterfaces: s.ipsFromInterfaces, IPsFromInterfacesList: s.ipsFromInterfacesList, diff --git a/internal/staticsources/handler.go b/internal/staticsources/handler.go index 80b18616..dc97f800 100644 --- a/internal/staticsources/handler.go +++ b/internal/staticsources/handler.go @@ -67,6 +67,7 @@ type Handler struct { WriteQueueSize int UDPReadBufferSize uint RTPMaxPayloadSize int + SupportsIPv6 bool Matches []string PathManager handlerPathManager Parent handlerParent @@ -147,6 +148,7 @@ func (s *Handler) Initialize() { DumpPackets: s.DumpPackets, ReadTimeout: s.ReadTimeout, UDPReadBufferSize: s.UDPReadBufferSize, + SupportsIPv6: s.SupportsIPv6, Parent: s, } diff --git a/internal/staticsources/webrtc/source.go b/internal/staticsources/webrtc/source.go index 855ebb01..80231a1b 100644 --- a/internal/staticsources/webrtc/source.go +++ b/internal/staticsources/webrtc/source.go @@ -31,6 +31,7 @@ type Source struct { DumpPackets bool ReadTimeout conf.Duration UDPReadBufferSize uint + SupportsIPv6 bool Parent parent } @@ -76,6 +77,7 @@ func (s *Source) Run(params defs.StaticSourceRunParams) error { }, BearerToken: params.Conf.WHEPBearerToken, UDPReadBufferSize: s.UDPReadBufferSize, + SupportsIPv6: s.SupportsIPv6, STUNGatherTimeout: time.Duration(params.Conf.WHEPSTUNGatherTimeout), HandshakeTimeout: time.Duration(params.Conf.WHEPHandshakeTimeout), TrackGatherTimeout: time.Duration(params.Conf.WHEPTrackGatherTimeout),