package torrent import ( "net" "strconv" "time" "github.com/pion/datachannel" "github.com/pion/webrtc/v3" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "github.com/anacrolix/torrent/webtorrent" ) const webrtcNetwork = "webrtc" type webrtcNetConn struct { datachannel.ReadWriteCloser webtorrent.DataChannelContext } type webrtcNetAddr struct { *webrtc.ICECandidate } var _ net.Addr = webrtcNetAddr{} func (webrtcNetAddr) Network() string { // Now that we have the ICE candidate, we can tell if it's over udp or tcp. But should we use // that for the network? return webrtcNetwork } func (me webrtcNetAddr) String() string { return net.JoinHostPort(me.Address, strconv.FormatUint(uint64(me.Port), 10)) } func (me webrtcNetConn) LocalAddr() net.Addr { // I'm not sure if this evolves over time. It might also be unavailable if the PeerConnection is // closed or closes itself. The same concern applies to RemoteAddr. pair, err := me.DataChannelContext.GetSelectedIceCandidatePair() if err != nil { panic(err) } return webrtcNetAddr{pair.Local} } func (me webrtcNetConn) RemoteAddr() net.Addr { // See comments on LocalAddr. pair, err := me.DataChannelContext.GetSelectedIceCandidatePair() if err != nil { panic(err) } return webrtcNetAddr{pair.Remote} } // Do we need these for WebRTC connections exposed as net.Conns? Can we set them somewhere inside // PeerConnection or on the channel or some transport? func (w webrtcNetConn) SetDeadline(t time.Time) error { w.Span.AddEvent("SetDeadline", trace.WithAttributes(attribute.String("time", t.String()))) return nil } func (w webrtcNetConn) SetReadDeadline(t time.Time) error { w.Span.AddEvent("SetReadDeadline", trace.WithAttributes(attribute.String("time", t.String()))) return nil } func (w webrtcNetConn) SetWriteDeadline(t time.Time) error { w.Span.AddEvent("SetWriteDeadline", trace.WithAttributes(attribute.String("time", t.String()))) return nil } func (w webrtcNetConn) Read(b []byte) (n int, err error) { _, span := otel.Tracer(tracerName).Start(w.Context, "Read") defer span.End() span.SetAttributes(attribute.Int("buf_len", len(b))) n, err = w.ReadWriteCloser.Read(b) span.RecordError(err) span.SetAttributes(attribute.Int("bytes_read", n)) return }