github.com/pion/webrtc/v4@v4.0.1/examples/ice-tcp/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-tcp demonstrates Pion WebRTC's ICE TCP abilities. 8 package main 9 10 import ( 11 "encoding/json" 12 "errors" 13 "fmt" 14 "io" 15 "net" 16 "net/http" 17 "time" 18 19 "github.com/pion/webrtc/v4" 20 ) 21 22 var api *webrtc.API //nolint 23 24 func doSignaling(w http.ResponseWriter, r *http.Request) { 25 peerConnection, err := api.NewPeerConnection(webrtc.Configuration{}) 26 if err != nil { 27 panic(err) 28 } 29 30 // Set the handler for ICE connection state 31 // This will notify you when the peer has connected/disconnected 32 peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) { 33 fmt.Printf("ICE Connection State has changed: %s\n", connectionState.String()) 34 }) 35 36 // Send the current time via a DataChannel to the remote peer every 3 seconds 37 peerConnection.OnDataChannel(func(d *webrtc.DataChannel) { 38 d.OnOpen(func() { 39 for range time.Tick(time.Second * 3) { 40 if err = d.SendText(time.Now().String()); err != nil { 41 if errors.Is(err, io.ErrClosedPipe) { 42 return 43 } 44 panic(err) 45 } 46 } 47 }) 48 }) 49 50 var offer webrtc.SessionDescription 51 if err = json.NewDecoder(r.Body).Decode(&offer); err != nil { 52 panic(err) 53 } 54 55 if err = peerConnection.SetRemoteDescription(offer); err != nil { 56 panic(err) 57 } 58 59 // Create channel that is blocked until ICE Gathering is complete 60 gatherComplete := webrtc.GatheringCompletePromise(peerConnection) 61 62 answer, err := peerConnection.CreateAnswer(nil) 63 if err != nil { 64 panic(err) 65 } else if err = peerConnection.SetLocalDescription(answer); err != nil { 66 panic(err) 67 } 68 69 // Block until ICE Gathering is complete, disabling trickle ICE 70 // we do this because we only can exchange one signaling message 71 // in a production application you should exchange ICE Candidates via OnICECandidate 72 <-gatherComplete 73 74 response, err := json.Marshal(*peerConnection.LocalDescription()) 75 if err != nil { 76 panic(err) 77 } 78 79 w.Header().Set("Content-Type", "application/json") 80 if _, err := w.Write(response); err != nil { 81 panic(err) 82 } 83 } 84 85 func main() { 86 settingEngine := webrtc.SettingEngine{} 87 88 // Enable support only for TCP ICE candidates. 89 settingEngine.SetNetworkTypes([]webrtc.NetworkType{ 90 webrtc.NetworkTypeTCP4, 91 webrtc.NetworkTypeTCP6, 92 }) 93 94 tcpListener, err := net.ListenTCP("tcp", &net.TCPAddr{ 95 IP: net.IP{0, 0, 0, 0}, 96 Port: 8443, 97 }) 98 if err != nil { 99 panic(err) 100 } 101 102 fmt.Printf("Listening for ICE TCP at %s\n", tcpListener.Addr()) 103 104 tcpMux := webrtc.NewICETCPMux(nil, tcpListener, 8) 105 settingEngine.SetICETCPMux(tcpMux) 106 107 api = webrtc.NewAPI(webrtc.WithSettingEngine(settingEngine)) 108 109 http.Handle("/", http.FileServer(http.Dir("."))) 110 http.HandleFunc("/doSignaling", doSignaling) 111 112 fmt.Println("Open http://localhost:8080 to access this demo") 113 // nolint: gosec 114 panic(http.ListenAndServe(":8080", nil)) 115 }