webrtc: skip unresolvable webrtcAdditionalHosts entries instead of aborting (#5845)

Since #4866, hostnames in webrtcAdditionalHosts are resolved server-side via
net.LookupIP, and a resolution failure aborts the entire WHEP/WHIP session.
A single entry that can't be resolved on the server (e.g. air-gapped networks
without DNS, or a name that only resolves on the client) therefore takes down
all WebRTC playback, even when the other entries are valid.

Log a warning and skip the unresolvable entry instead of returning an error,
so the remaining valid candidates are still offered.

Signed-off-by: suMin <sumin77123@gmail.com>
This commit is contained in:
suMin
2026-06-22 21:14:04 +02:00
committed by GitHub
parent d31c0b3900
commit 8fcbd0a796
2 changed files with 53 additions and 1 deletions
+6 -1
View File
@@ -504,7 +504,12 @@ func (co *PeerConnection) addAdditionalCandidates(firstMedia *sdp.MediaDescripti
} else {
tmp, err := net.LookupIP(host)
if err != nil {
return err
// The host can't be resolved server-side - e.g. in air-gapped
// networks without DNS, or with split-horizon / overlay DNS
// names that only resolve on the client. Skip it instead of
// failing the entire session, so the other entries still work.
co.Log.Log(logger.Warn, "cannot resolve additional host %q, skipping it: %v", host, err)
continue
}
ips = make([]string, len(tmp))
@@ -886,3 +886,50 @@ func TestPeerConnectionPublishDataChannel(t *testing.T) {
<-dataReceived
}
func TestPeerConnectionAdditionalHostsUnresolvable(t *testing.T) {
// A host in AdditionalHosts that can't be resolved server-side - for
// instance air-gapped networks without DNS, or split-horizon / overlay
// DNS names that only resolve on the client - must be skipped instead of
// aborting the session; the other (valid) entries must still produce
// candidates.
clientPC := &PeerConnection{
LocalRandomUDP: true,
IPsFromInterfaces: true,
IPsFromInterfacesList: []string{"lo"},
Log: test.NilLogger,
}
err := clientPC.Start()
require.NoError(t, err)
defer clientPC.Close()
ln, err := net.ListenPacket("udp4", ":0")
require.NoError(t, err)
defer ln.Close()
udpMux := webrtc.NewICEUDPMux(webrtcNilLogger, ln)
serverPC := &PeerConnection{
ICEUDPMux: udpMux,
AdditionalHosts: []string{"127.0.0.1", "unresolvable.invalid"},
Publish: true,
OutboundTracks: []*OutboundTrack{{
Caps: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeAV1,
ClockRate: 90000,
},
}},
Log: test.NilLogger,
}
err = serverPC.Start()
require.NoError(t, err)
defer serverPC.Close()
offer, err := clientPC.CreatePartialOffer(false)
require.NoError(t, err)
answer, err := serverPC.CreateFullAnswer(offer, false)
require.NoError(t, err)
require.Contains(t, answer.SDP, "127.0.0.1")
require.NotContains(t, answer.SDP, "unresolvable.invalid")
}