github.com/pion/webrtc/v4@v4.0.1/examples/ice-tcp/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-tcp demonstrates Pion WebRTC's ICE TCP abilities.
     8  package main
     9  
    10  import (
    11  	"encoding/json"
    12  	"errors"
    13  	"fmt"
    14  	"io"
    15  	"net"
    16  	"net/http"
    17  	"time"
    18  
    19  	"github.com/pion/webrtc/v4"
    20  )
    21  
    22  var api *webrtc.API //nolint
    23  
    24  func doSignaling(w http.ResponseWriter, r *http.Request) {
    25  	peerConnection, err := api.NewPeerConnection(webrtc.Configuration{})
    26  	if err != nil {
    27  		panic(err)
    28  	}
    29  
    30  	// Set the handler for ICE connection state
    31  	// This will notify you when the peer has connected/disconnected
    32  	peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) {
    33  		fmt.Printf("ICE Connection State has changed: %s\n", connectionState.String())
    34  	})
    35  
    36  	// Send the current time via a DataChannel to the remote peer every 3 seconds
    37  	peerConnection.OnDataChannel(func(d *webrtc.DataChannel) {
    38  		d.OnOpen(func() {
    39  			for range time.Tick(time.Second * 3) {
    40  				if err = d.SendText(time.Now().String()); err != nil {
    41  					if errors.Is(err, io.ErrClosedPipe) {
    42  						return
    43  					}
    44  					panic(err)
    45  				}
    46  			}
    47  		})
    48  	})
    49  
    50  	var offer webrtc.SessionDescription
    51  	if err = json.NewDecoder(r.Body).Decode(&offer); err != nil {
    52  		panic(err)
    53  	}
    54  
    55  	if err = peerConnection.SetRemoteDescription(offer); err != nil {
    56  		panic(err)
    57  	}
    58  
    59  	// Create channel that is blocked until ICE Gathering is complete
    60  	gatherComplete := webrtc.GatheringCompletePromise(peerConnection)
    61  
    62  	answer, err := peerConnection.CreateAnswer(nil)
    63  	if err != nil {
    64  		panic(err)
    65  	} else if err = peerConnection.SetLocalDescription(answer); err != nil {
    66  		panic(err)
    67  	}
    68  
    69  	// Block until ICE Gathering is complete, disabling trickle ICE
    70  	// we do this because we only can exchange one signaling message
    71  	// in a production application you should exchange ICE Candidates via OnICECandidate
    72  	<-gatherComplete
    73  
    74  	response, err := json.Marshal(*peerConnection.LocalDescription())
    75  	if err != nil {
    76  		panic(err)
    77  	}
    78  
    79  	w.Header().Set("Content-Type", "application/json")
    80  	if _, err := w.Write(response); err != nil {
    81  		panic(err)
    82  	}
    83  }
    84  
    85  func main() {
    86  	settingEngine := webrtc.SettingEngine{}
    87  
    88  	// Enable support only for TCP ICE candidates.
    89  	settingEngine.SetNetworkTypes([]webrtc.NetworkType{
    90  		webrtc.NetworkTypeTCP4,
    91  		webrtc.NetworkTypeTCP6,
    92  	})
    93  
    94  	tcpListener, err := net.ListenTCP("tcp", &net.TCPAddr{
    95  		IP:   net.IP{0, 0, 0, 0},
    96  		Port: 8443,
    97  	})
    98  	if err != nil {
    99  		panic(err)
   100  	}
   101  
   102  	fmt.Printf("Listening for ICE TCP at %s\n", tcpListener.Addr())
   103  
   104  	tcpMux := webrtc.NewICETCPMux(nil, tcpListener, 8)
   105  	settingEngine.SetICETCPMux(tcpMux)
   106  
   107  	api = webrtc.NewAPI(webrtc.WithSettingEngine(settingEngine))
   108  
   109  	http.Handle("/", http.FileServer(http.Dir(".")))
   110  	http.HandleFunc("/doSignaling", doSignaling)
   111  
   112  	fmt.Println("Open http://localhost:8080 to access this demo")
   113  	// nolint: gosec
   114  	panic(http.ListenAndServe(":8080", nil))
   115  }