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:
Jakob Borg
2014-06-30 01:42:03 +02:00
parent fee8289c0a
commit 8f3effed32
35 changed files with 563 additions and 478 deletions

View File

@@ -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()

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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