main.go 3.0 KB

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