1package util 2 3import ( 4 "encoding/json" 5 "errors" 6 "net" 7 8 "github.com/pion/ice/v2" 9 "github.com/pion/sdp/v3" 10 "github.com/pion/webrtc/v3" 11) 12 13func SerializeSessionDescription(desc *webrtc.SessionDescription) (string, error) { 14 bytes, err := json.Marshal(*desc) 15 if err != nil { 16 return "", err 17 } 18 return string(bytes), nil 19} 20 21func DeserializeSessionDescription(msg string) (*webrtc.SessionDescription, error) { 22 var parsed map[string]interface{} 23 err := json.Unmarshal([]byte(msg), &parsed) 24 if err != nil { 25 return nil, err 26 } 27 if _, ok := parsed["type"]; !ok { 28 return nil, errors.New("cannot deserialize SessionDescription without type field") 29 } 30 if _, ok := parsed["sdp"]; !ok { 31 return nil, errors.New("cannot deserialize SessionDescription without sdp field") 32 } 33 34 var stype webrtc.SDPType 35 switch parsed["type"].(string) { 36 default: 37 return nil, errors.New("Unknown SDP type") 38 case "offer": 39 stype = webrtc.SDPTypeOffer 40 case "pranswer": 41 stype = webrtc.SDPTypePranswer 42 case "answer": 43 stype = webrtc.SDPTypeAnswer 44 case "rollback": 45 stype = webrtc.SDPTypeRollback 46 } 47 48 return &webrtc.SessionDescription{ 49 Type: stype, 50 SDP: parsed["sdp"].(string), 51 }, nil 52} 53 54// Stolen from https://github.com/golang/go/pull/30278 55func IsLocal(ip net.IP) bool { 56 if ip4 := ip.To4(); ip4 != nil { 57 // Local IPv4 addresses are defined in https://tools.ietf.org/html/rfc1918 58 return ip4[0] == 10 || 59 (ip4[0] == 172 && ip4[1]&0xf0 == 16) || 60 (ip4[0] == 192 && ip4[1] == 168) || 61 // Carrier-Grade NAT as per https://tools.ietf.org/htm/rfc6598 62 (ip4[0] == 100 && ip4[1]&0xc0 == 64) || 63 // Dynamic Configuration as per https://tools.ietf.org/htm/rfc3927 64 (ip4[0] == 169 && ip4[1] == 254) 65 } 66 // Local IPv6 addresses are defined in https://tools.ietf.org/html/rfc4193 67 return len(ip) == net.IPv6len && ip[0]&0xfe == 0xfc 68} 69 70// Removes local LAN address ICE candidates 71func StripLocalAddresses(str string) string { 72 var desc sdp.SessionDescription 73 err := desc.Unmarshal([]byte(str)) 74 if err != nil { 75 return str 76 } 77 for _, m := range desc.MediaDescriptions { 78 attrs := make([]sdp.Attribute, 0) 79 for _, a := range m.Attributes { 80 if a.IsICECandidate() { 81 c, err := ice.UnmarshalCandidate(a.Value) 82 if err == nil && c.Type() == ice.CandidateTypeHost { 83 ip := net.ParseIP(c.Address()) 84 if ip != nil && (IsLocal(ip) || ip.IsUnspecified() || ip.IsLoopback()) { 85 /* no append in this case */ 86 continue 87 } 88 } 89 } 90 attrs = append(attrs, a) 91 } 92 m.Attributes = attrs 93 } 94 bts, err := desc.Marshal() 95 if err != nil { 96 return str 97 } 98 return string(bts) 99} 100