Files
webrtc/examples/ortc/main.go
Sean DuBois 721b342e2e Properly generate DataChannel streamId
Before we computed DataChannel IDs before signaling, this
is incorrect because IDs must take into account if we are
running an DTLS Client or Server.

This updates the DataChannel ID generation code to take this
into account before generating a streamId.

Resolves #908
2019-11-14 10:51:05 -08:00

171 lines
3.9 KiB
Go

package main
import (
"flag"
"fmt"
"time"
"github.com/pion/webrtc/v2"
"github.com/pion/webrtc/v2/examples/internal/signal"
)
func main() {
isOffer := flag.Bool("offer", false, "Act as the offerer if set")
flag.Parse()
// Everything below is the Pion WebRTC (ORTC) API! Thanks for using it ❤️.
// Prepare ICE gathering options
iceOptions := webrtc.ICEGatherOptions{
ICEServers: []webrtc.ICEServer{
{URLs: []string{"stun:stun.l.google.com:19302"}},
},
}
// Create an API object
api := webrtc.NewAPI()
// Create the ICE gatherer
gatherer, err := api.NewICEGatherer(iceOptions)
if err != nil {
panic(err)
}
// Construct the ICE transport
ice := api.NewICETransport(gatherer)
// Construct the DTLS transport
dtls, err := api.NewDTLSTransport(ice, nil)
if err != nil {
panic(err)
}
// Construct the SCTP transport
sctp := api.NewSCTPTransport(dtls)
// Handle incoming data channels
sctp.OnDataChannel(func(channel *webrtc.DataChannel) {
fmt.Printf("New DataChannel %s %d\n", channel.Label(), channel.ID())
// Register the handlers
channel.OnOpen(handleOnOpen(channel))
channel.OnMessage(func(msg webrtc.DataChannelMessage) {
fmt.Printf("Message from DataChannel '%s': '%s'\n", channel.Label(), string(msg.Data))
})
})
// Gather candidates
err = gatherer.Gather()
if err != nil {
panic(err)
}
iceCandidates, err := gatherer.GetLocalCandidates()
if err != nil {
panic(err)
}
iceParams, err := gatherer.GetLocalParameters()
if err != nil {
panic(err)
}
dtlsParams, err := dtls.GetLocalParameters()
if err != nil {
panic(err)
}
sctpCapabilities := sctp.GetCapabilities()
s := Signal{
ICECandidates: iceCandidates,
ICEParameters: iceParams,
DTLSParameters: dtlsParams,
SCTPCapabilities: sctpCapabilities,
}
// Exchange the information
fmt.Println(signal.Encode(s))
remoteSignal := Signal{}
signal.Decode(signal.MustReadStdin(), &remoteSignal)
iceRole := webrtc.ICERoleControlled
if *isOffer {
iceRole = webrtc.ICERoleControlling
}
err = ice.SetRemoteCandidates(remoteSignal.ICECandidates)
if err != nil {
panic(err)
}
// Start the ICE transport
err = ice.Start(nil, remoteSignal.ICEParameters, &iceRole)
if err != nil {
panic(err)
}
// Start the DTLS transport
err = dtls.Start(remoteSignal.DTLSParameters)
if err != nil {
panic(err)
}
// Start the SCTP transport
err = sctp.Start(remoteSignal.SCTPCapabilities)
if err != nil {
panic(err)
}
// Construct the data channel as the offerer
if *isOffer {
var id uint16 = 1
dcParams := &webrtc.DataChannelParameters{
Label: "Foo",
ID: &id,
}
var channel *webrtc.DataChannel
channel, err = api.NewDataChannel(sctp, dcParams)
if err != nil {
panic(err)
}
// Register the handlers
// channel.OnOpen(handleOnOpen(channel)) // TODO: OnOpen on handle ChannelAck
go handleOnOpen(channel)() // Temporary alternative
channel.OnMessage(func(msg webrtc.DataChannelMessage) {
fmt.Printf("Message from DataChannel '%s': '%s'\n", channel.Label(), string(msg.Data))
})
}
select {}
}
// Signal is used to exchange signaling info.
// This is not part of the ORTC spec. You are free
// to exchange this information any way you want.
type Signal struct {
ICECandidates []webrtc.ICECandidate `json:"iceCandidates"`
ICEParameters webrtc.ICEParameters `json:"iceParameters"`
DTLSParameters webrtc.DTLSParameters `json:"dtlsParameters"`
SCTPCapabilities webrtc.SCTPCapabilities `json:"sctpCapabilities"`
}
func handleOnOpen(channel *webrtc.DataChannel) func() {
return func() {
fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", channel.Label(), channel.ID())
for range time.NewTicker(5 * time.Second).C {
message := signal.RandSeq(15)
fmt.Printf("Sending '%s' \n", message)
err := channel.SendText(message)
if err != nil {
panic(err)
}
}
}
}