From: Matt Joiner Date: Wed, 12 Jan 2022 03:22:42 +0000 (+1100) Subject: Use webrtc selected ICE candidate for peer addresses X-Git-Tag: v1.41.0~21 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=c47e6b1f605143e1f0f8d2172c2b5dfadd8fff71;p=btrtrc.git Use webrtc selected ICE candidate for peer addresses --- diff --git a/torrent.go b/torrent.go index 8e83d3d3..3e74df63 100644 --- a/torrent.go +++ b/torrent.go @@ -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), ) diff --git a/webrtc.go b/webrtc.go index e8b0213c..44ef6ca2 100644 --- 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 "" + // 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 } diff --git a/webtorrent/tracker-client.go b/webtorrent/tracker-client.go index 9f02c7e7..1ec4b9d9 100644 --- a/webtorrent/tracker-client.go +++ b/webtorrent/tracker-client.go @@ -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 {