From 11845a7f56ef1f0e6446f1880bc2119c4f1e6f4b Mon Sep 17 00:00:00 2001 From: sirzooro Date: Sat, 6 Jul 2024 14:52:09 +0200 Subject: [PATCH] Remove IPv6 ZoneID from ICE candidates (#704) Link-local IPv6 addresses may have ZoneID attached at the end. It has local meaning only and should not be send to other parties. This change removes ZoneID from generated candidate string, and ignores ZoneID when received candidate is parsed. --- candidate_base.go | 11 +++++++++-- candidate_test.go | 31 ++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/candidate_base.go b/candidate_base.go index 1a60899..e1fbfe1 100644 --- a/candidate_base.go +++ b/candidate_base.go @@ -460,6 +460,13 @@ func (c *candidateBase) copy() (Candidate, error) { return UnmarshalCandidate(c.Marshal()) } +func removeZoneIDFromAddress(addr string) string { + if i := strings.Index(addr, "%"); i != -1 { + return addr[:i] + } + return addr +} + // Marshal returns the string representation of the ICECandidate func (c *candidateBase) Marshal() string { val := c.Foundation() @@ -472,7 +479,7 @@ func (c *candidateBase) Marshal() string { c.Component(), c.NetworkType().NetworkShort(), c.Priority(), - c.Address(), + removeZoneIDFromAddress(c.Address()), c.Port(), c.Type()) @@ -522,7 +529,7 @@ func UnmarshalCandidate(raw string) (Candidate, error) { priority := uint32(priorityRaw) // Address - address := split[4] + address := removeZoneIDFromAddress(split[4]) // Port rawPort, err := strconv.ParseUint(split[5], 10, 16) diff --git a/candidate_test.go b/candidate_test.go index 04bb17c..aecea11 100644 --- a/candidate_test.go +++ b/candidate_test.go @@ -392,7 +392,7 @@ func TestCandidateMarshal(t *testing.T) { require.NoError(t, err) - require.True(t, test.candidate.Equal(actualCandidate)) + require.Truef(t, test.candidate.Equal(actualCandidate), "%s != %s", test.candidate.String(), actualCandidate.String()) require.Equal(t, test.marshaled, actualCandidate.Marshal()) }) } @@ -437,3 +437,32 @@ func TestCandidateWriteTo(t *testing.T) { _, err = c1.writeTo([]byte("test"), c2) require.Error(t, err, "writing to closed conn") } + +func TestMarshalUnmarshalCandidateWithZoneID(t *testing.T) { + candidateWithZoneID := mustCandidateHost(&CandidateHostConfig{ + Network: NetworkTypeUDP6.String(), + Address: "fcd9:e3b8:12ce:9fc5:74a5:c6bb:d8b:e08a%Local Connection", + Port: 53987, + Priority: 500, + Foundation: "750", + }) + candidateStr := "750 0 udp 500 fcd9:e3b8:12ce:9fc5:74a5:c6bb:d8b:e08a 53987 typ host" + require.Equal(t, candidateStr, candidateWithZoneID.Marshal()) + + candidate := mustCandidateHost(&CandidateHostConfig{ + Network: NetworkTypeUDP6.String(), + Address: "fcd9:e3b8:12ce:9fc5:74a5:c6bb:d8b:e08a", + Port: 53987, + Priority: 500, + Foundation: "750", + }) + candidateWithZoneIDStr := "750 0 udp 500 fcd9:e3b8:12ce:9fc5:74a5:c6bb:d8b:e08a%eth0 53987 typ host" + candidate2, err := UnmarshalCandidate(candidateWithZoneIDStr) + require.NoError(t, err) + require.Truef(t, candidate.Equal(candidate2), "%s != %s", candidate.String(), candidate2.String()) + + candidateWithZoneIDStr2 := "750 0 udp 500 fcd9:e3b8:12ce:9fc5:74a5:c6bb:d8b:e08a%eth0%eth1 53987 typ host" + candidate2, err = UnmarshalCandidate(candidateWithZoneIDStr2) + require.NoError(t, err) + require.Truef(t, candidate.Equal(candidate2), "%s != %s", candidate.String(), candidate2.String()) +}