github.com/anacrolix/torrent@v1.61.0/webrtc.go (about)

     1  package torrent
     2  
     3  import (
     4  	"io"
     5  	"net"
     6  	"strconv"
     7  	"time"
     8  
     9  	"github.com/pion/webrtc/v4"
    10  	"go.opentelemetry.io/otel"
    11  	"go.opentelemetry.io/otel/attribute"
    12  	"go.opentelemetry.io/otel/trace"
    13  
    14  	"github.com/anacrolix/torrent/webtorrent"
    15  )
    16  
    17  const webrtcNetwork = "webrtc"
    18  
    19  type webrtcNetConn struct {
    20  	io.ReadWriteCloser
    21  	webtorrent.DataChannelContext
    22  }
    23  
    24  type webrtcNetAddr struct {
    25  	*webrtc.ICECandidate
    26  }
    27  
    28  var _ net.Addr = webrtcNetAddr{}
    29  
    30  func (webrtcNetAddr) Network() string {
    31  	// Now that we have the ICE candidate, we can tell if it's over udp or tcp. But should we use
    32  	// that for the network?
    33  	return webrtcNetwork
    34  }
    35  
    36  func (me webrtcNetAddr) String() string {
    37  	return net.JoinHostPort(me.Address, strconv.FormatUint(uint64(me.Port), 10))
    38  }
    39  
    40  func (me webrtcNetConn) LocalAddr() net.Addr {
    41  	// I'm not sure if this evolves over time. It might also be unavailable if the PeerConnection is
    42  	// closed or closes itself. The same concern applies to RemoteAddr.
    43  	pair, err := me.DataChannelContext.GetSelectedIceCandidatePair()
    44  	if err != nil {
    45  		panic(err)
    46  	}
    47  	return webrtcNetAddr{pair.Local}
    48  }
    49  
    50  func (me webrtcNetConn) RemoteAddr() net.Addr {
    51  	// See comments on LocalAddr.
    52  	pair, err := me.DataChannelContext.GetSelectedIceCandidatePair()
    53  	if err != nil {
    54  		panic(err)
    55  	}
    56  	return webrtcNetAddr{pair.Remote}
    57  }
    58  
    59  // Do we need these for WebRTC connections exposed as net.Conns? Can we set them somewhere inside
    60  // PeerConnection or on the channel or some transport?
    61  
    62  func (w webrtcNetConn) SetDeadline(t time.Time) error {
    63  	w.Span.AddEvent("SetDeadline", trace.WithAttributes(attribute.String("time", t.String())))
    64  	return nil
    65  }
    66  
    67  func (w webrtcNetConn) SetReadDeadline(t time.Time) error {
    68  	w.Span.AddEvent("SetReadDeadline", trace.WithAttributes(attribute.String("time", t.String())))
    69  	return nil
    70  }
    71  
    72  func (w webrtcNetConn) SetWriteDeadline(t time.Time) error {
    73  	w.Span.AddEvent("SetWriteDeadline", trace.WithAttributes(attribute.String("time", t.String())))
    74  	return nil
    75  }
    76  
    77  func (w webrtcNetConn) Read(b []byte) (n int, err error) {
    78  	_, span := otel.Tracer(tracerName).Start(w.Context, "Read")
    79  	defer span.End()
    80  	span.SetAttributes(attribute.Int("buf_len", len(b)))
    81  	n, err = w.ReadWriteCloser.Read(b)
    82  	span.RecordError(err)
    83  	span.SetAttributes(attribute.Int("bytes_read", n))
    84  	return
    85  }