github.com/pion/webrtc/v3@v3.2.24/examples/ortc/main.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 //go:build !js 5 // +build !js 6 7 // ortc demonstrates Pion WebRTC's ORTC capabilities. 8 package main 9 10 import ( 11 "flag" 12 "fmt" 13 "time" 14 15 "github.com/pion/webrtc/v3" 16 "github.com/pion/webrtc/v3/examples/internal/signal" 17 ) 18 19 func main() { 20 isOffer := flag.Bool("offer", false, "Act as the offerer if set") 21 flag.Parse() 22 23 // Everything below is the Pion WebRTC (ORTC) API! Thanks for using it ❤️. 24 25 // Prepare ICE gathering options 26 iceOptions := webrtc.ICEGatherOptions{ 27 ICEServers: []webrtc.ICEServer{ 28 {URLs: []string{"stun:stun.l.google.com:19302"}}, 29 }, 30 } 31 32 // Create an API object 33 api := webrtc.NewAPI() 34 35 // Create the ICE gatherer 36 gatherer, err := api.NewICEGatherer(iceOptions) 37 if err != nil { 38 panic(err) 39 } 40 41 // Construct the ICE transport 42 ice := api.NewICETransport(gatherer) 43 44 // Construct the DTLS transport 45 dtls, err := api.NewDTLSTransport(ice, nil) 46 if err != nil { 47 panic(err) 48 } 49 50 // Construct the SCTP transport 51 sctp := api.NewSCTPTransport(dtls) 52 53 // Handle incoming data channels 54 sctp.OnDataChannel(func(channel *webrtc.DataChannel) { 55 fmt.Printf("New DataChannel %s %d\n", channel.Label(), channel.ID()) 56 57 // Register the handlers 58 channel.OnOpen(handleOnOpen(channel)) 59 channel.OnMessage(func(msg webrtc.DataChannelMessage) { 60 fmt.Printf("Message from DataChannel '%s': '%s'\n", channel.Label(), string(msg.Data)) 61 }) 62 }) 63 64 gatherFinished := make(chan struct{}) 65 gatherer.OnLocalCandidate(func(i *webrtc.ICECandidate) { 66 if i == nil { 67 close(gatherFinished) 68 } 69 }) 70 71 // Gather candidates 72 err = gatherer.Gather() 73 if err != nil { 74 panic(err) 75 } 76 77 <-gatherFinished 78 79 iceCandidates, err := gatherer.GetLocalCandidates() 80 if err != nil { 81 panic(err) 82 } 83 84 iceParams, err := gatherer.GetLocalParameters() 85 if err != nil { 86 panic(err) 87 } 88 89 dtlsParams, err := dtls.GetLocalParameters() 90 if err != nil { 91 panic(err) 92 } 93 94 sctpCapabilities := sctp.GetCapabilities() 95 96 s := Signal{ 97 ICECandidates: iceCandidates, 98 ICEParameters: iceParams, 99 DTLSParameters: dtlsParams, 100 SCTPCapabilities: sctpCapabilities, 101 } 102 103 // Exchange the information 104 fmt.Println(signal.Encode(s)) 105 remoteSignal := Signal{} 106 signal.Decode(signal.MustReadStdin(), &remoteSignal) 107 108 iceRole := webrtc.ICERoleControlled 109 if *isOffer { 110 iceRole = webrtc.ICERoleControlling 111 } 112 113 err = ice.SetRemoteCandidates(remoteSignal.ICECandidates) 114 if err != nil { 115 panic(err) 116 } 117 118 // Start the ICE transport 119 err = ice.Start(nil, remoteSignal.ICEParameters, &iceRole) 120 if err != nil { 121 panic(err) 122 } 123 124 // Start the DTLS transport 125 err = dtls.Start(remoteSignal.DTLSParameters) 126 if err != nil { 127 panic(err) 128 } 129 130 // Start the SCTP transport 131 err = sctp.Start(remoteSignal.SCTPCapabilities) 132 if err != nil { 133 panic(err) 134 } 135 136 // Construct the data channel as the offerer 137 if *isOffer { 138 var id uint16 = 1 139 140 dcParams := &webrtc.DataChannelParameters{ 141 Label: "Foo", 142 ID: &id, 143 } 144 var channel *webrtc.DataChannel 145 channel, err = api.NewDataChannel(sctp, dcParams) 146 if err != nil { 147 panic(err) 148 } 149 150 // Register the handlers 151 // channel.OnOpen(handleOnOpen(channel)) // TODO: OnOpen on handle ChannelAck 152 go handleOnOpen(channel)() // Temporary alternative 153 channel.OnMessage(func(msg webrtc.DataChannelMessage) { 154 fmt.Printf("Message from DataChannel '%s': '%s'\n", channel.Label(), string(msg.Data)) 155 }) 156 } 157 158 select {} 159 } 160 161 // Signal is used to exchange signaling info. 162 // This is not part of the ORTC spec. You are free 163 // to exchange this information any way you want. 164 type Signal struct { 165 ICECandidates []webrtc.ICECandidate `json:"iceCandidates"` 166 ICEParameters webrtc.ICEParameters `json:"iceParameters"` 167 DTLSParameters webrtc.DTLSParameters `json:"dtlsParameters"` 168 SCTPCapabilities webrtc.SCTPCapabilities `json:"sctpCapabilities"` 169 } 170 171 func handleOnOpen(channel *webrtc.DataChannel) func() { 172 return func() { 173 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()) 174 175 for range time.NewTicker(5 * time.Second).C { 176 message := signal.RandSeq(15) 177 fmt.Printf("Sending '%s' \n", message) 178 179 err := channel.SendText(message) 180 if err != nil { 181 panic(err) 182 } 183 } 184 } 185 }