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