client.go | 53 +++++++++++++++++++++++------------------------------ dialer.go | 10 +++++----- socket.go | 5 +++++ diff --git a/client.go b/client.go index 032f253a7640333976474ef87c76bb97ae3f3299..c7a5f87c560ba7036524d11048fdbed0b00d24cf 100644 --- a/client.go +++ b/client.go @@ -553,9 +553,9 @@ func (cl *Client) torrent(ih metainfo.Hash) *Torrent { return cl.torrents[ih] } -type dialResult struct { - Conn net.Conn - Network string +type DialResult struct { + Conn net.Conn + Dialer Dialer } func countDialResult(err error) { @@ -581,14 +581,19 @@ return ok } // Returns a connection over UTP or TCP, whichever is first to connect. -func (cl *Client) dialFirst(ctx context.Context, addr string) (res dialResult) { +func (cl *Client) dialFirst(ctx context.Context, addr string) (res DialResult) { + return DialFirst(ctx, addr, cl.dialers) +} + +// Returns a connection over UTP or TCP, whichever is first to connect. +func DialFirst(ctx context.Context, addr string, dialers []Dialer) (res DialResult) { { t := perf.NewTimer(perf.CallerName(0)) defer func() { if res.Conn == nil { t.Mark(fmt.Sprintf("returned no conn (context: %v)", ctx.Err())) } else { - t.Mark("returned conn over " + res.Network) + t.Mark("returned conn over " + res.Dialer.DialerNetwork()) } }() } @@ -596,24 +601,17 @@ ctx, cancel := context.WithCancel(ctx) // As soon as we return one connection, cancel the others. defer cancel() left := 0 - resCh := make(chan dialResult, left) - func() { - cl.lock() - defer cl.unlock() - cl.eachDialer(func(s Dialer) bool { - func() { - left++ - //cl.logger.Printf("dialing %s on %s/%s", addr, s.Addr().Network(), s.Addr()) - go func() { - resCh <- dialResult{ - cl.dialFromSocket(ctx, s, addr), - s.LocalAddr().Network(), - } - }() - }() - return true - }) - }() + resCh := make(chan DialResult, left) + for _, _s := range dialers { + left++ + s := _s + go func() { + resCh <- DialResult{ + dialFromSocket(ctx, s, addr), + s, + } + }() + } // Wait for a successful connection. func() { defer perf.ScopeTimer()() @@ -633,15 +631,10 @@ }() if res.Conn != nil { go torrent.Add(fmt.Sprintf("network dialed first: %s", res.Conn.RemoteAddr().Network()), 1) } - //if res.Conn != nil { - // cl.logger.Printf("first connection for %s from %s/%s", addr, res.Conn.LocalAddr().Network(), res.Conn.LocalAddr().String()) - //} else { - // cl.logger.Printf("failed to dial %s", addr) - //} return res } -func (cl *Client) dialFromSocket(ctx context.Context, s Dialer, addr string) net.Conn { +func dialFromSocket(ctx context.Context, s Dialer, addr string) net.Conn { c, err := s.Dial(ctx, addr) // This is a bit optimistic, but it looks non-trivial to thread this through the proxy code. Set // it now in case we close the connection forthwith. @@ -711,7 +704,7 @@ return nil, xerrors.Errorf("dialing: %w", dialCtx.Err()) } return nil, errors.New("dial failed") } - c, err := cl.initiateProtocolHandshakes(context.Background(), nc, t, true, obfuscatedHeader, addr, dr.Network, regularNetConnPeerConnConnString(nc)) + c, err := cl.initiateProtocolHandshakes(context.Background(), nc, t, true, obfuscatedHeader, addr, dr.Dialer.DialerNetwork(), regularNetConnPeerConnConnString(nc)) if err != nil { nc.Close() } diff --git a/dialer.go b/dialer.go index 32ab91f704198289e6a263e2036071456d421824..e8126bd664ce0200e51f386d764df4b7429d7417 100644 --- a/dialer.go +++ b/dialer.go @@ -8,17 +8,17 @@ "github.com/anacrolix/missinggo/perf" ) type Dialer interface { - // The network is implied by the instance. Dial(_ context.Context, addr string) (net.Conn, error) - // This is required for registering with the connection tracker (router connection table - // emulating rate-limiter) before dialing. TODO: What about connections that wouldn't infringe - // on routers, like localhost or unix sockets. - LocalAddr() net.Addr + DialerNetwork() string } type NetDialer struct { Network string Dialer net.Dialer +} + +func (me NetDialer) DialerNetwork() string { + return me.Network } func (me NetDialer) Dial(ctx context.Context, addr string) (_ net.Conn, err error) { diff --git a/socket.go b/socket.go index d9654aceb587c022f156ab0b668dc10b5a4df6ea..ba2a091bd28987f982352718a8ef800a6962f50e 100644 --- a/socket.go +++ b/socket.go @@ -106,9 +106,14 @@ us, err := NewUtpSocket(network, addr, fc) return utpSocketSocket{us, network}, err } +// utpSocket wrapper, additionally wrapped for the torrent package's socket interface. type utpSocketSocket struct { utpSocket network string +} + +func (me utpSocketSocket) DialerNetwork() string { + return me.network } func (me utpSocketSocket) Dial(ctx context.Context, addr string) (conn net.Conn, err error) {