| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
- // SPDX-License-Identifier: MIT
- // trickle-ice demonstrates Pion WebRTC's Trickle ICE APIs. ICE is the subsystem WebRTC uses to establish connectivity.
- package main
- import (
- "encoding/json"
- "fmt"
- "net/http"
- "time"
- "github.com/pion/webrtc/v3"
- "golang.org/x/net/websocket"
- )
- // websocketServer is called for every new inbound WebSocket
- func websocketServer(ws *websocket.Conn) { // nolint:gocognit
- // Create a new RTCPeerConnection
- peerConnection, err := webrtc.NewPeerConnection(webrtc.Configuration{})
- if err != nil {
- panic(err)
- }
- // When Pion gathers a new ICE Candidate send it to the client. This is how
- // ice trickle is implemented. Everytime we have a new candidate available we send
- // it as soon as it is ready. We don't wait to emit a Offer/Answer until they are
- // all available
- peerConnection.OnICECandidate(func(c *webrtc.ICECandidate) {
- if c == nil {
- return
- }
- outbound, marshalErr := json.Marshal(c.ToJSON())
- if marshalErr != nil {
- panic(marshalErr)
- }
- if _, err = ws.Write(outbound); err != nil {
- panic(err)
- }
- })
- // Set the handler for ICE connection state
- // This will notify you when the peer has connected/disconnected
- peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) {
- fmt.Printf("ICE Connection State has changed: %s\n", connectionState.String())
- })
- // Send the current time via a DataChannel to the remote peer every 3 seconds
- peerConnection.OnDataChannel(func(d *webrtc.DataChannel) {
- d.OnOpen(func() {
- for range time.Tick(time.Second * 3) {
- if err = d.SendText(time.Now().String()); err != nil {
- panic(err)
- }
- }
- })
- })
- buf := make([]byte, 1500)
- for {
- // Read each inbound WebSocket Message
- n, err := ws.Read(buf)
- if err != nil {
- panic(err)
- }
- // Unmarshal each inbound WebSocket message
- var (
- candidate webrtc.ICECandidateInit
- offer webrtc.SessionDescription
- )
- switch {
- // Attempt to unmarshal as a SessionDescription. If the SDP field is empty
- // assume it is not one.
- case json.Unmarshal(buf[:n], &offer) == nil && offer.SDP != "":
- if err = peerConnection.SetRemoteDescription(offer); err != nil {
- panic(err)
- }
- answer, answerErr := peerConnection.CreateAnswer(nil)
- if answerErr != nil {
- panic(answerErr)
- }
- if err = peerConnection.SetLocalDescription(answer); err != nil {
- panic(err)
- }
- outbound, marshalErr := json.Marshal(answer)
- if marshalErr != nil {
- panic(marshalErr)
- }
- if _, err = ws.Write(outbound); err != nil {
- panic(err)
- }
- // Attempt to unmarshal as a ICECandidateInit. If the candidate field is empty
- // assume it is not one.
- case json.Unmarshal(buf[:n], &candidate) == nil && candidate.Candidate != "":
- if err = peerConnection.AddICECandidate(candidate); err != nil {
- panic(err)
- }
- default:
- panic("Unknown message")
- }
- }
- }
- func main() {
- http.Handle("/", http.FileServer(http.Dir(".")))
- http.Handle("/websocket", websocket.Handler(websocketServer))
- fmt.Println("Open http://localhost:8080 to access this demo")
- // nolint: gosec
- panic(http.ListenAndServe(":8080", nil))
- }
|