main.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. //go:build js && wasm
  4. // +build js,wasm
  5. package main
  6. import (
  7. "fmt"
  8. "syscall/js"
  9. "github.com/pion/webrtc/v3"
  10. "github.com/pion/webrtc/v3/examples/internal/signal"
  11. )
  12. func main() {
  13. // Configure and create a new PeerConnection.
  14. config := webrtc.Configuration{
  15. ICEServers: []webrtc.ICEServer{
  16. {
  17. URLs: []string{"stun:stun.l.google.com:19302"},
  18. },
  19. },
  20. }
  21. pc, err := webrtc.NewPeerConnection(config)
  22. if err != nil {
  23. handleError(err)
  24. }
  25. // Create DataChannel.
  26. sendChannel, err := pc.CreateDataChannel("foo", nil)
  27. if err != nil {
  28. handleError(err)
  29. }
  30. sendChannel.OnClose(func() {
  31. fmt.Println("sendChannel has closed")
  32. })
  33. sendChannel.OnOpen(func() {
  34. fmt.Println("sendChannel has opened")
  35. candidatePair, err := pc.SCTP().Transport().ICETransport().GetSelectedCandidatePair()
  36. fmt.Println(candidatePair)
  37. fmt.Println(err)
  38. })
  39. sendChannel.OnMessage(func(msg webrtc.DataChannelMessage) {
  40. log(fmt.Sprintf("Message from DataChannel %s payload %s", sendChannel.Label(), string(msg.Data)))
  41. })
  42. // Create offer
  43. offer, err := pc.CreateOffer(nil)
  44. if err != nil {
  45. handleError(err)
  46. }
  47. if err := pc.SetLocalDescription(offer); err != nil {
  48. handleError(err)
  49. }
  50. // Add handlers for setting up the connection.
  51. pc.OnICEConnectionStateChange(func(state webrtc.ICEConnectionState) {
  52. log(fmt.Sprint(state))
  53. })
  54. pc.OnICECandidate(func(candidate *webrtc.ICECandidate) {
  55. if candidate != nil {
  56. encodedDescr := signal.Encode(pc.LocalDescription())
  57. el := getElementByID("localSessionDescription")
  58. el.Set("value", encodedDescr)
  59. }
  60. })
  61. // Set up global callbacks which will be triggered on button clicks.
  62. js.Global().Set("sendMessage", js.FuncOf(func(_ js.Value, _ []js.Value) interface{} {
  63. go func() {
  64. el := getElementByID("message")
  65. message := el.Get("value").String()
  66. if message == "" {
  67. js.Global().Call("alert", "Message must not be empty")
  68. return
  69. }
  70. if err := sendChannel.SendText(message); err != nil {
  71. handleError(err)
  72. }
  73. }()
  74. return js.Undefined()
  75. }))
  76. js.Global().Set("startSession", js.FuncOf(func(_ js.Value, _ []js.Value) interface{} {
  77. go func() {
  78. el := getElementByID("remoteSessionDescription")
  79. sd := el.Get("value").String()
  80. if sd == "" {
  81. js.Global().Call("alert", "Session Description must not be empty")
  82. return
  83. }
  84. descr := webrtc.SessionDescription{}
  85. signal.Decode(sd, &descr)
  86. if err := pc.SetRemoteDescription(descr); err != nil {
  87. handleError(err)
  88. }
  89. }()
  90. return js.Undefined()
  91. }))
  92. js.Global().Set("copySDP", js.FuncOf(func(_ js.Value, _ []js.Value) interface{} {
  93. go func() {
  94. defer func() {
  95. if e := recover(); e != nil {
  96. switch e := e.(type) {
  97. case error:
  98. handleError(e)
  99. default:
  100. handleError(fmt.Errorf("recovered with non-error value: (%T) %s", e, e))
  101. }
  102. }
  103. }()
  104. browserSDP := getElementByID("localSessionDescription")
  105. browserSDP.Call("focus")
  106. browserSDP.Call("select")
  107. copyStatus := js.Global().Get("document").Call("execCommand", "copy")
  108. if copyStatus.Bool() {
  109. log("Copying SDP was successful")
  110. } else {
  111. log("Copying SDP was unsuccessful")
  112. }
  113. }()
  114. return js.Undefined()
  115. }))
  116. // Stay alive
  117. select {}
  118. }
  119. func log(msg string) {
  120. el := getElementByID("logs")
  121. el.Set("innerHTML", el.Get("innerHTML").String()+msg+"<br>")
  122. }
  123. func handleError(err error) {
  124. log("Unexpected error. Check console.")
  125. panic(err)
  126. }
  127. func getElementByID(id string) js.Value {
  128. return js.Global().Get("document").Call("getElementById", id)
  129. }