@cryptotaxi247 / kubo / commits / 5b4a3c09b

p2p/net/swarm: more connection bugs

* filtering InterfaceListenAddresses(s) instead * return error if for loops skip * large dial timeout

Juan Batiz-Benet committed Jan 13, 2015 at 03:28 UTC 5b4a3c09bd3a45f5258123850cae78f2806e0f06
1 file changed +28 -4
p2p/net/swarm/swarm_dial.go
+28 -4
@@ -4,6 +4,7 @@ import (
4 "errors"
5 "fmt"
6 "sync"
7 + "time"
8
9 conn "github.com/jbenet/go-ipfs/p2p/net/conn"
10 addrutil "github.com/jbenet/go-ipfs/p2p/net/swarm/addr"
@@ -17,6 +18,11 @@ import (
18 // dialAttempts governs how many times a goroutine will try to dial a given peer.
19 const dialAttempts = 3
20
21 +// DialTimeout is the amount of time each dial attempt has. We can think about making
22 +// this larger down the road, or putting more granular timeouts (i.e. within each
23 +// subcomponent of Dial)
24 +var DialTimeout time.Duration = time.Second * 30
25 +
26 // dialsync is a small object that helps manage ongoing dials.
27 // this way, if we receive many simultaneous dial requests, one
28 // can do its thing, while the rest wait.
@@ -118,6 +124,7 @@ func (s *Swarm) Dial(ctx context.Context, p peer.ID) (*Conn, error) {
124
125 // check if there's an ongoing dial to this peer
126 if ok, wait := s.dsync.Lock(p); !ok {
127 + log.Debugf("swarm %s dialing %s -- waiting for ongoing dial", s.local, p)
128 select {
129 case <-wait: // wait for that dial to finish.
130 continue // and see if it worked (loop), OR we got an incoming dial.
@@ -128,13 +135,19 @@ func (s *Swarm) Dial(ctx context.Context, p peer.ID) (*Conn, error) {
135
136 // ok, we have been charged to dial! let's do it.
137 // if it succeeds, dial will add the conn to the swarm itself.
131 - conn, err = s.dial(ctx, p)
138 + log.Debugf("swarm %s dialing %s -- dial start", s.local, p)
139 + ctxT, _ := context.WithTimeout(ctx, DialTimeout)
140 + conn, err = s.dial(ctxT, p)
141 s.dsync.Unlock(p)
142 + log.Debugf("swarm %s dialing %s -- dial end %s", s.local, p, conn)
143 if err != nil {
144 continue // ok, we failed. try again. (if loop is done, our error is output)
145 }
146 return conn, nil
147 }
148 + if err == nil {
149 + err = fmt.Errorf("%s failed to dial %s after %d attempts", s.local, p, dialAttempts)
150 + }
151 return nil, err
152 }
153
@@ -162,7 +175,10 @@ func (s *Swarm) dial(ctx context.Context, p peer.ID) (*Conn, error) {
175 remoteAddrs = addrutil.FilterUsableAddrs(remoteAddrs)
176 // drop out any addrs that would just dial ourselves. use ListenAddresses
177 // as that is a more authoritative view than localAddrs.
165 - remoteAddrs = addrutil.Subtract(remoteAddrs, s.ListenAddresses())
178 + ila, _ := InterfaceListenAddresses(s)
179 + remoteAddrs = addrutil.Subtract(remoteAddrs, ila)
180 + remoteAddrs = addrutil.Subtract(remoteAddrs, s.peers.Addresses(s.local))
181 + log.Debugf("%s swarm dialing %s -- remote:%s local:%s", s.local, p, remoteAddrs, s.ListenAddresses())
182 if len(remoteAddrs) == 0 {
183 return nil, errors.New("peer has no addresses")
184 }
@@ -198,15 +214,20 @@ func (s *Swarm) dialAddrs(ctx context.Context, d *conn.Dialer, p peer.ID, remote
214 // try to connect to one of the peer's known addresses.
215 // for simplicity, we do this sequentially.
216 // A future commit will do this asynchronously.
217 + log.Debugf("%s swarm dialing %s %s", s.local, p, remoteAddrs)
218 + var err error
219 for _, addr := range remoteAddrs {
202 - connC, err := d.Dial(ctx, addr, p)
220 + log.Debugf("%s swarm dialing %s %s", s.local, p, addr)
221 + var connC conn.Conn
222 + connC, err = d.Dial(ctx, addr, p)
223 if err != nil {
224 + log.Info("%s --> %s dial attempt failed: %s", s.local, p, err)
225 continue
226 }
227
228 // if the connection is not to whom we thought it would be...
229 if connC.RemotePeer() != p {
209 - log.Infof("misdial to %s through %s (got %s)", p, addr, connC.RemoteMultiaddr())
230 + log.Infof("misdial to %s through %s (got %s)", p, addr, connC.RemotePeer())
231 connC.Close()
232 continue
233 }
@@ -223,6 +244,9 @@ func (s *Swarm) dialAddrs(ctx context.Context, d *conn.Dialer, p peer.ID, remote
244 // success! we got one!
245 return connC, nil
246 }
247 + if err != nil {
248 + return nil, err
249 + }
250 return nil, fmt.Errorf("failed to dial %s", p)
251 }
252