| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
- // SPDX-License-Identifier: MIT
- //go:build !js
- // +build !js
- // ortc demonstrates Pion WebRTC's ORTC capabilities.
- package main
- import (
- "flag"
- "fmt"
- "time"
- "github.com/pion/webrtc/v3"
- "github.com/pion/webrtc/v3/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))
- })
- })
- gatherFinished := make(chan struct{})
- gatherer.OnLocalCandidate(func(i *webrtc.ICECandidate) {
- if i == nil {
- close(gatherFinished)
- }
- })
- // Gather candidates
- err = gatherer.Gather()
- if err != nil {
- panic(err)
- }
- <-gatherFinished
- 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)
- }
- }
- }
- }
|