Fix dht find value and updates from latest protocol changes #90
5 changed files with 49 additions and 16 deletions
|
@ -17,7 +17,7 @@ const (
|
|||
|
||||
// TODO: all these constants should be defaults, and should be used to set values in the standard Config. then the code should use values in the config
|
||||
// TODO: alternatively, have a global Config for constants. at least that way tests can modify the values
|
||||
alpha = 3 // this is the constant alpha in the spec
|
||||
alpha = 5 // this is the constant alpha in the spec
|
||||
bucketSize = 8 // this is the constant k in the spec
|
||||
nodeIDLength = bits.NumBytes // bytes. this is the constant B in the spec
|
||||
messageIDLength = 20 // bytes.
|
||||
|
|
|
@ -2,6 +2,7 @@ package dht
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
@ -41,6 +42,20 @@ func (c Contact) String() string {
|
|||
return str
|
||||
}
|
||||
|
||||
func (c Contact) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(&struct {
|
||||
ID string
|
||||
IP string
|
||||
Port int
|
||||
PeerPort int
|
||||
}{
|
||||
ID: c.ID.Hex(),
|
||||
IP: c.IP.String(),
|
||||
Port: c.Port,
|
||||
PeerPort: c.PeerPort,
|
||||
})
|
||||
}
|
||||
|
||||
// MarshalCompact returns a compact byteslice representation of the contact
|
||||
// NOTE: The compact representation always uses the tcp PeerPort, not the udp Port. This is dumb, but that's how the python daemon does it
|
||||
func (c Contact) MarshalCompact() ([]byte, error) {
|
||||
|
|
|
@ -40,6 +40,7 @@ const (
|
|||
headerPayloadField = "3"
|
||||
headerArgsField = "4"
|
||||
contactsField = "contacts"
|
||||
pageField = "p"
|
||||
tokenField = "token"
|
||||
protocolVersionField = "protocolVersion"
|
||||
)
|
||||
|
@ -270,6 +271,7 @@ type Response struct {
|
|||
FindValueKey string
|
||||
Token string
|
||||
ProtocolVersion int
|
||||
Page uint8
|
||||
}
|
||||
|
||||
func (r Response) argsDebug() string {
|
||||
|
@ -390,27 +392,34 @@ func (r *Response) UnmarshalBencode(b []byte) error {
|
|||
|
||||
if contacts, ok := rawData[contactsField]; ok {
|
||||
err = bencode.DecodeBytes(contacts, &r.Contacts)
|
||||
delete(rawData, contactsField) // so it doesnt mess up findValue key finding below
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
for k, v := range rawData {
|
||||
r.FindValueKey = k
|
||||
var compactContacts [][]byte
|
||||
err = bencode.DecodeBytes(v, &compactContacts)
|
||||
}
|
||||
if page, ok := rawData[pageField]; ok {
|
||||
err = bencode.DecodeBytes(page, &r.Page)
|
||||
delete(rawData, pageField) // so it doesnt mess up findValue key finding below
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for k, v := range rawData {
|
||||
r.FindValueKey = k
|
||||
var compactContacts [][]byte
|
||||
err = bencode.DecodeBytes(v, &compactContacts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, compact := range compactContacts {
|
||||
var c Contact
|
||||
err = c.UnmarshalCompact(compact)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, compact := range compactContacts {
|
||||
var c Contact
|
||||
err = c.UnmarshalCompact(compact)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Contacts = append(r.Contacts, c)
|
||||
}
|
||||
break
|
||||
r.Contacts = append(r.Contacts, c)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
10
dht/rpc.go
10
dht/rpc.go
|
@ -102,6 +102,7 @@ type RpcIterativeFindValueArgs struct {
|
|||
type RpcIterativeFindValueResult struct {
|
||||
Contacts []Contact
|
||||
FoundValue bool
|
||||
Values []Contact
|
||||
}
|
||||
|
||||
func (rpc *rpcReceiver) IterativeFindValue(r *http.Request, args *RpcIterativeFindValueArgs, result *RpcIterativeFindValueResult) error {
|
||||
|
@ -109,12 +110,19 @@ func (rpc *rpcReceiver) IterativeFindValue(r *http.Request, args *RpcIterativeFi
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
foundContacts, found, err := FindContacts(rpc.dht.node, key, false, nil)
|
||||
foundContacts, found, err := FindContacts(rpc.dht.node, key, true, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result.Contacts = foundContacts
|
||||
result.FoundValue = found
|
||||
if found {
|
||||
for _, contact := range foundContacts {
|
||||
if contact.PeerPort > 0 {
|
||||
result.Values = append(result.Values, contact)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ func NormalizeName(s string) string {
|
|||
c := cases.Fold()
|
||||
return c.String(norm.NFD.String(s))
|
||||
}
|
||||
|
||||
// ReverseBytesInPlace reverse the bytes. thanks, Satoshi 😒
|
||||
func ReverseBytesInPlace(s []byte) {
|
||||
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
|
||||
|
|
Loading…
Reference in a new issue