Skip to content

Commit 94262c1

Browse files
committed
Add DTLS, ICE and SCTP Transport to WASM
Only available in the browser, not in wrtc yet. Resolves #2099
1 parent 5dfbe08 commit 94262c1

File tree

7 files changed

+158
-16
lines changed

7 files changed

+158
-16
lines changed

dtlstransport_js.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//go:build js && wasm
2+
// +build js,wasm
3+
4+
package webrtc
5+
6+
import "syscall/js"
7+
8+
// DTLSTransport allows an application access to information about the DTLS
9+
// transport over which RTP and RTCP packets are sent and received by
10+
// RTPSender and RTPReceiver, as well other data such as SCTP packets sent
11+
// and received by data channels.
12+
type DTLSTransport struct {
13+
// Pointer to the underlying JavaScript DTLSTransport object.
14+
underlying js.Value
15+
}
16+
17+
// ICETransport returns the currently-configured *ICETransport or nil
18+
// if one has not been configured
19+
func (r *DTLSTransport) ICETransport() *ICETransport {
20+
underlying := r.underlying.Get("iceTransport")
21+
if underlying.IsNull() || underlying.IsUndefined() {
22+
return nil
23+
}
24+
25+
return &ICETransport{
26+
underlying: underlying,
27+
}
28+
}

examples/data-channels/jsfiddle/main.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ func main() {
3535
})
3636
sendChannel.OnOpen(func() {
3737
fmt.Println("sendChannel has opened")
38+
39+
candidatePair, err := pc.SCTP().Transport().ICETransport().GetSelectedCandidatePair()
40+
41+
fmt.Println(candidatePair)
42+
fmt.Println(err)
3843
})
3944
sendChannel.OnMessage(func(msg webrtc.DataChannelMessage) {
4045
log(fmt.Sprintf("Message from DataChannel %s payload %s", sendChannel.Label(), string(msg.Data)))
@@ -93,6 +98,33 @@ func main() {
9398
}()
9499
return js.Undefined()
95100
}))
101+
js.Global().Set("copySDP", js.FuncOf(func(_ js.Value, _ []js.Value) interface{} {
102+
go func() {
103+
defer func() {
104+
if e := recover(); e != nil {
105+
switch e := e.(type) {
106+
case error:
107+
handleError(e)
108+
default:
109+
handleError(fmt.Errorf("recovered with non-error value: (%T) %s", e, e))
110+
}
111+
}
112+
}()
113+
114+
browserSDP := getElementByID("localSessionDescription")
115+
116+
browserSDP.Call("focus")
117+
browserSDP.Call("select")
118+
119+
copyStatus := js.Global().Get("document").Call("execCommand", "copy")
120+
if copyStatus.Bool() {
121+
log("Copying SDP was successful")
122+
} else {
123+
log("Copying SDP was unsuccessful")
124+
}
125+
}()
126+
return js.Undefined()
127+
}))
96128

97129
// Stay alive
98130
select {}

icetransport_js.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//go:build js && wasm
2+
// +build js,wasm
3+
4+
package webrtc
5+
6+
import "syscall/js"
7+
8+
// ICETransport allows an application access to information about the ICE
9+
// transport over which packets are sent and received.
10+
type ICETransport struct {
11+
// Pointer to the underlying JavaScript ICETransport object.
12+
underlying js.Value
13+
}
14+
15+
// GetSelectedCandidatePair returns the selected candidate pair on which packets are sent
16+
// if there is no selected pair nil is returned
17+
func (t *ICETransport) GetSelectedCandidatePair() (*ICECandidatePair, error) {
18+
val := t.underlying.Call("getSelectedCandidatePair")
19+
if val.IsNull() || val.IsUndefined() {
20+
return nil, nil
21+
}
22+
23+
return NewICECandidatePair(
24+
valueToICECandidate(val.Get("local")),
25+
valueToICECandidate(val.Get("remote")),
26+
), nil
27+
}

peerconnection_js.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,21 @@ func (pc *PeerConnection) GetTransceivers() (transceivers []*RTPTransceiver) {
523523
return
524524
}
525525

526+
// SCTP returns the SCTPTransport for this PeerConnection
527+
//
528+
// The SCTP transport over which SCTP data is sent and received. If SCTP has not been negotiated, the value is nil.
529+
// https://www.w3.org/TR/webrtc/#attributes-15
530+
func (pc *PeerConnection) SCTP() *SCTPTransport {
531+
underlying := pc.underlying.Get("sctp")
532+
if underlying.IsNull() || underlying.IsUndefined() {
533+
return nil
534+
}
535+
536+
return &SCTPTransport{
537+
underlying: underlying,
538+
}
539+
}
540+
526541
// Converts a Configuration to js.Value so it can be passed
527542
// through to the JavaScript WebRTC API. Any zero values are converted to
528543
// js.Undefined(), which will result in the default value being used.

peerconnection_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,24 @@ func offerMediaHasDirection(offer SessionDescription, kind RTPCodecType, directi
8383
return false
8484
}
8585

86+
func untilConnectionState(state PeerConnectionState, peers ...*PeerConnection) *sync.WaitGroup {
87+
var triggered sync.WaitGroup
88+
triggered.Add(len(peers))
89+
90+
for _, p := range peers {
91+
done := false
92+
hdlr := func(p PeerConnectionState) {
93+
if !done && p == state {
94+
done = true
95+
triggered.Done()
96+
}
97+
}
98+
99+
p.OnConnectionStateChange(hdlr)
100+
}
101+
return &triggered
102+
}
103+
86104
func TestNew(t *testing.T) {
87105
pc, err := NewPeerConnection(Configuration{
88106
ICEServers: []ICEServer{
@@ -716,3 +734,17 @@ func TestAddTransceiver(t *testing.T) {
716734
assert.NoError(t, pc.Close())
717735
}
718736
}
737+
738+
// Assert that SCTPTransport -> DTLSTransport -> ICETransport works after connected
739+
func TestTransportChain(t *testing.T) {
740+
offer, answer, err := newPair()
741+
assert.NoError(t, err)
742+
743+
peerConnectionsConnected := untilConnectionState(PeerConnectionStateConnected, offer, answer)
744+
assert.NoError(t, signalPair(offer, answer))
745+
peerConnectionsConnected.Wait()
746+
747+
assert.NotNil(t, offer.SCTP().Transport().ICETransport())
748+
749+
closePairNow(t, offer, answer)
750+
}

rtpsender_test.go

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"context"
88
"errors"
99
"io"
10-
"sync"
1110
"sync/atomic"
1211
"testing"
1312
"time"
@@ -17,21 +16,6 @@ import (
1716
"github.com/stretchr/testify/assert"
1817
)
1918

20-
func untilConnectionState(state PeerConnectionState, peers ...*PeerConnection) *sync.WaitGroup {
21-
var triggered sync.WaitGroup
22-
triggered.Add(len(peers))
23-
24-
hdlr := func(p PeerConnectionState) {
25-
if p == state {
26-
triggered.Done()
27-
}
28-
}
29-
for _, p := range peers {
30-
p.OnConnectionStateChange(hdlr)
31-
}
32-
return &triggered
33-
}
34-
3519
func Test_RTPSender_ReplaceTrack(t *testing.T) {
3620
lim := test.TimeOut(time.Second * 10)
3721
defer lim.Stop()

sctptransport_js.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//go:build js && wasm
2+
// +build js,wasm
3+
4+
package webrtc
5+
6+
import "syscall/js"
7+
8+
// SCTPTransport provides details about the SCTP transport.
9+
type SCTPTransport struct {
10+
// Pointer to the underlying JavaScript SCTPTransport object.
11+
underlying js.Value
12+
}
13+
14+
// Transport returns the DTLSTransport instance the SCTPTransport is sending over.
15+
func (r *SCTPTransport) Transport() *DTLSTransport {
16+
underlying := r.underlying.Get("transport")
17+
if underlying.IsNull() || underlying.IsUndefined() {
18+
return nil
19+
}
20+
21+
return &DTLSTransport{
22+
underlying: underlying,
23+
}
24+
}

0 commit comments

Comments
 (0)