]> Sergey Matveev's repositories - btrtrc.git/blobdiff - webtorrent/transport.go
Add WebRTC ICE servers config (#824)
[btrtrc.git] / webtorrent / transport.go
index da56e40d1a2ef1d9ec34d8b0ca780c489d139b3b..856625874c8becc00be22a6ee600d401c260b13a 100644 (file)
@@ -4,6 +4,10 @@ import (
        "context"
        "expvar"
        "fmt"
+       "io"
+       "sync"
+       "time"
+
        "github.com/anacrolix/log"
        "github.com/anacrolix/missinggo/v2/pproffd"
        "github.com/pion/datachannel"
@@ -12,9 +16,6 @@ import (
        "go.opentelemetry.io/otel/attribute"
        "go.opentelemetry.io/otel/codes"
        "go.opentelemetry.io/otel/trace"
-       "io"
-       "sync"
-       "time"
 )
 
 const (
@@ -28,7 +29,6 @@ var (
                s.DetachDataChannels()
                return webrtc.NewAPI(webrtc.WithSettingEngine(s))
        }()
-       config              = webrtc.Configuration{ICEServers: []webrtc.ICEServer{{URLs: []string{"stun:stun.l.google.com:19302"}}}}
        newPeerConnectionMu sync.Mutex
 )
 
@@ -48,11 +48,14 @@ func (me *wrappedPeerConnection) Close() error {
        return err
 }
 
-func newPeerConnection(logger log.Logger) (*wrappedPeerConnection, error) {
+func newPeerConnection(logger log.Logger, iceServers []string) (*wrappedPeerConnection, error) {
        newPeerConnectionMu.Lock()
        defer newPeerConnectionMu.Unlock()
        ctx, span := otel.Tracer(tracerName).Start(context.Background(), "PeerConnection")
-       pc, err := api.NewPeerConnection(config)
+
+       pcConfig := webrtc.Configuration{ICEServers: []webrtc.ICEServer{{URLs: iceServers}}}
+
+       pc, err := api.NewPeerConnection(pcConfig)
        if err != nil {
                span.SetStatus(codes.Error, err.Error())
                span.RecordError(err)
@@ -98,7 +101,7 @@ func (tc *TrackerClient) newOffer(
        offer webrtc.SessionDescription,
        err error,
 ) {
-       peerConnection, err = newPeerConnection(logger)
+       peerConnection, err = newPeerConnection(logger, tc.ICEServers)
        if err != nil {
                return
        }
@@ -127,12 +130,14 @@ func (tc *TrackerClient) newOffer(
 
        offer, err = peerConnection.CreateOffer(nil)
        if err != nil {
+               dataChannel.Close()
                peerConnection.Close()
                return
        }
 
        offer, err = setAndGatherLocalDescription(peerConnection, offer)
        if err != nil {
+               dataChannel.Close()
                peerConnection.Close()
        }
        return
@@ -188,7 +193,7 @@ func (tc *TrackerClient) newAnsweringPeerConnection(
 ) (
        peerConn *wrappedPeerConnection, answer webrtc.SessionDescription, err error,
 ) {
-       peerConn, err = newPeerConnection(tc.Logger)
+       peerConn, err = newPeerConnection(tc.Logger, tc.ICEServers)
        if err != nil {
                err = fmt.Errorf("failed to create new connection: %w", err)
                return
@@ -232,13 +237,18 @@ func initDataChannel(
                        // This shouldn't happen if the API is configured correctly, and we call from OnOpen.
                        panic(err)
                }
-               onOpen(hookDataChannelCloser(raw, pc, span), ctx, span)
+               onOpen(hookDataChannelCloser(raw, pc, span, dc), ctx, span)
        })
 }
 
 // Hooks the datachannel's Close to Close the owning PeerConnection. The datachannel takes ownership
 // and responsibility for the PeerConnection.
-func hookDataChannelCloser(dcrwc datachannel.ReadWriteCloser, pc *wrappedPeerConnection, dataChannelSpan trace.Span) datachannel.ReadWriteCloser {
+func hookDataChannelCloser(
+       dcrwc datachannel.ReadWriteCloser,
+       pc *wrappedPeerConnection,
+       dataChannelSpan trace.Span,
+       originalDataChannel *webrtc.DataChannel,
+) datachannel.ReadWriteCloser {
        return struct {
                datachannelReadWriter
                io.Closer
@@ -247,6 +257,7 @@ func hookDataChannelCloser(dcrwc datachannel.ReadWriteCloser, pc *wrappedPeerCon
                ioCloserFunc(func() error {
                        dcrwc.Close()
                        pc.Close()
+                       originalDataChannel.Close()
                        dataChannelSpan.End()
                        return nil
                }),