- go func() {
- // Binding to the listen address and dialing via net.Dialer gives
- // "address in use" error. It seems it's not possible to dial out from
- // this address so that peers associate our local address with our
- // listen address.
-
- // Initiate connections via TCP and UTP simultaneously. Use the first
- // one that succeeds.
- left := 0
- if !me.disableUTP {
- left++
- }
- if !me.disableTCP {
- left++
- }
- resCh := make(chan dialResult, left)
- if !me.disableUTP {
- go doDial(func(addr string) (net.Conn, error) {
- return me.utpSock.DialTimeout(addr, dialTimeout)
- }, resCh, true, addr)
- }
- if !me.disableTCP {
- go doDial(func(addr string) (net.Conn, error) {
- // time.Sleep(time.Second) // Give uTP a bit of a head start.
- return net.DialTimeout("tcp", addr, dialTimeout)
- }, resCh, false, addr)
- }
- var res dialResult
- for ; left > 0 && res.Conn == nil; left-- {
- res = <-resCh
- }
- // Whether or not the connection attempt succeeds, the half open
- // counter should be decremented, and new connection attempts made.
+ go me.outgoingConnection(t, addr, peer.Source)
+}
+
+func (me *Client) dialTimeout(t *torrent) time.Duration {
+ return reducedDialTimeout(nominalDialTimeout, me.halfOpenLimit, len(t.Peers))
+}
+
+func (me *Client) dialTCP(addr string, t *torrent) (c net.Conn, err error) {
+ c, err = net.DialTimeout("tcp", addr, me.dialTimeout(t))
+ if err == nil {
+ c.(*net.TCPConn).SetLinger(0)
+ }
+ return
+}
+
+func (me *Client) dialUTP(addr string, t *torrent) (c net.Conn, err error) {
+ return me.utpSock.DialTimeout(addr, me.dialTimeout(t))
+}
+
+// Returns a connection over UTP or TCP.
+func (me *Client) dial(addr string, t *torrent) (conn net.Conn, utp bool) {
+ // Initiate connections via TCP and UTP simultaneously. Use the first one
+ // that succeeds.
+ left := 0
+ if !me.disableUTP {
+ left++
+ }
+ if !me.disableTCP {
+ left++
+ }
+ resCh := make(chan dialResult, left)
+ if !me.disableUTP {
+ go doDial(me.dialUTP, resCh, true, addr, t)
+ }
+ if !me.disableTCP {
+ go doDial(me.dialTCP, resCh, false, addr, t)
+ }
+ var res dialResult
+ // Wait for a successful connection.
+ for ; left > 0 && res.Conn == nil; left-- {
+ res = <-resCh
+ }
+ if left > 0 {
+ // There are still incompleted dials.