github.com/pion/webrtc/v4@v4.0.1/examples/ice-single-port/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 // ice-single-port demonstrates Pion WebRTC's ability to serve many PeerConnections on a single port. 8 package main 9 10 import ( 11 "encoding/json" 12 "fmt" 13 "net/http" 14 "time" 15 16 "github.com/pion/ice/v4" 17 "github.com/pion/webrtc/v4" 18 ) 19 20 var api *webrtc.API //nolint 21 22 // Everything below is the Pion WebRTC API! Thanks for using it ❤️. 23 func doSignaling(w http.ResponseWriter, r *http.Request) { 24 peerConnection, err := api.NewPeerConnection(webrtc.Configuration{}) 25 if err != nil { 26 panic(err) 27 } 28 29 // Set the handler for ICE connection state 30 // This will notify you when the peer has connected/disconnected 31 peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) { 32 fmt.Printf("ICE Connection State has changed: %s\n", connectionState.String()) 33 }) 34 35 // Send the current time via a DataChannel to the remote peer every 3 seconds 36 peerConnection.OnDataChannel(func(d *webrtc.DataChannel) { 37 d.OnOpen(func() { 38 for range time.Tick(time.Second * 3) { 39 if err = d.SendText(time.Now().String()); err != nil { 40 panic(err) 41 } 42 } 43 }) 44 }) 45 46 var offer webrtc.SessionDescription 47 if err = json.NewDecoder(r.Body).Decode(&offer); err != nil { 48 panic(err) 49 } 50 51 if err = peerConnection.SetRemoteDescription(offer); err != nil { 52 panic(err) 53 } 54 55 // Create channel that is blocked until ICE Gathering is complete 56 gatherComplete := webrtc.GatheringCompletePromise(peerConnection) 57 58 answer, err := peerConnection.CreateAnswer(nil) 59 if err != nil { 60 panic(err) 61 } else if err = peerConnection.SetLocalDescription(answer); err != nil { 62 panic(err) 63 } 64 65 // Block until ICE Gathering is complete, disabling trickle ICE 66 // we do this because we only can exchange one signaling message 67 // in a production application you should exchange ICE Candidates via OnICECandidate 68 <-gatherComplete 69 70 response, err := json.Marshal(*peerConnection.LocalDescription()) 71 if err != nil { 72 panic(err) 73 } 74 75 w.Header().Set("Content-Type", "application/json") 76 if _, err := w.Write(response); err != nil { 77 panic(err) 78 } 79 } 80 81 func main() { 82 // Create a SettingEngine, this allows non-standard WebRTC behavior 83 settingEngine := webrtc.SettingEngine{} 84 85 // Configure our SettingEngine to use our UDPMux. By default a PeerConnection has 86 // no global state. The API+SettingEngine allows the user to share state between them. 87 // In this case we are sharing our listening port across many. 88 // Listen on UDP Port 8443, will be used for all WebRTC traffic 89 mux, err := ice.NewMultiUDPMuxFromPort(8443) 90 if err != nil { 91 panic(err) 92 } 93 fmt.Printf("Listening for WebRTC traffic at %d\n", 8443) 94 settingEngine.SetICEUDPMux(mux) 95 96 // Create a new API using our SettingEngine 97 api = webrtc.NewAPI(webrtc.WithSettingEngine(settingEngine)) 98 99 http.Handle("/", http.FileServer(http.Dir("."))) 100 http.HandleFunc("/doSignaling", doSignaling) 101 102 fmt.Println("Open http://localhost:8080 to access this demo") 103 // nolint: gosec 104 panic(http.ListenAndServe(":8080", nil)) 105 }