mirror of
https://github.com/pion/webrtc.git
synced 2025-10-16 12:10:44 +08:00

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
171 lines
3.9 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|
|
}
|