2020-04-07 08:59:10 +08:00
|
|
|
package torrent
|
|
|
|
|
|
|
|
import (
|
2022-07-11 09:38:06 +08:00
|
|
|
"go.opentelemetry.io/otel"
|
|
|
|
"go.opentelemetry.io/otel/attribute"
|
|
|
|
"go.opentelemetry.io/otel/trace"
|
2020-04-07 08:59:10 +08:00
|
|
|
"net"
|
2022-07-12 08:41:56 +08:00
|
|
|
"strconv"
|
2020-04-07 08:59:10 +08:00
|
|
|
"time"
|
|
|
|
|
2022-01-12 11:22:42 +08:00
|
|
|
"github.com/anacrolix/torrent/webtorrent"
|
2020-04-07 08:59:10 +08:00
|
|
|
"github.com/pion/datachannel"
|
2021-02-22 05:30:34 +08:00
|
|
|
"github.com/pion/webrtc/v3"
|
2020-04-07 08:59:10 +08:00
|
|
|
)
|
|
|
|
|
2020-04-07 12:30:27 +08:00
|
|
|
const webrtcNetwork = "webrtc"
|
|
|
|
|
2020-04-07 08:59:10 +08:00
|
|
|
type webrtcNetConn struct {
|
|
|
|
datachannel.ReadWriteCloser
|
2020-04-07 12:30:27 +08:00
|
|
|
webtorrent.DataChannelContext
|
2020-04-07 08:59:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type webrtcNetAddr struct {
|
2022-01-12 11:22:42 +08:00
|
|
|
*webrtc.ICECandidate
|
2020-04-07 08:59:10 +08:00
|
|
|
}
|
|
|
|
|
2022-01-12 11:22:42 +08:00
|
|
|
var _ net.Addr = webrtcNetAddr{}
|
|
|
|
|
2020-04-07 08:59:10 +08:00
|
|
|
func (webrtcNetAddr) Network() string {
|
2022-01-12 11:22:42 +08:00
|
|
|
// 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?
|
2020-04-07 12:30:27 +08:00
|
|
|
return webrtcNetwork
|
2020-04-07 08:59:10 +08:00
|
|
|
}
|
|
|
|
|
2020-04-07 12:30:27 +08:00
|
|
|
func (me webrtcNetAddr) String() string {
|
2022-07-12 08:41:56 +08:00
|
|
|
return net.JoinHostPort(me.Address, strconv.FormatUint(uint64(me.Port), 10))
|
2020-04-07 08:59:10 +08:00
|
|
|
}
|
|
|
|
|
2020-04-07 12:30:27 +08:00
|
|
|
func (me webrtcNetConn) LocalAddr() net.Addr {
|
2022-01-12 11:22:42 +08:00
|
|
|
// 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}
|
2020-04-07 08:59:10 +08:00
|
|
|
}
|
|
|
|
|
2020-04-07 12:30:27 +08:00
|
|
|
func (me webrtcNetConn) RemoteAddr() net.Addr {
|
2022-01-12 11:22:42 +08:00
|
|
|
// See comments on LocalAddr.
|
|
|
|
pair, err := me.DataChannelContext.GetSelectedIceCandidatePair()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return webrtcNetAddr{pair.Remote}
|
2020-04-07 08:59:10 +08:00
|
|
|
}
|
|
|
|
|
2022-01-12 11:22:42 +08:00
|
|
|
// 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?
|
|
|
|
|
2020-04-07 08:59:10 +08:00
|
|
|
func (w webrtcNetConn) SetDeadline(t time.Time) error {
|
2022-07-11 09:38:06 +08:00
|
|
|
w.Span.AddEvent("SetDeadline", trace.WithAttributes(attribute.String("time", t.String())))
|
2020-04-07 08:59:10 +08:00
|
|
|
return nil
|
|
|
|
}
|
2022-02-11 19:45:12 +08:00
|
|
|
|
2020-04-07 08:59:10 +08:00
|
|
|
func (w webrtcNetConn) SetReadDeadline(t time.Time) error {
|
2022-07-11 09:38:06 +08:00
|
|
|
w.Span.AddEvent("SetReadDeadline", trace.WithAttributes(attribute.String("time", t.String())))
|
2020-04-07 08:59:10 +08:00
|
|
|
return nil
|
|
|
|
}
|
2022-02-11 19:45:12 +08:00
|
|
|
|
2020-04-07 08:59:10 +08:00
|
|
|
func (w webrtcNetConn) SetWriteDeadline(t time.Time) error {
|
2022-07-11 09:38:06 +08:00
|
|
|
w.Span.AddEvent("SetWriteDeadline", trace.WithAttributes(attribute.String("time", t.String())))
|
2020-04-07 08:59:10 +08:00
|
|
|
return nil
|
|
|
|
}
|
2022-07-11 09:38:06 +08:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|