github.com/pion/webrtc/v3@v3.2.24/examples/data-channels/main.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
     2  // SPDX-License-Identifier: MIT
     3  
     4  // data-channels is a Pion WebRTC application that shows how you can send/recv DataChannel messages from a web browser
     5  package main
     6  
     7  import (
     8  	"fmt"
     9  	"os"
    10  	"time"
    11  
    12  	"github.com/pion/webrtc/v3"
    13  	"github.com/pion/webrtc/v3/examples/internal/signal"
    14  )
    15  
    16  func main() {
    17  	// Everything below is the Pion WebRTC API! Thanks for using it ❤️.
    18  
    19  	// Prepare the configuration
    20  	config := webrtc.Configuration{
    21  		ICEServers: []webrtc.ICEServer{
    22  			{
    23  				URLs: []string{"stun:stun.l.google.com:19302"},
    24  			},
    25  		},
    26  	}
    27  
    28  	// Create a new RTCPeerConnection
    29  	peerConnection, err := webrtc.NewPeerConnection(config)
    30  	if err != nil {
    31  		panic(err)
    32  	}
    33  	defer func() {
    34  		if cErr := peerConnection.Close(); cErr != nil {
    35  			fmt.Printf("cannot close peerConnection: %v\n", cErr)
    36  		}
    37  	}()
    38  
    39  	// Set the handler for Peer connection state
    40  	// This will notify you when the peer has connected/disconnected
    41  	peerConnection.OnConnectionStateChange(func(s webrtc.PeerConnectionState) {
    42  		fmt.Printf("Peer Connection State has changed: %s\n", s.String())
    43  
    44  		if s == webrtc.PeerConnectionStateFailed {
    45  			// Wait until PeerConnection has had no network activity for 30 seconds or another failure. It may be reconnected using an ICE Restart.
    46  			// Use webrtc.PeerConnectionStateDisconnected if you are interested in detecting faster timeout.
    47  			// Note that the PeerConnection may come back from PeerConnectionStateDisconnected.
    48  			fmt.Println("Peer Connection has gone to failed exiting")
    49  			os.Exit(0)
    50  		}
    51  	})
    52  
    53  	// Register data channel creation handling
    54  	peerConnection.OnDataChannel(func(d *webrtc.DataChannel) {
    55  		fmt.Printf("New DataChannel %s %d\n", d.Label(), d.ID())
    56  
    57  		// Register channel opening handling
    58  		d.OnOpen(func() {
    59  			fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", d.Label(), d.ID())
    60  
    61  			for range time.NewTicker(5 * time.Second).C {
    62  				message := signal.RandSeq(15)
    63  				fmt.Printf("Sending '%s'\n", message)
    64  
    65  				// Send the message as text
    66  				sendErr := d.SendText(message)
    67  				if sendErr != nil {
    68  					panic(sendErr)
    69  				}
    70  			}
    71  		})
    72  
    73  		// Register text message handling
    74  		d.OnMessage(func(msg webrtc.DataChannelMessage) {
    75  			fmt.Printf("Message from DataChannel '%s': '%s'\n", d.Label(), string(msg.Data))
    76  		})
    77  	})
    78  
    79  	// Wait for the offer to be pasted
    80  	offer := webrtc.SessionDescription{}
    81  	signal.Decode(signal.MustReadStdin(), &offer)
    82  
    83  	// Set the remote SessionDescription
    84  	err = peerConnection.SetRemoteDescription(offer)
    85  	if err != nil {
    86  		panic(err)
    87  	}
    88  
    89  	// Create an answer
    90  	answer, err := peerConnection.CreateAnswer(nil)
    91  	if err != nil {
    92  		panic(err)
    93  	}
    94  
    95  	// Create channel that is blocked until ICE Gathering is complete
    96  	gatherComplete := webrtc.GatheringCompletePromise(peerConnection)
    97  
    98  	// Sets the LocalDescription, and starts our UDP listeners
    99  	err = peerConnection.SetLocalDescription(answer)
   100  	if err != nil {
   101  		panic(err)
   102  	}
   103  
   104  	// Block until ICE Gathering is complete, disabling trickle ICE
   105  	// we do this because we only can exchange one signaling message
   106  	// in a production application you should exchange ICE Candidates via OnICECandidate
   107  	<-gatherComplete
   108  
   109  	// Output the answer in base64 so we can paste it in browser
   110  	fmt.Println(signal.Encode(*peerConnection.LocalDescription()))
   111  
   112  	// Block forever
   113  	select {}
   114  }