mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2024-12-24 16:57:53 +00:00
Merge pull request #103 from Arceliar/switchMsg
Use new switchMsg format
This commit is contained in:
commit
dde7653bf4
@ -160,17 +160,13 @@ func testPaths(store map[[32]byte]*Node) bool {
|
|||||||
ttl := ^uint64(0)
|
ttl := ^uint64(0)
|
||||||
oldTTL := ttl
|
oldTTL := ttl
|
||||||
for here := source; here != dest; {
|
for here := source; here != dest; {
|
||||||
if ttl == 0 {
|
|
||||||
fmt.Println("Drop:", source.index, here.index, dest.index, oldTTL)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
temp++
|
temp++
|
||||||
if temp > 4096 {
|
if temp > 4096 {
|
||||||
panic("Loop?")
|
fmt.Println("Loop?")
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
oldTTL = ttl
|
nextPort := here.core.DEBUG_switchLookup(coords)
|
||||||
nextPort, newTTL := here.core.DEBUG_switchLookup(coords, ttl)
|
|
||||||
ttl = newTTL
|
|
||||||
// First check if "here" is accepting packets from the previous node
|
// First check if "here" is accepting packets from the previous node
|
||||||
// TODO explain how this works
|
// TODO explain how this works
|
||||||
ports := here.core.DEBUG_getPeers().DEBUG_getPorts()
|
ports := here.core.DEBUG_getPeers().DEBUG_getPorts()
|
||||||
@ -201,12 +197,16 @@ func testPaths(store map[[32]byte]*Node) bool {
|
|||||||
source.index, source.core.DEBUG_getLocator(),
|
source.index, source.core.DEBUG_getLocator(),
|
||||||
here.index, here.core.DEBUG_getLocator(),
|
here.index, here.core.DEBUG_getLocator(),
|
||||||
dest.index, dest.core.DEBUG_getLocator())
|
dest.index, dest.core.DEBUG_getLocator())
|
||||||
here.core.DEBUG_getSwitchTable().DEBUG_dumpTable()
|
//here.core.DEBUG_getSwitchTable().DEBUG_dumpTable()
|
||||||
}
|
}
|
||||||
if here != source {
|
if here != source {
|
||||||
// This is sufficient to check for routing loops or blackholes
|
// This is sufficient to check for routing loops or blackholes
|
||||||
//break
|
//break
|
||||||
}
|
}
|
||||||
|
if here == next {
|
||||||
|
fmt.Println("Drop:", source.index, here.index, dest.index, oldTTL)
|
||||||
|
return false
|
||||||
|
}
|
||||||
here = next
|
here = next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -227,7 +227,7 @@ func stressTest(store map[[32]byte]*Node) {
|
|||||||
start := time.Now()
|
start := time.Now()
|
||||||
for _, source := range store {
|
for _, source := range store {
|
||||||
for _, coords := range dests {
|
for _, coords := range dests {
|
||||||
source.core.DEBUG_switchLookup(coords, ^uint64(0))
|
source.core.DEBUG_switchLookup(coords)
|
||||||
lookups++
|
lookups++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,11 +103,6 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.switchTable.start(); err != nil {
|
|
||||||
c.log.Println("Failed to start switch table ticker")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.admin.start(); err != nil {
|
if err := c.admin.start(); err != nil {
|
||||||
c.log.Println("Failed to start admin socket")
|
c.log.Println("Failed to start admin socket")
|
||||||
return err
|
return err
|
||||||
|
@ -36,7 +36,6 @@ func (c *Core) Init() {
|
|||||||
spub, spriv := newSigKeys()
|
spub, spriv := newSigKeys()
|
||||||
c.init(bpub, bpriv, spub, spriv)
|
c.init(bpub, bpriv, spub, spriv)
|
||||||
c.router.start()
|
c.router.start()
|
||||||
c.switchTable.start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -127,8 +126,8 @@ func (l *switchLocator) DEBUG_getCoords() []byte {
|
|||||||
return l.getCoords()
|
return l.getCoords()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Core) DEBUG_switchLookup(dest []byte, ttl uint64) (switchPort, uint64) {
|
func (c *Core) DEBUG_switchLookup(dest []byte) switchPort {
|
||||||
return c.switchTable.lookup(dest, ttl)
|
return c.switchTable.lookup(dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -310,9 +309,6 @@ func (c *Core) DEBUG_init(bpub []byte,
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.switchTable.start(); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -453,16 +449,25 @@ func (c *Core) DEBUG_addAllowedEncryptionPublicKey(boxStr string) {
|
|||||||
|
|
||||||
func DEBUG_simLinkPeers(p, q *peer) {
|
func DEBUG_simLinkPeers(p, q *peer) {
|
||||||
// Sets q.out() to point to p and starts p.linkLoop()
|
// Sets q.out() to point to p and starts p.linkLoop()
|
||||||
plinkIn := make(chan []byte, 1)
|
p.linkOut, q.linkOut = make(chan []byte, 1), make(chan []byte, 1)
|
||||||
qlinkIn := make(chan []byte, 1)
|
go func() {
|
||||||
|
for bs := range p.linkOut {
|
||||||
|
q.handlePacket(bs)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
for bs := range q.linkOut {
|
||||||
|
p.handlePacket(bs)
|
||||||
|
}
|
||||||
|
}()
|
||||||
p.out = func(bs []byte) {
|
p.out = func(bs []byte) {
|
||||||
go q.handlePacket(bs, qlinkIn)
|
go q.handlePacket(bs)
|
||||||
}
|
}
|
||||||
q.out = func(bs []byte) {
|
q.out = func(bs []byte) {
|
||||||
go p.handlePacket(bs, plinkIn)
|
go p.handlePacket(bs)
|
||||||
}
|
}
|
||||||
go p.linkLoop(plinkIn)
|
go p.linkLoop()
|
||||||
go q.linkLoop(qlinkIn)
|
go q.linkLoop()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Core) DEBUG_simFixMTU() {
|
func (c *Core) DEBUG_simFixMTU() {
|
||||||
|
@ -36,6 +36,7 @@ type dhtInfo struct {
|
|||||||
send time.Time // When we last sent a message
|
send time.Time // When we last sent a message
|
||||||
recv time.Time // When we last received a message
|
recv time.Time // When we last received a message
|
||||||
pings int // Decide when to drop
|
pings int // Decide when to drop
|
||||||
|
throttle uint8 // Number of seconds to wait before pinging a node to bootstrap buckets, gradually increases up to 1 minute
|
||||||
}
|
}
|
||||||
|
|
||||||
func (info *dhtInfo) getNodeID() *NodeID {
|
func (info *dhtInfo) getNodeID() *NodeID {
|
||||||
@ -81,7 +82,7 @@ type dht struct {
|
|||||||
func (t *dht) init(c *Core) {
|
func (t *dht) init(c *Core) {
|
||||||
t.core = c
|
t.core = c
|
||||||
t.nodeID = *t.core.GetNodeID()
|
t.nodeID = *t.core.GetNodeID()
|
||||||
t.peers = make(chan *dhtInfo, 1)
|
t.peers = make(chan *dhtInfo, 1024)
|
||||||
t.reqs = make(map[boxPubKey]map[NodeID]time.Time)
|
t.reqs = make(map[boxPubKey]map[NodeID]time.Time)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,10 +117,11 @@ func (t *dht) handleRes(res *dhtRes) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
rinfo := dhtInfo{
|
rinfo := dhtInfo{
|
||||||
key: res.Key,
|
key: res.Key,
|
||||||
coords: res.Coords,
|
coords: res.Coords,
|
||||||
send: time.Now(), // Technically wrong but should be OK...
|
send: time.Now(), // Technically wrong but should be OK...
|
||||||
recv: time.Now(),
|
recv: time.Now(),
|
||||||
|
throttle: 1,
|
||||||
}
|
}
|
||||||
// If they're already in the table, then keep the correct send time
|
// If they're already in the table, then keep the correct send time
|
||||||
bidx, isOK := t.getBucketIndex(rinfo.getNodeID())
|
bidx, isOK := t.getBucketIndex(rinfo.getNodeID())
|
||||||
@ -130,11 +132,13 @@ func (t *dht) handleRes(res *dhtRes) {
|
|||||||
for _, oldinfo := range b.peers {
|
for _, oldinfo := range b.peers {
|
||||||
if oldinfo.key == rinfo.key {
|
if oldinfo.key == rinfo.key {
|
||||||
rinfo.send = oldinfo.send
|
rinfo.send = oldinfo.send
|
||||||
|
rinfo.throttle += oldinfo.throttle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, oldinfo := range b.other {
|
for _, oldinfo := range b.other {
|
||||||
if oldinfo.key == rinfo.key {
|
if oldinfo.key == rinfo.key {
|
||||||
rinfo.send = oldinfo.send
|
rinfo.send = oldinfo.send
|
||||||
|
rinfo.throttle += oldinfo.throttle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Insert into table
|
// Insert into table
|
||||||
@ -231,6 +235,9 @@ func (t *dht) insert(info *dhtInfo, isPeer bool) {
|
|||||||
// This speeds up bootstrapping
|
// This speeds up bootstrapping
|
||||||
info.recv = info.recv.Add(-time.Hour)
|
info.recv = info.recv.Add(-time.Hour)
|
||||||
}
|
}
|
||||||
|
if isPeer || info.throttle > 60 {
|
||||||
|
info.throttle = 60
|
||||||
|
}
|
||||||
// First drop any existing entry from the bucket
|
// First drop any existing entry from the bucket
|
||||||
b.drop(&info.key)
|
b.drop(&info.key)
|
||||||
// Now add to the *end* of the bucket
|
// Now add to the *end* of the bucket
|
||||||
@ -319,7 +326,6 @@ func (t *dht) sendReq(req *dhtReq, dest *dhtInfo) {
|
|||||||
shared := t.core.sessions.getSharedKey(&t.core.boxPriv, &dest.key)
|
shared := t.core.sessions.getSharedKey(&t.core.boxPriv, &dest.key)
|
||||||
payload, nonce := boxSeal(shared, bs, nil)
|
payload, nonce := boxSeal(shared, bs, nil)
|
||||||
p := wire_protoTrafficPacket{
|
p := wire_protoTrafficPacket{
|
||||||
TTL: ^uint64(0),
|
|
||||||
Coords: dest.coords,
|
Coords: dest.coords,
|
||||||
ToKey: dest.key,
|
ToKey: dest.key,
|
||||||
FromKey: t.core.boxPub,
|
FromKey: t.core.boxPub,
|
||||||
@ -345,7 +351,6 @@ func (t *dht) sendRes(res *dhtRes, req *dhtReq) {
|
|||||||
shared := t.core.sessions.getSharedKey(&t.core.boxPriv, &req.Key)
|
shared := t.core.sessions.getSharedKey(&t.core.boxPriv, &req.Key)
|
||||||
payload, nonce := boxSeal(shared, bs, nil)
|
payload, nonce := boxSeal(shared, bs, nil)
|
||||||
p := wire_protoTrafficPacket{
|
p := wire_protoTrafficPacket{
|
||||||
TTL: ^uint64(0),
|
|
||||||
Coords: req.Coords,
|
Coords: req.Coords,
|
||||||
ToKey: req.Key,
|
ToKey: req.Key,
|
||||||
FromKey: t.core.boxPub,
|
FromKey: t.core.boxPub,
|
||||||
@ -460,7 +465,7 @@ func (t *dht) doMaintenance() {
|
|||||||
}
|
}
|
||||||
target := t.getTarget(t.offset)
|
target := t.getTarget(t.offset)
|
||||||
for _, info := range t.lookup(target, true) {
|
for _, info := range t.lookup(target, true) {
|
||||||
if time.Since(info.recv) > time.Minute {
|
if time.Since(info.recv) > time.Duration(info.throttle)*time.Second {
|
||||||
t.addToMill(info, target)
|
t.addToMill(info, target)
|
||||||
t.offset++
|
t.offset++
|
||||||
break
|
break
|
||||||
@ -520,9 +525,15 @@ func dht_firstCloserThanThird(first *NodeID,
|
|||||||
|
|
||||||
func (t *dht) reset() {
|
func (t *dht) reset() {
|
||||||
// This is mostly so bootstrapping will reset to resend coords into the network
|
// This is mostly so bootstrapping will reset to resend coords into the network
|
||||||
|
t.offset = 0
|
||||||
|
t.rumorMill = nil // reset mill
|
||||||
for _, b := range t.buckets_hidden {
|
for _, b := range t.buckets_hidden {
|
||||||
b.peers = b.peers[:0]
|
b.peers = b.peers[:0]
|
||||||
|
for _, info := range b.other {
|
||||||
|
// Add other nodes to the rumor mill so they'll be pinged soon
|
||||||
|
// This will hopefully tell them our coords and re-learn theirs quickly if they haven't changed
|
||||||
|
t.addToMill(info, info.getNodeID())
|
||||||
|
}
|
||||||
b.other = b.other[:0]
|
b.other = b.other[:0]
|
||||||
}
|
}
|
||||||
t.offset = 0
|
|
||||||
}
|
}
|
||||||
|
@ -11,17 +11,6 @@ package yggdrasil
|
|||||||
// It needs to ignore messages with a lower seq
|
// It needs to ignore messages with a lower seq
|
||||||
// Probably best to start setting seq to a timestamp in that case...
|
// Probably best to start setting seq to a timestamp in that case...
|
||||||
|
|
||||||
// FIXME (!?) if it takes too long to communicate all the msgHops, then things hit a horizon
|
|
||||||
// That could happen with a peer over a high-latency link, with many msgHops
|
|
||||||
// Possible workarounds:
|
|
||||||
// 1. Pre-emptively send all hops when one is requested, or after any change
|
|
||||||
// Maybe requires changing how the throttle works and msgHops are saved
|
|
||||||
// In case some arrive out of order or are dropped
|
|
||||||
// This is relatively easy to implement, but could be wasteful
|
|
||||||
// 2. Save your old locator, sigs, etc, so you can respond to older ancs
|
|
||||||
// And finish requesting an old anc before updating to a new one
|
|
||||||
// But that may lead to other issues if not done carefully...
|
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
import "sync"
|
import "sync"
|
||||||
import "sync/atomic"
|
import "sync/atomic"
|
||||||
@ -83,38 +72,23 @@ func (ps *peers) putPorts(ports map[switchPort]*peer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type peer struct {
|
type peer struct {
|
||||||
// Rolling approximation of bandwidth, in bps, used by switch, updated by packet sends
|
queueSize int64 // used to track local backpressure
|
||||||
// use get/update methods only! (atomic accessors as float64)
|
|
||||||
queueSize int64
|
|
||||||
bytesSent uint64 // To track bandwidth usage for getPeers
|
bytesSent uint64 // To track bandwidth usage for getPeers
|
||||||
bytesRecvd uint64 // To track bandwidth usage for getPeers
|
bytesRecvd uint64 // To track bandwidth usage for getPeers
|
||||||
// BUG: sync/atomic, 32 bit platforms need the above to be the first element
|
// BUG: sync/atomic, 32 bit platforms need the above to be the first element
|
||||||
firstSeen time.Time // To track uptime for getPeers
|
core *Core
|
||||||
|
port switchPort
|
||||||
box boxPubKey
|
box boxPubKey
|
||||||
sig sigPubKey
|
sig sigPubKey
|
||||||
shared boxSharedKey
|
shared boxSharedKey
|
||||||
//in <-chan []byte
|
firstSeen time.Time // To track uptime for getPeers
|
||||||
//out chan<- []byte
|
linkOut (chan []byte) // used for protocol traffic (to bypass queues)
|
||||||
//in func([]byte)
|
doSend (chan struct{}) // tell the linkLoop to send a switchMsg
|
||||||
out func([]byte)
|
dinfo *dhtInfo // used to keep the DHT working
|
||||||
core *Core
|
out func([]byte) // Set up by whatever created the peers struct, used to send packets to other nodes
|
||||||
port switchPort
|
close func() // Called when a peer is removed, to close the underlying connection, or via admin api
|
||||||
msgAnc *msgAnnounce
|
|
||||||
msgHops []*msgHop
|
|
||||||
myMsg *switchMessage
|
|
||||||
mySigs []sigInfo
|
|
||||||
// This is used to limit how often we perform expensive operations
|
|
||||||
// Specifically, processing switch messages, signing, and verifying sigs
|
|
||||||
// Resets at the start of each tick
|
|
||||||
throttle uint8
|
|
||||||
// Called when a peer is removed, to close the underlying connection, or via admin api
|
|
||||||
close func()
|
|
||||||
// To allow the peer to call close if idle for too long
|
|
||||||
lastAnc time.Time
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const peer_Throttle = 1
|
|
||||||
|
|
||||||
func (p *peer) getQueueSize() int64 {
|
func (p *peer) getQueueSize() int64 {
|
||||||
return atomic.LoadInt64(&p.queueSize)
|
return atomic.LoadInt64(&p.queueSize)
|
||||||
}
|
}
|
||||||
@ -123,14 +97,13 @@ func (p *peer) updateQueueSize(delta int64) {
|
|||||||
atomic.AddInt64(&p.queueSize, delta)
|
atomic.AddInt64(&p.queueSize, delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ps *peers) newPeer(box *boxPubKey,
|
func (ps *peers) newPeer(box *boxPubKey, sig *sigPubKey) *peer {
|
||||||
sig *sigPubKey) *peer {
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
p := peer{box: *box,
|
p := peer{box: *box,
|
||||||
sig: *sig,
|
sig: *sig,
|
||||||
shared: *getSharedKey(&ps.core.boxPriv, box),
|
shared: *getSharedKey(&ps.core.boxPriv, box),
|
||||||
lastAnc: now,
|
|
||||||
firstSeen: now,
|
firstSeen: now,
|
||||||
|
doSend: make(chan struct{}, 1),
|
||||||
core: ps.core}
|
core: ps.core}
|
||||||
ps.mutex.Lock()
|
ps.mutex.Lock()
|
||||||
defer ps.mutex.Unlock()
|
defer ps.mutex.Unlock()
|
||||||
@ -151,10 +124,12 @@ func (ps *peers) newPeer(box *boxPubKey,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ps *peers) removePeer(port switchPort) {
|
func (ps *peers) removePeer(port switchPort) {
|
||||||
// TODO? store linkIn in the peer struct, close it here? (once)
|
|
||||||
if port == 0 {
|
if port == 0 {
|
||||||
return
|
return
|
||||||
} // Can't remove self peer
|
} // Can't remove self peer
|
||||||
|
ps.core.router.doAdmin(func() {
|
||||||
|
ps.core.switchTable.removePeer(port)
|
||||||
|
})
|
||||||
ps.mutex.Lock()
|
ps.mutex.Lock()
|
||||||
oldPorts := ps.getPorts()
|
oldPorts := ps.getPorts()
|
||||||
p, isIn := oldPorts[port]
|
p, isIn := oldPorts[port]
|
||||||
@ -165,56 +140,47 @@ func (ps *peers) removePeer(port switchPort) {
|
|||||||
delete(newPorts, port)
|
delete(newPorts, port)
|
||||||
ps.putPorts(newPorts)
|
ps.putPorts(newPorts)
|
||||||
ps.mutex.Unlock()
|
ps.mutex.Unlock()
|
||||||
if isIn && p.close != nil {
|
if isIn {
|
||||||
p.close()
|
if p.close != nil {
|
||||||
|
p.close()
|
||||||
|
}
|
||||||
|
close(p.doSend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *peer) linkLoop(in <-chan []byte) {
|
func (ps *peers) sendSwitchMsgs() {
|
||||||
ticker := time.NewTicker(time.Second)
|
ports := ps.getPorts()
|
||||||
defer ticker.Stop()
|
for _, p := range ports {
|
||||||
var counter uint8
|
if p.port == 0 {
|
||||||
var lastRSeq uint64
|
continue
|
||||||
for {
|
}
|
||||||
select {
|
select {
|
||||||
case packet, ok := <-in:
|
case p.doSend <- struct{}{}:
|
||||||
if !ok {
|
default:
|
||||||
return
|
|
||||||
}
|
|
||||||
p.handleLinkTraffic(packet)
|
|
||||||
case <-ticker.C:
|
|
||||||
if time.Since(p.lastAnc) > 16*time.Second && p.close != nil {
|
|
||||||
// Seems to have timed out, try to trigger a close
|
|
||||||
p.close()
|
|
||||||
}
|
|
||||||
p.throttle = 0
|
|
||||||
if p.port == 0 {
|
|
||||||
continue
|
|
||||||
} // Don't send announces on selfInterface
|
|
||||||
p.myMsg, p.mySigs = p.core.switchTable.createMessage(p.port)
|
|
||||||
var update bool
|
|
||||||
switch {
|
|
||||||
case p.msgAnc == nil:
|
|
||||||
update = true
|
|
||||||
case lastRSeq != p.msgAnc.Seq:
|
|
||||||
update = true
|
|
||||||
case p.msgAnc.Rseq != p.myMsg.seq:
|
|
||||||
update = true
|
|
||||||
case counter%4 == 0:
|
|
||||||
update = true
|
|
||||||
}
|
|
||||||
if update {
|
|
||||||
if p.msgAnc != nil {
|
|
||||||
lastRSeq = p.msgAnc.Seq
|
|
||||||
}
|
|
||||||
p.sendSwitchAnnounce()
|
|
||||||
}
|
|
||||||
counter = (counter + 1) % 4
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *peer) handlePacket(packet []byte, linkIn chan<- []byte) {
|
func (p *peer) linkLoop() {
|
||||||
|
go func() { p.doSend <- struct{}{} }()
|
||||||
|
tick := time.NewTicker(time.Second)
|
||||||
|
defer tick.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case _, ok := <-p.doSend:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.sendSwitchMsg()
|
||||||
|
case _ = <-tick.C:
|
||||||
|
if p.dinfo != nil {
|
||||||
|
p.core.dht.peers <- p.dinfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *peer) handlePacket(packet []byte) {
|
||||||
// TODO See comment in sendPacket about atomics technically being done wrong
|
// TODO See comment in sendPacket about atomics technically being done wrong
|
||||||
atomic.AddUint64(&p.bytesRecvd, uint64(len(packet)))
|
atomic.AddUint64(&p.bytesRecvd, uint64(len(packet)))
|
||||||
pType, pTypeLen := wire_decode_uint64(packet)
|
pType, pTypeLen := wire_decode_uint64(packet)
|
||||||
@ -227,31 +193,22 @@ func (p *peer) handlePacket(packet []byte, linkIn chan<- []byte) {
|
|||||||
case wire_ProtocolTraffic:
|
case wire_ProtocolTraffic:
|
||||||
p.handleTraffic(packet, pTypeLen)
|
p.handleTraffic(packet, pTypeLen)
|
||||||
case wire_LinkProtocolTraffic:
|
case wire_LinkProtocolTraffic:
|
||||||
{
|
p.handleLinkTraffic(packet)
|
||||||
select {
|
default:
|
||||||
case linkIn <- packet:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: /*panic(pType) ;*/
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *peer) handleTraffic(packet []byte, pTypeLen int) {
|
func (p *peer) handleTraffic(packet []byte, pTypeLen int) {
|
||||||
if p.port != 0 && p.msgAnc == nil {
|
if p.port != 0 && p.dinfo == nil {
|
||||||
// Drop traffic until the peer manages to send us at least one anc
|
// Drop traffic until the peer manages to send us at least one good switchMsg
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ttl, ttlLen := wire_decode_uint64(packet[pTypeLen:])
|
coords, coordLen := wire_decode_coords(packet[pTypeLen:])
|
||||||
ttlBegin := pTypeLen
|
if coordLen >= len(packet) {
|
||||||
ttlEnd := pTypeLen + ttlLen
|
|
||||||
coords, coordLen := wire_decode_coords(packet[ttlEnd:])
|
|
||||||
coordEnd := ttlEnd + coordLen
|
|
||||||
if coordEnd == len(packet) {
|
|
||||||
return
|
return
|
||||||
} // No payload
|
} // No payload
|
||||||
toPort, newTTL := p.core.switchTable.lookup(coords, ttl)
|
toPort := p.core.switchTable.lookup(coords)
|
||||||
if toPort == p.port {
|
if toPort == p.port {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -259,13 +216,6 @@ func (p *peer) handleTraffic(packet []byte, pTypeLen int) {
|
|||||||
if to == nil {
|
if to == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// This mutates the packet in-place if the length of the TTL changes!
|
|
||||||
ttlSlice := wire_encode_uint64(newTTL)
|
|
||||||
newTTLLen := len(ttlSlice)
|
|
||||||
shift := ttlLen - newTTLLen
|
|
||||||
copy(packet[shift:], packet[:pTypeLen])
|
|
||||||
copy(packet[ttlBegin+shift:], ttlSlice)
|
|
||||||
packet = packet[shift:]
|
|
||||||
to.sendPacket(packet)
|
to.sendPacket(packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +234,7 @@ func (p *peer) sendLinkPacket(packet []byte) {
|
|||||||
Payload: bs,
|
Payload: bs,
|
||||||
}
|
}
|
||||||
packet = linkPacket.encode()
|
packet = linkPacket.encode()
|
||||||
p.sendPacket(packet)
|
p.linkOut <- packet
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *peer) handleLinkTraffic(bs []byte) {
|
func (p *peer) handleLinkTraffic(bs []byte) {
|
||||||
@ -301,219 +251,70 @@ func (p *peer) handleLinkTraffic(bs []byte) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch pType {
|
switch pType {
|
||||||
case wire_SwitchAnnounce:
|
case wire_SwitchMsg:
|
||||||
p.handleSwitchAnnounce(payload)
|
p.handleSwitchMsg(payload)
|
||||||
case wire_SwitchHopRequest:
|
default: // TODO?...
|
||||||
p.handleSwitchHopRequest(payload)
|
|
||||||
case wire_SwitchHop:
|
|
||||||
p.handleSwitchHop(payload)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *peer) handleSwitchAnnounce(packet []byte) {
|
func (p *peer) sendSwitchMsg() {
|
||||||
//p.core.log.Println("DEBUG: handleSwitchAnnounce")
|
msg := p.core.switchTable.getMsg()
|
||||||
anc := msgAnnounce{}
|
if msg == nil {
|
||||||
//err := wire_decode_struct(packet, &anc)
|
|
||||||
//if err != nil { return }
|
|
||||||
if !anc.decode(packet) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//if p.msgAnc != nil && anc.Seq != p.msgAnc.Seq { p.msgHops = nil }
|
bs := getBytesForSig(&p.sig, msg)
|
||||||
if p.msgAnc == nil ||
|
msg.Hops = append(msg.Hops, switchMsgHop{
|
||||||
anc.Root != p.msgAnc.Root ||
|
Port: p.port,
|
||||||
anc.Tstamp != p.msgAnc.Tstamp ||
|
Next: p.sig,
|
||||||
anc.Seq != p.msgAnc.Seq {
|
Sig: *sign(&p.core.sigPriv, bs),
|
||||||
p.msgHops = nil
|
})
|
||||||
}
|
packet := msg.encode()
|
||||||
p.msgAnc = &anc
|
//p.core.log.Println("Encoded msg:", msg, "; bytes:", packet)
|
||||||
p.processSwitchMessage()
|
//fmt.Println("Encoded msg:", msg, "; bytes:", packet)
|
||||||
p.lastAnc = time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *peer) requestHop(hop uint64) {
|
|
||||||
//p.core.log.Println("DEBUG requestHop")
|
|
||||||
req := msgHopReq{}
|
|
||||||
req.Root = p.msgAnc.Root
|
|
||||||
req.Tstamp = p.msgAnc.Tstamp
|
|
||||||
req.Seq = p.msgAnc.Seq
|
|
||||||
req.Hop = hop
|
|
||||||
packet := req.encode()
|
|
||||||
p.sendLinkPacket(packet)
|
p.sendLinkPacket(packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *peer) handleSwitchHopRequest(packet []byte) {
|
func (p *peer) handleSwitchMsg(packet []byte) {
|
||||||
//p.core.log.Println("DEBUG: handleSwitchHopRequest")
|
var msg switchMsg
|
||||||
if p.throttle > peer_Throttle {
|
if !msg.decode(packet) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if p.myMsg == nil {
|
//p.core.log.Println("Decoded msg:", msg, "; bytes:", packet)
|
||||||
return
|
if len(msg.Hops) < 1 {
|
||||||
|
p.core.peers.removePeer(p.port)
|
||||||
}
|
}
|
||||||
req := msgHopReq{}
|
var loc switchLocator
|
||||||
if !req.decode(packet) {
|
prevKey := msg.Root
|
||||||
return
|
for idx, hop := range msg.Hops {
|
||||||
}
|
// Check signatures and collect coords for dht
|
||||||
if req.Root != p.myMsg.locator.root {
|
sigMsg := msg
|
||||||
return
|
sigMsg.Hops = msg.Hops[:idx]
|
||||||
}
|
|
||||||
if req.Tstamp != p.myMsg.locator.tstamp {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if req.Seq != p.myMsg.seq {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if uint64(len(p.myMsg.locator.coords)) <= req.Hop {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
res := msgHop{}
|
|
||||||
res.Root = p.myMsg.locator.root
|
|
||||||
res.Tstamp = p.myMsg.locator.tstamp
|
|
||||||
res.Seq = p.myMsg.seq
|
|
||||||
res.Hop = req.Hop
|
|
||||||
res.Port = p.myMsg.locator.coords[res.Hop]
|
|
||||||
sinfo := p.getSig(res.Hop)
|
|
||||||
//p.core.log.Println("DEBUG sig:", sinfo)
|
|
||||||
res.Next = sinfo.next
|
|
||||||
res.Sig = sinfo.sig
|
|
||||||
packet = res.encode()
|
|
||||||
p.sendLinkPacket(packet)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *peer) handleSwitchHop(packet []byte) {
|
|
||||||
//p.core.log.Println("DEBUG: handleSwitchHop")
|
|
||||||
if p.throttle > peer_Throttle {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if p.msgAnc == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
res := msgHop{}
|
|
||||||
if !res.decode(packet) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if res.Root != p.msgAnc.Root {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if res.Tstamp != p.msgAnc.Tstamp {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if res.Seq != p.msgAnc.Seq {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if res.Hop != uint64(len(p.msgHops)) {
|
|
||||||
return
|
|
||||||
} // always process in order
|
|
||||||
loc := switchLocator{coords: make([]switchPort, 0, len(p.msgHops)+1)}
|
|
||||||
loc.root = res.Root
|
|
||||||
loc.tstamp = res.Tstamp
|
|
||||||
for _, hop := range p.msgHops {
|
|
||||||
loc.coords = append(loc.coords, hop.Port)
|
loc.coords = append(loc.coords, hop.Port)
|
||||||
}
|
bs := getBytesForSig(&hop.Next, &sigMsg)
|
||||||
loc.coords = append(loc.coords, res.Port)
|
if !p.core.sigs.check(&prevKey, &hop.Sig, bs) {
|
||||||
thisHopKey := &res.Root
|
p.core.peers.removePeer(p.port)
|
||||||
if res.Hop != 0 {
|
|
||||||
thisHopKey = &p.msgHops[res.Hop-1].Next
|
|
||||||
}
|
|
||||||
bs := getBytesForSig(&res.Next, &loc)
|
|
||||||
if p.core.sigs.check(thisHopKey, &res.Sig, bs) {
|
|
||||||
p.msgHops = append(p.msgHops, &res)
|
|
||||||
p.processSwitchMessage()
|
|
||||||
} else {
|
|
||||||
p.throttle++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *peer) processSwitchMessage() {
|
|
||||||
//p.core.log.Println("DEBUG: processSwitchMessage")
|
|
||||||
if p.throttle > peer_Throttle {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if p.msgAnc == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if uint64(len(p.msgHops)) < p.msgAnc.Len {
|
|
||||||
p.requestHop(uint64(len(p.msgHops)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.throttle++
|
|
||||||
if p.msgAnc.Len != uint64(len(p.msgHops)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
msg := switchMessage{}
|
|
||||||
coords := make([]switchPort, 0, len(p.msgHops))
|
|
||||||
sigs := make([]sigInfo, 0, len(p.msgHops))
|
|
||||||
for idx, hop := range p.msgHops {
|
|
||||||
// Consistency checks, should be redundant (already checked these...)
|
|
||||||
if hop.Root != p.msgAnc.Root {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if hop.Tstamp != p.msgAnc.Tstamp {
|
prevKey = hop.Next
|
||||||
return
|
|
||||||
}
|
|
||||||
if hop.Seq != p.msgAnc.Seq {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if hop.Hop != uint64(idx) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
coords = append(coords, hop.Port)
|
|
||||||
sigs = append(sigs, sigInfo{next: hop.Next, sig: hop.Sig})
|
|
||||||
}
|
}
|
||||||
msg.from = p.sig
|
p.core.switchTable.handleMsg(&msg, p.port)
|
||||||
msg.locator.root = p.msgAnc.Root
|
|
||||||
msg.locator.tstamp = p.msgAnc.Tstamp
|
|
||||||
msg.locator.coords = coords
|
|
||||||
msg.seq = p.msgAnc.Seq
|
|
||||||
//msg.RSeq = p.msgAnc.RSeq
|
|
||||||
//msg.Degree = p.msgAnc.Deg
|
|
||||||
p.core.switchTable.handleMessage(&msg, p.port, sigs)
|
|
||||||
if len(coords) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Reuse locator, set the coords to the peer's coords, to use in dht
|
|
||||||
msg.locator.coords = coords[:len(coords)-1]
|
|
||||||
// Pass a mesage to the dht informing it that this peer (still) exists
|
// Pass a mesage to the dht informing it that this peer (still) exists
|
||||||
|
loc.coords = loc.coords[:len(loc.coords)-1]
|
||||||
dinfo := dhtInfo{
|
dinfo := dhtInfo{
|
||||||
key: p.box,
|
key: p.box,
|
||||||
coords: msg.locator.getCoords(),
|
coords: loc.getCoords(),
|
||||||
}
|
}
|
||||||
p.core.dht.peers <- &dinfo
|
p.core.dht.peers <- &dinfo
|
||||||
|
p.dinfo = &dinfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *peer) sendSwitchAnnounce() {
|
func getBytesForSig(next *sigPubKey, msg *switchMsg) []byte {
|
||||||
anc := msgAnnounce{}
|
var loc switchLocator
|
||||||
anc.Root = p.myMsg.locator.root
|
for _, hop := range msg.Hops {
|
||||||
anc.Tstamp = p.myMsg.locator.tstamp
|
loc.coords = append(loc.coords, hop.Port)
|
||||||
anc.Seq = p.myMsg.seq
|
|
||||||
anc.Len = uint64(len(p.myMsg.locator.coords))
|
|
||||||
//anc.Deg = p.myMsg.Degree
|
|
||||||
if p.msgAnc != nil {
|
|
||||||
anc.Rseq = p.msgAnc.Seq
|
|
||||||
}
|
}
|
||||||
packet := anc.encode()
|
|
||||||
p.sendLinkPacket(packet)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *peer) getSig(hop uint64) sigInfo {
|
|
||||||
//p.core.log.Println("DEBUG getSig:", len(p.mySigs), hop)
|
|
||||||
if hop < uint64(len(p.mySigs)) {
|
|
||||||
return p.mySigs[hop]
|
|
||||||
}
|
|
||||||
bs := getBytesForSig(&p.sig, &p.myMsg.locator)
|
|
||||||
sig := sigInfo{}
|
|
||||||
sig.next = p.sig
|
|
||||||
sig.sig = *sign(&p.core.sigPriv, bs)
|
|
||||||
p.mySigs = append(p.mySigs, sig)
|
|
||||||
//p.core.log.Println("DEBUG sig bs:", bs)
|
|
||||||
return sig
|
|
||||||
}
|
|
||||||
|
|
||||||
func getBytesForSig(next *sigPubKey, loc *switchLocator) []byte {
|
|
||||||
//bs, err := wire_encode_locator(loc)
|
|
||||||
//if err != nil { panic(err) }
|
|
||||||
bs := append([]byte(nil), next[:]...)
|
bs := append([]byte(nil), next[:]...)
|
||||||
bs = append(bs, wire_encode_locator(loc)...)
|
bs = append(bs, msg.Root[:]...)
|
||||||
//bs := wire_encode_locator(loc)
|
bs = append(bs, wire_encode_uint64(wire_intToUint(msg.TStamp))...)
|
||||||
//bs = append(next[:], bs...)
|
bs = append(bs, wire_encode_coords(loc.getCoords())...)
|
||||||
return bs
|
return bs
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ func (r *router) init(core *Core) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.in = in
|
r.in = in
|
||||||
r.out = func(packet []byte) { p.handlePacket(packet, nil) } // The caller is responsible for go-ing if it needs to not block
|
r.out = func(packet []byte) { p.handlePacket(packet) } // The caller is responsible for go-ing if it needs to not block
|
||||||
recv := make(chan []byte, 32)
|
recv := make(chan []byte, 32)
|
||||||
send := make(chan []byte, 32)
|
send := make(chan []byte, 32)
|
||||||
r.recv = recv
|
r.recv = recv
|
||||||
@ -91,7 +91,9 @@ func (r *router) mainLoop() {
|
|||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
{
|
{
|
||||||
// Any periodic maintenance stuff goes here
|
// Any periodic maintenance stuff goes here
|
||||||
|
r.core.switchTable.doMaintenance()
|
||||||
r.core.dht.doMaintenance()
|
r.core.dht.doMaintenance()
|
||||||
|
//r.core.peers.sendSwitchMsgs() // FIXME debugging
|
||||||
util_getBytes() // To slowly drain things
|
util_getBytes() // To slowly drain things
|
||||||
}
|
}
|
||||||
case f := <-r.admin:
|
case f := <-r.admin:
|
||||||
|
@ -107,7 +107,10 @@ func (s *searches) doSearchStep(sinfo *searchInfo) {
|
|||||||
// Send to the next search target
|
// Send to the next search target
|
||||||
var next *dhtInfo
|
var next *dhtInfo
|
||||||
next, sinfo.toVisit = sinfo.toVisit[0], sinfo.toVisit[1:]
|
next, sinfo.toVisit = sinfo.toVisit[0], sinfo.toVisit[1:]
|
||||||
|
var oldPings int
|
||||||
|
oldPings, next.pings = next.pings, 0
|
||||||
s.core.dht.ping(next, &sinfo.dest)
|
s.core.dht.ping(next, &sinfo.dest)
|
||||||
|
next.pings = oldPings // Don't evict a node for searching with it too much
|
||||||
sinfo.visited[*next.getNodeID()] = true
|
sinfo.visited[*next.getNodeID()] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,7 +255,6 @@ func (ss *sessions) sendPingPong(sinfo *sessionInfo, isPong bool) {
|
|||||||
shared := ss.getSharedKey(&ss.core.boxPriv, &sinfo.theirPermPub)
|
shared := ss.getSharedKey(&ss.core.boxPriv, &sinfo.theirPermPub)
|
||||||
payload, nonce := boxSeal(shared, bs, nil)
|
payload, nonce := boxSeal(shared, bs, nil)
|
||||||
p := wire_protoTrafficPacket{
|
p := wire_protoTrafficPacket{
|
||||||
TTL: ^uint64(0),
|
|
||||||
Coords: sinfo.coords,
|
Coords: sinfo.coords,
|
||||||
ToKey: sinfo.theirPermPub,
|
ToKey: sinfo.theirPermPub,
|
||||||
FromKey: ss.core.boxPub,
|
FromKey: ss.core.boxPub,
|
||||||
@ -383,7 +382,6 @@ func (sinfo *sessionInfo) doSend(bs []byte) {
|
|||||||
payload, nonce := boxSeal(&sinfo.sharedSesKey, bs, &sinfo.myNonce)
|
payload, nonce := boxSeal(&sinfo.sharedSesKey, bs, &sinfo.myNonce)
|
||||||
defer util_putBytes(payload)
|
defer util_putBytes(payload)
|
||||||
p := wire_trafficPacket{
|
p := wire_trafficPacket{
|
||||||
TTL: ^uint64(0),
|
|
||||||
Coords: sinfo.coords,
|
Coords: sinfo.coords,
|
||||||
Handle: sinfo.theirHandle,
|
Handle: sinfo.theirHandle,
|
||||||
Nonce: *nonce,
|
Nonce: *nonce,
|
||||||
|
@ -9,7 +9,7 @@ package yggdrasil
|
|||||||
// TODO document/comment everything in a lot more detail
|
// TODO document/comment everything in a lot more detail
|
||||||
|
|
||||||
// TODO? use a pre-computed lookup table (python version had this)
|
// TODO? use a pre-computed lookup table (python version had this)
|
||||||
// A little annoying to do with constant changes from bandwidth estimates
|
// A little annoying to do with constant changes from backpressure
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
import "sort"
|
import "sort"
|
||||||
@ -113,17 +113,10 @@ type peerInfo struct {
|
|||||||
key sigPubKey // ID of this peer
|
key sigPubKey // ID of this peer
|
||||||
locator switchLocator // Should be able to respond with signatures upon request
|
locator switchLocator // Should be able to respond with signatures upon request
|
||||||
degree uint64 // Self-reported degree
|
degree uint64 // Self-reported degree
|
||||||
coords []switchPort // Coords of this peer (taken from coords of the sent locator)
|
|
||||||
time time.Time // Time this node was last seen
|
time time.Time // Time this node was last seen
|
||||||
firstSeen time.Time
|
firstSeen time.Time
|
||||||
port switchPort // Interface number of this peer
|
port switchPort // Interface number of this peer
|
||||||
seq uint64 // Seq number we last saw this peer advertise
|
msg switchMsg // The wire switchMsg used
|
||||||
}
|
|
||||||
|
|
||||||
type switchMessage struct {
|
|
||||||
from sigPubKey // key of the sender
|
|
||||||
locator switchLocator // Locator advertised for the receiver, not the sender's loc!
|
|
||||||
seq uint64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type switchPort uint64
|
type switchPort uint64
|
||||||
@ -143,7 +136,7 @@ type switchData struct {
|
|||||||
locator switchLocator
|
locator switchLocator
|
||||||
seq uint64 // Sequence number, reported to peers, so they know about changes
|
seq uint64 // Sequence number, reported to peers, so they know about changes
|
||||||
peers map[switchPort]peerInfo
|
peers map[switchPort]peerInfo
|
||||||
sigs []sigInfo
|
msg *switchMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
type switchTable struct {
|
type switchTable struct {
|
||||||
@ -170,31 +163,17 @@ func (t *switchTable) init(core *Core, key sigPubKey) {
|
|||||||
t.drop = make(map[sigPubKey]int64)
|
t.drop = make(map[sigPubKey]int64)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *switchTable) start() error {
|
|
||||||
doTicker := func() {
|
|
||||||
ticker := time.NewTicker(time.Second)
|
|
||||||
defer ticker.Stop()
|
|
||||||
for {
|
|
||||||
<-ticker.C
|
|
||||||
t.Tick()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
go doTicker()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *switchTable) getLocator() switchLocator {
|
func (t *switchTable) getLocator() switchLocator {
|
||||||
t.mutex.RLock()
|
t.mutex.RLock()
|
||||||
defer t.mutex.RUnlock()
|
defer t.mutex.RUnlock()
|
||||||
return t.data.locator.clone()
|
return t.data.locator.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *switchTable) Tick() {
|
func (t *switchTable) doMaintenance() {
|
||||||
// Periodic maintenance work to keep things internally consistent
|
// Periodic maintenance work to keep things internally consistent
|
||||||
t.mutex.Lock() // Write lock
|
t.mutex.Lock() // Write lock
|
||||||
defer t.mutex.Unlock() // Release lock when we're done
|
defer t.mutex.Unlock() // Release lock when we're done
|
||||||
t.cleanRoot()
|
t.cleanRoot()
|
||||||
t.cleanPeers()
|
|
||||||
t.cleanDropped()
|
t.cleanDropped()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,22 +215,16 @@ func (t *switchTable) cleanRoot() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.data.locator = switchLocator{root: t.key, tstamp: now.Unix()}
|
t.data.locator = switchLocator{root: t.key, tstamp: now.Unix()}
|
||||||
t.data.sigs = nil
|
t.core.peers.sendSwitchMsgs()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *switchTable) cleanPeers() {
|
func (t *switchTable) removePeer(port switchPort) {
|
||||||
now := time.Now()
|
delete(t.data.peers, port)
|
||||||
changed := false
|
t.updater.Store(&sync.Once{})
|
||||||
for idx, info := range t.data.peers {
|
// TODO if parent, find a new peer to use as parent instead
|
||||||
if info.port != switchPort(0) && now.Sub(info.time) > 6*time.Second /*switch_timeout*/ {
|
for _, info := range t.data.peers {
|
||||||
//fmt.Println("peer timed out", t.key, info.locator)
|
t.unlockedHandleMsg(&info.msg, info.port)
|
||||||
delete(t.data.peers, idx)
|
|
||||||
changed = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if changed {
|
|
||||||
t.updater.Store(&sync.Once{})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,33 +237,64 @@ func (t *switchTable) cleanDropped() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *switchTable) createMessage(port switchPort) (*switchMessage, []sigInfo) {
|
type switchMsg struct {
|
||||||
t.mutex.RLock()
|
Root sigPubKey
|
||||||
defer t.mutex.RUnlock()
|
TStamp int64
|
||||||
msg := switchMessage{from: t.key, locator: t.data.locator.clone()}
|
Hops []switchMsgHop
|
||||||
msg.locator.coords = append(msg.locator.coords, port)
|
|
||||||
msg.seq = t.data.seq
|
|
||||||
return &msg, t.data.sigs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *switchTable) handleMessage(msg *switchMessage, fromPort switchPort, sigs []sigInfo) {
|
type switchMsgHop struct {
|
||||||
|
Port switchPort
|
||||||
|
Next sigPubKey
|
||||||
|
Sig sigBytes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *switchTable) getMsg() *switchMsg {
|
||||||
|
t.mutex.RLock()
|
||||||
|
defer t.mutex.RUnlock()
|
||||||
|
if t.parent == 0 {
|
||||||
|
return &switchMsg{Root: t.key, TStamp: t.data.locator.tstamp}
|
||||||
|
} else if parent, isIn := t.data.peers[t.parent]; isIn {
|
||||||
|
msg := parent.msg
|
||||||
|
msg.Hops = append([]switchMsgHop(nil), msg.Hops...)
|
||||||
|
return &msg
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *switchTable) handleMsg(msg *switchMsg, fromPort switchPort) {
|
||||||
t.mutex.Lock()
|
t.mutex.Lock()
|
||||||
defer t.mutex.Unlock()
|
defer t.mutex.Unlock()
|
||||||
|
t.unlockedHandleMsg(msg, fromPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort) {
|
||||||
|
// TODO directly use a switchMsg instead of switchMessage + sigs
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
if len(msg.locator.coords) == 0 {
|
// Set up the sender peerInfo
|
||||||
return
|
var sender peerInfo
|
||||||
} // Should always have >=1 links
|
sender.locator.root = msg.Root
|
||||||
|
sender.locator.tstamp = msg.TStamp
|
||||||
|
prevKey := msg.Root
|
||||||
|
for _, hop := range msg.Hops {
|
||||||
|
// Build locator and signatures
|
||||||
|
var sig sigInfo
|
||||||
|
sig.next = hop.Next
|
||||||
|
sig.sig = hop.Sig
|
||||||
|
sender.locator.coords = append(sender.locator.coords, hop.Port)
|
||||||
|
sender.key = prevKey
|
||||||
|
prevKey = hop.Next
|
||||||
|
}
|
||||||
|
sender.msg = *msg
|
||||||
oldSender, isIn := t.data.peers[fromPort]
|
oldSender, isIn := t.data.peers[fromPort]
|
||||||
if !isIn {
|
if !isIn {
|
||||||
oldSender.firstSeen = now
|
oldSender.firstSeen = now
|
||||||
}
|
}
|
||||||
sender := peerInfo{key: msg.from,
|
sender.firstSeen = oldSender.firstSeen
|
||||||
locator: msg.locator,
|
sender.port = fromPort
|
||||||
coords: msg.locator.coords[:len(msg.locator.coords)-1],
|
sender.time = now
|
||||||
time: now,
|
// Decide what to do
|
||||||
firstSeen: oldSender.firstSeen,
|
|
||||||
port: fromPort,
|
|
||||||
seq: msg.seq}
|
|
||||||
equiv := func(x *switchLocator, y *switchLocator) bool {
|
equiv := func(x *switchLocator, y *switchLocator) bool {
|
||||||
if x.root != y.root {
|
if x.root != y.root {
|
||||||
return false
|
return false
|
||||||
@ -306,20 +310,21 @@ func (t *switchTable) handleMessage(msg *switchMessage, fromPort switchPort, sig
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
doUpdate := false
|
doUpdate := false
|
||||||
if !equiv(&msg.locator, &oldSender.locator) {
|
if !equiv(&sender.locator, &oldSender.locator) {
|
||||||
doUpdate = true
|
doUpdate = true
|
||||||
|
//sender.firstSeen = now // TODO? uncomment to prevent flapping?
|
||||||
}
|
}
|
||||||
t.data.peers[fromPort] = sender
|
t.data.peers[fromPort] = sender
|
||||||
updateRoot := false
|
updateRoot := false
|
||||||
oldParent, isIn := t.data.peers[t.parent]
|
oldParent, isIn := t.data.peers[t.parent]
|
||||||
noParent := !isIn
|
noParent := !isIn
|
||||||
noLoop := func() bool {
|
noLoop := func() bool {
|
||||||
for idx := 0; idx < len(sigs)-1; idx++ {
|
for idx := 0; idx < len(msg.Hops)-1; idx++ {
|
||||||
if sigs[idx].next == t.core.sigPub {
|
if msg.Hops[idx].Next == t.core.sigPub {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if msg.locator.root == t.core.sigPub {
|
if sender.locator.root == t.core.sigPub {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -328,30 +333,30 @@ func (t *switchTable) handleMessage(msg *switchMessage, fromPort switchPort, sig
|
|||||||
pTime := oldParent.time.Sub(oldParent.firstSeen) + switch_timeout
|
pTime := oldParent.time.Sub(oldParent.firstSeen) + switch_timeout
|
||||||
// Really want to compare sLen/sTime and pLen/pTime
|
// Really want to compare sLen/sTime and pLen/pTime
|
||||||
// Cross multiplied to avoid divide-by-zero
|
// Cross multiplied to avoid divide-by-zero
|
||||||
cost := len(msg.locator.coords) * int(pTime.Seconds())
|
cost := len(sender.locator.coords) * int(pTime.Seconds())
|
||||||
pCost := len(t.data.locator.coords) * int(sTime.Seconds())
|
pCost := len(t.data.locator.coords) * int(sTime.Seconds())
|
||||||
dropTstamp, isIn := t.drop[msg.locator.root]
|
dropTstamp, isIn := t.drop[sender.locator.root]
|
||||||
// Here be dragons
|
// Here be dragons
|
||||||
switch {
|
switch {
|
||||||
case !noLoop: // do nothing
|
case !noLoop: // do nothing
|
||||||
case isIn && dropTstamp >= msg.locator.tstamp: // do nothing
|
case isIn && dropTstamp >= sender.locator.tstamp: // do nothing
|
||||||
case firstIsBetter(&msg.locator.root, &t.data.locator.root):
|
case firstIsBetter(&sender.locator.root, &t.data.locator.root):
|
||||||
updateRoot = true
|
updateRoot = true
|
||||||
case t.data.locator.root != msg.locator.root: // do nothing
|
case t.data.locator.root != sender.locator.root: // do nothing
|
||||||
case t.data.locator.tstamp > msg.locator.tstamp: // do nothing
|
case t.data.locator.tstamp > sender.locator.tstamp: // do nothing
|
||||||
case noParent:
|
case noParent:
|
||||||
updateRoot = true
|
updateRoot = true
|
||||||
case cost < pCost:
|
case cost < pCost:
|
||||||
updateRoot = true
|
updateRoot = true
|
||||||
case sender.port != t.parent: // do nothing
|
case sender.port != t.parent: // do nothing
|
||||||
case !equiv(&msg.locator, &t.data.locator):
|
case !equiv(&sender.locator, &t.data.locator):
|
||||||
updateRoot = true
|
updateRoot = true
|
||||||
case now.Sub(t.time) < switch_throttle: // do nothing
|
case now.Sub(t.time) < switch_throttle: // do nothing
|
||||||
case msg.locator.tstamp > t.data.locator.tstamp:
|
case sender.locator.tstamp > t.data.locator.tstamp:
|
||||||
updateRoot = true
|
updateRoot = true
|
||||||
}
|
}
|
||||||
if updateRoot {
|
if updateRoot {
|
||||||
if !equiv(&msg.locator, &t.data.locator) {
|
if !equiv(&sender.locator, &t.data.locator) {
|
||||||
doUpdate = true
|
doUpdate = true
|
||||||
t.data.seq++
|
t.data.seq++
|
||||||
select {
|
select {
|
||||||
@ -361,13 +366,13 @@ func (t *switchTable) handleMessage(msg *switchMessage, fromPort switchPort, sig
|
|||||||
//t.core.log.Println("Switch update:", msg.locator.root, msg.locator.tstamp, msg.locator.coords)
|
//t.core.log.Println("Switch update:", msg.locator.root, msg.locator.tstamp, msg.locator.coords)
|
||||||
//fmt.Println("Switch update:", msg.Locator.Root, msg.Locator.Tstamp, msg.Locator.Coords)
|
//fmt.Println("Switch update:", msg.Locator.Root, msg.Locator.Tstamp, msg.Locator.Coords)
|
||||||
}
|
}
|
||||||
if t.data.locator.tstamp != msg.locator.tstamp {
|
if t.data.locator.tstamp != sender.locator.tstamp {
|
||||||
t.time = now
|
t.time = now
|
||||||
}
|
}
|
||||||
t.data.locator = msg.locator
|
t.data.locator = sender.locator
|
||||||
t.parent = sender.port
|
t.parent = sender.port
|
||||||
t.data.sigs = sigs
|
|
||||||
//t.core.log.Println("Switch update:", msg.Locator.Root, msg.Locator.Tstamp, msg.Locator.Coords)
|
//t.core.log.Println("Switch update:", msg.Locator.Root, msg.Locator.Tstamp, msg.Locator.Coords)
|
||||||
|
t.core.peers.sendSwitchMsgs()
|
||||||
}
|
}
|
||||||
if doUpdate {
|
if doUpdate {
|
||||||
t.updater.Store(&sync.Once{})
|
t.updater.Store(&sync.Once{})
|
||||||
@ -408,19 +413,19 @@ func (t *switchTable) updateTable() {
|
|||||||
t.table.Store(newTable)
|
t.table.Store(newTable)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *switchTable) lookup(dest []byte, ttl uint64) (switchPort, uint64) {
|
func (t *switchTable) lookup(dest []byte) switchPort {
|
||||||
t.updater.Load().(*sync.Once).Do(t.updateTable)
|
t.updater.Load().(*sync.Once).Do(t.updateTable)
|
||||||
table := t.table.Load().(lookupTable)
|
table := t.table.Load().(lookupTable)
|
||||||
myDist := table.self.dist(dest) //getDist(table.self.coords)
|
myDist := table.self.dist(dest)
|
||||||
if !(uint64(myDist) < ttl) {
|
if myDist == 0 {
|
||||||
return 0, 0
|
return 0
|
||||||
}
|
}
|
||||||
// cost is in units of (expected distance) + (expected queue size), where expected distance is used as an approximation of the minimum backpressure gradient needed for packets to flow
|
// cost is in units of (expected distance) + (expected queue size), where expected distance is used as an approximation of the minimum backpressure gradient needed for packets to flow
|
||||||
ports := t.core.peers.getPorts()
|
ports := t.core.peers.getPorts()
|
||||||
var best switchPort
|
var best switchPort
|
||||||
bestCost := int64(^uint64(0) >> 1)
|
bestCost := int64(^uint64(0) >> 1)
|
||||||
for _, info := range table.elems {
|
for _, info := range table.elems {
|
||||||
dist := info.locator.dist(dest) //getDist(info.locator.coords)
|
dist := info.locator.dist(dest)
|
||||||
if !(dist < myDist) {
|
if !(dist < myDist) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -434,8 +439,8 @@ func (t *switchTable) lookup(dest []byte, ttl uint64) (switchPort, uint64) {
|
|||||||
bestCost = cost
|
bestCost = cost
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//t.core.log.Println("DEBUG: sending to", best, "bandwidth", getBandwidth(best))
|
//t.core.log.Println("DEBUG: sending to", best, "cost", bestCost)
|
||||||
return best, uint64(myDist)
|
return best
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -15,7 +15,6 @@ import "time"
|
|||||||
import "errors"
|
import "errors"
|
||||||
import "sync"
|
import "sync"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "bufio"
|
|
||||||
import "golang.org/x/net/proxy"
|
import "golang.org/x/net/proxy"
|
||||||
|
|
||||||
const tcp_msgSize = 2048 + 65535 // TODO figure out what makes sense
|
const tcp_msgSize = 2048 + 65535 // TODO figure out what makes sense
|
||||||
@ -208,40 +207,61 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
|
|||||||
}()
|
}()
|
||||||
// Note that multiple connections to the same node are allowed
|
// Note that multiple connections to the same node are allowed
|
||||||
// E.g. over different interfaces
|
// E.g. over different interfaces
|
||||||
linkIn := make(chan []byte, 1)
|
p := iface.core.peers.newPeer(&info.box, &info.sig)
|
||||||
p := iface.core.peers.newPeer(&info.box, &info.sig) //, in, out)
|
p.linkOut = make(chan []byte, 1)
|
||||||
in := func(bs []byte) {
|
in := func(bs []byte) {
|
||||||
p.handlePacket(bs, linkIn)
|
p.handlePacket(bs)
|
||||||
}
|
}
|
||||||
out := make(chan []byte, 32) // TODO? what size makes sense
|
out := make(chan []byte, 32) // TODO? what size makes sense
|
||||||
defer close(out)
|
defer close(out)
|
||||||
buf := bufio.NewWriterSize(sock, tcp_msgSize)
|
|
||||||
send := func(msg []byte) {
|
|
||||||
msgLen := wire_encode_uint64(uint64(len(msg)))
|
|
||||||
buf.Write(tcp_msg[:])
|
|
||||||
buf.Write(msgLen)
|
|
||||||
buf.Write(msg)
|
|
||||||
p.updateQueueSize(-1)
|
|
||||||
util_putBytes(msg)
|
|
||||||
}
|
|
||||||
go func() {
|
go func() {
|
||||||
|
var shadow uint64
|
||||||
var stack [][]byte
|
var stack [][]byte
|
||||||
put := func(msg []byte) {
|
put := func(msg []byte) {
|
||||||
stack = append(stack, msg)
|
stack = append(stack, msg)
|
||||||
for len(stack) > 32 {
|
for len(stack) > 32 {
|
||||||
util_putBytes(stack[0])
|
util_putBytes(stack[0])
|
||||||
stack = stack[1:]
|
stack = stack[1:]
|
||||||
p.updateQueueSize(-1)
|
shadow++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for msg := range out {
|
send := func(msg []byte) {
|
||||||
put(msg)
|
msgLen := wire_encode_uint64(uint64(len(msg)))
|
||||||
|
buf := net.Buffers{tcp_msg[:], msgLen, msg}
|
||||||
|
buf.WriteTo(sock)
|
||||||
|
util_putBytes(msg)
|
||||||
|
}
|
||||||
|
timerInterval := 4 * time.Second
|
||||||
|
timer := time.NewTimer(timerInterval)
|
||||||
|
defer timer.Stop()
|
||||||
|
for {
|
||||||
|
for ; shadow > 0; shadow-- {
|
||||||
|
p.updateQueueSize(-1)
|
||||||
|
}
|
||||||
|
timer.Stop()
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
timer.Reset(timerInterval)
|
||||||
|
select {
|
||||||
|
case _ = <-timer.C:
|
||||||
|
//iface.core.log.Println("DEBUG: sending keep-alive:", sock.RemoteAddr().String())
|
||||||
|
send(nil) // TCP keep-alive traffic
|
||||||
|
case msg := <-p.linkOut:
|
||||||
|
send(msg)
|
||||||
|
case msg, ok := <-out:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
put(msg)
|
||||||
|
}
|
||||||
for len(stack) > 0 {
|
for len(stack) > 0 {
|
||||||
// Keep trying to fill the stack (LIFO order) while sending
|
|
||||||
select {
|
select {
|
||||||
|
case msg := <-p.linkOut:
|
||||||
|
send(msg)
|
||||||
case msg, ok := <-out:
|
case msg, ok := <-out:
|
||||||
if !ok {
|
if !ok {
|
||||||
buf.Flush()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
put(msg)
|
put(msg)
|
||||||
@ -249,9 +269,9 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
|
|||||||
msg := stack[len(stack)-1]
|
msg := stack[len(stack)-1]
|
||||||
stack = stack[:len(stack)-1]
|
stack = stack[:len(stack)-1]
|
||||||
send(msg)
|
send(msg)
|
||||||
|
p.updateQueueSize(-1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buf.Flush()
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
p.out = func(msg []byte) {
|
p.out = func(msg []byte) {
|
||||||
@ -265,11 +285,10 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
|
|||||||
}
|
}
|
||||||
p.close = func() { sock.Close() }
|
p.close = func() { sock.Close() }
|
||||||
setNoDelay(sock, true)
|
setNoDelay(sock, true)
|
||||||
go p.linkLoop(linkIn)
|
go p.linkLoop()
|
||||||
defer func() {
|
defer func() {
|
||||||
// Put all of our cleanup here...
|
// Put all of our cleanup here...
|
||||||
p.core.peers.removePeer(p.port)
|
p.core.peers.removePeer(p.port)
|
||||||
close(linkIn)
|
|
||||||
}()
|
}()
|
||||||
them, _, _ := net.SplitHostPort(sock.RemoteAddr().String())
|
them, _, _ := net.SplitHostPort(sock.RemoteAddr().String())
|
||||||
themNodeID := getNodeID(&info.box)
|
themNodeID := getNodeID(&info.box)
|
||||||
|
@ -12,9 +12,7 @@ const (
|
|||||||
wire_Traffic = iota // data being routed somewhere, handle for crypto
|
wire_Traffic = iota // data being routed somewhere, handle for crypto
|
||||||
wire_ProtocolTraffic // protocol traffic, pub keys for crypto
|
wire_ProtocolTraffic // protocol traffic, pub keys for crypto
|
||||||
wire_LinkProtocolTraffic // link proto traffic, pub keys for crypto
|
wire_LinkProtocolTraffic // link proto traffic, pub keys for crypto
|
||||||
wire_SwitchAnnounce // inside protocol traffic header
|
wire_SwitchMsg // inside link protocol traffic header
|
||||||
wire_SwitchHopRequest // inside protocol traffic header
|
|
||||||
wire_SwitchHop // inside protocol traffic header
|
|
||||||
wire_SessionPing // inside protocol traffic header
|
wire_SessionPing // inside protocol traffic header
|
||||||
wire_SessionPong // inside protocol traffic header
|
wire_SessionPong // inside protocol traffic header
|
||||||
wire_DHTLookupRequest // inside protocol traffic header
|
wire_DHTLookupRequest // inside protocol traffic header
|
||||||
@ -117,144 +115,48 @@ func wire_decode_coords(packet []byte) ([]byte, int) {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Announces that we can send parts of a Message with a particular seq
|
func (m *switchMsg) encode() []byte {
|
||||||
type msgAnnounce struct {
|
bs := wire_encode_uint64(wire_SwitchMsg)
|
||||||
Root sigPubKey
|
|
||||||
Tstamp int64
|
|
||||||
Seq uint64
|
|
||||||
Len uint64
|
|
||||||
//Deg uint64
|
|
||||||
Rseq uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *msgAnnounce) encode() []byte {
|
|
||||||
bs := wire_encode_uint64(wire_SwitchAnnounce)
|
|
||||||
bs = append(bs, m.Root[:]...)
|
bs = append(bs, m.Root[:]...)
|
||||||
bs = append(bs, wire_encode_uint64(wire_intToUint(m.Tstamp))...)
|
bs = append(bs, wire_encode_uint64(wire_intToUint(m.TStamp))...)
|
||||||
bs = append(bs, wire_encode_uint64(m.Seq)...)
|
for _, hop := range m.Hops {
|
||||||
bs = append(bs, wire_encode_uint64(m.Len)...)
|
bs = append(bs, wire_encode_uint64(uint64(hop.Port))...)
|
||||||
bs = append(bs, wire_encode_uint64(m.Rseq)...)
|
bs = append(bs, hop.Next[:]...)
|
||||||
|
bs = append(bs, hop.Sig[:]...)
|
||||||
|
}
|
||||||
return bs
|
return bs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *msgAnnounce) decode(bs []byte) bool {
|
func (m *switchMsg) decode(bs []byte) bool {
|
||||||
var pType uint64
|
var pType uint64
|
||||||
var tstamp uint64
|
var tstamp uint64
|
||||||
switch {
|
switch {
|
||||||
case !wire_chop_uint64(&pType, &bs):
|
case !wire_chop_uint64(&pType, &bs):
|
||||||
return false
|
return false
|
||||||
case pType != wire_SwitchAnnounce:
|
case pType != wire_SwitchMsg:
|
||||||
return false
|
return false
|
||||||
case !wire_chop_slice(m.Root[:], &bs):
|
case !wire_chop_slice(m.Root[:], &bs):
|
||||||
return false
|
return false
|
||||||
case !wire_chop_uint64(&tstamp, &bs):
|
case !wire_chop_uint64(&tstamp, &bs):
|
||||||
return false
|
return false
|
||||||
case !wire_chop_uint64(&m.Seq, &bs):
|
|
||||||
return false
|
|
||||||
case !wire_chop_uint64(&m.Len, &bs):
|
|
||||||
return false
|
|
||||||
case !wire_chop_uint64(&m.Rseq, &bs):
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
m.Tstamp = wire_intFromUint(tstamp)
|
m.TStamp = wire_intFromUint(tstamp)
|
||||||
|
for len(bs) > 0 {
|
||||||
|
var hop switchMsgHop
|
||||||
|
switch {
|
||||||
|
case !wire_chop_uint64((*uint64)(&hop.Port), &bs):
|
||||||
|
return false
|
||||||
|
case !wire_chop_slice(hop.Next[:], &bs):
|
||||||
|
return false
|
||||||
|
case !wire_chop_slice(hop.Sig[:], &bs):
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
m.Hops = append(m.Hops, hop)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
type msgHopReq struct {
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
Root sigPubKey
|
|
||||||
Tstamp int64
|
|
||||||
Seq uint64
|
|
||||||
Hop uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *msgHopReq) encode() []byte {
|
|
||||||
bs := wire_encode_uint64(wire_SwitchHopRequest)
|
|
||||||
bs = append(bs, m.Root[:]...)
|
|
||||||
bs = append(bs, wire_encode_uint64(wire_intToUint(m.Tstamp))...)
|
|
||||||
bs = append(bs, wire_encode_uint64(m.Seq)...)
|
|
||||||
bs = append(bs, wire_encode_uint64(m.Hop)...)
|
|
||||||
return bs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *msgHopReq) decode(bs []byte) bool {
|
|
||||||
var pType uint64
|
|
||||||
var tstamp uint64
|
|
||||||
switch {
|
|
||||||
case !wire_chop_uint64(&pType, &bs):
|
|
||||||
return false
|
|
||||||
case pType != wire_SwitchHopRequest:
|
|
||||||
return false
|
|
||||||
case !wire_chop_slice(m.Root[:], &bs):
|
|
||||||
return false
|
|
||||||
case !wire_chop_uint64(&tstamp, &bs):
|
|
||||||
return false
|
|
||||||
case !wire_chop_uint64(&m.Seq, &bs):
|
|
||||||
return false
|
|
||||||
case !wire_chop_uint64(&m.Hop, &bs):
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
m.Tstamp = wire_intFromUint(tstamp)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type msgHop struct {
|
|
||||||
Root sigPubKey
|
|
||||||
Tstamp int64
|
|
||||||
Seq uint64
|
|
||||||
Hop uint64
|
|
||||||
Port switchPort
|
|
||||||
Next sigPubKey
|
|
||||||
Sig sigBytes
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *msgHop) encode() []byte {
|
|
||||||
bs := wire_encode_uint64(wire_SwitchHop)
|
|
||||||
bs = append(bs, m.Root[:]...)
|
|
||||||
bs = append(bs, wire_encode_uint64(wire_intToUint(m.Tstamp))...)
|
|
||||||
bs = append(bs, wire_encode_uint64(m.Seq)...)
|
|
||||||
bs = append(bs, wire_encode_uint64(m.Hop)...)
|
|
||||||
bs = append(bs, wire_encode_uint64(uint64(m.Port))...)
|
|
||||||
bs = append(bs, m.Next[:]...)
|
|
||||||
bs = append(bs, m.Sig[:]...)
|
|
||||||
return bs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *msgHop) decode(bs []byte) bool {
|
|
||||||
var pType uint64
|
|
||||||
var tstamp uint64
|
|
||||||
switch {
|
|
||||||
case !wire_chop_uint64(&pType, &bs):
|
|
||||||
return false
|
|
||||||
case pType != wire_SwitchHop:
|
|
||||||
return false
|
|
||||||
case !wire_chop_slice(m.Root[:], &bs):
|
|
||||||
return false
|
|
||||||
case !wire_chop_uint64(&tstamp, &bs):
|
|
||||||
return false
|
|
||||||
case !wire_chop_uint64(&m.Seq, &bs):
|
|
||||||
return false
|
|
||||||
case !wire_chop_uint64(&m.Hop, &bs):
|
|
||||||
return false
|
|
||||||
case !wire_chop_uint64((*uint64)(&m.Port), &bs):
|
|
||||||
return false
|
|
||||||
case !wire_chop_slice(m.Next[:], &bs):
|
|
||||||
return false
|
|
||||||
case !wire_chop_slice(m.Sig[:], &bs):
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
m.Tstamp = wire_intFromUint(tstamp)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format used to check signatures only, so no need to also support decoding
|
|
||||||
func wire_encode_locator(loc *switchLocator) []byte {
|
|
||||||
coords := wire_encode_coords(loc.getCoords())
|
|
||||||
var bs []byte
|
|
||||||
bs = append(bs, loc.root[:]...)
|
|
||||||
bs = append(bs, wire_encode_uint64(wire_intToUint(loc.tstamp))...)
|
|
||||||
bs = append(bs, coords...)
|
|
||||||
return bs
|
|
||||||
}
|
|
||||||
|
|
||||||
func wire_chop_slice(toSlice []byte, fromSlice *[]byte) bool {
|
func wire_chop_slice(toSlice []byte, fromSlice *[]byte) bool {
|
||||||
if len(*fromSlice) < len(toSlice) {
|
if len(*fromSlice) < len(toSlice) {
|
||||||
@ -290,7 +192,6 @@ func wire_chop_uint64(toUInt64 *uint64, fromSlice *[]byte) bool {
|
|||||||
// Wire traffic packets
|
// Wire traffic packets
|
||||||
|
|
||||||
type wire_trafficPacket struct {
|
type wire_trafficPacket struct {
|
||||||
TTL uint64
|
|
||||||
Coords []byte
|
Coords []byte
|
||||||
Handle handle
|
Handle handle
|
||||||
Nonce boxNonce
|
Nonce boxNonce
|
||||||
@ -301,7 +202,6 @@ type wire_trafficPacket struct {
|
|||||||
func (p *wire_trafficPacket) encode() []byte {
|
func (p *wire_trafficPacket) encode() []byte {
|
||||||
bs := util_getBytes()
|
bs := util_getBytes()
|
||||||
bs = wire_put_uint64(wire_Traffic, bs)
|
bs = wire_put_uint64(wire_Traffic, bs)
|
||||||
bs = wire_put_uint64(p.TTL, bs)
|
|
||||||
bs = wire_put_coords(p.Coords, bs)
|
bs = wire_put_coords(p.Coords, bs)
|
||||||
bs = append(bs, p.Handle[:]...)
|
bs = append(bs, p.Handle[:]...)
|
||||||
bs = append(bs, p.Nonce[:]...)
|
bs = append(bs, p.Nonce[:]...)
|
||||||
@ -317,8 +217,6 @@ func (p *wire_trafficPacket) decode(bs []byte) bool {
|
|||||||
return false
|
return false
|
||||||
case pType != wire_Traffic:
|
case pType != wire_Traffic:
|
||||||
return false
|
return false
|
||||||
case !wire_chop_uint64(&p.TTL, &bs):
|
|
||||||
return false
|
|
||||||
case !wire_chop_coords(&p.Coords, &bs):
|
case !wire_chop_coords(&p.Coords, &bs):
|
||||||
return false
|
return false
|
||||||
case !wire_chop_slice(p.Handle[:], &bs):
|
case !wire_chop_slice(p.Handle[:], &bs):
|
||||||
@ -331,7 +229,6 @@ func (p *wire_trafficPacket) decode(bs []byte) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type wire_protoTrafficPacket struct {
|
type wire_protoTrafficPacket struct {
|
||||||
TTL uint64
|
|
||||||
Coords []byte
|
Coords []byte
|
||||||
ToKey boxPubKey
|
ToKey boxPubKey
|
||||||
FromKey boxPubKey
|
FromKey boxPubKey
|
||||||
@ -342,7 +239,6 @@ type wire_protoTrafficPacket struct {
|
|||||||
func (p *wire_protoTrafficPacket) encode() []byte {
|
func (p *wire_protoTrafficPacket) encode() []byte {
|
||||||
coords := wire_encode_coords(p.Coords)
|
coords := wire_encode_coords(p.Coords)
|
||||||
bs := wire_encode_uint64(wire_ProtocolTraffic)
|
bs := wire_encode_uint64(wire_ProtocolTraffic)
|
||||||
bs = append(bs, wire_encode_uint64(p.TTL)...)
|
|
||||||
bs = append(bs, coords...)
|
bs = append(bs, coords...)
|
||||||
bs = append(bs, p.ToKey[:]...)
|
bs = append(bs, p.ToKey[:]...)
|
||||||
bs = append(bs, p.FromKey[:]...)
|
bs = append(bs, p.FromKey[:]...)
|
||||||
@ -358,8 +254,6 @@ func (p *wire_protoTrafficPacket) decode(bs []byte) bool {
|
|||||||
return false
|
return false
|
||||||
case pType != wire_ProtocolTraffic:
|
case pType != wire_ProtocolTraffic:
|
||||||
return false
|
return false
|
||||||
case !wire_chop_uint64(&p.TTL, &bs):
|
|
||||||
return false
|
|
||||||
case !wire_chop_coords(&p.Coords, &bs):
|
case !wire_chop_coords(&p.Coords, &bs):
|
||||||
return false
|
return false
|
||||||
case !wire_chop_slice(p.ToKey[:], &bs):
|
case !wire_chop_slice(p.ToKey[:], &bs):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user