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