address issues from code review (issue #25)
Jeromy committed
Aug 8, 2014 at 18:09 UTC
ae6285e5a3253a9f8e989e2b11f67d755d3f4db0
13 files changed
+379
-279
peer/peer.go
+13
-10
@@ -1,13 +1,13 @@
1
package peer
2
3
import (
4
- "encoding/hex"
4
"time"
5
"sync"
6
7
u "github.com/jbenet/go-ipfs/util"
8
ma "github.com/jbenet/go-multiaddr"
9
mh "github.com/jbenet/go-multihash"
10
+ b58 "github.com/jbenet/go-base58"
11
12
"bytes"
13
)
@@ -21,7 +21,7 @@ func (id ID) Equal(other ID) bool {
21
}
22
23
func (id ID) Pretty() string {
24
- return hex.EncodeToString(id)
24
+ return b58.Encode(id)
25
}
26
27
// Map maps Key (string) : *Peer (slices are not comparable).
@@ -33,8 +33,8 @@ type Peer struct {
33
ID ID
34
Addresses []*ma.Multiaddr
35
36
- distance time.Duration
37
- distLock sync.RWMutex
36
+ latency time.Duration
37
+ latenLock sync.RWMutex
38
}
39
40
// Key returns the ID as a Key (string) for maps.
@@ -64,12 +64,15 @@ func (p *Peer) NetAddress(n string) *ma.Multiaddr {
64
return nil
65
}
66
67
-func (p *Peer) GetDistance() time.Duration {
68
- return p.distance
67
+func (p *Peer) GetLatency() (out time.Duration) {
68
+ p.latenLock.RLock()
69
+ out = p.latency
70
+ p.latenLock.RUnlock()
71
+ return
72
}
73
71
-func (p *Peer) SetDistance(dist time.Duration) {
72
- p.distLock.Lock()
73
- p.distance = dist
74
- p.distLock.Unlock()
74
+func (p *Peer) SetLatency(laten time.Duration) {
75
+ p.latenLock.Lock()
76
+ p.latency = laten
77
+ p.latenLock.Unlock()
78
}
routing/dht/DHTMessage.go
renamed
+8
-8
@@ -1,17 +1,17 @@
1
package dht
2
3
// A helper struct to make working with protbuf types easier
4
-type pDHTMessage struct {
5
- Type DHTMessage_MessageType
6
- Key string
7
- Value []byte
4
+type DHTMessage struct {
5
+ Type PBDHTMessage_MessageType
6
+ Key string
7
+ Value []byte
8
Response bool
9
- Id uint64
10
- Success bool
9
+ Id uint64
10
+ Success bool
11
}
12
13
-func (m *pDHTMessage) ToProtobuf() *DHTMessage {
14
- pmes := new(DHTMessage)
13
+func (m *DHTMessage) ToProtobuf() *PBDHTMessage {
14
+ pmes := new(PBDHTMessage)
15
if m.Value != nil {
16
pmes.Value = m.Value
17
}
routing/dht/bucket.go
+1
-1
@@ -49,7 +49,7 @@ func (b *Bucket) Split(cpl int, target ID) *Bucket {
49
e := bucket_list.Front()
50
for e != nil {
51
peer_id := convertPeerID(e.Value.(*peer.Peer).ID)
52
- peer_cpl := xor(peer_id, target).commonPrefixLen()
52
+ peer_cpl := prefLen(peer_id, target)
53
if peer_cpl > cpl {
54
cur := e
55
out.PushBack(e.Value)
routing/dht/dht.go
+136
-140
@@ -1,15 +1,15 @@
1
package dht
2
3
import (
4
- "sync"
5
- "time"
4
"bytes"
5
"encoding/json"
6
+ "errors"
7
+ "sync"
8
+ "time"
9
9
- peer "github.com/jbenet/go-ipfs/peer"
10
- swarm "github.com/jbenet/go-ipfs/swarm"
11
- u "github.com/jbenet/go-ipfs/util"
12
- identify "github.com/jbenet/go-ipfs/identify"
10
+ peer "github.com/jbenet/go-ipfs/peer"
11
+ swarm "github.com/jbenet/go-ipfs/swarm"
12
+ u "github.com/jbenet/go-ipfs/util"
13
14
ma "github.com/jbenet/go-multiaddr"
15
@@ -37,7 +37,7 @@ type IpfsDHT struct {
37
38
// Map keys to peers that can provide their value
39
// TODO: implement a TTL on each of these keys
40
- providers map[u.Key][]*providerInfo
40
+ providers map[u.Key][]*providerInfo
41
providerLock sync.RWMutex
42
43
// map of channels waiting for reply messages
@@ -54,21 +54,27 @@ type IpfsDHT struct {
54
diaglock sync.Mutex
55
}
56
57
+// The listen info struct holds information about a message that is being waited for
58
type listenInfo struct {
59
+ // Responses matching the listen ID will be sent through resp
60
resp chan *swarm.Message
61
+
62
+ // count is the number of responses to listen for
63
count int
64
+
65
+ // eol is the time at which this listener will expire
66
eol time.Time
67
}
68
69
// Create a new DHT object with the given peer as the 'local' host
70
func NewDHT(p *peer.Peer) (*IpfsDHT, error) {
71
if p == nil {
66
- panic("Tried to create new dht with nil peer")
72
+ return nil, errors.New("nil peer passed to NewDHT()")
73
}
74
network := swarm.NewSwarm(p)
75
err := network.Listen()
76
if err != nil {
71
- return nil,err
77
+ return nil, err
78
}
79
80
dht := new(IpfsDHT)
@@ -90,50 +96,24 @@ func (dht *IpfsDHT) Start() {
96
}
97
98
// Connect to a new peer at the given address
93
-// TODO: move this into swarm
99
func (dht *IpfsDHT) Connect(addr *ma.Multiaddr) (*peer.Peer, error) {
95
- maddrstr,_ := addr.String()
100
+ maddrstr, _ := addr.String()
101
u.DOut("Connect to new peer: %s", maddrstr)
97
- if addr == nil {
98
- panic("addr was nil!")
99
- }
100
- peer := new(peer.Peer)
101
- peer.AddAddress(addr)
102
-
103
- conn,err := swarm.Dial("tcp", peer)
104
- if err != nil {
105
- return nil, err
106
- }
107
-
108
- err = identify.Handshake(dht.self, peer, conn.Incoming.MsgChan, conn.Outgoing.MsgChan)
102
+ npeer, err := dht.network.Connect(addr)
103
if err != nil {
104
return nil, err
105
}
106
113
- // Send node an address that you can be reached on
114
- myaddr := dht.self.NetAddress("tcp")
115
- mastr,err := myaddr.String()
116
- if err != nil {
117
- panic("No local address to send")
118
- }
119
-
120
- conn.Outgoing.MsgChan <- []byte(mastr)
121
-
122
- dht.network.StartConn(conn)
123
-
124
- removed := dht.routes[0].Update(peer)
125
- if removed != nil {
126
- panic("need to remove this peer.")
127
- }
107
+ dht.Update(npeer)
108
109
// Ping new peer to register in their routing table
110
// NOTE: this should be done better...
131
- err = dht.Ping(peer, time.Second * 2)
111
+ err = dht.Ping(npeer, time.Second*2)
112
if err != nil {
133
- panic("Failed to ping new peer.")
113
+ return nil, errors.New("Failed to ping newly connected peer.")
114
}
115
136
- return peer, nil
116
+ return npeer, nil
117
}
118
119
// Read in all messages from swarm and handle them appropriately
@@ -144,23 +124,19 @@ func (dht *IpfsDHT) handleMessages() {
124
checkTimeouts := time.NewTicker(time.Minute * 5)
125
for {
126
select {
147
- case mes,ok := <-dht.network.Chan.Incoming:
127
+ case mes, ok := <-dht.network.Chan.Incoming:
128
if !ok {
129
u.DOut("handleMessages closing, bad recv on incoming")
130
return
131
}
152
- pmes := new(DHTMessage)
132
+ pmes := new(PBDHTMessage)
133
err := proto.Unmarshal(mes.Data, pmes)
134
if err != nil {
135
u.PErr("Failed to decode protobuf message: %s", err)
136
continue
137
}
138
159
- // Update peers latest visit in routing table
160
- removed := dht.routes[0].Update(mes.Peer)
161
- if removed != nil {
162
- panic("Need to handle removed peer.")
163
- }
139
+ dht.Update(mes.Peer)
140
141
// Note: not sure if this is the correct place for this
142
if pmes.GetResponse() {
@@ -180,7 +156,6 @@ func (dht *IpfsDHT) handleMessages() {
156
dht.Unlisten(pmes.GetId())
157
}
158
} else {
183
- // this is expected behaviour during a timeout
159
u.DOut("Received response with nobody listening...")
160
}
161
@@ -190,65 +165,73 @@ func (dht *IpfsDHT) handleMessages() {
165
166
u.DOut("[peer: %s]", dht.self.ID.Pretty())
167
u.DOut("Got message type: '%s' [id = %x, from = %s]",
193
- DHTMessage_MessageType_name[int32(pmes.GetType())],
168
+ PBDHTMessage_MessageType_name[int32(pmes.GetType())],
169
pmes.GetId(), mes.Peer.ID.Pretty())
170
switch pmes.GetType() {
196
- case DHTMessage_GET_VALUE:
171
+ case PBDHTMessage_GET_VALUE:
172
dht.handleGetValue(mes.Peer, pmes)
198
- case DHTMessage_PUT_VALUE:
173
+ case PBDHTMessage_PUT_VALUE:
174
dht.handlePutValue(mes.Peer, pmes)
200
- case DHTMessage_FIND_NODE:
175
+ case PBDHTMessage_FIND_NODE:
176
dht.handleFindPeer(mes.Peer, pmes)
202
- case DHTMessage_ADD_PROVIDER:
177
+ case PBDHTMessage_ADD_PROVIDER:
178
dht.handleAddProvider(mes.Peer, pmes)
204
- case DHTMessage_GET_PROVIDERS:
179
+ case PBDHTMessage_GET_PROVIDERS:
180
dht.handleGetProviders(mes.Peer, pmes)
206
- case DHTMessage_PING:
181
+ case PBDHTMessage_PING:
182
dht.handlePing(mes.Peer, pmes)
208
- case DHTMessage_DIAGNOSTIC:
183
+ case PBDHTMessage_DIAGNOSTIC:
184
dht.handleDiagnostic(mes.Peer, pmes)
185
}
186
187
case err := <-dht.network.Chan.Errors:
188
u.DErr("dht err: %s", err)
214
- panic(err)
189
case <-dht.shutdown:
190
checkTimeouts.Stop()
191
return
192
case <-checkTimeouts.C:
219
- dht.providerLock.Lock()
220
- for k,parr := range dht.providers {
221
- var cleaned []*providerInfo
222
- for _,v := range parr {
223
- if time.Since(v.Creation) < time.Hour {
224
- cleaned = append(cleaned, v)
225
- }
226
- }
227
- dht.providers[k] = cleaned
228
- }
229
- dht.providerLock.Unlock()
230
- dht.listenLock.Lock()
231
- var remove []uint64
232
- now := time.Now()
233
- for k,v := range dht.listeners {
234
- if now.After(v.eol) {
235
- remove = append(remove, k)
236
- }
237
- }
238
- for _,k := range remove {
239
- delete(dht.listeners, k)
193
+ // Time to collect some garbage!
194
+ dht.cleanExpiredProviders()
195
+ dht.cleanExpiredListeners()
196
+ }
197
+ }
198
+}
199
+
200
+func (dht *IpfsDHT) cleanExpiredProviders() {
201
+ dht.providerLock.Lock()
202
+ for k, parr := range dht.providers {
203
+ var cleaned []*providerInfo
204
+ for _, v := range parr {
205
+ if time.Since(v.Creation) < time.Hour {
206
+ cleaned = append(cleaned, v)
207
}
241
- dht.listenLock.Unlock()
208
}
209
+ dht.providers[k] = cleaned
210
}
211
+ dht.providerLock.Unlock()
212
+}
213
+
214
+func (dht *IpfsDHT) cleanExpiredListeners() {
215
+ dht.listenLock.Lock()
216
+ var remove []uint64
217
+ now := time.Now()
218
+ for k, v := range dht.listeners {
219
+ if now.After(v.eol) {
220
+ remove = append(remove, k)
221
+ }
222
+ }
223
+ for _, k := range remove {
224
+ delete(dht.listeners, k)
225
+ }
226
+ dht.listenLock.Unlock()
227
}
228
229
func (dht *IpfsDHT) putValueToPeer(p *peer.Peer, key string, value []byte) error {
247
- pmes := pDHTMessage{
248
- Type: DHTMessage_PUT_VALUE,
249
- Key: key,
230
+ pmes := DHTMessage{
231
+ Type: PBDHTMessage_PUT_VALUE,
232
+ Key: key,
233
Value: value,
251
- Id: GenerateMessageID(),
234
+ Id: GenerateMessageID(),
235
}
236
237
mes := swarm.NewMessage(p, pmes.ToProtobuf())
@@ -256,27 +239,27 @@ func (dht *IpfsDHT) putValueToPeer(p *peer.Peer, key string, value []byte) error
239
return nil
240
}
241
259
-func (dht *IpfsDHT) handleGetValue(p *peer.Peer, pmes *DHTMessage) {
242
+func (dht *IpfsDHT) handleGetValue(p *peer.Peer, pmes *PBDHTMessage) {
243
dskey := ds.NewKey(pmes.GetKey())
261
- var resp *pDHTMessage
244
+ var resp *DHTMessage
245
i_val, err := dht.datastore.Get(dskey)
246
if err == nil {
264
- resp = &pDHTMessage{
247
+ resp = &DHTMessage{
248
Response: true,
266
- Id: *pmes.Id,
267
- Key: *pmes.Key,
268
- Value: i_val.([]byte),
269
- Success: true,
249
+ Id: *pmes.Id,
250
+ Key: *pmes.Key,
251
+ Value: i_val.([]byte),
252
+ Success: true,
253
}
254
} else if err == ds.ErrNotFound {
255
// Find closest peer(s) to desired key and reply with that info
256
closer := dht.routes[0].NearestPeer(convertKey(u.Key(pmes.GetKey())))
274
- resp = &pDHTMessage{
257
+ resp = &DHTMessage{
258
Response: true,
276
- Id: *pmes.Id,
277
- Key: *pmes.Key,
278
- Value: closer.ID,
279
- Success: false,
259
+ Id: *pmes.Id,
260
+ Key: *pmes.Key,
261
+ Value: closer.ID,
262
+ Success: false,
263
}
264
}
265
@@ -285,7 +268,7 @@ func (dht *IpfsDHT) handleGetValue(p *peer.Peer, pmes *DHTMessage) {
268
}
269
270
// Store a value in this peer local storage
288
-func (dht *IpfsDHT) handlePutValue(p *peer.Peer, pmes *DHTMessage) {
271
+func (dht *IpfsDHT) handlePutValue(p *peer.Peer, pmes *PBDHTMessage) {
272
dskey := ds.NewKey(pmes.GetKey())
273
err := dht.datastore.Put(dskey, pmes.GetValue())
274
if err != nil {
@@ -294,46 +277,51 @@ func (dht *IpfsDHT) handlePutValue(p *peer.Peer, pmes *DHTMessage) {
277
}
278
}
279
297
-func (dht *IpfsDHT) handlePing(p *peer.Peer, pmes *DHTMessage) {
298
- resp := pDHTMessage{
299
- Type: pmes.GetType(),
280
+func (dht *IpfsDHT) handlePing(p *peer.Peer, pmes *PBDHTMessage) {
281
+ resp := DHTMessage{
282
+ Type: pmes.GetType(),
283
Response: true,
301
- Id: pmes.GetId(),
284
+ Id: pmes.GetId(),
285
}
286
304
- dht.network.Chan.Outgoing <-swarm.NewMessage(p, resp.ToProtobuf())
287
+ dht.network.Chan.Outgoing <- swarm.NewMessage(p, resp.ToProtobuf())
288
}
289
307
-func (dht *IpfsDHT) handleFindPeer(p *peer.Peer, pmes *DHTMessage) {
290
+func (dht *IpfsDHT) handleFindPeer(p *peer.Peer, pmes *PBDHTMessage) {
291
+ success := true
292
u.POut("handleFindPeer: searching for '%s'", peer.ID(pmes.GetKey()).Pretty())
293
closest := dht.routes[0].NearestPeer(convertKey(u.Key(pmes.GetKey())))
294
if closest == nil {
311
- panic("could not find anything.")
295
+ u.PErr("handleFindPeer: could not find anything.")
296
+ success = false
297
}
298
299
if len(closest.Addresses) == 0 {
315
- panic("no addresses for connected peer...")
300
+ u.PErr("handleFindPeer: no addresses for connected peer...")
301
+ success = false
302
}
303
304
u.POut("handleFindPeer: sending back '%s'", closest.ID.Pretty())
305
320
- addr,err := closest.Addresses[0].String()
306
+ addr, err := closest.Addresses[0].String()
307
if err != nil {
322
- panic(err)
308
+ u.PErr(err.Error())
309
+ success = false
310
}
311
325
- resp := pDHTMessage{
326
- Type: pmes.GetType(),
312
+ resp := DHTMessage{
313
+ Type: pmes.GetType(),
314
Response: true,
328
- Id: pmes.GetId(),
329
- Value: []byte(addr),
315
+ Id: pmes.GetId(),
316
+ Value: []byte(addr),
317
+ Success: success,
318
}
319
320
mes := swarm.NewMessage(p, resp.ToProtobuf())
333
- dht.network.Chan.Outgoing <-mes
321
+ dht.network.Chan.Outgoing <- mes
322
}
323
336
-func (dht *IpfsDHT) handleGetProviders(p *peer.Peer, pmes *DHTMessage) {
324
+func (dht *IpfsDHT) handleGetProviders(p *peer.Peer, pmes *PBDHTMessage) {
325
dht.providerLock.RLock()
326
providers := dht.providers[u.Key(pmes.GetKey())]
327
dht.providerLock.RUnlock()
@@ -344,9 +332,9 @@ func (dht *IpfsDHT) handleGetProviders(p *peer.Peer, pmes *DHTMessage) {
332
333
// This is just a quick hack, formalize method of sending addrs later
334
addrs := make(map[u.Key]string)
347
- for _,prov := range providers {
335
+ for _, prov := range providers {
336
ma := prov.Value.NetAddress("tcp")
349
- str,err := ma.String()
337
+ str, err := ma.String()
338
if err != nil {
339
u.PErr("Error: %s", err)
340
continue
@@ -355,35 +343,38 @@ func (dht *IpfsDHT) handleGetProviders(p *peer.Peer, pmes *DHTMessage) {
343
addrs[prov.Value.Key()] = str
344
}
345
358
- data,err := json.Marshal(addrs)
346
+ success := true
347
+ data, err := json.Marshal(addrs)
348
if err != nil {
360
- panic(err)
349
+ u.POut("handleGetProviders: error marshalling struct to JSON: %s", err)
350
+ data = nil
351
+ success = false
352
}
353
363
- resp := pDHTMessage{
364
- Type: DHTMessage_GET_PROVIDERS,
365
- Key: pmes.GetKey(),
366
- Value: data,
367
- Id: pmes.GetId(),
354
+ resp := DHTMessage{
355
+ Type: PBDHTMessage_GET_PROVIDERS,
356
+ Key: pmes.GetKey(),
357
+ Value: data,
358
+ Id: pmes.GetId(),
359
Response: true,
360
+ Success: success,
361
}
362
363
mes := swarm.NewMessage(p, resp.ToProtobuf())
372
- dht.network.Chan.Outgoing <-mes
364
+ dht.network.Chan.Outgoing <- mes
365
}
366
367
type providerInfo struct {
368
Creation time.Time
377
- Value *peer.Peer
369
+ Value *peer.Peer
370
}
371
380
-func (dht *IpfsDHT) handleAddProvider(p *peer.Peer, pmes *DHTMessage) {
372
+func (dht *IpfsDHT) handleAddProvider(p *peer.Peer, pmes *PBDHTMessage) {
373
//TODO: need to implement TTLs on providers
374
key := u.Key(pmes.GetKey())
375
dht.addProviderEntry(key, p)
376
}
377
386
-
378
// Register a handler for a specific message ID, used for getting replies
379
// to certain messages (i.e. response to a GET_VALUE message)
380
func (dht *IpfsDHT) ListenFor(mesid uint64, count int, timeout time.Duration) <-chan *swarm.Message {
@@ -407,7 +398,7 @@ func (dht *IpfsDHT) Unlisten(mesid uint64) {
398
399
func (dht *IpfsDHT) IsListening(mesid uint64) bool {
400
dht.listenLock.RLock()
410
- li,ok := dht.listeners[mesid]
401
+ li, ok := dht.listeners[mesid]
402
dht.listenLock.RUnlock()
403
if time.Now().After(li.eol) {
404
dht.listenLock.Lock()
@@ -432,7 +423,7 @@ func (dht *IpfsDHT) addProviderEntry(key u.Key, p *peer.Peer) {
423
dht.providerLock.Unlock()
424
}
425
435
-func (dht *IpfsDHT) handleDiagnostic(p *peer.Peer, pmes *DHTMessage) {
426
+func (dht *IpfsDHT) handleDiagnostic(p *peer.Peer, pmes *PBDHTMessage) {
427
dht.diaglock.Lock()
428
if dht.IsListening(pmes.GetId()) {
429
//TODO: ehhh..........
@@ -442,15 +433,13 @@ func (dht *IpfsDHT) handleDiagnostic(p *peer.Peer, pmes *DHTMessage) {
433
dht.diaglock.Unlock()
434
435
seq := dht.routes[0].NearestPeers(convertPeerID(dht.self.ID), 10)
445
- listen_chan := dht.ListenFor(pmes.GetId(), len(seq), time.Second * 30)
436
+ listen_chan := dht.ListenFor(pmes.GetId(), len(seq), time.Second*30)
437
447
- for _,ps := range seq {
438
+ for _, ps := range seq {
439
mes := swarm.NewMessage(ps, pmes)
449
- dht.network.Chan.Outgoing <-mes
440
+ dht.network.Chan.Outgoing <- mes
441
}
442
452
-
453
-
443
buf := new(bytes.Buffer)
444
di := dht.getDiagInfo()
445
buf.Write(di.Marshal())
@@ -464,7 +453,7 @@ func (dht *IpfsDHT) handleDiagnostic(p *peer.Peer, pmes *DHTMessage) {
453
//Timeout, return what we have
454
goto out
455
case req_resp := <-listen_chan:
467
- pmes_out := new(DHTMessage)
456
+ pmes_out := new(PBDHTMessage)
457
err := proto.Unmarshal(req_resp.Data, pmes_out)
458
if err != nil {
459
// It broke? eh, whatever, keep going
@@ -476,19 +465,19 @@ func (dht *IpfsDHT) handleDiagnostic(p *peer.Peer, pmes *DHTMessage) {
465
}
466
467
out:
479
- resp := pDHTMessage{
480
- Type: DHTMessage_DIAGNOSTIC,
481
- Id: pmes.GetId(),
482
- Value: buf.Bytes(),
468
+ resp := DHTMessage{
469
+ Type: PBDHTMessage_DIAGNOSTIC,
470
+ Id: pmes.GetId(),
471
+ Value: buf.Bytes(),
472
Response: true,
473
}
474
475
mes := swarm.NewMessage(p, resp.ToProtobuf())
487
- dht.network.Chan.Outgoing <-mes
476
+ dht.network.Chan.Outgoing <- mes
477
}
478
479
func (dht *IpfsDHT) GetLocal(key u.Key) ([]byte, error) {
491
- v,err := dht.datastore.Get(ds.NewKey(string(key)))
480
+ v, err := dht.datastore.Get(ds.NewKey(string(key)))
481
if err != nil {
482
return nil, err
483
}
@@ -498,3 +487,10 @@ func (dht *IpfsDHT) GetLocal(key u.Key) ([]byte, error) {
487
func (dht *IpfsDHT) PutLocal(key u.Key, value []byte) error {
488
return dht.datastore.Put(ds.NewKey(string(key)), value)
489
}
490
+
491
+func (dht *IpfsDHT) Update(p *peer.Peer) {
492
+ removed := dht.routes[0].Update(p)
493
+ if removed != nil {
494
+ dht.network.Drop(removed)
495
+ }
496
+}
routing/dht/dht_test.go
+22
-20
@@ -2,21 +2,22 @@ package dht
2
3
import (
4
"testing"
5
+
6
peer "github.com/jbenet/go-ipfs/peer"
6
- ma "github.com/jbenet/go-multiaddr"
7
u "github.com/jbenet/go-ipfs/util"
8
+ ma "github.com/jbenet/go-multiaddr"
9
9
- "time"
10
"fmt"
11
+ "time"
12
)
13
14
func TestPing(t *testing.T) {
15
u.Debug = false
15
- addr_a,err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/1234")
16
+ addr_a, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/1234")
17
if err != nil {
18
t.Fatal(err)
19
}
19
- addr_b,err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/5678")
20
+ addr_b, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/5678")
21
if err != nil {
22
t.Fatal(err)
23
}
@@ -29,12 +30,12 @@ func TestPing(t *testing.T) {
30
peer_b.AddAddress(addr_b)
31
peer_b.ID = peer.ID([]byte("peer_b"))
32
32
- dht_a,err := NewDHT(peer_a)
33
+ dht_a, err := NewDHT(peer_a)
34
if err != nil {
35
t.Fatal(err)
36
}
37
37
- dht_b,err := NewDHT(peer_b)
38
+ dht_b, err := NewDHT(peer_b)
39
if err != nil {
40
t.Fatal(err)
41
}
@@ -42,13 +43,13 @@ func TestPing(t *testing.T) {
43
dht_a.Start()
44
dht_b.Start()
45
45
- _,err = dht_a.Connect(addr_b)
46
+ _, err = dht_a.Connect(addr_b)
47
if err != nil {
48
t.Fatal(err)
49
}
50
51
//Test that we can ping the node
51
- err = dht_a.Ping(peer_b, time.Second * 2)
52
+ err = dht_a.Ping(peer_b, time.Second*2)
53
if err != nil {
54
t.Fatal(err)
55
}
@@ -59,11 +60,11 @@ func TestPing(t *testing.T) {
60
61
func TestValueGetSet(t *testing.T) {
62
u.Debug = false
62
- addr_a,err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/1235")
63
+ addr_a, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/1235")
64
if err != nil {
65
t.Fatal(err)
66
}
66
- addr_b,err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/5679")
67
+ addr_b, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/5679")
68
if err != nil {
69
t.Fatal(err)
70
}
@@ -76,12 +77,12 @@ func TestValueGetSet(t *testing.T) {
77
peer_b.AddAddress(addr_b)
78
peer_b.ID = peer.ID([]byte("peer_b"))
79
79
- dht_a,err := NewDHT(peer_a)
80
+ dht_a, err := NewDHT(peer_a)
81
if err != nil {
82
t.Fatal(err)
83
}
84
84
- dht_b,err := NewDHT(peer_b)
85
+ dht_b, err := NewDHT(peer_b)
86
if err != nil {
87
t.Fatal(err)
88
}
@@ -89,7 +90,7 @@ func TestValueGetSet(t *testing.T) {
90
dht_a.Start()
91
dht_b.Start()
92
92
- _,err = dht_a.Connect(addr_b)
93
+ _, err = dht_a.Connect(addr_b)
94
if err != nil {
95
t.Fatal(err)
96
}
@@ -99,7 +100,7 @@ func TestValueGetSet(t *testing.T) {
100
t.Fatal(err)
101
}
102
102
- val, err := dht_a.GetValue("hello", time.Second * 2)
103
+ val, err := dht_a.GetValue("hello", time.Second*2)
104
if err != nil {
105
t.Fatal(err)
106
}
@@ -113,14 +114,13 @@ func TestProvides(t *testing.T) {
114
u.Debug = false
115
var addrs []*ma.Multiaddr
116
for i := 0; i < 4; i++ {
116
- a,err := ma.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", 5000 + i))
117
+ a, err := ma.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", 5000+i))
118
if err != nil {
119
t.Fatal(err)
120
}
121
addrs = append(addrs, a)
122
}
123
123
-
124
var peers []*peer.Peer
125
for i := 0; i < 4; i++ {
126
p := new(peer.Peer)
@@ -131,7 +131,7 @@ func TestProvides(t *testing.T) {
131
132
var dhts []*IpfsDHT
133
for i := 0; i < 4; i++ {
134
- d,err := NewDHT(peers[i])
134
+ d, err := NewDHT(peers[i])
135
if err != nil {
136
t.Fatal(err)
137
}
@@ -166,7 +166,7 @@ func TestProvides(t *testing.T) {
166
167
time.Sleep(time.Millisecond * 60)
168
169
- provs,err := dhts[0].FindProviders(u.Key("hello"), time.Second)
169
+ provs, err := dhts[0].FindProviders(u.Key("hello"), time.Second)
170
if err != nil {
171
t.Fatal(err)
172
}
@@ -174,6 +174,8 @@ func TestProvides(t *testing.T) {
174
if len(provs) != 1 {
175
t.Fatal("Didnt get back providers")
176
}
177
-}
178
-
177
178
+ for i := 0; i < 4; i++ {
179
+ dhts[i].Halt()
180
+ }
181
+}
routing/dht/diag.go
+1
-1
@@ -38,7 +38,7 @@ func (dht *IpfsDHT) getDiagInfo() *diagInfo {
38
di.Keys = nil // Currently no way to query datastore
39
40
for _,p := range dht.routes[0].listpeers() {
41
- di.Connections = append(di.Connections, connDiagInfo{p.GetDistance(), p.ID})
41
+ di.Connections = append(di.Connections, connDiagInfo{p.GetLatency(), p.ID})
42
}
43
return di
44
}
routing/dht/messages.pb.go
+69
-37
@@ -9,7 +9,7 @@ It is generated from these files:
9
messages.proto
10
11
It has these top-level messages:
12
- DHTMessage
12
+ PBDHTMessage
13
*/
14
package dht
15
@@ -20,19 +20,19 @@ import math "math"
20
var _ = proto.Marshal
21
var _ = math.Inf
22
23
-type DHTMessage_MessageType int32
23
+type PBDHTMessage_MessageType int32
24
25
const (
26
- DHTMessage_PUT_VALUE DHTMessage_MessageType = 0
27
- DHTMessage_GET_VALUE DHTMessage_MessageType = 1
28
- DHTMessage_ADD_PROVIDER DHTMessage_MessageType = 2
29
- DHTMessage_GET_PROVIDERS DHTMessage_MessageType = 3
30
- DHTMessage_FIND_NODE DHTMessage_MessageType = 4
31
- DHTMessage_PING DHTMessage_MessageType = 5
32
- DHTMessage_DIAGNOSTIC DHTMessage_MessageType = 6
26
+ PBDHTMessage_PUT_VALUE PBDHTMessage_MessageType = 0
27
+ PBDHTMessage_GET_VALUE PBDHTMessage_MessageType = 1
28
+ PBDHTMessage_ADD_PROVIDER PBDHTMessage_MessageType = 2
29
+ PBDHTMessage_GET_PROVIDERS PBDHTMessage_MessageType = 3
30
+ PBDHTMessage_FIND_NODE PBDHTMessage_MessageType = 4
31
+ PBDHTMessage_PING PBDHTMessage_MessageType = 5
32
+ PBDHTMessage_DIAGNOSTIC PBDHTMessage_MessageType = 6
33
)
34
35
-var DHTMessage_MessageType_name = map[int32]string{
35
+var PBDHTMessage_MessageType_name = map[int32]string{
36
0: "PUT_VALUE",
37
1: "GET_VALUE",
38
2: "ADD_PROVIDER",
@@ -41,7 +41,7 @@ var DHTMessage_MessageType_name = map[int32]string{
41
5: "PING",
42
6: "DIAGNOSTIC",
43
}
44
-var DHTMessage_MessageType_value = map[string]int32{
44
+var PBDHTMessage_MessageType_value = map[string]int32{
45
"PUT_VALUE": 0,
46
"GET_VALUE": 1,
47
"ADD_PROVIDER": 2,
@@ -51,79 +51,111 @@ var DHTMessage_MessageType_value = map[string]int32{
51
"DIAGNOSTIC": 6,
52
}
53
54
-func (x DHTMessage_MessageType) Enum() *DHTMessage_MessageType {
55
- p := new(DHTMessage_MessageType)
54
+func (x PBDHTMessage_MessageType) Enum() *PBDHTMessage_MessageType {
55
+ p := new(PBDHTMessage_MessageType)
56
*p = x
57
return p
58
}
59
-func (x DHTMessage_MessageType) String() string {
60
- return proto.EnumName(DHTMessage_MessageType_name, int32(x))
59
+func (x PBDHTMessage_MessageType) String() string {
60
+ return proto.EnumName(PBDHTMessage_MessageType_name, int32(x))
61
}
62
-func (x *DHTMessage_MessageType) UnmarshalJSON(data []byte) error {
63
- value, err := proto.UnmarshalJSONEnum(DHTMessage_MessageType_value, data, "DHTMessage_MessageType")
62
+func (x *PBDHTMessage_MessageType) UnmarshalJSON(data []byte) error {
63
+ value, err := proto.UnmarshalJSONEnum(PBDHTMessage_MessageType_value, data, "PBDHTMessage_MessageType")
64
if err != nil {
65
return err
66
}
67
- *x = DHTMessage_MessageType(value)
67
+ *x = PBDHTMessage_MessageType(value)
68
return nil
69
}
70
71
-type DHTMessage struct {
72
- Type *DHTMessage_MessageType `protobuf:"varint,1,req,name=type,enum=dht.DHTMessage_MessageType" json:"type,omitempty"`
73
- Key *string `protobuf:"bytes,2,opt,name=key" json:"key,omitempty"`
74
- Value []byte `protobuf:"bytes,3,opt,name=value" json:"value,omitempty"`
75
- Id *uint64 `protobuf:"varint,4,req,name=id" json:"id,omitempty"`
76
- Response *bool `protobuf:"varint,5,opt,name=response" json:"response,omitempty"`
77
- Success *bool `protobuf:"varint,6,opt,name=success" json:"success,omitempty"`
78
- XXX_unrecognized []byte `json:"-"`
71
+type PBDHTMessage struct {
72
+ Type *PBDHTMessage_MessageType `protobuf:"varint,1,req,name=type,enum=dht.PBDHTMessage_MessageType" json:"type,omitempty"`
73
+ Key *string `protobuf:"bytes,2,opt,name=key" json:"key,omitempty"`
74
+ Value []byte `protobuf:"bytes,3,opt,name=value" json:"value,omitempty"`
75
+ Id *uint64 `protobuf:"varint,4,req,name=id" json:"id,omitempty"`
76
+ Response *bool `protobuf:"varint,5,opt,name=response" json:"response,omitempty"`
77
+ Success *bool `protobuf:"varint,6,opt,name=success" json:"success,omitempty"`
78
+ Peers []*PBDHTMessage_PBPeer `protobuf:"bytes,7,rep,name=peers" json:"peers,omitempty"`
79
+ XXX_unrecognized []byte `json:"-"`
80
}
81
81
-func (m *DHTMessage) Reset() { *m = DHTMessage{} }
82
-func (m *DHTMessage) String() string { return proto.CompactTextString(m) }
83
-func (*DHTMessage) ProtoMessage() {}
82
+func (m *PBDHTMessage) Reset() { *m = PBDHTMessage{} }
83
+func (m *PBDHTMessage) String() string { return proto.CompactTextString(m) }
84
+func (*PBDHTMessage) ProtoMessage() {}
85
85
-func (m *DHTMessage) GetType() DHTMessage_MessageType {
86
+func (m *PBDHTMessage) GetType() PBDHTMessage_MessageType {
87
if m != nil && m.Type != nil {
88
return *m.Type
89
}
89
- return DHTMessage_PUT_VALUE
90
+ return PBDHTMessage_PUT_VALUE
91
}
92
92
-func (m *DHTMessage) GetKey() string {
93
+func (m *PBDHTMessage) GetKey() string {
94
if m != nil && m.Key != nil {
95
return *m.Key
96
}
97
return ""
98
}
99
99
-func (m *DHTMessage) GetValue() []byte {
100
+func (m *PBDHTMessage) GetValue() []byte {
101
if m != nil {
102
return m.Value
103
}
104
return nil
105
}
106
106
-func (m *DHTMessage) GetId() uint64 {
107
+func (m *PBDHTMessage) GetId() uint64 {
108
if m != nil && m.Id != nil {
109
return *m.Id
110
}
111
return 0
112
}
113
113
-func (m *DHTMessage) GetResponse() bool {
114
+func (m *PBDHTMessage) GetResponse() bool {
115
if m != nil && m.Response != nil {
116
return *m.Response
117
}
118
return false
119
}
120
120
-func (m *DHTMessage) GetSuccess() bool {
121
+func (m *PBDHTMessage) GetSuccess() bool {
122
if m != nil && m.Success != nil {
123
return *m.Success
124
}
125
return false
126
}
127
128
+func (m *PBDHTMessage) GetPeers() []*PBDHTMessage_PBPeer {
129
+ if m != nil {
130
+ return m.Peers
131
+ }
132
+ return nil
133
+}
134
+
135
+type PBDHTMessage_PBPeer struct {
136
+ Id *string `protobuf:"bytes,1,req,name=id" json:"id,omitempty"`
137
+ Addr *string `protobuf:"bytes,2,req,name=addr" json:"addr,omitempty"`
138
+ XXX_unrecognized []byte `json:"-"`
139
+}
140
+
141
+func (m *PBDHTMessage_PBPeer) Reset() { *m = PBDHTMessage_PBPeer{} }
142
+func (m *PBDHTMessage_PBPeer) String() string { return proto.CompactTextString(m) }
143
+func (*PBDHTMessage_PBPeer) ProtoMessage() {}
144
+
145
+func (m *PBDHTMessage_PBPeer) GetId() string {
146
+ if m != nil && m.Id != nil {
147
+ return *m.Id
148
+ }
149
+ return ""
150
+}
151
+
152
+func (m *PBDHTMessage_PBPeer) GetAddr() string {
153
+ if m != nil && m.Addr != nil {
154
+ return *m.Addr
155
+ }
156
+ return ""
157
+}
158
+
159
func init() {
128
- proto.RegisterEnum("dht.DHTMessage_MessageType", DHTMessage_MessageType_name, DHTMessage_MessageType_value)
160
+ proto.RegisterEnum("dht.PBDHTMessage_MessageType", PBDHTMessage_MessageType_name, PBDHTMessage_MessageType_value)
161
}
routing/dht/messages.proto
+9
-1
@@ -2,7 +2,7 @@ package dht;
2
3
//run `protoc --go_out=. *.proto` to generate
4
5
-message DHTMessage {
5
+message PBDHTMessage {
6
enum MessageType {
7
PUT_VALUE = 0;
8
GET_VALUE = 1;
@@ -13,6 +13,11 @@ message DHTMessage {
13
DIAGNOSTIC = 6;
14
}
15
16
+ message PBPeer {
17
+ required string id = 1;
18
+ required string addr = 2;
19
+ }
20
+
21
required MessageType type = 1;
22
optional string key = 2;
23
optional bytes value = 3;
@@ -23,4 +28,7 @@ message DHTMessage {
28
// Signals whether or not this message is a response to another message
29
optional bool response = 5;
30
optional bool success = 6;
31
+
32
+ // Used for returning peers from queries (normally, peers closer to X)
33
+ repeated PBPeer peers = 7;
34
}
routing/dht/routing.go
+42
-43
@@ -1,10 +1,11 @@
1
package dht
2
3
import (
4
- "math/rand"
5
- "time"
4
"bytes"
5
"encoding/json"
6
+ "errors"
7
+ "math/rand"
8
+ "time"
9
10
proto "code.google.com/p/goprotobuf/proto"
11
@@ -34,7 +35,7 @@ func (s *IpfsDHT) PutValue(key u.Key, value []byte) error {
35
var p *peer.Peer
36
p = s.routes[0].NearestPeer(convertKey(key))
37
if p == nil {
37
- panic("Table returned nil peer!")
38
+ return errors.New("Table returned nil peer!")
39
}
40
41
return s.putValueToPeer(p, string(key), value)
@@ -47,13 +48,13 @@ func (s *IpfsDHT) GetValue(key u.Key, timeout time.Duration) ([]byte, error) {
48
var p *peer.Peer
49
p = s.routes[0].NearestPeer(convertKey(key))
50
if p == nil {
50
- panic("Table returned nil peer!")
51
+ return nil, errors.New("Table returned nil peer!")
52
}
53
53
- pmes := pDHTMessage{
54
- Type: DHTMessage_GET_VALUE,
55
- Key: string(key),
56
- Id: GenerateMessageID(),
54
+ pmes := DHTMessage{
55
+ Type: PBDHTMessage_GET_VALUE,
56
+ Key: string(key),
57
+ Id: GenerateMessageID(),
58
}
59
response_chan := s.ListenFor(pmes.Id, 1, time.Minute)
60
@@ -68,15 +69,13 @@ func (s *IpfsDHT) GetValue(key u.Key, timeout time.Duration) ([]byte, error) {
69
return nil, u.ErrTimeout
70
case resp, ok := <-response_chan:
71
if !ok {
71
- panic("Channel was closed...")
72
+ u.PErr("response channel closed before timeout, please investigate.")
73
+ return nil, u.ErrTimeout
74
}
73
- if resp == nil {
74
- panic("Why the hell is this response nil?")
75
- }
76
- pmes_out := new(DHTMessage)
75
+ pmes_out := new(PBDHTMessage)
76
err := proto.Unmarshal(resp.Data, pmes_out)
77
if err != nil {
79
- return nil,err
78
+ return nil, err
79
}
80
if pmes_out.GetSuccess() {
81
return pmes_out.GetValue(), nil
@@ -96,15 +95,15 @@ func (s *IpfsDHT) Provide(key u.Key) error {
95
//return an error
96
}
97
99
- pmes := pDHTMessage{
100
- Type: DHTMessage_ADD_PROVIDER,
101
- Key: string(key),
98
+ pmes := DHTMessage{
99
+ Type: PBDHTMessage_ADD_PROVIDER,
100
+ Key: string(key),
101
}
102
pbmes := pmes.ToProtobuf()
103
105
- for _,p := range peers {
104
+ for _, p := range peers {
105
mes := swarm.NewMessage(p, pbmes)
107
- s.network.Chan.Outgoing <-mes
106
+ s.network.Chan.Outgoing <- mes
107
}
108
return nil
109
}
@@ -113,17 +112,17 @@ func (s *IpfsDHT) Provide(key u.Key) error {
112
func (s *IpfsDHT) FindProviders(key u.Key, timeout time.Duration) ([]*peer.Peer, error) {
113
p := s.routes[0].NearestPeer(convertKey(key))
114
116
- pmes := pDHTMessage{
117
- Type: DHTMessage_GET_PROVIDERS,
118
- Key: string(key),
119
- Id: GenerateMessageID(),
115
+ pmes := DHTMessage{
116
+ Type: PBDHTMessage_GET_PROVIDERS,
117
+ Key: string(key),
118
+ Id: GenerateMessageID(),
119
}
120
121
mes := swarm.NewMessage(p, pmes.ToProtobuf())
122
123
listen_chan := s.ListenFor(pmes.Id, 1, time.Minute)
124
u.DOut("Find providers for: '%s'", key)
126
- s.network.Chan.Outgoing <-mes
125
+ s.network.Chan.Outgoing <- mes
126
after := time.After(timeout)
127
select {
128
case <-after:
@@ -131,7 +130,7 @@ func (s *IpfsDHT) FindProviders(key u.Key, timeout time.Duration) ([]*peer.Peer,
130
return nil, u.ErrTimeout
131
case resp := <-listen_chan:
132
u.DOut("FindProviders: got response.")
134
- pmes_out := new(DHTMessage)
133
+ pmes_out := new(PBDHTMessage)
134
err := proto.Unmarshal(resp.Data, pmes_out)
135
if err != nil {
136
return nil, err
@@ -143,10 +142,10 @@ func (s *IpfsDHT) FindProviders(key u.Key, timeout time.Duration) ([]*peer.Peer,
142
}
143
144
var prov_arr []*peer.Peer
146
- for pid,addr := range addrs {
145
+ for pid, addr := range addrs {
146
p := s.network.Find(pid)
147
if p == nil {
149
- maddr,err := ma.NewMultiaddr(addr)
148
+ maddr, err := ma.NewMultiaddr(addr)
149
if err != nil {
150
u.PErr("error connecting to new peer: %s", err)
151
continue
@@ -171,23 +170,23 @@ func (s *IpfsDHT) FindProviders(key u.Key, timeout time.Duration) ([]*peer.Peer,
170
func (s *IpfsDHT) FindPeer(id peer.ID, timeout time.Duration) (*peer.Peer, error) {
171
p := s.routes[0].NearestPeer(convertPeerID(id))
172
174
- pmes := pDHTMessage{
175
- Type: DHTMessage_FIND_NODE,
176
- Key: string(id),
177
- Id: GenerateMessageID(),
173
+ pmes := DHTMessage{
174
+ Type: PBDHTMessage_FIND_NODE,
175
+ Key: string(id),
176
+ Id: GenerateMessageID(),
177
}
178
179
mes := swarm.NewMessage(p, pmes.ToProtobuf())
180
181
listen_chan := s.ListenFor(pmes.Id, 1, time.Minute)
183
- s.network.Chan.Outgoing <-mes
182
+ s.network.Chan.Outgoing <- mes
183
after := time.After(timeout)
184
select {
185
case <-after:
186
s.Unlisten(pmes.Id)
187
return nil, u.ErrTimeout
188
case resp := <-listen_chan:
190
- pmes_out := new(DHTMessage)
189
+ pmes_out := new(PBDHTMessage)
190
err := proto.Unmarshal(resp.Data, pmes_out)
191
if err != nil {
192
return nil, err
@@ -218,7 +217,7 @@ func (dht *IpfsDHT) Ping(p *peer.Peer, timeout time.Duration) error {
217
// Thoughts: maybe this should accept an ID and do a peer lookup?
218
u.DOut("Enter Ping.")
219
221
- pmes := pDHTMessage{Id: GenerateMessageID(), Type: DHTMessage_PING}
220
+ pmes := DHTMessage{Id: GenerateMessageID(), Type: PBDHTMessage_PING}
221
mes := swarm.NewMessage(p, pmes.ToProtobuf())
222
223
before := time.Now()
@@ -229,7 +228,7 @@ func (dht *IpfsDHT) Ping(p *peer.Peer, timeout time.Duration) error {
228
select {
229
case <-response_chan:
230
roundtrip := time.Since(before)
232
- p.SetDistance(roundtrip)
231
+ p.SetLatency(roundtrip)
232
u.POut("Ping took %s.", roundtrip.String())
233
return nil
234
case <-tout:
@@ -246,17 +245,17 @@ func (dht *IpfsDHT) GetDiagnostic(timeout time.Duration) ([]*diagInfo, error) {
245
targets := dht.routes[0].NearestPeers(convertPeerID(dht.self.ID), 10)
246
247
// TODO: Add timeout to this struct so nodes know when to return
249
- pmes := pDHTMessage{
250
- Type: DHTMessage_DIAGNOSTIC,
251
- Id: GenerateMessageID(),
248
+ pmes := DHTMessage{
249
+ Type: PBDHTMessage_DIAGNOSTIC,
250
+ Id: GenerateMessageID(),
251
}
252
254
- listen_chan := dht.ListenFor(pmes.Id, len(targets), time.Minute * 2)
253
+ listen_chan := dht.ListenFor(pmes.Id, len(targets), time.Minute*2)
254
255
pbmes := pmes.ToProtobuf()
257
- for _,p := range targets {
256
+ for _, p := range targets {
257
mes := swarm.NewMessage(p, pbmes)
259
- dht.network.Chan.Outgoing <-mes
258
+ dht.network.Chan.Outgoing <- mes
259
}
260
261
var out []*diagInfo
@@ -267,7 +266,7 @@ func (dht *IpfsDHT) GetDiagnostic(timeout time.Duration) ([]*diagInfo, error) {
266
u.DOut("Diagnostic request timed out.")
267
return out, u.ErrTimeout
268
case resp := <-listen_chan:
270
- pmes_out := new(DHTMessage)
269
+ pmes_out := new(PBDHTMessage)
270
err := proto.Unmarshal(resp.Data, pmes_out)
271
if err != nil {
272
// NOTE: here and elsewhere, need to audit error handling,
@@ -288,5 +287,5 @@ func (dht *IpfsDHT) GetDiagnostic(timeout time.Duration) ([]*diagInfo, error) {
287
}
288
}
289
291
- return nil,nil
290
+ return nil, nil
291
}
routing/dht/table.go
+1
-1
@@ -125,7 +125,7 @@ func (rt *RoutingTable) NearestPeer(id ID) *peer.Peer {
125
func (rt *RoutingTable) NearestPeers(id ID, count int) []*peer.Peer {
126
rt.tabLock.RLock()
127
defer rt.tabLock.RUnlock()
128
- cpl := xor(id, rt.local).commonPrefixLen()
128
+ cpl := prefLen(id, rt.local)
129
130
// Get bucket at cpl index or last bucket
131
var bucket *Bucket
routing/dht/util.go
+4
@@ -40,6 +40,10 @@ func (id ID) commonPrefixLen() int {
40
return len(id)*8 - 1
41
}
42
43
+func prefLen(a, b ID) int {
44
+ return xor(a, b).commonPrefixLen()
45
+}
46
+
47
func xor(a, b ID) ID {
48
a, b = equalizeSizes(a, b)
49
swarm/swarm.go
+63
-11
@@ -1,15 +1,16 @@
1
package swarm
2
3
import (
4
+ "errors"
5
"fmt"
6
"net"
7
"sync"
8
9
+ proto "code.google.com/p/goprotobuf/proto"
10
+ ident "github.com/jbenet/go-ipfs/identify"
11
peer "github.com/jbenet/go-ipfs/peer"
12
u "github.com/jbenet/go-ipfs/util"
13
ma "github.com/jbenet/go-multiaddr"
11
- ident "github.com/jbenet/go-ipfs/identify"
12
- proto "code.google.com/p/goprotobuf/proto"
14
)
15
16
// Message represents a packet of information sent to or received from a
@@ -24,9 +25,10 @@ type Message struct {
25
26
// Cleaner looking helper function to make a new message struct
27
func NewMessage(p *peer.Peer, data proto.Message) *Message {
27
- bytes,err := proto.Marshal(data)
28
+ bytes, err := proto.Marshal(data)
29
if err != nil {
29
- panic(err)
30
+ u.PErr(err.Error())
31
+ return nil
32
}
33
return &Message{
34
Peer: p,
@@ -63,7 +65,7 @@ func (se *SwarmListenErr) Error() string {
65
return "<nil error>"
66
}
67
var out string
66
- for i,v := range se.Errors {
68
+ for i, v := range se.Errors {
69
if v != nil {
70
out += fmt.Sprintf("%d: %s\n", i, v)
71
}
@@ -80,7 +82,7 @@ type Swarm struct {
82
conns ConnMap
83
connsLock sync.RWMutex
84
83
- local *peer.Peer
85
+ local *peer.Peer
86
listeners []net.Listener
87
}
88
@@ -137,7 +139,7 @@ func (s *Swarm) connListen(maddr *ma.Multiaddr) error {
139
if err != nil {
140
e := fmt.Errorf("Failed to accept connection: %s - %s [%s]",
141
netstr, addr, err)
140
- go func() {s.Chan.Errors <- e}()
142
+ go func() { s.Chan.Errors <- e }()
143
return
144
}
145
go s.handleNewConn(nconn)
@@ -160,7 +162,9 @@ func (s *Swarm) handleNewConn(nconn net.Conn) {
162
163
err := ident.Handshake(s.local, p, conn.Incoming.MsgChan, conn.Outgoing.MsgChan)
164
if err != nil {
163
- panic(err)
165
+ u.PErr(err.Error())
166
+ conn.Close()
167
+ return
168
}
169
170
// Get address to contact remote peer from
@@ -186,7 +190,7 @@ func (s *Swarm) Close() {
190
s.Chan.Close <- true // fan out
191
s.Chan.Close <- true // listener
192
189
- for _,list := range s.listeners {
193
+ for _, list := range s.listeners {
194
list.Close()
195
}
196
}
@@ -220,9 +224,9 @@ func (s *Swarm) Dial(peer *peer.Peer) (*Conn, error) {
224
return conn, nil
225
}
226
223
-func (s *Swarm) StartConn(conn *Conn) {
227
+func (s *Swarm) StartConn(conn *Conn) error {
228
if conn == nil {
225
- panic("tried to start nil Conn!")
229
+ return errors.New("Tried to start nil connection.")
230
}
231
232
u.DOut("Starting connection: %s", conn.Peer.Key().Pretty())
@@ -233,6 +237,7 @@ func (s *Swarm) StartConn(conn *Conn) {
237
238
// kick off reader goroutine
239
go s.fanIn(conn)
240
+ return nil
241
}
242
243
// Handles the unwrapping + sending of messages to the right connection.
@@ -303,3 +308,50 @@ func (s *Swarm) Find(key u.Key) *peer.Peer {
308
}
309
return conn.Peer
310
}
311
+
312
+func (s *Swarm) Connect(addr *ma.Multiaddr) (*peer.Peer, error) {
313
+ if addr == nil {
314
+ return nil, errors.New("nil Multiaddr passed to swarm.Connect()")
315
+ }
316
+ npeer := new(peer.Peer)
317
+ npeer.AddAddress(addr)
318
+
319
+ conn, err := Dial("tcp", npeer)
320
+ if err != nil {
321
+ return nil, err
322
+ }
323
+
324
+ err = ident.Handshake(s.local, npeer, conn.Incoming.MsgChan, conn.Outgoing.MsgChan)
325
+ if err != nil {
326
+ return nil, err
327
+ }
328
+
329
+ // Send node an address that you can be reached on
330
+ myaddr := s.local.NetAddress("tcp")
331
+ mastr, err := myaddr.String()
332
+ if err != nil {
333
+ return nil, errors.New("No local address to send to peer.")
334
+ }
335
+
336
+ conn.Outgoing.MsgChan <- []byte(mastr)
337
+
338
+ s.StartConn(conn)
339
+
340
+ return npeer, nil
341
+}
342
+
343
+// Removes a given peer from the swarm and closes connections to it
344
+func (s *Swarm) Drop(p *peer.Peer) error {
345
+ s.connsLock.RLock()
346
+ conn, found := s.conns[u.Key(p.ID)]
347
+ s.connsLock.RUnlock()
348
+ if !found {
349
+ return u.ErrNotFound
350
+ }
351
+
352
+ s.connsLock.Lock()
353
+ delete(s.conns, u.Key(p.ID))
354
+ s.connsLock.Unlock()
355
+
356
+ return conn.Close()
357
+}
util/util.go
+10
-6
@@ -1,13 +1,14 @@
1
package util
2
3
import (
4
- "fmt"
4
"errors"
6
- mh "github.com/jbenet/go-multihash"
5
+ "fmt"
6
"os"
7
"os/user"
8
"strings"
10
- "encoding/hex"
9
+
10
+ b58 "github.com/jbenet/go-base58"
11
+ mh "github.com/jbenet/go-multihash"
12
)
13
14
// Debug is a global flag for debugging.
@@ -23,11 +24,14 @@ var ErrTimeout = errors.New("Error: Call timed out.")
24
// find the expected node, but did find 'a' node.
25
var ErrSearchIncomplete = errors.New("Error: Search Incomplete.")
26
27
+// ErrNotFound is returned when a search fails to find anything
28
+var ErrNotFound = errors.New("Error: Not Found.")
29
+
30
// Key is a string representation of multihash for use with maps.
31
type Key string
32
33
func (k Key) Pretty() string {
30
- return hex.EncodeToString([]byte(k))
34
+ return b58.Encode([]byte(k))
35
}
36
37
// Hash is the global IPFS hash function. uses multihash SHA2_256, 256 bits
@@ -51,12 +55,12 @@ func TildeExpansion(filename string) (string, error) {
55
56
// PErr is a shorthand printing function to output to Stderr.
57
func PErr(format string, a ...interface{}) {
54
- fmt.Fprintf(os.Stderr, format + "\n", a...)
58
+ fmt.Fprintf(os.Stderr, format+"\n", a...)
59
}
60
61
// POut is a shorthand printing function to output to Stdout.
62
func POut(format string, a ...interface{}) {
59
- fmt.Fprintf(os.Stdout, format + "\n", a...)
63
+ fmt.Fprintf(os.Stdout, format+"\n", a...)
64
}
65
66
// DErr is a shorthand debug printing function to output to Stderr.