-
Notifications
You must be signed in to change notification settings - Fork 10
/
signal.go
139 lines (122 loc) · 3.66 KB
/
signal.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package webrtc
import (
"encoding/json"
"github.com/aperturerobotics/bifrost/peer"
"github.com/aperturerobotics/util/scrub"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/pion/sdp/v3"
"github.com/pion/webrtc/v4"
"github.com/pkg/errors"
)
// SignalingCryptContext is the encryption context to use for the signaling messages.
var SignalingCryptContext = "github.com/aperturerobotics/bifrost 2024-01-15 17:58:55 webrtc signaling"
// EncodeWebRtcSignal marshals and encrypts the WebRtcSignal message.
func EncodeWebRtcSignal(s *WebRtcSignal, dstPeer crypto.PubKey) ([]byte, error) {
msgSrc, err := s.MarshalVT()
if err != nil {
return nil, err
}
defer scrub.Scrub(msgSrc)
return peer.EncryptToPubKey(dstPeer, SignalingCryptContext, msgSrc)
}
// DecodeWebRtcSignal decrypts and unmarshals the WebRtcSignal message.
func DecodeWebRtcSignal(msg []byte, privKey crypto.PrivKey) (*WebRtcSignal, error) {
msgDec, err := peer.DecryptWithPrivKey(privKey, SignalingCryptContext, msg)
if err != nil {
return nil, err
}
defer scrub.Scrub(msgDec)
out := &WebRtcSignal{}
if err := out.UnmarshalVT(msgDec); err != nil {
return nil, err
}
return out, nil
}
// Validate validates the WebRtcSignal message.
func (m *WebRtcSignal) Validate() error {
// Validate body
switch b := m.GetBody().(type) {
case *WebRtcSignal_RequestOffer:
case *WebRtcSignal_Sdp:
if err := b.Sdp.Validate(); err != nil {
return err
}
case *WebRtcSignal_Ice:
if err := b.Ice.Validate(); err != nil {
return err
}
default:
return errors.New("unknown webrtc signal message type")
}
return nil
}
// NewWebRtcSdp constructs a new WebRtcSdp from a SessionDescription.
func NewWebRtcSdp(txSeqno uint64, desc *webrtc.SessionDescription) *WebRtcSdp {
return &WebRtcSdp{
TxSeqno: txSeqno,
SdpType: desc.Type.String(),
Sdp: desc.SDP,
}
}
// Validate validates the WebRtcSdp message.
func (s *WebRtcSdp) Validate() error {
if s.GetSdpType() == "" {
return errors.New("sdp_type: cannot be empty")
}
if s.ParseSDPType() == webrtc.SDPTypeUnknown {
return errors.Errorf("sdp_type: unknown sdp type: %v", s.GetSdpType())
}
if _, err := s.ParseSDP(); err != nil {
return err
}
return nil
}
// ParseSDPType parses the SDP type field.
func (s *WebRtcSdp) ParseSDPType() webrtc.SDPType {
return webrtc.NewSDPType(s.GetSdpType())
}
// ToSessionDescription converts the sdp into a webrtc session description object.
//
// Returns nil if the message is empty.
func (s *WebRtcSdp) ToSessionDescription() *webrtc.SessionDescription {
if s.GetSdpType() == "" {
return nil
}
return &webrtc.SessionDescription{
Type: s.ParseSDPType(),
SDP: s.GetSdp(),
}
}
// ParseSDP parses the SDP from the type and sdp fields.
//
// Returns nil, nil if the message is empty.
func (s *WebRtcSdp) ParseSDP() (*sdp.SessionDescription, error) {
desc := s.ToSessionDescription()
if desc == nil {
return nil, nil
}
return desc.Unmarshal()
}
// Validate validates the WebRtcIce message.
func (s *WebRtcIce) Validate() error {
if _, err := s.ParseICECandidateInit(); err != nil {
return err
}
return nil
}
// NewWebRtcIce constructs a new WebRtcIce from a ICECandidateInit.
func NewWebRtcIce(candidate *webrtc.ICECandidateInit) (*WebRtcIce, error) {
data, err := json.Marshal(candidate)
if err != nil {
return nil, err
}
return &WebRtcIce{Candidate: string(data)}, nil
}
// ParseICECandidateInit parses the ICECandidate from the JSON encoded body.
func (s *WebRtcIce) ParseICECandidateInit() (*webrtc.ICECandidateInit, error) {
msg := &webrtc.ICECandidateInit{}
if err := json.Unmarshal([]byte(s.GetCandidate()), msg); err != nil {
return nil, errors.Wrap(err, "invalid ice candidate json")
}
return msg, nil
}