Unmarshal the SDP to filter attributes

Instead of string manipulation.
This commit is contained in:
Arlo Breault 2020-02-07 15:39:44 -05:00
parent 0fae4ee8ea
commit 846473b354
2 changed files with 46 additions and 36 deletions

View file

@ -358,17 +358,17 @@ func TestSnowflakeClient(t *testing.T) {
}) })
Convey("Strip", t, func() { Convey("Strip", t, func() {
const offerStart = `{"type":"offer","sdp":"v=0\r\no=- 4358805017720277108 2 IN IP4 8.8.8.8\r\ns=-\r\nt=0 0\r\na=group:BUNDLE data\r\na=msid-semantic: WMS\r\nm=application 56688 DTLS/SCTP 5000\r\nc=IN IP4 8.8.8.8\r\n` const offerStart = "v=0\r\no=- 4358805017720277108 2 IN IP4 8.8.8.8\r\ns=-\r\nt=0 0\r\na=group:BUNDLE data\r\na=msid-semantic: WMS\r\nm=application 56688 DTLS/SCTP 5000\r\nc=IN IP4 8.8.8.8\r\n"
const goodCandidate = `a=candidate:3769337065 1 udp 2122260223 8.8.8.8 56688 typ host generation 0 network-id 1 network-cost 50\r\n` const goodCandidate = "a=candidate:3769337065 1 udp 2122260223 8.8.8.8 56688 typ host generation 0 network-id 1 network-cost 50\r\n"
const offerEnd = `a=ice-ufrag:aMAZ\r\na=ice-pwd:jcHb08Jjgrazp2dzjdrvPPvV\r\na=ice-options:trickle\r\na=fingerprint:sha-256 C8:88:EE:B9:E7:02:2E:21:37:ED:7A:D1:EB:2B:A3:15:A2:3B:5B:1C:3D:D4:D5:1F:06:CF:52:40:03:F8:DD:66\r\na=setup:actpass\r\na=mid:data\r\na=sctpmap:5000 webrtc-datachannel 1024\r\n"}` const offerEnd = "a=ice-ufrag:aMAZ\r\na=ice-pwd:jcHb08Jjgrazp2dzjdrvPPvV\r\na=ice-options:trickle\r\na=fingerprint:sha-256 C8:88:EE:B9:E7:02:2E:21:37:ED:7A:D1:EB:2B:A3:15:A2:3B:5B:1C:3D:D4:D5:1F:06:CF:52:40:03:F8:DD:66\r\na=setup:actpass\r\na=mid:data\r\na=sctpmap:5000 webrtc-datachannel 1024\r\n"
offer := offerStart + goodCandidate + offer := offerStart + goodCandidate +
`a=candidate:3769337065 1 udp 2122260223 192.168.0.100 56688 typ host generation 0 network-id 1 network-cost 50\r\n` + // IsLocal IPv4 "a=candidate:3769337065 1 udp 2122260223 192.168.0.100 56688 typ host generation 0 network-id 1 network-cost 50\r\n" + // IsLocal IPv4
`a=candidate:3769337065 1 udp 2122260223 fdf8:f53b:82e4::53 56688 typ host generation 0 network-id 1 network-cost 50\r\n` + // IsLocal IPv6 "a=candidate:3769337065 1 udp 2122260223 fdf8:f53b:82e4::53 56688 typ host generation 0 network-id 1 network-cost 50\r\n" + // IsLocal IPv6
`a=candidate:3769337065 1 udp 2122260223 0.0.0.0 56688 typ host generation 0 network-id 1 network-cost 50\r\n` + // IsUnspecified IPv4 "a=candidate:3769337065 1 udp 2122260223 0.0.0.0 56688 typ host generation 0 network-id 1 network-cost 50\r\n" + // IsUnspecified IPv4
`a=candidate:3769337065 1 udp 2122260223 :: 56688 typ host generation 0 network-id 1 network-cost 50\r\n` + // IsUnspecified IPv6 "a=candidate:3769337065 1 udp 2122260223 :: 56688 typ host generation 0 network-id 1 network-cost 50\r\n" + // IsUnspecified IPv6
`a=candidate:3769337065 1 udp 2122260223 127.0.0.1 56688 typ host generation 0 network-id 1 network-cost 50\r\n` + // IsLoopback IPv4 "a=candidate:3769337065 1 udp 2122260223 127.0.0.1 56688 typ host generation 0 network-id 1 network-cost 50\r\n" + // IsLoopback IPv4
`a=candidate:3769337065 1 udp 2122260223 ::1 56688 typ host generation 0 network-id 1 network-cost 50\r\n` + // IsLoopback IPv6 "a=candidate:3769337065 1 udp 2122260223 ::1 56688 typ host generation 0 network-id 1 network-cost 50\r\n" + // IsLoopback IPv6
offerEnd offerEnd
So(stripLocalAddresses(offer), ShouldEqual, offerStart+goodCandidate+offerEnd) So(stripLocalAddresses(offer), ShouldEqual, offerStart+goodCandidate+offerEnd)

View file

@ -17,7 +17,6 @@ import (
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
"regexp"
"github.com/pion/sdp" "github.com/pion/sdp"
"github.com/pion/webrtc" "github.com/pion/webrtc"
@ -95,25 +94,40 @@ func IsLocal(ip net.IP) bool {
// Removes local LAN address ICE candidates // Removes local LAN address ICE candidates
func stripLocalAddresses(str string) string { func stripLocalAddresses(str string) string {
re := regexp.MustCompile(`a=candidate:.*?\\r\\n`) var desc sdp.SessionDescription
return re.ReplaceAllStringFunc(str, func(s string) string { err := desc.Unmarshal([]byte(str))
t := s[len("a=candidate:") : len(s)-len("\\r\\n")]
var ice sdp.ICECandidate
err := ice.Unmarshal(t)
if err != nil { if err != nil {
return s return str
}
for _, m := range desc.MediaDescriptions {
attrs := make([]sdp.Attribute, 0)
for _, a := range m.Attributes {
if a.IsICECandidate() {
ice, err := a.ToICECandidate()
if err != nil {
attrs = append(attrs, a)
continue
} }
if ice.Typ == "host" { if ice.Typ == "host" {
ip := net.ParseIP(ice.Address) ip := net.ParseIP(ice.Address)
if ip == nil { if ip == nil {
return s attrs = append(attrs, a)
continue
} }
if IsLocal(ip) || ip.IsUnspecified() || ip.IsLoopback() { if IsLocal(ip) || ip.IsUnspecified() || ip.IsLoopback() {
return "" continue
} }
} }
return s }
}) attrs = append(attrs, a)
}
m.Attributes = attrs
}
bts, err := desc.Marshal()
if err != nil {
return str
}
return string(bts)
} }
// Roundtrip HTTP POST using WebRTC SessionDescriptions. // Roundtrip HTTP POST using WebRTC SessionDescriptions.
@ -124,20 +138,16 @@ func (bc *BrokerChannel) Negotiate(offer *webrtc.SessionDescription) (
*webrtc.SessionDescription, error) { *webrtc.SessionDescription, error) {
log.Println("Negotiating via BrokerChannel...\nTarget URL: ", log.Println("Negotiating via BrokerChannel...\nTarget URL: ",
bc.Host, "\nFront URL: ", bc.url.Host) bc.Host, "\nFront URL: ", bc.url.Host)
str := serializeSessionDescription(offer)
// Ideally, we could specify an `RTCIceTransportPolicy` that would handle // Ideally, we could specify an `RTCIceTransportPolicy` that would handle
// this for us. However, "public" was removed from the draft spec. // this for us. However, "public" was removed from the draft spec.
// See https://developer.mozilla.org/en-US/docs/Web/API/RTCConfiguration#RTCIceTransportPolicy_enum // See https://developer.mozilla.org/en-US/docs/Web/API/RTCConfiguration#RTCIceTransportPolicy_enum
//
// FIXME: We are stripping local addresses from the JSON serialized string,
// which is expedient but unsatisfying. We could advocate upstream to
// implement a non-standard ICE transport policy, or to somehow alter
// APIs to avoid adding the undesirable candidates or a method to filter
// them from the marshalled session description.
if !bc.keepLocalAddresses { if !bc.keepLocalAddresses {
str = stripLocalAddresses(str) offer = &webrtc.SessionDescription{
Type: offer.Type,
SDP: stripLocalAddresses(offer.SDP),
} }
data := bytes.NewReader([]byte(str)) }
data := bytes.NewReader([]byte(serializeSessionDescription(offer)))
// Suffix with broker's client registration handler. // Suffix with broker's client registration handler.
clientURL := bc.url.ResolveReference(&url.URL{Path: "client"}) clientURL := bc.url.ResolveReference(&url.URL{Path: "client"})
request, err := http.NewRequest("POST", clientURL.String(), data) request, err := http.NewRequest("POST", clientURL.String(), data)