Skip to content

Commit 9dfb5c2

Browse files
committedJan 31, 2025··
Allow for empty extension values
While not spec compliant, some implementations allow for empty extension values. This aligns with our behavior for empty foundation values. And makes the parser more forgiving for bad implementations.
1 parent 47dad55 commit 9dfb5c2

File tree

2 files changed

+47
-22
lines changed

2 files changed

+47
-22
lines changed
 

‎candidate_base.go

+10-12
Original file line numberDiff line numberDiff line change
@@ -1032,19 +1032,17 @@ func unmarshalCandidateExtensions(raw string) (extensions []CandidateExtension,
10321032
}
10331033
i = next
10341034

1035-
if i >= len(raw) {
1036-
return extensions, "", fmt.Errorf(
1037-
"%w: missing value for %s in %s", errParseExtension, key, raw, //nolint: errorlint // we are wrapping the error
1038-
)
1039-
}
1040-
1041-
value, next, err := readCandidateByteString(raw, i)
1042-
if err != nil {
1043-
return extensions, "", fmt.Errorf(
1044-
"%w: failed to read value %v", errParseExtension, err, //nolint: errorlint // we are wrapping the error
1045-
)
1035+
// while not spec-compliant, we allow for empty values, as seen in the wild
1036+
var value string
1037+
if i < len(raw) {
1038+
value, next, err = readCandidateByteString(raw, i)
1039+
if err != nil {
1040+
return extensions, "", fmt.Errorf(
1041+
"%w: failed to read value %v", errParseExtension, err, //nolint: errorlint // we are wrapping the error
1042+
)
1043+
}
1044+
i = next
10461045
}
1047-
i = next
10481046

10491047
if key == "tcptype" {
10501048
rawTCPTypeRaw = value

‎candidate_test.go

+37-10
Original file line numberDiff line numberDiff line change
@@ -698,8 +698,20 @@ func TestCandidateExtensionsMarshal(t *testing.T) {
698698
"1052353102 1 tcp 2128609279 192.168.0.196 0 typ host",
699699
},
700700
{
701-
[]CandidateExtension{},
702-
"1052353102 1 tcp 2128609279 192.168.0.196 0 typ host",
701+
[]CandidateExtension{
702+
{"tcptype", "active"},
703+
{"empty-value-1", ""},
704+
{"empty-value-2", ""},
705+
},
706+
"1052353102 1 tcp 2128609279 192.168.0.196 0 typ host tcptype active empty-value-1 empty-value-2",
707+
},
708+
{
709+
[]CandidateExtension{
710+
{"tcptype", "active"},
711+
{"empty-value-1", ""},
712+
{"empty-value-2", ""},
713+
},
714+
"1052353102 1 tcp 2128609279 192.168.0.196 0 typ host tcptype active empty-value-1 empty-value-2 ",
703715
},
704716
}
705717

@@ -967,16 +979,10 @@ func TestUnmarshalCandidateExtensions(t *testing.T) {
967979
},
968980
fail: false,
969981
},
970-
{
971-
name: "invalid extension string",
972-
value: "invalid",
973-
expected: []CandidateExtension{},
974-
fail: true,
975-
},
976982
{
977983
name: "invalid extension",
978-
value: " a b",
979-
expected: []CandidateExtension{{"a", "b"}, {"c", "d"}},
984+
value: " a b d",
985+
expected: []CandidateExtension{{"", "a"}, {"b", "d"}},
980986
fail: true,
981987
},
982988
}
@@ -1357,6 +1363,27 @@ func TestCandidateAddExtension(t *testing.T) {
13571363

13581364
require.Error(t, candidate.AddExtension(CandidateExtension{"tcptype", "INVALID"}))
13591365
})
1366+
1367+
t.Run("Add empty extension", func(t *testing.T) {
1368+
candidate, err := NewCandidateHost(&CandidateHostConfig{
1369+
Network: NetworkTypeUDP4.String(),
1370+
Address: "fcd9:e3b8:12ce:9fc5:74a5:c6bb:d8b:e08a",
1371+
Port: 53987,
1372+
Priority: 500,
1373+
Foundation: "750",
1374+
})
1375+
if err != nil {
1376+
t.Error(err)
1377+
}
1378+
1379+
require.Error(t, candidate.AddExtension(CandidateExtension{"", ""}))
1380+
1381+
require.NoError(t, candidate.AddExtension(CandidateExtension{"a", ""}))
1382+
1383+
extensions := candidate.Extensions()
1384+
1385+
require.Equal(t, []CandidateExtension{{"a", ""}}, extensions)
1386+
})
13601387
}
13611388

13621389
func TestCandidateRemoveExtension(t *testing.T) {

0 commit comments

Comments
 (0)
Please sign in to comment.