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