@cryptotaxi247 / kubo / commits / ae6285e5a

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.