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  }