]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Use webrtc selected ICE candidate for peer addresses
authorMatt Joiner <anacrolix@gmail.com>
Wed, 12 Jan 2022 03:22:42 +0000 (14:22 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Sat, 22 Jan 2022 07:35:06 +0000 (18:35 +1100)
torrent.go
webrtc.go
webtorrent/tracker-client.go

index 8e83d3d38a252361eca585629e07218fb87dafbe..3e74df6394d160eec83a4fc31015c03938c20476 100644 (file)
@@ -1532,13 +1532,21 @@ func (t *Torrent) onWebRtcConn(
        dcc webtorrent.DataChannelContext,
 ) {
        defer c.Close()
+       netConn := webrtcNetConn{
+               ReadWriteCloser:    c,
+               DataChannelContext: dcc,
+       }
+       peerRemoteAddr := netConn.RemoteAddr()
+       if t.cl.badPeerAddr(peerRemoteAddr) {
+               return
+       }
        pc, err := t.cl.initiateProtocolHandshakes(
                context.Background(),
-               webrtcNetConn{c, dcc},
+               netConn,
                t,
                dcc.LocalOffered,
                false,
-               webrtcNetAddr{dcc.Remote},
+               netConn.RemoteAddr(),
                webrtcNetwork,
                fmt.Sprintf("webrtc offer_id %x", dcc.OfferId),
        )
index e8b0213cd7aa89d72a9ee216ab977d1e91a434f1..44ef6ca24099a1a88a7c966806350d99a370840b 100644 (file)
--- a/webrtc.go
+++ b/webrtc.go
@@ -1,13 +1,13 @@
 package torrent
 
 import (
+       "fmt"
        "net"
        "time"
 
+       "github.com/anacrolix/torrent/webtorrent"
        "github.com/pion/datachannel"
        "github.com/pion/webrtc/v3"
-
-       "github.com/anacrolix/torrent/webtorrent"
 )
 
 const webrtcNetwork = "webrtc"
@@ -18,34 +18,51 @@ type webrtcNetConn struct {
 }
 
 type webrtcNetAddr struct {
-       webrtc.SessionDescription
+       *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 {
-       // TODO: What can I show here that's more like other protocols?
-       return "<WebRTC>"
+       // Probably makes sense to return the IP:port expected of most net.Addrs. I'm not sure if
+       // Address would be quoted for IPv6 already. If not, net.JoinHostPort might be appropriate.
+       return fmt.Sprintf("%s:%d", me.Address, me.Port)
 }
 
 func (me webrtcNetConn) LocalAddr() net.Addr {
-       return webrtcNetAddr{me.Local}
+       // 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 {
-       return webrtcNetAddr{me.Remote}
+       // 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 {
        return nil
 }
-
 func (w webrtcNetConn) SetReadDeadline(t time.Time) error {
        return nil
 }
-
 func (w webrtcNetConn) SetWriteDeadline(t time.Time) error {
        return nil
 }
index 9f02c7e785f38e7767e86e73f3304eb61a322ef8..1ec4b9d9c6f917200c2795665283a2ad8e286df9 100644 (file)
@@ -58,10 +58,17 @@ type outboundOffer struct {
 }
 
 type DataChannelContext struct {
+       // Can these be obtained by just calling the relevant methods on peerConnection?
        Local, Remote webrtc.SessionDescription
        OfferId       string
        LocalOffered  bool
        InfoHash      [20]byte
+       // This is private as some methods might not be appropriate with data channel context.
+       peerConnection *wrappedPeerConnection
+}
+
+func (me *DataChannelContext) GetSelectedIceCandidatePair() (*webrtc.ICECandidatePair, error) {
+       return me.peerConnection.SCTP().Transport().ICETransport().GetSelectedCandidatePair()
 }
 
 type onDataChannelOpen func(_ datachannel.ReadWriteCloser, dcc DataChannelContext)
@@ -318,11 +325,12 @@ func (tc *TrackerClient) handleOffer(
                        tc.stats.ConvertedInboundConns++
                        tc.mu.Unlock()
                        tc.OnConn(dc, DataChannelContext{
-                               Local:        answer,
-                               Remote:       offer,
-                               OfferId:      offerId,
-                               LocalOffered: false,
-                               InfoHash:     infoHash,
+                               Local:          answer,
+                               Remote:         offer,
+                               OfferId:        offerId,
+                               LocalOffered:   false,
+                               InfoHash:       infoHash,
+                               peerConnection: peerConnection,
                        })
                })
        })
@@ -345,11 +353,12 @@ func (tc *TrackerClient) handleAnswer(offerId string, answer webrtc.SessionDescr
                tc.stats.ConvertedOutboundConns++
                tc.mu.Unlock()
                tc.OnConn(dc, DataChannelContext{
-                       Local:        offer.originalOffer,
-                       Remote:       answer,
-                       OfferId:      offerId,
-                       LocalOffered: true,
-                       InfoHash:     offer.infoHash,
+                       Local:          offer.originalOffer,
+                       Remote:         answer,
+                       OfferId:        offerId,
+                       LocalOffered:   true,
+                       InfoHash:       offer.infoHash,
+                       peerConnection: offer.peerConnection,
                })
        })
        if err != nil {