github.com/pion/webrtc/v4@v4.0.1/examples/ice-single-port/main.go (about)

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