Refactor node ID handling, use check digits (fixes #269)
New node ID:s contain four Luhn check digits and are grouped differently. Code uses NodeID type instead of string, so it's formatted homogenously everywhere.
This commit is contained in:
@@ -17,6 +17,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/calmh/syncthing/discover"
|
||||
"github.com/calmh/syncthing/protocol"
|
||||
"github.com/golang/groupcache/lru"
|
||||
"github.com/juju/ratelimit"
|
||||
)
|
||||
@@ -32,7 +33,7 @@ type address struct {
|
||||
}
|
||||
|
||||
var (
|
||||
nodes = make(map[string]node)
|
||||
nodes = make(map[protocol.NodeID]node)
|
||||
lock sync.Mutex
|
||||
queries = 0
|
||||
announces = 0
|
||||
@@ -182,8 +183,16 @@ func handleAnnounceV2(addr *net.UDPAddr, buf []byte) {
|
||||
updated: time.Now(),
|
||||
}
|
||||
|
||||
var id protocol.NodeID
|
||||
if len(pkt.This.ID) == 32 {
|
||||
// Raw node ID
|
||||
copy(id[:], pkt.This.ID)
|
||||
} else {
|
||||
id.UnmarshalText(pkt.This.ID)
|
||||
}
|
||||
|
||||
lock.Lock()
|
||||
nodes[pkt.This.ID] = node
|
||||
nodes[id] = node
|
||||
lock.Unlock()
|
||||
}
|
||||
|
||||
@@ -199,8 +208,16 @@ func handleQueryV2(conn *net.UDPConn, addr *net.UDPAddr, buf []byte) {
|
||||
log.Printf("<- %v %#v", addr, pkt)
|
||||
}
|
||||
|
||||
var id protocol.NodeID
|
||||
if len(pkt.NodeID) == 32 {
|
||||
// Raw node ID
|
||||
copy(id[:], pkt.NodeID)
|
||||
} else {
|
||||
id.UnmarshalText(pkt.NodeID)
|
||||
}
|
||||
|
||||
lock.Lock()
|
||||
node, ok := nodes[pkt.NodeID]
|
||||
node, ok := nodes[id]
|
||||
queries++
|
||||
lock.Unlock()
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package discover
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -14,15 +15,16 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/calmh/syncthing/beacon"
|
||||
"github.com/calmh/syncthing/protocol"
|
||||
)
|
||||
|
||||
type Discoverer struct {
|
||||
myID string
|
||||
myID protocol.NodeID
|
||||
listenAddrs []string
|
||||
localBcastIntv time.Duration
|
||||
globalBcastIntv time.Duration
|
||||
beacon *beacon.Beacon
|
||||
registry map[string][]string
|
||||
registry map[protocol.NodeID][]string
|
||||
registryLock sync.RWMutex
|
||||
extServer string
|
||||
extPort uint16
|
||||
@@ -41,7 +43,7 @@ var (
|
||||
// When we hit this many errors in succession, we stop.
|
||||
const maxErrors = 30
|
||||
|
||||
func NewDiscoverer(id string, addresses []string, localPort int) (*Discoverer, error) {
|
||||
func NewDiscoverer(id protocol.NodeID, addresses []string, localPort int) (*Discoverer, error) {
|
||||
b, err := beacon.New(localPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -52,7 +54,7 @@ func NewDiscoverer(id string, addresses []string, localPort int) (*Discoverer, e
|
||||
localBcastIntv: 30 * time.Second,
|
||||
globalBcastIntv: 1800 * time.Second,
|
||||
beacon: b,
|
||||
registry: make(map[string][]string),
|
||||
registry: make(map[protocol.NodeID][]string),
|
||||
}
|
||||
|
||||
go disc.recvAnnouncements()
|
||||
@@ -78,7 +80,7 @@ func (d *Discoverer) ExtAnnounceOK() bool {
|
||||
return d.extAnnounceOK
|
||||
}
|
||||
|
||||
func (d *Discoverer) Lookup(node string) []string {
|
||||
func (d *Discoverer) Lookup(node protocol.NodeID) []string {
|
||||
d.registryLock.Lock()
|
||||
addr, ok := d.registry[node]
|
||||
d.registryLock.Unlock()
|
||||
@@ -94,15 +96,17 @@ func (d *Discoverer) Lookup(node string) []string {
|
||||
|
||||
func (d *Discoverer) Hint(node string, addrs []string) {
|
||||
resAddrs := resolveAddrs(addrs)
|
||||
var id protocol.NodeID
|
||||
id.UnmarshalText([]byte(node))
|
||||
d.registerNode(nil, Node{
|
||||
ID: node,
|
||||
Addresses: resAddrs,
|
||||
ID: id[:],
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Discoverer) All() map[string][]string {
|
||||
func (d *Discoverer) All() map[protocol.NodeID][]string {
|
||||
d.registryLock.RLock()
|
||||
nodes := make(map[string][]string, len(d.registry))
|
||||
nodes := make(map[protocol.NodeID][]string, len(d.registry))
|
||||
for node, addrs := range d.registry {
|
||||
addrsCopy := make([]string, len(addrs))
|
||||
copy(addrsCopy, addrs)
|
||||
@@ -132,7 +136,7 @@ func (d *Discoverer) announcementPkt() []byte {
|
||||
}
|
||||
var pkt = AnnounceV2{
|
||||
Magic: AnnouncementMagicV2,
|
||||
This: Node{d.myID, addrs},
|
||||
This: Node{d.myID[:], addrs},
|
||||
}
|
||||
return pkt.MarshalXDR()
|
||||
}
|
||||
@@ -142,7 +146,7 @@ func (d *Discoverer) sendLocalAnnouncements() {
|
||||
|
||||
var pkt = AnnounceV2{
|
||||
Magic: AnnouncementMagicV2,
|
||||
This: Node{d.myID, addrs},
|
||||
This: Node{d.myID[:], addrs},
|
||||
}
|
||||
|
||||
for {
|
||||
@@ -153,7 +157,7 @@ func (d *Discoverer) sendLocalAnnouncements() {
|
||||
break
|
||||
}
|
||||
|
||||
anode := Node{node, resolveAddrs(addrs)}
|
||||
anode := Node{node[:], resolveAddrs(addrs)}
|
||||
pkt.Extra = append(pkt.Extra, anode)
|
||||
}
|
||||
d.registryLock.RUnlock()
|
||||
@@ -184,7 +188,7 @@ func (d *Discoverer) sendExternalAnnouncements() {
|
||||
if d.extPort != 0 {
|
||||
var pkt = AnnounceV2{
|
||||
Magic: AnnouncementMagicV2,
|
||||
This: Node{d.myID, []Address{{Port: d.extPort}}},
|
||||
This: Node{d.myID[:], []Address{{Port: d.extPort}}},
|
||||
}
|
||||
buf = pkt.MarshalXDR()
|
||||
} else {
|
||||
@@ -246,11 +250,11 @@ func (d *Discoverer) recvAnnouncements() {
|
||||
}
|
||||
|
||||
var newNode bool
|
||||
if pkt.This.ID != d.myID {
|
||||
if bytes.Compare(pkt.This.ID, d.myID[:]) != 0 {
|
||||
n := d.registerNode(addr, pkt.This)
|
||||
newNode = newNode || n
|
||||
for _, node := range pkt.Extra {
|
||||
if node.ID != d.myID {
|
||||
if bytes.Compare(node.ID, d.myID[:]) != 0 {
|
||||
n := d.registerNode(nil, node)
|
||||
newNode = newNode || n
|
||||
}
|
||||
@@ -287,14 +291,16 @@ func (d *Discoverer) registerNode(addr net.Addr, node Node) bool {
|
||||
if debug {
|
||||
l.Debugf("discover: register: %s -> %#v", node.ID, addrs)
|
||||
}
|
||||
var id protocol.NodeID
|
||||
copy(id[:], node.ID)
|
||||
d.registryLock.Lock()
|
||||
_, seen := d.registry[node.ID]
|
||||
d.registry[node.ID] = addrs
|
||||
_, seen := d.registry[id]
|
||||
d.registry[id] = addrs
|
||||
d.registryLock.Unlock()
|
||||
return !seen
|
||||
}
|
||||
|
||||
func (d *Discoverer) externalLookup(node string) []string {
|
||||
func (d *Discoverer) externalLookup(node protocol.NodeID) []string {
|
||||
extIP, err := net.ResolveUDPAddr("udp", d.extServer)
|
||||
if err != nil {
|
||||
if debug {
|
||||
@@ -320,7 +326,7 @@ func (d *Discoverer) externalLookup(node string) []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
buf := QueryV2{QueryMagicV2, node}.MarshalXDR()
|
||||
buf := QueryV2{QueryMagicV2, node[:]}.MarshalXDR()
|
||||
_, err = conn.Write(buf)
|
||||
if err != nil {
|
||||
if debug {
|
||||
|
||||
@@ -11,7 +11,7 @@ const (
|
||||
|
||||
type QueryV2 struct {
|
||||
Magic uint32
|
||||
NodeID string // max:64
|
||||
NodeID []byte // max:32
|
||||
}
|
||||
|
||||
type AnnounceV2 struct {
|
||||
@@ -21,7 +21,7 @@ type AnnounceV2 struct {
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
ID string // max:64
|
||||
ID []byte // max:32
|
||||
Addresses []Address // max:16
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
// Copyright (C) 2014 Jakob Borg and other contributors. All rights reserved.
|
||||
// Use of this source code is governed by an MIT-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package discover
|
||||
|
||||
import (
|
||||
@@ -25,10 +21,10 @@ func (o QueryV2) MarshalXDR() []byte {
|
||||
|
||||
func (o QueryV2) encodeXDR(xw *xdr.Writer) (int, error) {
|
||||
xw.WriteUint32(o.Magic)
|
||||
if len(o.NodeID) > 64 {
|
||||
if len(o.NodeID) > 32 {
|
||||
return xw.Tot(), xdr.ErrElementSizeExceeded
|
||||
}
|
||||
xw.WriteString(o.NodeID)
|
||||
xw.WriteBytes(o.NodeID)
|
||||
return xw.Tot(), xw.Error()
|
||||
}
|
||||
|
||||
@@ -45,7 +41,7 @@ func (o *QueryV2) UnmarshalXDR(bs []byte) error {
|
||||
|
||||
func (o *QueryV2) decodeXDR(xr *xdr.Reader) error {
|
||||
o.Magic = xr.ReadUint32()
|
||||
o.NodeID = xr.ReadStringMax(64)
|
||||
o.NodeID = xr.ReadBytesMax(32)
|
||||
return xr.Error()
|
||||
}
|
||||
|
||||
@@ -112,10 +108,10 @@ func (o Node) MarshalXDR() []byte {
|
||||
}
|
||||
|
||||
func (o Node) encodeXDR(xw *xdr.Writer) (int, error) {
|
||||
if len(o.ID) > 64 {
|
||||
if len(o.ID) > 32 {
|
||||
return xw.Tot(), xdr.ErrElementSizeExceeded
|
||||
}
|
||||
xw.WriteString(o.ID)
|
||||
xw.WriteBytes(o.ID)
|
||||
if len(o.Addresses) > 16 {
|
||||
return xw.Tot(), xdr.ErrElementSizeExceeded
|
||||
}
|
||||
@@ -138,7 +134,7 @@ func (o *Node) UnmarshalXDR(bs []byte) error {
|
||||
}
|
||||
|
||||
func (o *Node) decodeXDR(xr *xdr.Reader) error {
|
||||
o.ID = xr.ReadStringMax(64)
|
||||
o.ID = xr.ReadBytesMax(32)
|
||||
_AddressesSize := int(xr.ReadUint32())
|
||||
if _AddressesSize > 16 {
|
||||
return xdr.ErrElementSizeExceeded
|
||||
|
||||
Reference in New Issue
Block a user