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: 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
|
// 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
|
bucketSize = 8 // this is the constant k in the spec
|
||||||
nodeIDLength = bits.NumBytes // bytes. this is the constant B in the spec
|
nodeIDLength = bits.NumBytes // bytes. this is the constant B in the spec
|
||||||
messageIDLength = 20 // bytes.
|
messageIDLength = 20 // bytes.
|
||||||
|
|
|
@ -2,6 +2,7 @@ package dht
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -41,6 +42,20 @@ func (c Contact) String() string {
|
||||||
return str
|
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
|
// 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
|
// 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) {
|
func (c Contact) MarshalCompact() ([]byte, error) {
|
||||||
|
|
|
@ -40,6 +40,7 @@ const (
|
||||||
headerPayloadField = "3"
|
headerPayloadField = "3"
|
||||||
headerArgsField = "4"
|
headerArgsField = "4"
|
||||||
contactsField = "contacts"
|
contactsField = "contacts"
|
||||||
|
pageField = "p"
|
||||||
tokenField = "token"
|
tokenField = "token"
|
||||||
protocolVersionField = "protocolVersion"
|
protocolVersionField = "protocolVersion"
|
||||||
)
|
)
|
||||||
|
@ -270,6 +271,7 @@ type Response struct {
|
||||||
FindValueKey string
|
FindValueKey string
|
||||||
Token string
|
Token string
|
||||||
ProtocolVersion int
|
ProtocolVersion int
|
||||||
|
Page uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Response) argsDebug() string {
|
func (r Response) argsDebug() string {
|
||||||
|
@ -390,27 +392,34 @@ func (r *Response) UnmarshalBencode(b []byte) error {
|
||||||
|
|
||||||
if contacts, ok := rawData[contactsField]; ok {
|
if contacts, ok := rawData[contactsField]; ok {
|
||||||
err = bencode.DecodeBytes(contacts, &r.Contacts)
|
err = bencode.DecodeBytes(contacts, &r.Contacts)
|
||||||
|
delete(rawData, contactsField) // so it doesnt mess up findValue key finding below
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
for k, v := range rawData {
|
if page, ok := rawData[pageField]; ok {
|
||||||
r.FindValueKey = k
|
err = bencode.DecodeBytes(page, &r.Page)
|
||||||
var compactContacts [][]byte
|
delete(rawData, pageField) // so it doesnt mess up findValue key finding below
|
||||||
err = bencode.DecodeBytes(v, &compactContacts)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, compact := range compactContacts {
|
r.Contacts = append(r.Contacts, c)
|
||||||
var c Contact
|
|
||||||
err = c.UnmarshalCompact(compact)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r.Contacts = append(r.Contacts, c)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
10
dht/rpc.go
10
dht/rpc.go
|
@ -102,6 +102,7 @@ type RpcIterativeFindValueArgs struct {
|
||||||
type RpcIterativeFindValueResult struct {
|
type RpcIterativeFindValueResult struct {
|
||||||
Contacts []Contact
|
Contacts []Contact
|
||||||
FoundValue bool
|
FoundValue bool
|
||||||
|
Values []Contact
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rpc *rpcReceiver) IterativeFindValue(r *http.Request, args *RpcIterativeFindValueArgs, result *RpcIterativeFindValueResult) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
result.Contacts = foundContacts
|
result.Contacts = foundContacts
|
||||||
result.FoundValue = found
|
result.FoundValue = found
|
||||||
|
if found {
|
||||||
|
for _, contact := range foundContacts {
|
||||||
|
if contact.PeerPort > 0 {
|
||||||
|
result.Values = append(result.Values, contact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ func NormalizeName(s string) string {
|
||||||
c := cases.Fold()
|
c := cases.Fold()
|
||||||
return c.String(norm.NFD.String(s))
|
return c.String(norm.NFD.String(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReverseBytesInPlace reverse the bytes. thanks, Satoshi 😒
|
// ReverseBytesInPlace reverse the bytes. thanks, Satoshi 😒
|
||||||
func ReverseBytesInPlace(s []byte) {
|
func ReverseBytesInPlace(s []byte) {
|
||||||
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
|
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
|
||||||
|
|
Loading…
Reference in a new issue