Adds a happyDomain checker that probes STUN/TURN servers end-to-end:
DNS/SRV discovery, UDP/TCP/TLS/DTLS dial, STUN binding + reflexive-addr
sanity, open-relay detection, authenticated TURN Allocate (long-term
creds or REST-API HMAC), public-relay check, CreatePermission + Send
round-trip through the relay, and optional ChannelBind.
Failing sub-tests carry a remediation string (`Fix`) that the HTML
report surfaces as a yellow headline callout and inline next to each
row. Mapping covers the most common coturn misconfigurations
(external-ip, relay-ip, lt-cred-mech, min-port/max-port, cert issues,
401 nonce drift, 441/442/486/508 allocation errors).
Implements sdk.EndpointDiscoverer (checker/discovery.go): every
stuns:/turns:/DTLS endpoint observed during Collect is published as a
DiscoveredEndpoint{Type: "tls"|"dtls"} so a downstream TLS checker can
verify certificates without re-parsing the observation.
Backed by pion/stun/v3 + pion/turn/v4 + pion/dtls/v3; SDK pinned to a
local replace until the EndpointDiscoverer interface ships in a tagged
release.
66 lines
2.1 KiB
Go
66 lines
2.1 KiB
Go
package checker
|
|
|
|
import "testing"
|
|
|
|
func TestParseURI(t *testing.T) {
|
|
cases := []struct {
|
|
in string
|
|
host string
|
|
port uint16
|
|
transport Transport
|
|
secure bool
|
|
isTURN bool
|
|
wantErr bool
|
|
}{
|
|
{"stun:turn.example.com", "turn.example.com", 3478, TransportUDP, false, false, false},
|
|
{"stun:turn.example.com:3478", "turn.example.com", 3478, TransportUDP, false, false, false},
|
|
{"stuns:turn.example.com:5349", "turn.example.com", 5349, TransportTLS, true, false, false},
|
|
{"turn:turn.example.com:3478?transport=udp", "turn.example.com", 3478, TransportUDP, false, true, false},
|
|
{"turn:turn.example.com:3478?transport=tcp", "turn.example.com", 3478, TransportTCP, false, true, false},
|
|
{"turns:turn.example.com:5349?transport=tcp", "turn.example.com", 5349, TransportTLS, true, true, false},
|
|
{"turns:turn.example.com?transport=dtls", "turn.example.com", 5349, TransportDTLS, true, true, false},
|
|
{"http://example.com", "", 0, "", false, false, true},
|
|
{"stun:", "", 0, "", false, false, true},
|
|
}
|
|
for _, tc := range cases {
|
|
ep, err := parseURI(tc.in)
|
|
if tc.wantErr {
|
|
if err == nil {
|
|
t.Errorf("%q: expected error, got nil", tc.in)
|
|
}
|
|
continue
|
|
}
|
|
if err != nil {
|
|
t.Errorf("%q: unexpected error: %v", tc.in, err)
|
|
continue
|
|
}
|
|
if ep.Host != tc.host || ep.Port != tc.port || ep.Transport != tc.transport ||
|
|
ep.Secure != tc.secure || ep.IsTURN != tc.isTURN {
|
|
t.Errorf("%q: got %+v, want host=%s port=%d transport=%s secure=%v isTURN=%v",
|
|
tc.in, ep, tc.host, tc.port, tc.transport, tc.secure, tc.isTURN)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseTransports(t *testing.T) {
|
|
got := parseTransports("udp, TLS ,dtls")
|
|
want := []Transport{TransportUDP, TransportTLS, TransportDTLS}
|
|
if len(got) != len(want) {
|
|
t.Fatalf("got %v want %v", got, want)
|
|
}
|
|
for i := range got {
|
|
if got[i] != want[i] {
|
|
t.Fatalf("index %d: got %s want %s", i, got[i], want[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRestAPICredentials(t *testing.T) {
|
|
c := restAPICredentials("topsecret", "alice", "example.com", 0)
|
|
if c.Username == "" || c.Password == "" {
|
|
t.Fatalf("empty creds: %+v", c)
|
|
}
|
|
if c.Realm != "example.com" {
|
|
t.Fatalf("realm mismatch: %s", c.Realm)
|
|
}
|
|
}
|