main.go 2.8 KB

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