Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
p2p
go-p2p-kad-dht
Commits
891400d2
Commit
891400d2
authored
Aug 11, 2014
by
Jeromy
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
more tests and add in table filtering by peer latency
parent
653841f2
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
81 additions
and
15 deletions
+81
-15
dht.go
dht.go
+42
-7
ext_test.go
ext_test.go
+36
-3
routing.go
routing.go
+3
-5
No files found.
dht.go
View file @
891400d2
...
...
@@ -74,8 +74,12 @@ func NewDHT(p *peer.Peer, net swarm.Network) *IpfsDHT {
dht
.
listeners
=
make
(
map
[
uint64
]
*
listenInfo
)
dht
.
providers
=
make
(
map
[
u
.
Key
][]
*
providerInfo
)
dht
.
shutdown
=
make
(
chan
struct
{})
dht
.
routes
=
make
([]
*
kb
.
RoutingTable
,
1
)
dht
.
routes
[
0
]
=
kb
.
NewRoutingTable
(
20
,
kb
.
ConvertPeerID
(
p
.
ID
))
dht
.
routes
=
make
([]
*
kb
.
RoutingTable
,
3
)
dht
.
routes
[
0
]
=
kb
.
NewRoutingTable
(
20
,
kb
.
ConvertPeerID
(
p
.
ID
),
time
.
Millisecond
*
30
)
dht
.
routes
[
1
]
=
kb
.
NewRoutingTable
(
20
,
kb
.
ConvertPeerID
(
p
.
ID
),
time
.
Millisecond
*
100
)
dht
.
routes
[
2
]
=
kb
.
NewRoutingTable
(
20
,
kb
.
ConvertPeerID
(
p
.
ID
),
time
.
Hour
)
dht
.
birth
=
time
.
Now
()
return
dht
}
...
...
@@ -253,7 +257,13 @@ func (dht *IpfsDHT) handleGetValue(p *peer.Peer, pmes *PBDHTMessage) {
// No providers?
// Find closest peer on given cluster to desired key and reply with that info
level
:=
pmes
.
GetValue
()[
0
]
// Using value field to specify cluster level
level
:=
0
if
len
(
pmes
.
GetValue
())
<
1
{
// TODO: maybe return an error? Defaulting isnt a good idea IMO
u
.
PErr
(
"handleGetValue: no routing level specified, assuming 0"
)
}
else
{
level
=
int
(
pmes
.
GetValue
()[
0
])
// Using value field to specify cluster level
}
closer
:=
dht
.
routes
[
level
]
.
NearestPeer
(
kb
.
ConvertKey
(
u
.
Key
(
pmes
.
GetKey
())))
...
...
@@ -477,6 +487,7 @@ func (dht *IpfsDHT) getValueSingle(p *peer.Peer, key u.Key, timeout time.Duratio
response_chan
:=
dht
.
ListenFor
(
pmes
.
Id
,
1
,
time
.
Minute
)
mes
:=
swarm
.
NewMessage
(
p
,
pmes
.
ToProtobuf
())
t
:=
time
.
Now
()
dht
.
network
.
Send
(
mes
)
// Wait for either the response or a timeout
...
...
@@ -490,6 +501,8 @@ func (dht *IpfsDHT) getValueSingle(p *peer.Peer, key u.Key, timeout time.Duratio
u
.
PErr
(
"response channel closed before timeout, please investigate."
)
return
nil
,
u
.
ErrTimeout
}
roundtrip
:=
time
.
Since
(
t
)
resp
.
Peer
.
SetLatency
(
roundtrip
)
pmes_out
:=
new
(
PBDHTMessage
)
err
:=
proto
.
Unmarshal
(
resp
.
Data
,
pmes_out
)
if
err
!=
nil
{
...
...
@@ -513,7 +526,8 @@ func (dht *IpfsDHT) getFromPeerList(key u.Key, timeout time.Duration,
u
.
PErr
(
"getValue error: %s"
,
err
)
continue
}
p
,
err
=
dht
.
Connect
(
maddr
)
p
,
err
=
dht
.
network
.
Connect
(
maddr
)
if
err
!=
nil
{
u
.
PErr
(
"getValue error: %s"
,
err
)
continue
...
...
@@ -547,9 +561,21 @@ func (dht *IpfsDHT) PutLocal(key u.Key, value []byte) error {
}
func
(
dht
*
IpfsDHT
)
Update
(
p
*
peer
.
Peer
)
{
removed
:=
dht
.
routes
[
0
]
.
Update
(
p
)
if
removed
!=
nil
{
dht
.
network
.
Drop
(
removed
)
for
_
,
route
:=
range
dht
.
routes
{
removed
:=
route
.
Update
(
p
)
// Only drop the connection if no tables refer to this peer
if
removed
!=
nil
{
found
:=
false
for
_
,
r
:=
range
dht
.
routes
{
if
r
.
Find
(
removed
.
ID
)
!=
nil
{
found
=
true
break
}
}
if
!
found
{
dht
.
network
.
Drop
(
removed
)
}
}
}
}
...
...
@@ -574,6 +600,7 @@ func (dht *IpfsDHT) findPeerSingle(p *peer.Peer, id peer.ID, timeout time.Durati
mes
:=
swarm
.
NewMessage
(
p
,
pmes
.
ToProtobuf
())
listenChan
:=
dht
.
ListenFor
(
pmes
.
Id
,
1
,
time
.
Minute
)
t
:=
time
.
Now
()
dht
.
network
.
Send
(
mes
)
after
:=
time
.
After
(
timeout
)
select
{
...
...
@@ -581,6 +608,8 @@ func (dht *IpfsDHT) findPeerSingle(p *peer.Peer, id peer.ID, timeout time.Durati
dht
.
Unlisten
(
pmes
.
Id
)
return
nil
,
u
.
ErrTimeout
case
resp
:=
<-
listenChan
:
roundtrip
:=
time
.
Since
(
t
)
resp
.
Peer
.
SetLatency
(
roundtrip
)
pmes_out
:=
new
(
PBDHTMessage
)
err
:=
proto
.
Unmarshal
(
resp
.
Data
,
pmes_out
)
if
err
!=
nil
{
...
...
@@ -590,3 +619,9 @@ func (dht *IpfsDHT) findPeerSingle(p *peer.Peer, id peer.ID, timeout time.Durati
return
pmes_out
,
nil
}
}
func
(
dht
*
IpfsDHT
)
PrintTables
()
{
for
_
,
route
:=
range
dht
.
routes
{
route
.
Print
()
}
}
ext_test.go
View file @
891400d2
...
...
@@ -16,13 +16,16 @@ import (
// fauxNet is a standin for a swarm.Network in order to more easily recreate
// different testing scenarios
type
fauxNet
struct
{
Chan
*
swarm
.
Chan
Chan
*
swarm
.
Chan
handlers
[]
mesHandleFunc
swarm
.
Network
handlers
[]
mesHandleFunc
}
// mesHandleFunc is a function that takes in outgoing messages
// and can respond to them, simulating other peers on the network.
// returning nil will chose not to respond and pass the message onto the
// next registered handler
type
mesHandleFunc
func
(
*
swarm
.
Message
)
*
swarm
.
Message
func
newFauxNet
()
*
fauxNet
{
...
...
@@ -32,6 +35,9 @@ func newFauxNet() *fauxNet {
return
fn
}
// Instead of 'Listening' Start up a goroutine that will check
// all outgoing messages against registered message handlers,
// and reply if needed
func
(
f
*
fauxNet
)
Listen
()
error
{
go
func
()
{
for
{
...
...
@@ -95,6 +101,7 @@ func TestGetFailures(t *testing.T) {
t
.
Fatal
(
"Did not get expected error!"
)
}
// Reply with failures to every message
fn
.
AddHandler
(
func
(
mes
*
swarm
.
Message
)
*
swarm
.
Message
{
pmes
:=
new
(
PBDHTMessage
)
err
:=
proto
.
Unmarshal
(
mes
.
Data
,
pmes
)
...
...
@@ -120,4 +127,30 @@ func TestGetFailures(t *testing.T) {
}
else
{
t
.
Fatal
(
"expected error, got none."
)
}
success
:=
make
(
chan
struct
{})
fn
.
handlers
=
nil
fn
.
AddHandler
(
func
(
mes
*
swarm
.
Message
)
*
swarm
.
Message
{
resp
:=
new
(
PBDHTMessage
)
err
:=
proto
.
Unmarshal
(
mes
.
Data
,
resp
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
resp
.
GetSuccess
()
{
t
.
Fatal
(
"Get returned success when it shouldnt have."
)
}
success
<-
struct
{}{}
return
nil
})
// Now we test this DHT's handleGetValue failure
req
:=
DHTMessage
{
Type
:
PBDHTMessage_GET_VALUE
,
Key
:
"hello"
,
Id
:
GenerateMessageID
(),
Value
:
[]
byte
{
0
},
}
fn
.
Chan
.
Incoming
<-
swarm
.
NewMessage
(
other
,
req
.
ToProtobuf
())
<-
success
}
routing.go
View file @
891400d2
...
...
@@ -89,9 +89,7 @@ func (s *IpfsDHT) GetValue(key u.Key, timeout time.Duration) ([]byte, error) {
panic
(
"not yet implemented"
)
}
// TODO: dht.Connect has overhead due to an internal
// ping to the target. Use something else
p
,
err
=
s
.
Connect
(
maddr
)
p
,
err
=
s
.
network
.
Connect
(
maddr
)
if
err
!=
nil
{
// Move up route level
panic
(
"not yet implemented."
)
...
...
@@ -167,7 +165,7 @@ func (s *IpfsDHT) FindProviders(key u.Key, timeout time.Duration) ([]*peer.Peer,
u
.
PErr
(
"error connecting to new peer: %s"
,
err
)
continue
}
p
,
err
=
s
.
Connect
(
maddr
)
p
,
err
=
s
.
network
.
Connect
(
maddr
)
if
err
!=
nil
{
u
.
PErr
(
"error connecting to new peer: %s"
,
err
)
continue
...
...
@@ -204,7 +202,7 @@ func (s *IpfsDHT) FindPeer(id peer.ID, timeout time.Duration) (*peer.Peer, error
return
nil
,
u
.
WrapError
(
err
,
"FindPeer received bad info"
)
}
nxtPeer
,
err
:=
s
.
Connect
(
addr
)
nxtPeer
,
err
:=
s
.
network
.
Connect
(
addr
)
if
err
!=
nil
{
return
nil
,
u
.
WrapError
(
err
,
"FindPeer failed to connect to new peer."
)
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment