5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-11-22 15:20:30 +00:00

Merge pull request #1 from neilalexander/master

Add support for tun ifname on Linux, run gofmt
This commit is contained in:
Arceliar 2018-01-04 16:50:27 -06:00 committed by GitHub
commit b76fcbb402
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 5051 additions and 4286 deletions

View File

@ -22,15 +22,21 @@ var doSig = flag.Bool("sig", false, "generate new signing keys instead")
func main() { func main() {
flag.Parse() flag.Parse()
switch { switch {
case *doSig: doSigKeys() case *doSig:
default: doBoxKeys() doSigKeys()
default:
doBoxKeys()
} }
} }
func isBetter(oldID, newID []byte) bool { func isBetter(oldID, newID []byte) bool {
for idx := range oldID { for idx := range oldID {
if newID[idx] > oldID[idx] { return true } if newID[idx] > oldID[idx] {
if newID[idx] < oldID[idx] { return false } return true
}
if newID[idx] < oldID[idx] {
return false
}
} }
return false return false
} }
@ -45,7 +51,9 @@ func doBoxKeys() {
for { for {
pub, priv := c.DEBUG_newBoxKeys() pub, priv := c.DEBUG_newBoxKeys()
id := c.DEBUG_getNodeID(pub) id := c.DEBUG_getNodeID(pub)
if !isBetter(bestID[:], id[:]) { continue } if !isBetter(bestID[:], id[:]) {
continue
}
bestID = id bestID = id
ip := c.DEBUG_addrForNodeID(id) ip := c.DEBUG_addrForNodeID(id)
fmt.Println("--------------------------------------------------------------------------------") fmt.Println("--------------------------------------------------------------------------------")
@ -66,7 +74,9 @@ func doSigKeys() {
for { for {
pub, priv := c.DEBUG_newSigKeys() pub, priv := c.DEBUG_newSigKeys()
id := c.DEBUG_getTreeID(pub) id := c.DEBUG_getTreeID(pub)
if !isBetter(bestID[:], id[:]) { continue } if !isBetter(bestID[:], id[:]) {
continue
}
bestID = id bestID = id
fmt.Println("--------------------------------------------------------------------------------") fmt.Println("--------------------------------------------------------------------------------")
fmt.Println("sigPriv:", hex.EncodeToString(priv[:])) fmt.Println("sigPriv:", hex.EncodeToString(priv[:]))
@ -74,4 +84,3 @@ func doSigKeys() {
fmt.Println("TreeID:", hex.EncodeToString(id[:])) fmt.Println("TreeID:", hex.EncodeToString(id[:]))
} }
} }

View File

@ -39,10 +39,10 @@ func linkNodes(m, n *Node) {
func makeStoreSquareGrid(sideLength int) map[router.NodeID]*Node { func makeStoreSquareGrid(sideLength int) map[router.NodeID]*Node {
store := make(map[router.NodeID]*Node) store := make(map[router.NodeID]*Node)
nNodes := sideLength*sideLength nNodes := sideLength * sideLength
nodeIDs := make([]router.NodeID, 0, nNodes) nodeIDs := make([]router.NodeID, 0, nNodes)
// TODO shuffle nodeIDs // TODO shuffle nodeIDs
for nodeID := 1 ; nodeID <= nNodes ; nodeID++ { for nodeID := 1; nodeID <= nNodes; nodeID++ {
nodeIDs = append(nodeIDs, router.NodeID(nodeID)) nodeIDs = append(nodeIDs, router.NodeID(nodeID))
} }
for _, nodeID := range nodeIDs { for _, nodeID := range nodeIDs {
@ -50,7 +50,7 @@ func makeStoreSquareGrid(sideLength int) map[router.NodeID]*Node {
node.init(nodeID) node.init(nodeID)
store[nodeID] = node store[nodeID] = node
} }
for idx := 0 ; idx < nNodes ; idx++ { for idx := 0; idx < nNodes; idx++ {
if (idx % sideLength) != 0 { if (idx % sideLength) != 0 {
linkNodes(store[nodeIDs[idx]], store[nodeIDs[idx-1]]) linkNodes(store[nodeIDs[idx]], store[nodeIDs[idx-1]])
} }
@ -63,7 +63,9 @@ func makeStoreSquareGrid(sideLength int) map[router.NodeID]*Node {
func loadGraph(path string) map[router.NodeID]*Node { func loadGraph(path string) map[router.NodeID]*Node {
f, err := os.Open(path) f, err := os.Open(path)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer f.Close() defer f.Close()
store := make(map[router.NodeID]*Node) store := make(map[router.NodeID]*Node)
s := bufio.NewScanner(f) s := bufio.NewScanner(f)
@ -95,7 +97,7 @@ func idleUntilConverged(store map[router.NodeID]*Node) {
timeOfLastChange := 0 timeOfLastChange := 0
step := 0 step := 0
// Idle untl the network has converged // Idle untl the network has converged
for step - timeOfLastChange < 4*router.TIMEOUT { for step-timeOfLastChange < 4*router.TIMEOUT {
step++ step++
fmt.Println("Step:", step, "--", "last change:", timeOfLastChange) fmt.Println("Step:", step, "--", "last change:", timeOfLastChange)
for _, node := range store { for _, node := range store {
@ -134,9 +136,11 @@ func testPaths(store map[router.NodeID]*Node) {
//if source == dest { continue } //if source == dest { continue }
destLoc := dest.table.GetLocator() destLoc := dest.table.GetLocator()
temp := 0 temp := 0
for here := source ; here != dest ; { for here := source; here != dest; {
temp++ temp++
if temp > 16 { panic("Loop?") } if temp > 16 {
panic("Loop?")
}
next := here.links[here.table.Lookup(destLoc)] next := here.links[here.table.Lookup(destLoc)]
if next == here { if next == here {
//for idx, link := range here.links { //for idx, link := range here.links {

View File

@ -46,7 +46,9 @@ func (n *Node) startPeers() {
func linkNodes(m, n *Node) { func linkNodes(m, n *Node) {
// Don't allow duplicates // Don't allow duplicates
if m.core.DEBUG_getPeers().DEBUG_hasPeer(n.core.DEBUG_getSigPub()) { return } if m.core.DEBUG_getPeers().DEBUG_hasPeer(n.core.DEBUG_getSigPub()) {
return
}
// Create peers // Create peers
// Buffering reduces packet loss in the sim // Buffering reduces packet loss in the sim
// This slightly speeds up testing (fewer delays before retrying a ping) // This slightly speeds up testing (fewer delays before retrying a ping)
@ -60,10 +62,10 @@ func linkNodes(m, n *Node) {
func makeStoreSquareGrid(sideLength int) map[int]*Node { func makeStoreSquareGrid(sideLength int) map[int]*Node {
store := make(map[int]*Node) store := make(map[int]*Node)
nNodes := sideLength*sideLength nNodes := sideLength * sideLength
idxs := make([]int, 0, nNodes) idxs := make([]int, 0, nNodes)
// TODO shuffle nodeIDs // TODO shuffle nodeIDs
for idx := 1 ; idx <= nNodes ; idx++ { for idx := 1; idx <= nNodes; idx++ {
idxs = append(idxs, idx) idxs = append(idxs, idx)
} }
for _, idx := range idxs { for _, idx := range idxs {
@ -71,7 +73,7 @@ func makeStoreSquareGrid(sideLength int) map[int]*Node {
node.init(idx) node.init(idx)
store[idx] = node store[idx] = node
} }
for idx := 0 ; idx < nNodes ; idx++ { for idx := 0; idx < nNodes; idx++ {
if (idx % sideLength) != 0 { if (idx % sideLength) != 0 {
linkNodes(store[idxs[idx]], store[idxs[idx-1]]) linkNodes(store[idxs[idx]], store[idxs[idx-1]])
} }
@ -88,7 +90,7 @@ func makeStoreStar(nNodes int) map[int]*Node {
center := &Node{} center := &Node{}
center.init(0) center.init(0)
store[0] = center store[0] = center
for idx := 1 ; idx < nNodes ; idx++ { for idx := 1; idx < nNodes; idx++ {
node := &Node{} node := &Node{}
node.init(idx) node.init(idx)
store[idx] = node store[idx] = node
@ -99,7 +101,9 @@ func makeStoreStar(nNodes int) map[int]*Node {
func loadGraph(path string) map[int]*Node { func loadGraph(path string) map[int]*Node {
f, err := os.Open(path) f, err := os.Open(path)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer f.Close() defer f.Close()
store := make(map[int]*Node) store := make(map[int]*Node)
s := bufio.NewScanner(f) s := bufio.NewScanner(f)
@ -153,13 +157,15 @@ func testPaths(store map[[32]byte]*Node) bool {
temp := 0 temp := 0
ttl := ^uint64(0) ttl := ^uint64(0)
oldTTL := ttl oldTTL := ttl
for here := source ; here != dest ; { for here := source; here != dest; {
if ttl == 0 { if ttl == 0 {
fmt.Println("Drop:", source.index, here.index, dest.index, oldTTL) fmt.Println("Drop:", source.index, here.index, dest.index, oldTTL)
return false return false
} }
temp++ temp++
if temp > 4096 { panic("Loop?") } if temp > 4096 {
panic("Loop?")
}
oldTTL = ttl oldTTL = ttl
nextPort, newTTL := here.core.DEBUG_switchLookup(coords, ttl) nextPort, newTTL := here.core.DEBUG_switchLookup(coords, ttl)
ttl = newTTL ttl = newTTL
@ -195,7 +201,7 @@ func testPaths(store map[[32]byte]*Node) bool {
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
} }
@ -234,10 +240,14 @@ func pingNodes(store map[[32]byte]*Node) {
fmt.Println("Sending pings...") fmt.Println("Sending pings...")
nNodes := len(store) nNodes := len(store)
count := 0 count := 0
equiv := func (a []byte, b []byte) bool { equiv := func(a []byte, b []byte) bool {
if len(a) != len(b) { return false } if len(a) != len(b) {
for idx := 0 ; idx < len(a) ; idx++ { return false
if a[idx] != b[idx] { return false } }
for idx := 0; idx < len(a); idx++ {
if a[idx] != b[idx] {
return false
}
} }
return true return true
} }
@ -248,12 +258,12 @@ func pingNodes(store map[[32]byte]*Node) {
sourceKey := source.core.DEBUG_getBoxPub() sourceKey := source.core.DEBUG_getBoxPub()
payload := sourceKey[:] payload := sourceKey[:]
sourceAddr := source.core.DEBUG_getAddr()[:] sourceAddr := source.core.DEBUG_getAddr()[:]
sendTo := func (bs []byte, destAddr []byte) { sendTo := func(bs []byte, destAddr []byte) {
packet := make([]byte, 40+len(bs)) packet := make([]byte, 40+len(bs))
copy(packet[8:24], sourceAddr) copy(packet[8:24], sourceAddr)
copy(packet[24:40], destAddr) copy(packet[24:40], destAddr)
copy(packet[40:], bs) copy(packet[40:], bs)
source.send<-packet source.send <- packet
} }
destCount := 0 destCount := 0
for _, dest := range store { for _, dest := range store {
@ -264,26 +274,28 @@ func pingNodes(store map[[32]byte]*Node) {
continue continue
} }
destAddr := dest.core.DEBUG_getAddr()[:] destAddr := dest.core.DEBUG_getAddr()[:]
ticker := time.NewTicker(150*time.Millisecond) ticker := time.NewTicker(150 * time.Millisecond)
ch := make(chan bool, 1) ch := make(chan bool, 1)
ch<-true ch <- true
doTicker := func () { doTicker := func() {
for _ = range ticker.C { for range ticker.C {
select { select {
case ch<-true: case ch <- true:
default: default:
} }
} }
} }
go doTicker() go doTicker()
for loop := true ; loop ; { for loop := true; loop; {
select { select {
case packet := <-dest.recv: { case packet := <-dest.recv:
{
if equiv(payload, packet[len(packet)-len(payload):]) { if equiv(payload, packet[len(packet)-len(payload):]) {
loop = false loop = false
} }
} }
case <-ch: sendTo(payload, destAddr) case <-ch:
sendTo(payload, destAddr)
} }
} }
ticker.Stop() ticker.Stop()
@ -305,7 +317,7 @@ func pingBench(store map[[32]byte]*Node) {
for _, source := range store { for _, source := range store {
count++ count++
//fmt.Printf("Sending packets from node %d/%d (%d)\n", count, nNodes, source.index) //fmt.Printf("Sending packets from node %d/%d (%d)\n", count, nNodes, source.index)
getPing := func (key [32]byte, decodedCoords []byte) []byte { getPing := func(key [32]byte, decodedCoords []byte) []byte {
// TODO write some function to do this the right way, put... somewhere... // TODO write some function to do this the right way, put... somewhere...
coords := DEBUG_wire_encode_coords(decodedCoords) coords := DEBUG_wire_encode_coords(decodedCoords)
packet := make([]byte, 0, len(key)+len(coords)+len(payload)) packet := make([]byte, 0, len(key)+len(coords)+len(payload))
@ -321,7 +333,10 @@ func pingBench(store map[[32]byte]*Node) {
ping := getPing(key, coords) ping := getPing(key, coords)
// TODO make sure the session is open first // TODO make sure the session is open first
start := time.Now() start := time.Now()
for i := 0 ; i < 1000000 ; i++{ source.send<-ping ; nPings++ } for i := 0; i < 1000000; i++ {
source.send <- ping
nPings++
}
timed += time.Since(start) timed += time.Since(start)
break break
} }
@ -350,11 +365,15 @@ func dumpDHTSize(store map[[32]byte]*Node) {
} }
for _, node := range store { for _, node := range store {
num := node.core.DEBUG_getDHTSize() num := node.core.DEBUG_getDHTSize()
if num < min { min = num } if num < min {
if num > max { max = num } min = num
}
if num > max {
max = num
}
sum += num sum += num
} }
avg := float64(sum)/float64(len(store)) avg := float64(sum) / float64(len(store))
fmt.Printf("DHT min %d / avg %f / max %d\n", min, avg, max) fmt.Printf("DHT min %d / avg %f / max %d\n", min, avg, max)
} }
@ -380,7 +399,7 @@ func main() {
if err != nil { if err != nil {
panic(fmt.Sprintf("could not create memory profile: ", err)) panic(fmt.Sprintf("could not create memory profile: ", err))
} }
defer func () { pprof.WriteHeapProfile(f) ; f.Close() }() defer func() { pprof.WriteHeapProfile(f); f.Close() }()
} }
fmt.Println("Test") fmt.Println("Test")
Util_testAddrIDMask() Util_testAddrIDMask()
@ -400,11 +419,12 @@ func main() {
//time.Sleep(10*time.Second) //time.Sleep(10*time.Second)
// Note that testPaths only works if pressure is turend off // Note that testPaths only works if pressure is turend off
// Otherwise congestion can lead to routing loops? // Otherwise congestion can lead to routing loops?
for finished := false; !finished ; { finished = testPaths(kstore) } for finished := false; !finished; {
finished = testPaths(kstore)
}
pingNodes(kstore) pingNodes(kstore)
//pingBench(kstore) // Only after disabling debug output //pingBench(kstore) // Only after disabling debug output
//stressTest(kstore) //stressTest(kstore)
//time.Sleep(120*time.Second) //time.Sleep(120*time.Second)
dumpDHTSize(kstore) // note that this uses racey functions to read things... dumpDHTSize(kstore) // note that this uses racey functions to read things...
} }

View File

@ -8,15 +8,15 @@ import "runtime"
func main() { func main() {
var ops uint64 = 0 var ops uint64 = 0
for i := 0 ; i < 4 ; i++ { for i := 0; i < 4; i++ {
go func () { go func() {
for { for {
atomic.AddUint64(&ops, 1) atomic.AddUint64(&ops, 1)
runtime.Gosched() runtime.Gosched()
} }
}() }()
} }
time.Sleep(1*time.Second) time.Sleep(1 * time.Second)
opsFinal := atomic.LoadUint64(&ops) opsFinal := atomic.LoadUint64(&ops)
fmt.Println("ops:", opsFinal) fmt.Println("ops:", opsFinal)
} }

View File

@ -4,39 +4,50 @@ import "fmt"
import "net" import "net"
import "time" import "time"
func main () { func main() {
addr, err := net.ResolveTCPAddr("tcp", "[::1]:9001") addr, err := net.ResolveTCPAddr("tcp", "[::1]:9001")
if err != nil { panic(err) } if err != nil {
panic(err)
}
listener, err := net.ListenTCP("tcp", addr) listener, err := net.ListenTCP("tcp", addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer listener.Close() defer listener.Close()
packetSize := 65535 packetSize := 65535
numPackets := 65535 numPackets := 65535
go func () { go func() {
send, err := net.DialTCP("tcp", nil, addr) send, err := net.DialTCP("tcp", nil, addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer send.Close() defer send.Close()
msg := make([]byte, packetSize) msg := make([]byte, packetSize)
for idx := 0 ; idx < numPackets ; idx++ { send.Write(msg) } for idx := 0; idx < numPackets; idx++ {
send.Write(msg)
}
}() }()
start := time.Now() start := time.Now()
//msg := make([]byte, 1280) //msg := make([]byte, 1280)
sock, err := listener.AcceptTCP() sock, err := listener.AcceptTCP()
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer sock.Close() defer sock.Close()
read := 0 read := 0
buf := make([]byte, packetSize) buf := make([]byte, packetSize)
for { for {
n, err := sock.Read(buf) n, err := sock.Read(buf)
read += n read += n
if err != nil { break } if err != nil {
break
}
} }
timed := time.Since(start) timed := time.Since(start)
fmt.Printf("%f packets per second\n", float64(numPackets)/timed.Seconds()) fmt.Printf("%f packets per second\n", float64(numPackets)/timed.Seconds())
fmt.Printf("%f bits/sec\n", 8*float64(read)/timed.Seconds()) fmt.Printf("%f bits/sec\n", 8*float64(read)/timed.Seconds())
} }

View File

@ -8,13 +8,13 @@ func main() {
fmt.Println("Testing speed of recv+send loop") fmt.Println("Testing speed of recv+send loop")
const count = 10000000 const count = 10000000
c := make(chan []byte, 1) c := make(chan []byte, 1)
c<-[]byte{} c <- []byte{}
var wg sync.WaitGroup var wg sync.WaitGroup
worker := func () { worker := func() {
for idx := 0 ; idx < count ; idx++ { for idx := 0; idx < count; idx++ {
p := <-c p := <-c
select { select {
case c<-p: case c <- p:
default: default:
} }
} }
@ -22,7 +22,7 @@ func main() {
} }
nIter := 0 nIter := 0
start := time.Now() start := time.Now()
for idx := 0 ; idx < 1 ; idx++ { for idx := 0; idx < 1; idx++ {
go worker() go worker()
nIter += count nIter += count
wg.Add(1) wg.Add(1)

View File

@ -11,7 +11,6 @@ type testStruct struct {
Third []byte Third []byte
} }
func testFunc(tickerDuration time.Duration) { func testFunc(tickerDuration time.Duration) {
chn := make(chan []byte) chn := make(chan []byte)
ticker := time.NewTicker(tickerDuration) ticker := time.NewTicker(tickerDuration)
@ -20,33 +19,38 @@ func testFunc(tickerDuration time.Duration) {
buf := bytes.NewBuffer(nil) buf := bytes.NewBuffer(nil)
enc := gob.NewEncoder(buf) enc := gob.NewEncoder(buf)
dec := gob.NewDecoder(buf) dec := gob.NewDecoder(buf)
sendCall := func () { sendCall := func() {
err := enc.EncodeValue(&send) err := enc.EncodeValue(&send)
if err != nil { panic(err) } if err != nil {
panic(err)
}
bs := make([]byte, buf.Len()) bs := make([]byte, buf.Len())
buf.Read(bs) buf.Read(bs)
fmt.Println("send:", bs) fmt.Println("send:", bs)
go func() { chn<-bs }() go func() { chn <- bs }()
} }
recvCall := func (bs []byte) { recvCall := func(bs []byte) {
buf.Write(bs) buf.Write(bs)
recv := testStruct{} recv := testStruct{}
err := dec.DecodeValue(&recv) err := dec.DecodeValue(&recv)
fmt.Println("recv:", bs) fmt.Println("recv:", bs)
if err != nil { panic(err) } if err != nil {
panic(err)
}
} }
for { for {
select { select {
case bs := <-chn : recvCall(bs) case bs := <-chn:
case <-ticker.C : sendCall() recvCall(bs)
case <-ticker.C:
sendCall()
} }
} }
} }
func main() { func main() {
go testFunc(100*time.Millisecond) // Does not crash go testFunc(100 * time.Millisecond) // Does not crash
time.Sleep(time.Second) time.Sleep(time.Second)
go testFunc(time.Nanosecond) // Does crash go testFunc(time.Nanosecond) // Does crash
time.Sleep(time.Second) time.Sleep(time.Second)
} }

View File

@ -4,13 +4,13 @@ import "sync"
import "time" import "time"
import "fmt" import "fmt"
func main () { func main() {
const reqs = 1000000 const reqs = 1000000
var wg sync.WaitGroup var wg sync.WaitGroup
start := time.Now() start := time.Now()
for idx := 0 ; idx < reqs ; idx++ { for idx := 0; idx < reqs; idx++ {
wg.Add(1) wg.Add(1)
go func () { wg.Done() } () go func() { wg.Done() }()
} }
wg.Wait() wg.Wait()
stop := time.Now() stop := time.Now()

View File

@ -11,16 +11,24 @@ func basic_test() {
// TODO need a way to look up who our link-local neighbors are for each iface! // TODO need a way to look up who our link-local neighbors are for each iface!
//addr, err := net.ResolveUDPAddr("udp", "[ff02::1%veth0]:9001") //addr, err := net.ResolveUDPAddr("udp", "[ff02::1%veth0]:9001")
addr, err := net.ResolveUDPAddr("udp", "[ff02::1]:9001") addr, err := net.ResolveUDPAddr("udp", "[ff02::1]:9001")
if err != nil { panic(err) } if err != nil {
panic(err)
}
sock, err := net.ListenMulticastUDP("udp", nil, addr) sock, err := net.ListenMulticastUDP("udp", nil, addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer sock.Close() defer sock.Close()
go func () { go func() {
saddr, err := net.ResolveUDPAddr("udp", "[::]:0") saddr, err := net.ResolveUDPAddr("udp", "[::]:0")
if err != nil { panic(err) } if err != nil {
panic(err)
}
send, err := net.ListenUDP("udp", saddr) send, err := net.ListenUDP("udp", saddr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer send.Close() defer send.Close()
msg := make([]byte, 1280) msg := make([]byte, 1280)
for { for {
@ -32,7 +40,7 @@ func basic_test() {
numPackets := 1000 numPackets := 1000
start := time.Now() start := time.Now()
msg := make([]byte, 2000) msg := make([]byte, 2000)
for i := 0 ; i < numPackets ; i++ { for i := 0; i < numPackets; i++ {
//fmt.Println("Reading:", i) //fmt.Println("Reading:", i)
sock.ReadFromUDP(msg) sock.ReadFromUDP(msg)
} }
@ -42,7 +50,7 @@ func basic_test() {
} }
func main () { func main() {
basic_test() basic_test()

View File

@ -4,7 +4,6 @@ import "fmt"
import "net" import "net"
import "time" import "time"
// TODO look into netmap + libpcap to bypass the kernel as much as possible // TODO look into netmap + libpcap to bypass the kernel as much as possible
func basic_test() { func basic_test() {
@ -13,25 +12,37 @@ func basic_test() {
var ip *net.IP var ip *net.IP
ifaces, err := net.Interfaces() ifaces, err := net.Interfaces()
if err != nil { panic(err) } if err != nil {
panic(err)
}
var zone string var zone string
for _, iface := range ifaces { for _, iface := range ifaces {
addrs, err := iface.Addrs() addrs, err := iface.Addrs()
if err != nil { panic(err) } if err != nil {
panic(err)
}
for _, addr := range addrs { for _, addr := range addrs {
addrIP, _, _ := net.ParseCIDR(addr.String()) addrIP, _, _ := net.ParseCIDR(addr.String())
if addrIP.To4() != nil { continue } // IPv6 only if addrIP.To4() != nil {
if !addrIP.IsLinkLocalUnicast() { continue } continue
} // IPv6 only
if !addrIP.IsLinkLocalUnicast() {
continue
}
zone = iface.Name zone = iface.Name
ip = &addrIP ip = &addrIP
} }
addrs, err = iface.MulticastAddrs() addrs, err = iface.MulticastAddrs()
if err != nil { panic(err) } if err != nil {
panic(err)
}
for _, addr := range addrs { for _, addr := range addrs {
fmt.Println(addr.String()) fmt.Println(addr.String())
} }
} }
if ip == nil { panic("No link-local IPv6 found") } if ip == nil {
panic("No link-local IPv6 found")
}
fmt.Println("Using address:", *ip) fmt.Println("Using address:", *ip)
addr := net.UDPAddr{IP: *ip, Port: 9001, Zone: zone} addr := net.UDPAddr{IP: *ip, Port: 9001, Zone: zone}
@ -39,19 +50,22 @@ func basic_test() {
saddr := net.UDPAddr{IP: *ip, Port: 9002, Zone: zone} saddr := net.UDPAddr{IP: *ip, Port: 9002, Zone: zone}
send, err := net.ListenUDP("udp", &saddr) send, err := net.ListenUDP("udp", &saddr)
defer send.Close() defer send.Close()
if err != nil { panic(err) } if err != nil {
panic(err)
}
sock, err := net.ListenUDP("udp", &addr) sock, err := net.ListenUDP("udp", &addr)
defer sock.Close() defer sock.Close()
if err != nil { panic(err) } if err != nil {
panic(err)
}
const buffSize = 1048576*100 const buffSize = 1048576 * 100
send.SetWriteBuffer(buffSize) send.SetWriteBuffer(buffSize)
sock.SetReadBuffer(buffSize) sock.SetReadBuffer(buffSize)
sock.SetWriteBuffer(buffSize) sock.SetWriteBuffer(buffSize)
go func() {
go func () {
msg := make([]byte, 1280) msg := make([]byte, 1280)
for { for {
send.WriteTo(msg, &addr) send.WriteTo(msg, &addr)
@ -61,7 +75,7 @@ func basic_test() {
numPackets := 100000 numPackets := 100000
start := time.Now() start := time.Now()
msg := make([]byte, 2000) msg := make([]byte, 2000)
for i := 0 ; i < numPackets ; i++ { for i := 0; i < numPackets; i++ {
_, addr, _ := sock.ReadFrom(msg) _, addr, _ := sock.ReadFrom(msg)
sock.WriteTo(msg, addr) sock.WriteTo(msg, addr)
} }
@ -71,7 +85,7 @@ func basic_test() {
} }
func main () { func main() {
basic_test() basic_test()

View File

@ -1,6 +1,7 @@
package main package main
import "fmt" import "fmt"
//import "net" //import "net"
import "time" import "time"
import "runtime" import "runtime"
@ -17,8 +18,9 @@ func poolbench() {
f := <-ch f := <-ch
f() f()
select { select {
case workers<-(ch): case workers <- (ch):
default: return default:
return
} }
} }
}() }()
@ -26,48 +28,52 @@ func poolbench() {
} }
getWorker := func() chan<- func() { getWorker := func() chan<- func() {
select { select {
case ch := <-workers: return ch case ch := <-workers:
default: return makeWorker() return ch
default:
return makeWorker()
} }
} }
dispatcher := func() { dispatcher := func() {
for { for {
w := <-work w := <-work
ch := getWorker() ch := getWorker()
ch<-w ch <- w
} }
} }
go dispatcher() go dispatcher()
var count uint64 var count uint64
const nCounts = 1000000 const nCounts = 1000000
for idx := 0 ; idx < nCounts ; idx++ { for idx := 0; idx < nCounts; idx++ {
f := func() { atomic.AddUint64(&count, 1) } f := func() { atomic.AddUint64(&count, 1) }
work <- f work <- f
} }
for atomic.LoadUint64(&count) < nCounts {} for atomic.LoadUint64(&count) < nCounts {
}
} }
func normalbench() { func normalbench() {
var count uint64 var count uint64
const nCounts = 1000000 const nCounts = 1000000
ch := make(chan struct{}, 1) ch := make(chan struct{}, 1)
ch<-struct{}{} ch <- struct{}{}
for idx := 0 ; idx < nCounts ; idx++ { for idx := 0; idx < nCounts; idx++ {
f := func() { atomic.AddUint64(&count, 1) } f := func() { atomic.AddUint64(&count, 1) }
f() f()
<-ch <-ch
ch<-struct{}{} ch <- struct{}{}
} }
} }
func gobench() { func gobench() {
var count uint64 var count uint64
const nCounts = 1000000 const nCounts = 1000000
for idx := 0 ; idx < nCounts ; idx++ { for idx := 0; idx < nCounts; idx++ {
f := func() { atomic.AddUint64(&count, 1) } f := func() { atomic.AddUint64(&count, 1) }
go f() go f()
} }
for atomic.LoadUint64(&count) < nCounts {} for atomic.LoadUint64(&count) < nCounts {
}
} }
func main() { func main() {

View File

@ -1,39 +1,47 @@
package main package main
import ( import (
"fmt"
"time"
"bytes" "bytes"
"sync"
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"encoding/pem" "encoding/pem"
"math/big" "fmt"
quic "github.com/lucas-clemente/quic-go" quic "github.com/lucas-clemente/quic-go"
"math/big"
"sync"
"time"
) )
const addr = "[::1]:9001" const addr = "[::1]:9001"
func main () { func main() {
go run_server() go run_server()
run_client() run_client()
} }
func run_server() { func run_server() {
listener, err := quic.ListenAddr(addr, generateTLSConfig(), nil) listener, err := quic.ListenAddr(addr, generateTLSConfig(), nil)
if err != nil { panic(err) } if err != nil {
panic(err)
}
ses, err := listener.Accept() ses, err := listener.Accept()
if err != nil { panic(err) } if err != nil {
panic(err)
}
for { for {
stream, err := ses.AcceptStream() stream, err := ses.AcceptStream()
if err != nil { panic(err) } if err != nil {
panic(err)
}
go func() { go func() {
defer stream.Close() defer stream.Close()
bs := bytes.Buffer{} bs := bytes.Buffer{}
_, err := bs.ReadFrom(stream) _, err := bs.ReadFrom(stream)
if err != nil { panic(err) } //<-- TooManyOpenStreams if err != nil {
panic(err)
} //<-- TooManyOpenStreams
}() }()
} }
} }
@ -42,16 +50,20 @@ func run_client() {
msgSize := 1048576 msgSize := 1048576
msgCount := 128 msgCount := 128
ses, err := quic.DialAddr(addr, &tls.Config{InsecureSkipVerify: true}, nil) ses, err := quic.DialAddr(addr, &tls.Config{InsecureSkipVerify: true}, nil)
if err != nil { panic(err) } if err != nil {
panic(err)
}
bs := make([]byte, msgSize) bs := make([]byte, msgSize)
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
start := time.Now() start := time.Now()
for idx := 0 ; idx < msgCount ; idx++ { for idx := 0; idx < msgCount; idx++ {
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
stream, err := ses.OpenStreamSync() stream, err := ses.OpenStreamSync()
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer stream.Close() defer stream.Close()
stream.Write(bs) stream.Write(bs)
}() // "go" this later }() // "go" this later
@ -81,4 +93,3 @@ func generateTLSConfig() *tls.Config {
} }
return &tls.Config{Certificates: []tls.Certificate{tlsCert}} return &tls.Config{Certificates: []tls.Certificate{tlsCert}}
} }

View File

@ -14,14 +14,20 @@ func basic_test() {
// TODO need a way to look up who our link-local neighbors are for each iface! // TODO need a way to look up who our link-local neighbors are for each iface!
addr, err := net.ResolveUDPAddr("udp", "[::1]:9001") addr, err := net.ResolveUDPAddr("udp", "[::1]:9001")
if err != nil { panic(err) } if err != nil {
panic(err)
}
sock, err := net.ListenUDP("udp", addr) sock, err := net.ListenUDP("udp", addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer sock.Close() defer sock.Close()
go func () { go func() {
send, err := net.DialUDP("udp", nil, addr) send, err := net.DialUDP("udp", nil, addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer send.Close() defer send.Close()
msg := make([]byte, 1280) msg := make([]byte, 1280)
for { for {
@ -32,7 +38,7 @@ func basic_test() {
numPackets := 1000000 numPackets := 1000000
start := time.Now() start := time.Now()
msg := make([]byte, 2000) msg := make([]byte, 2000)
for i := 0 ; i < numPackets ; i++ { for i := 0; i < numPackets; i++ {
sock.ReadFrom(msg) sock.ReadFrom(msg)
} }
timed := time.Since(start) timed := time.Since(start)
@ -44,7 +50,7 @@ func basic_test() {
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`") var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to this file") var memprofile = flag.String("memprofile", "", "write memory profile to this file")
func main () { func main() {
flag.Parse() flag.Parse()
if *cpuprofile != "" { if *cpuprofile != "" {
f, err := os.Create(*cpuprofile) f, err := os.Create(*cpuprofile)
@ -61,9 +67,8 @@ func main () {
if err != nil { if err != nil {
panic(fmt.Sprintf("could not create memory profile: ", err)) panic(fmt.Sprintf("could not create memory profile: ", err))
} }
defer func () { pprof.WriteHeapProfile(f) ; f.Close() }() defer func() { pprof.WriteHeapProfile(f); f.Close() }()
} }
basic_test() basic_test()
} }

View File

@ -14,14 +14,20 @@ func basic_test() {
// TODO need a way to look up who our link-local neighbors are for each iface! // TODO need a way to look up who our link-local neighbors are for each iface!
addr, err := net.ResolveUDPAddr("udp", "[::1]:9001") addr, err := net.ResolveUDPAddr("udp", "[::1]:9001")
if err != nil { panic(err) } if err != nil {
panic(err)
}
sock, err := net.ListenUDP("udp", addr) sock, err := net.ListenUDP("udp", addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer sock.Close() defer sock.Close()
go func () { go func() {
send, err := net.DialUDP("udp", nil, addr) send, err := net.DialUDP("udp", nil, addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer send.Close() defer send.Close()
msg := make([]byte, 1280) msg := make([]byte, 1280)
bss := make(net.Buffers, 0, 1024) bss := make(net.Buffers, 0, 1024)
@ -38,9 +44,11 @@ func basic_test() {
numPackets := 1000 numPackets := 1000
start := time.Now() start := time.Now()
msg := make([]byte, 2000) msg := make([]byte, 2000)
for i := 0 ; i < numPackets ; i++ { for i := 0; i < numPackets; i++ {
n, err := sock.Read(msg) n, err := sock.Read(msg)
if err != nil { panic(err) } if err != nil {
panic(err)
}
fmt.Println(n) fmt.Println(n)
} }
timed := time.Since(start) timed := time.Since(start)
@ -52,7 +60,7 @@ func basic_test() {
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`") var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to this file") var memprofile = flag.String("memprofile", "", "write memory profile to this file")
func main () { func main() {
flag.Parse() flag.Parse()
if *cpuprofile != "" { if *cpuprofile != "" {
f, err := os.Create(*cpuprofile) f, err := os.Create(*cpuprofile)
@ -69,9 +77,8 @@ func main () {
if err != nil { if err != nil {
panic(fmt.Sprintf("could not create memory profile: ", err)) panic(fmt.Sprintf("could not create memory profile: ", err))
} }
defer func () { pprof.WriteHeapProfile(f) ; f.Close() }() defer func() { pprof.WriteHeapProfile(f); f.Close() }()
} }
basic_test() basic_test()
} }

View File

@ -15,20 +15,30 @@ func basic_test() {
var ip *net.IP var ip *net.IP
ifaces, err := net.Interfaces() ifaces, err := net.Interfaces()
if err != nil { panic(err) } if err != nil {
panic(err)
}
var zone string var zone string
for _, iface := range ifaces { for _, iface := range ifaces {
addrs, err := iface.Addrs() addrs, err := iface.Addrs()
if err != nil { panic(err) } if err != nil {
panic(err)
}
for _, addr := range addrs { for _, addr := range addrs {
addrIP, _, _ := net.ParseCIDR(addr.String()) addrIP, _, _ := net.ParseCIDR(addr.String())
if addrIP.To4() != nil { continue } // IPv6 only if addrIP.To4() != nil {
if !addrIP.IsLinkLocalUnicast() { continue } continue
} // IPv6 only
if !addrIP.IsLinkLocalUnicast() {
continue
}
fmt.Println(iface.Name, addrIP) fmt.Println(iface.Name, addrIP)
zone = iface.Name zone = iface.Name
ip = &addrIP ip = &addrIP
} }
if ip != nil { break } if ip != nil {
break
}
/* /*
addrs, err = iface.MulticastAddrs() addrs, err = iface.MulticastAddrs()
if err != nil { panic(err) } if err != nil { panic(err) }
@ -37,20 +47,28 @@ func basic_test() {
} }
*/ */
} }
if ip == nil { panic("No link-local IPv6 found") } if ip == nil {
panic("No link-local IPv6 found")
}
fmt.Println("Using address:", *ip) fmt.Println("Using address:", *ip)
addr := net.UDPAddr{IP: *ip, Port: 9001, Zone: zone} addr := net.UDPAddr{IP: *ip, Port: 9001, Zone: zone}
laddr, err := net.ResolveUDPAddr("udp", "[::]:9001") laddr, err := net.ResolveUDPAddr("udp", "[::]:9001")
if err != nil { panic(err) } if err != nil {
panic(err)
}
sock, err := net.ListenUDP("udp", laddr) sock, err := net.ListenUDP("udp", laddr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer sock.Close() defer sock.Close()
go func () { go func() {
send, err := net.DialUDP("udp", nil, &addr) send, err := net.DialUDP("udp", nil, &addr)
//send, err := net.ListenUDP("udp", nil) //send, err := net.ListenUDP("udp", nil)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer send.Close() defer send.Close()
msg := make([]byte, 1280) msg := make([]byte, 1280)
for { for {
@ -62,7 +80,7 @@ func basic_test() {
numPackets := 1000000 numPackets := 1000000
start := time.Now() start := time.Now()
msg := make([]byte, 2000) msg := make([]byte, 2000)
for i := 0 ; i < numPackets ; i++ { for i := 0; i < numPackets; i++ {
sock.ReadFromUDP(msg) sock.ReadFromUDP(msg)
} }
timed := time.Since(start) timed := time.Since(start)
@ -74,7 +92,7 @@ func basic_test() {
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`") var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to this file") var memprofile = flag.String("memprofile", "", "write memory profile to this file")
func main () { func main() {
flag.Parse() flag.Parse()
if *cpuprofile != "" { if *cpuprofile != "" {
f, err := os.Create(*cpuprofile) f, err := os.Create(*cpuprofile)
@ -91,9 +109,8 @@ func main () {
if err != nil { if err != nil {
panic(fmt.Sprintf("could not create memory profile: ", err)) panic(fmt.Sprintf("could not create memory profile: ", err))
} }
defer func () { pprof.WriteHeapProfile(f) ; f.Close() }() defer func() { pprof.WriteHeapProfile(f); f.Close() }()
} }
basic_test() basic_test()
} }

View File

@ -16,14 +16,20 @@ func basic_test() {
// TODO need a way to look up who our link-local neighbors are for each iface! // TODO need a way to look up who our link-local neighbors are for each iface!
addr, err := net.ResolveTCPAddr("tcp", "[::1]:9001") addr, err := net.ResolveTCPAddr("tcp", "[::1]:9001")
if err != nil { panic(err) } if err != nil {
panic(err)
}
listener, err := net.ListenTCP("tcp", addr) listener, err := net.ListenTCP("tcp", addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer listener.Close() defer listener.Close()
go func () { go func() {
send, err := net.DialTCP("tcp", nil, addr) send, err := net.DialTCP("tcp", nil, addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer send.Close() defer send.Close()
msg := make([]byte, 1280) msg := make([]byte, 1280)
bss := make(net.Buffers, 0, 1024) bss := make(net.Buffers, 0, 1024)
@ -31,7 +37,7 @@ func basic_test() {
for len(bss) < 1 { //buffSize { for len(bss) < 1 { //buffSize {
bss = append(bss, msg) bss = append(bss, msg)
} }
bss := net.Buffers{[]byte{0,1,2,3}, []byte{0,1}, msg} bss := net.Buffers{[]byte{0, 1, 2, 3}, []byte{0, 1}, msg}
bss.WriteTo(send) bss.WriteTo(send)
//send.Write(msg) //send.Write(msg)
} }
@ -41,12 +47,16 @@ func basic_test() {
start := time.Now() start := time.Now()
//msg := make([]byte, 1280) //msg := make([]byte, 1280)
sock, err := listener.AcceptTCP() sock, err := listener.AcceptTCP()
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer sock.Close() defer sock.Close()
for i := 0 ; i < numPackets ; i++ { for i := 0; i < numPackets; i++ {
msg := make([]byte, 1280*buffSize) msg := make([]byte, 1280*buffSize)
n, err := sock.Read(msg) n, err := sock.Read(msg)
if err != nil { panic(err) } if err != nil {
panic(err)
}
msg = msg[:n] msg = msg[:n]
for len(msg) > 1286 { for len(msg) > 1286 {
// handle message // handle message
@ -60,7 +70,7 @@ func basic_test() {
fmt.Printf("%f packets per second\n", float64(numPackets)/timed.Seconds()) fmt.Printf("%f packets per second\n", float64(numPackets)/timed.Seconds())
_ = func (in (chan<- int)) { _ = func(in chan<- int) {
close(in) close(in)
} }
@ -69,7 +79,7 @@ func basic_test() {
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`") var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to this file") var memprofile = flag.String("memprofile", "", "write memory profile to this file")
func main () { func main() {
flag.Parse() flag.Parse()
if *cpuprofile != "" { if *cpuprofile != "" {
f, err := os.Create(*cpuprofile) f, err := os.Create(*cpuprofile)
@ -86,9 +96,8 @@ func main () {
if err != nil { if err != nil {
panic(fmt.Sprintf("could not create memory profile: ", err)) panic(fmt.Sprintf("could not create memory profile: ", err))
} }
defer func () { pprof.WriteHeapProfile(f) ; f.Close() }() defer func() { pprof.WriteHeapProfile(f); f.Close() }()
} }
basic_test() basic_test()
} }

View File

@ -14,16 +14,22 @@ func basic_test() {
// TODO need a way to look up who our link-local neighbors are for each iface! // TODO need a way to look up who our link-local neighbors are for each iface!
addr, err := net.ResolveUDPAddr("udp", "[::1]:0") addr, err := net.ResolveUDPAddr("udp", "[::1]:0")
if err != nil { panic(err) } if err != nil {
panic(err)
}
sock, err := net.ListenUDP("udp", addr) sock, err := net.ListenUDP("udp", addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer sock.Close() defer sock.Close()
go func () { go func() {
raddr := sock.LocalAddr().(*net.UDPAddr) raddr := sock.LocalAddr().(*net.UDPAddr)
send, err := net.DialUDP("udp", nil, raddr) send, err := net.DialUDP("udp", nil, raddr)
//send, err := net.ListenUDP("udp", addr) //send, err := net.ListenUDP("udp", addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer send.Close() defer send.Close()
msg := make([]byte, 1280) msg := make([]byte, 1280)
for { for {
@ -35,7 +41,7 @@ func basic_test() {
numPackets := 1000000 numPackets := 1000000
start := time.Now() start := time.Now()
msg := make([]byte, 2000) msg := make([]byte, 2000)
for i := 0 ; i < numPackets ; i++ { for i := 0; i < numPackets; i++ {
sock.ReadFromUDP(msg) sock.ReadFromUDP(msg)
} }
timed := time.Since(start) timed := time.Since(start)
@ -47,7 +53,7 @@ func basic_test() {
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`") var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to this file") var memprofile = flag.String("memprofile", "", "write memory profile to this file")
func main () { func main() {
flag.Parse() flag.Parse()
if *cpuprofile != "" { if *cpuprofile != "" {
f, err := os.Create(*cpuprofile) f, err := os.Create(*cpuprofile)
@ -64,9 +70,8 @@ func main () {
if err != nil { if err != nil {
panic(fmt.Sprintf("could not create memory profile: ", err)) panic(fmt.Sprintf("could not create memory profile: ", err))
} }
defer func () { pprof.WriteHeapProfile(f) ; f.Close() }() defer func() { pprof.WriteHeapProfile(f); f.Close() }()
} }
basic_test() basic_test()
} }

View File

@ -14,19 +14,27 @@ func basic_test() {
// TODO need a way to look up who our link-local neighbors are for each iface! // TODO need a way to look up who our link-local neighbors are for each iface!
saddr, err := net.ResolveUDPAddr("udp", "[::1]:9001") saddr, err := net.ResolveUDPAddr("udp", "[::1]:9001")
if err != nil { panic(err) } if err != nil {
panic(err)
}
raddr, err := net.ResolveUDPAddr("udp", "[::1]:9002") raddr, err := net.ResolveUDPAddr("udp", "[::1]:9002")
if err != nil { panic(err) } if err != nil {
panic(err)
}
send, err := net.DialUDP("udp", saddr, raddr) send, err := net.DialUDP("udp", saddr, raddr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer send.Close() defer send.Close()
recv, err := net.DialUDP("udp", raddr, saddr) recv, err := net.DialUDP("udp", raddr, saddr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer recv.Close() defer recv.Close()
go func () { go func() {
msg := make([]byte, 1280) msg := make([]byte, 1280)
for { for {
send.Write(msg) send.Write(msg)
@ -36,7 +44,7 @@ func basic_test() {
numPackets := 1000000 numPackets := 1000000
start := time.Now() start := time.Now()
msg := make([]byte, 2000) msg := make([]byte, 2000)
for i := 0 ; i < numPackets ; i++ { for i := 0; i < numPackets; i++ {
recv.Read(msg) recv.Read(msg)
} }
timed := time.Since(start) timed := time.Since(start)
@ -47,7 +55,7 @@ func basic_test() {
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`") var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to this file") var memprofile = flag.String("memprofile", "", "write memory profile to this file")
func main () { func main() {
flag.Parse() flag.Parse()
if *cpuprofile != "" { if *cpuprofile != "" {
f, err := os.Create(*cpuprofile) f, err := os.Create(*cpuprofile)
@ -64,9 +72,8 @@ func main () {
if err != nil { if err != nil {
panic(fmt.Sprintf("could not create memory profile: ", err)) panic(fmt.Sprintf("could not create memory profile: ", err))
} }
defer func () { pprof.WriteHeapProfile(f) ; f.Close() }() defer func() { pprof.WriteHeapProfile(f); f.Close() }()
} }
basic_test() basic_test()
} }

View File

@ -14,12 +14,14 @@ func basic_test() {
// TODO need a way to look up who our link-local neighbors are for each iface! // TODO need a way to look up who our link-local neighbors are for each iface!
sock, err := net.ListenUDP("udp", nil) sock, err := net.ListenUDP("udp", nil)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer sock.Close() defer sock.Close()
ch := make(chan []byte, 1) ch := make(chan []byte, 1)
writer := func () { writer := func() {
raddr := sock.LocalAddr().(*net.UDPAddr) raddr := sock.LocalAddr().(*net.UDPAddr)
//send, err := net.ListenUDP("udp", nil) //send, err := net.ListenUDP("udp", nil)
//if err != nil { panic(err) } //if err != nil { panic(err) }
@ -43,13 +45,16 @@ func basic_test() {
size := 0 size := 0
start := time.Now() start := time.Now()
success := 0 success := 0
for i := 0 ; i < numPackets ; i++ { for i := 0; i < numPackets; i++ {
msg := make([]byte, 2048) msg := make([]byte, 2048)
n, _, err := sock.ReadFromUDP(msg) n, _, err := sock.ReadFromUDP(msg)
if err != nil { panic(err) } if err != nil {
panic(err)
}
size += n size += n
select { select {
case ch <- msg: success += 1 case ch <- msg:
success += 1
default: default:
} }
} }
@ -63,7 +68,7 @@ func basic_test() {
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`") var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to this file") var memprofile = flag.String("memprofile", "", "write memory profile to this file")
func main () { func main() {
flag.Parse() flag.Parse()
if *cpuprofile != "" { if *cpuprofile != "" {
f, err := os.Create(*cpuprofile) f, err := os.Create(*cpuprofile)
@ -80,9 +85,8 @@ func main () {
if err != nil { if err != nil {
panic(fmt.Sprintf("could not create memory profile: ", err)) panic(fmt.Sprintf("could not create memory profile: ", err))
} }
defer func () { pprof.WriteHeapProfile(f) ; f.Close() }() defer func() { pprof.WriteHeapProfile(f); f.Close() }()
} }
basic_test() basic_test()
} }

View File

@ -16,20 +16,26 @@ func basic_test() {
// TODO need a way to look up who our link-local neighbors are for each iface! // TODO need a way to look up who our link-local neighbors are for each iface!
udpAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0") udpAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
if err != nil { panic(err) } if err != nil {
panic(err)
}
sock, err := net.ListenUDP("udp", udpAddr) sock, err := net.ListenUDP("udp", udpAddr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer sock.Close() defer sock.Close()
writer := func () { writer := func() {
raddr := sock.LocalAddr().(*net.UDPAddr) raddr := sock.LocalAddr().(*net.UDPAddr)
send, err := net.ListenUDP("udp", nil) send, err := net.ListenUDP("udp", nil)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer send.Close() defer send.Close()
conn := ipv6.NewPacketConn(send) conn := ipv6.NewPacketConn(send)
defer conn.Close() defer conn.Close()
var msgs []ipv6.Message var msgs []ipv6.Message
for idx := 0 ; idx < 1024 ; idx++ { for idx := 0; idx < 1024; idx++ {
msg := ipv6.Message{Addr: raddr, Buffers: [][]byte{make([]byte, 1280)}} msg := ipv6.Message{Addr: raddr, Buffers: [][]byte{make([]byte, 1280)}}
msgs = append(msgs, msg) msgs = append(msgs, msg)
} }
@ -76,10 +82,12 @@ func basic_test() {
} }
//*/ //*/
//* //*
for ; count < numPackets ; count++ { for ; count < numPackets; count++ {
msg := make([]byte, 2048) msg := make([]byte, 2048)
n, _, err := sock.ReadFromUDP(msg) n, _, err := sock.ReadFromUDP(msg)
if err != nil { panic(err) } if err != nil {
panic(err)
}
size += n size += n
} }
//*/ //*/
@ -92,7 +100,7 @@ func basic_test() {
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`") var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to this file") var memprofile = flag.String("memprofile", "", "write memory profile to this file")
func main () { func main() {
flag.Parse() flag.Parse()
if *cpuprofile != "" { if *cpuprofile != "" {
f, err := os.Create(*cpuprofile) f, err := os.Create(*cpuprofile)
@ -109,9 +117,8 @@ func main () {
if err != nil { if err != nil {
panic(fmt.Sprintf("could not create memory profile: ", err)) panic(fmt.Sprintf("could not create memory profile: ", err))
} }
defer func () { pprof.WriteHeapProfile(f) ; f.Close() }() defer func() { pprof.WriteHeapProfile(f); f.Close() }()
} }
basic_test() basic_test()
} }

View File

@ -16,20 +16,26 @@ func basic_test() {
// TODO need a way to look up who our link-local neighbors are for each iface! // TODO need a way to look up who our link-local neighbors are for each iface!
addr, err := net.ResolveTCPAddr("tcp", "[::1]:9001") addr, err := net.ResolveTCPAddr("tcp", "[::1]:9001")
if err != nil { panic(err) } if err != nil {
panic(err)
}
listener, err := net.ListenTCP("tcp", addr) listener, err := net.ListenTCP("tcp", addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer listener.Close() defer listener.Close()
go func () { go func() {
send, err := net.DialTCP("tcp", nil, addr) send, err := net.DialTCP("tcp", nil, addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer send.Close() defer send.Close()
msg := make([]byte, 1280) msg := make([]byte, 1280)
bss := make(net.Buffers, 0, 1024) bss := make(net.Buffers, 0, 1024)
count := 0 count := 0
for { for {
time.Sleep(100*time.Millisecond) time.Sleep(100 * time.Millisecond)
for len(bss) < count { for len(bss) < count {
bss = append(bss, msg) bss = append(bss, msg)
} }
@ -43,12 +49,16 @@ func basic_test() {
start := time.Now() start := time.Now()
//msg := make([]byte, 1280) //msg := make([]byte, 1280)
sock, err := listener.AcceptTCP() sock, err := listener.AcceptTCP()
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer sock.Close() defer sock.Close()
for { for {
msg := make([]byte, 1280*buffSize) msg := make([]byte, 1280*buffSize)
n, err := sock.Read(msg) n, err := sock.Read(msg)
if err != nil { panic(err) } if err != nil {
panic(err)
}
msg = msg[:n] msg = msg[:n]
fmt.Println("Read:", n) fmt.Println("Read:", n)
for len(msg) > 1280 { for len(msg) > 1280 {
@ -62,7 +72,7 @@ func basic_test() {
fmt.Printf("%f packets per second\n", float64(numPackets)/timed.Seconds()) fmt.Printf("%f packets per second\n", float64(numPackets)/timed.Seconds())
_ = func (in (chan<- int)) { _ = func(in chan<- int) {
close(in) close(in)
} }
@ -71,7 +81,7 @@ func basic_test() {
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`") var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to this file") var memprofile = flag.String("memprofile", "", "write memory profile to this file")
func main () { func main() {
flag.Parse() flag.Parse()
if *cpuprofile != "" { if *cpuprofile != "" {
f, err := os.Create(*cpuprofile) f, err := os.Create(*cpuprofile)
@ -88,9 +98,8 @@ func main () {
if err != nil { if err != nil {
panic(fmt.Sprintf("could not create memory profile: ", err)) panic(fmt.Sprintf("could not create memory profile: ", err))
} }
defer func () { pprof.WriteHeapProfile(f) ; f.Close() }() defer func() { pprof.WriteHeapProfile(f); f.Close() }()
} }
basic_test() basic_test()
} }

View File

@ -46,7 +46,9 @@ func setup_dev1() *water.Interface {
func connect(ifce *water.Interface) { func connect(ifce *water.Interface) {
conn, err := net.DialTimeout("tcp", "192.168.2.2:9001", time.Second) conn, err := net.DialTimeout("tcp", "192.168.2.2:9001", time.Second)
if err != nil { panic(err) } if err != nil {
panic(err)
}
sock := conn.(*net.TCPConn) sock := conn.(*net.TCPConn)
// TODO go a worker to move packets to/from the tun // TODO go a worker to move packets to/from the tun
} }
@ -79,4 +81,3 @@ func main() {
log.Printf("Packet Received: % x\n", packet[:n]) log.Printf("Packet Received: % x\n", packet[:n])
} }
} }

View File

@ -124,4 +124,3 @@ func main() {
log.Printf("Packet Received: % x\n", packet[:n]) log.Printf("Packet Received: % x\n", packet[:n])
} }
} }

View File

@ -76,7 +76,6 @@ func setup_dev2() *water.Interface {
fmt.Println(string(out)) fmt.Println(string(out))
panic("Failed to move tun to netns") panic("Failed to move tun to netns")
} }
cmd =
cmd = exec.Command( cmd = exec.Command(
"ip", "-f", "inet6", "ip", "-f", "inet6",
"addr", "add", "fc00::2/8", "addr", "add", "fc00::2/8",
@ -127,4 +126,3 @@ func main() {
log.Printf("Packet Received: % x\n", packet[:n]) log.Printf("Packet Received: % x\n", packet[:n])
} }
} }

View File

@ -29,12 +29,16 @@ func main() {
address := net.ParseIP("fc00::1") address := net.ParseIP("fc00::1")
tuntap, err := tun.OpenTun(address) tuntap, err := tun.OpenTun(address)
if err != nil { panic(err) } if err != nil {
panic(err)
}
defer tuntap.Close() defer tuntap.Close()
// read data from tun into rCh channel. // read data from tun into rCh channel.
wg.Add(1) wg.Add(1)
go func() { go func() {
if err := tuntap.Read(rCh); err != nil { panic(err) } if err := tuntap.Read(rCh); err != nil {
panic(err)
}
wg.Done() wg.Done()
}() }()
wg.Wait() wg.Wait()

View File

@ -6,12 +6,14 @@ import "fmt"
import "time" import "time"
func main() { func main() {
for idx := 0 ; idx < 64 ; idx++ { for idx := 0; idx < 64; idx++ {
num := uint64(1) << uint(idx) num := uint64(1) << uint(idx)
encoded := make([]byte, 10) encoded := make([]byte, 10)
length := wire.Encode_uint64(num, encoded) length := wire.Encode_uint64(num, encoded)
decoded, _ := wire.Decode_uint64(encoded[:length]) decoded, _ := wire.Decode_uint64(encoded[:length])
if decoded != num { panic(fmt.Sprintf("%d != %d", decoded, num)) } if decoded != num {
panic(fmt.Sprintf("%d != %d", decoded, num))
}
} }
const count = 1000000 const count = 1000000
start := time.Now() start := time.Now()
@ -20,7 +22,7 @@ func main() {
num := ^uint64(0) >> 1 // Largest positive int64 (real use case) num := ^uint64(0) >> 1 // Largest positive int64 (real use case)
//num := uint64(0) // Shortest possible value, most will be of this length //num := uint64(0) // Shortest possible value, most will be of this length
length := wire.Encode_uint64(num, encoded) length := wire.Encode_uint64(num, encoded)
for idx := 0 ; idx < count ; idx++ { for idx := 0; idx < count; idx++ {
wire.Encode_uint64(num, encoded) wire.Encode_uint64(num, encoded)
} }
timed := time.Since(start) timed := time.Since(start)
@ -29,11 +31,10 @@ func main() {
encoded = encoded[:length] encoded = encoded[:length]
start = time.Now() start = time.Now()
for idx := 0 ; idx < count ; idx++ { for idx := 0; idx < count; idx++ {
wire.Decode_uint64(encoded) wire.Decode_uint64(encoded)
} }
timed = time.Since(start) timed = time.Since(start)
fmt.Println("Ops:", count/timed.Seconds()) fmt.Println("Ops:", count/timed.Seconds())
fmt.Println("Time:", timed.Nanoseconds()/count) fmt.Println("Time:", timed.Nanoseconds()/count)
} }

View File

@ -7,16 +7,20 @@ var address_prefix = [...]byte{0xfd} // For node addresses + local subnets
func (a *address) isValid() bool { func (a *address) isValid() bool {
for idx := range address_prefix { for idx := range address_prefix {
if (*a)[idx] != address_prefix[idx] { return false } if (*a)[idx] != address_prefix[idx] {
return false
} }
return (*a)[len(address_prefix)] & 0x80 == 0 }
return (*a)[len(address_prefix)]&0x80 == 0
} }
func (s *subnet) isValid() bool { func (s *subnet) isValid() bool {
for idx := range address_prefix { for idx := range address_prefix {
if (*s)[idx] != address_prefix[idx] { return false } if (*s)[idx] != address_prefix[idx] {
return false
} }
return (*s)[len(address_prefix)] & 0x80 != 0 }
return (*s)[len(address_prefix)]&0x80 != 0
} }
func address_addrForNodeID(nid *NodeID) *address { func address_addrForNodeID(nid *NodeID) *address {
@ -32,8 +36,8 @@ func address_addrForNodeID(nid *NodeID) *address {
ones := byte(0) ones := byte(0)
bits := byte(0) bits := byte(0)
nBits := 0 nBits := 0
for idx := 0 ; idx < 8*len(nid) ; idx++ { for idx := 0; idx < 8*len(nid); idx++ {
bit := (nid[idx/8] & (0x80 >> byte(idx % 8))) >> byte(7 - (idx % 8)) bit := (nid[idx/8] & (0x80 >> byte(idx%8))) >> byte(7-(idx%8))
if !done && bit != 0 { if !done && bit != 0 {
ones++ ones++
continue continue
@ -72,18 +76,22 @@ func (a *address) getNodeIDandMask() (*NodeID, *NodeID) {
var nid NodeID var nid NodeID
var mask NodeID var mask NodeID
ones := int(a[len(address_prefix)] & 0x7f) ones := int(a[len(address_prefix)] & 0x7f)
for idx := 0 ; idx < ones ; idx++ { nid[idx/8] |= 0x80 >> byte(idx % 8) } for idx := 0; idx < ones; idx++ {
nidOffset := ones+1 nid[idx/8] |= 0x80 >> byte(idx%8)
addrOffset := 8*len(address_prefix)+8 }
for idx := addrOffset ; idx < 8*len(a) ; idx++ { nidOffset := ones + 1
bits := a[idx/8] & (0x80 >> byte(idx % 8)) addrOffset := 8*len(address_prefix) + 8
for idx := addrOffset; idx < 8*len(a); idx++ {
bits := a[idx/8] & (0x80 >> byte(idx%8))
bits <<= byte(idx % 8) bits <<= byte(idx % 8)
nidIdx := nidOffset + (idx - addrOffset) nidIdx := nidOffset + (idx - addrOffset)
bits >>= byte(nidIdx % 8) bits >>= byte(nidIdx % 8)
nid[nidIdx/8] |= bits nid[nidIdx/8] |= bits
} }
maxMask := 8*(len(a) - len(address_prefix) - 1) + ones + 1 maxMask := 8*(len(a)-len(address_prefix)-1) + ones + 1
for idx := 0 ; idx < maxMask ; idx++ { mask[idx/8] |= 0x80 >> byte(idx % 8) } for idx := 0; idx < maxMask; idx++ {
mask[idx/8] |= 0x80 >> byte(idx%8)
}
return &nid, &mask return &nid, &mask
} }
@ -92,17 +100,21 @@ func (s *subnet) getNodeIDandMask() (*NodeID, *NodeID) {
var nid NodeID var nid NodeID
var mask NodeID var mask NodeID
ones := int(s[len(address_prefix)] & 0x7f) ones := int(s[len(address_prefix)] & 0x7f)
for idx := 0 ; idx < ones ; idx++ { nid[idx/8] |= 0x80 >> byte(idx % 8) } for idx := 0; idx < ones; idx++ {
nidOffset := ones+1 nid[idx/8] |= 0x80 >> byte(idx%8)
addrOffset := 8*len(address_prefix)+8 }
for idx := addrOffset ; idx < 8*len(s) ; idx++ { nidOffset := ones + 1
bits := s[idx/8] & (0x80 >> byte(idx % 8)) addrOffset := 8*len(address_prefix) + 8
for idx := addrOffset; idx < 8*len(s); idx++ {
bits := s[idx/8] & (0x80 >> byte(idx%8))
bits <<= byte(idx % 8) bits <<= byte(idx % 8)
nidIdx := nidOffset + (idx - addrOffset) nidIdx := nidOffset + (idx - addrOffset)
bits >>= byte(nidIdx % 8) bits >>= byte(nidIdx % 8)
nid[nidIdx/8] |= bits nid[nidIdx/8] |= bits
} }
maxMask := 8*(len(s) - len(address_prefix) - 1) + ones + 1 maxMask := 8*(len(s)-len(address_prefix)-1) + ones + 1
for idx := 0 ; idx < maxMask ; idx++ { mask[idx/8] |= 0x80 >> byte(idx % 8) } for idx := 0; idx < maxMask; idx++ {
mask[idx/8] |= 0x80 >> byte(idx%8)
}
return &nid, &mask return &nid, &mask
} }

View File

@ -61,4 +61,3 @@ func (c *Core) GetNodeID() *NodeID {
func (c *Core) GetTreeID() *TreeID { func (c *Core) GetTreeID() *TreeID {
return getTreeID(&c.sigPub) return getTreeID(&c.sigPub)
} }

View File

@ -40,7 +40,9 @@ func getTreeID(pub *sigPubKey) *TreeID {
func newHandle() *handle { func newHandle() *handle {
var h handle var h handle
_, err := rand.Read(h[:]) _, err := rand.Read(h[:])
if err != nil { panic(err) } if err != nil {
panic(err)
}
return &h return &h
} }
@ -60,7 +62,9 @@ func newSigKeys() (*sigPubKey, *sigPrivKey) {
var pub sigPubKey var pub sigPubKey
var priv sigPrivKey var priv sigPrivKey
pubSlice, privSlice, err := ed25519.GenerateKey(rand.Reader) pubSlice, privSlice, err := ed25519.GenerateKey(rand.Reader)
if err != nil { panic(err) } if err != nil {
panic(err)
}
copy(pub[:], pubSlice) copy(pub[:], pubSlice)
copy(priv[:], privSlice) copy(priv[:], privSlice)
return &pub, &priv return &pub, &priv
@ -95,7 +99,9 @@ type boxNonce [boxNonceLen]byte
func newBoxKeys() (*boxPubKey, *boxPrivKey) { func newBoxKeys() (*boxPubKey, *boxPrivKey) {
pubBytes, privBytes, err := box.GenerateKey(rand.Reader) pubBytes, privBytes, err := box.GenerateKey(rand.Reader)
if err != nil { panic(err) } if err != nil {
panic(err)
}
pub := (*boxPubKey)(pubBytes) pub := (*boxPubKey)(pubBytes)
priv := (*boxPrivKey)(privBytes) priv := (*boxPrivKey)(privBytes)
return pub, priv return pub, priv
@ -122,7 +128,9 @@ func boxOpen(shared *boxSharedKey,
} }
func boxSeal(shared *boxSharedKey, unboxed []byte, nonce *boxNonce) ([]byte, *boxNonce) { func boxSeal(shared *boxSharedKey, unboxed []byte, nonce *boxNonce) ([]byte, *boxNonce) {
if nonce == nil { nonce = newBoxNonce() } if nonce == nil {
nonce = newBoxNonce()
}
nonce.update() nonce.update()
out := util_getBytes() out := util_getBytes()
//return append(out, unboxed...), nonce // XXX HACK to test without encryption //return append(out, unboxed...), nonce // XXX HACK to test without encryption
@ -135,20 +143,23 @@ func boxSeal(shared *boxSharedKey, unboxed []byte, nonce *boxNonce) ([]byte, *bo
func newBoxNonce() *boxNonce { func newBoxNonce() *boxNonce {
var nonce boxNonce var nonce boxNonce
_, err := rand.Read(nonce[:]) _, err := rand.Read(nonce[:])
for ; err == nil && nonce[0] == 0xff ; _, err = rand.Read(nonce[:]){ for ; err == nil && nonce[0] == 0xff; _, err = rand.Read(nonce[:]) {
// Make sure nonce isn't too high // Make sure nonce isn't too high
// This is just to make rollover unlikely to happen // This is just to make rollover unlikely to happen
// Rollover is fine, but it may kill the session and force it to reopen // Rollover is fine, but it may kill the session and force it to reopen
} }
if err != nil { panic(err) } if err != nil {
panic(err)
}
return &nonce return &nonce
} }
func (n *boxNonce) update() { func (n *boxNonce) update() {
oldNonce := *n oldNonce := *n
n[len(n)-1] += 2 n[len(n)-1] += 2
for i := len(n)-2 ; i >= 0 ; i-- { for i := len(n) - 2; i >= 0; i-- {
if n[i+1] < oldNonce[i+1] { n[i] += 1 } if n[i+1] < oldNonce[i+1] {
n[i] += 1
}
} }
} }

View File

@ -22,11 +22,11 @@ func (c *Core) DEBUG_getBoxPub() boxPubKey {
return (boxPubKey)(c.boxPub) return (boxPubKey)(c.boxPub)
} }
func (c *Core) DEBUG_getSend() (chan<- []byte) { func (c *Core) DEBUG_getSend() chan<- []byte {
return c.tun.send return c.tun.send
} }
func (c *Core) DEBUG_getRecv() (<-chan []byte) { func (c *Core) DEBUG_getRecv() <-chan []byte {
return c.tun.recv return c.tun.recv
} }
@ -40,7 +40,7 @@ func (ps *peers) DEBUG_newPeer(box boxPubKey,
sig sigPubKey) *peer { sig sigPubKey) *peer {
//in <-chan []byte, //in <-chan []byte,
//out chan<- []byte) *peer { //out chan<- []byte) *peer {
return ps.newPeer(&box, &sig)//, in, out) return ps.newPeer(&box, &sig) //, in, out)
} }
/* /*
@ -57,8 +57,12 @@ func (ps *peers) DEBUG_startPeers() {
func (ps *peers) DEBUG_hasPeer(key sigPubKey) bool { func (ps *peers) DEBUG_hasPeer(key sigPubKey) bool {
ports := ps.ports.Load().(map[switchPort]*peer) ports := ps.ports.Load().(map[switchPort]*peer)
for _, p := range ports { for _, p := range ports {
if p == nil { continue } if p == nil {
if p.sig == key { return true } continue
}
if p.sig == key {
return true
}
} }
return false return false
} }
@ -66,7 +70,7 @@ func (ps *peers) DEBUG_hasPeer(key sigPubKey) bool {
func (ps *peers) DEBUG_getPorts() map[switchPort]*peer { func (ps *peers) DEBUG_getPorts() map[switchPort]*peer {
ports := ps.ports.Load().(map[switchPort]*peer) ports := ps.ports.Load().(map[switchPort]*peer)
newPeers := make(map[switchPort]*peer) newPeers := make(map[switchPort]*peer)
for port, p := range ports{ for port, p := range ports {
newPeers[port] = p newPeers[port] = p
} }
return newPeers return newPeers
@ -117,7 +121,7 @@ func (t *switchTable) DEBUG_dumpTable() {
//fmt.Println("DUMPTABLE:", t.treeID, peer.treeID, peer.port, //fmt.Println("DUMPTABLE:", t.treeID, peer.treeID, peer.port,
// peer.locator.Root, peer.coords, // peer.locator.Root, peer.coords,
// peer.reverse.Root, peer.reverse.Coords, peer.forward) // peer.reverse.Root, peer.reverse.Coords, peer.forward)
fmt.Println("DUMPTABLE:", t.key, peer.key, peer.locator.coords, peer.port/*, peer.forward*/) fmt.Println("DUMPTABLE:", t.key, peer.key, peer.locator.coords, peer.port /*, peer.forward*/)
} }
} }
@ -127,9 +131,13 @@ func (t *switchTable) DEBUG_getReversePort(port switchPort) switchPort {
t.mutex.RLock() t.mutex.RLock()
defer t.mutex.RUnlock() defer t.mutex.RUnlock()
data := t.data data := t.data
if port >= switchPort(len(data.peers)) { return switchPort(0) } if port >= switchPort(len(data.peers)) {
return switchPort(0)
}
pinfo := data.peers[port] pinfo := data.peers[port]
if len(pinfo.locator.coords) < 1 { return switchPort(0) } if len(pinfo.locator.coords) < 1 {
return switchPort(0)
}
return pinfo.locator.coords[len(pinfo.locator.coords)-1] return pinfo.locator.coords[len(pinfo.locator.coords)-1]
} }
@ -143,7 +151,7 @@ func DEBUG_wire_encode_coords(coords []byte) []byte {
func (c *Core) DEBUG_getDHTSize() int { func (c *Core) DEBUG_getDHTSize() int {
total := 0 total := 0
for bidx := 0 ; bidx < c.dht.nBuckets() ; bidx++ { for bidx := 0; bidx < c.dht.nBuckets(); bidx++ {
b := c.dht.getBucket(bidx) b := c.dht.getBucket(bidx)
total += len(b.infos) total += len(b.infos)
} }
@ -196,15 +204,17 @@ func (c *Core) DEBUG_getAddr() *address {
return address_addrForNodeID(&c.dht.nodeID) return address_addrForNodeID(&c.dht.nodeID)
} }
func (c *Core) DEBUG_startTun() { func (c *Core) DEBUG_startTun(ifname string) {
c.DEBUG_startTunWithMTU(1280) c.DEBUG_startTunWithMTU(ifname, 1280)
} }
func (c *Core) DEBUG_startTunWithMTU(mtu int) { func (c *Core) DEBUG_startTunWithMTU(ifname string, mtu int) {
addr := c.DEBUG_getAddr() addr := c.DEBUG_getAddr()
straddr := fmt.Sprintf("%s/%v", net.IP(addr[:]).String(), 8*len(address_prefix)) straddr := fmt.Sprintf("%s/%v", net.IP(addr[:]).String(), 8*len(address_prefix))
err := c.tun.setup(straddr, mtu) err := c.tun.setup(ifname, straddr, mtu)
if err != nil { panic(err) } if err != nil {
panic(err)
}
go c.tun.read() go c.tun.read()
go c.tun.write() go c.tun.write()
} }
@ -267,7 +277,9 @@ func (c *Core) DEBUG_maybeSendUDPKeys(saddr string) {
c.udp.mutex.RLock() c.udp.mutex.RLock()
_, isIn := c.udp.conns[connAddr(addr)] _, isIn := c.udp.conns[connAddr(addr)]
c.udp.mutex.RUnlock() c.udp.mutex.RUnlock()
if !isIn { c.udp.sendKeys(addr) } if !isIn {
c.udp.sendKeys(addr)
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -286,6 +298,7 @@ func (c *Core) DEBUG_getGlobalTCPAddr() *net.TCPAddr {
func (c *Core) DEBUG_addTCPConn(saddr string) { func (c *Core) DEBUG_addTCPConn(saddr string) {
c.tcp.call(saddr) c.tcp.call(saddr)
} }
//*/ //*/
/* /*
@ -336,4 +349,3 @@ func DEBUG_simLinkPeers(p, q *peer) {
go p.linkLoop(plinkIn) go p.linkLoop(plinkIn)
go q.linkLoop(qlinkIn) go q.linkLoop(qlinkIn)
} }

View File

@ -24,13 +24,14 @@ Slight changes *do* make it blackhole hard, bootstrapping isn't an easy problem
import "sort" import "sort"
import "time" import "time"
//import "fmt" //import "fmt"
// Maximum size for buckets and lookups // Maximum size for buckets and lookups
// Exception for buckets if the next one is non-full // Exception for buckets if the next one is non-full
const dht_bucket_size = 2 // This should be at least 2 const dht_bucket_size = 2 // This should be at least 2
const dht_lookup_size = 2 // This should be at least 1, below 2 is impractical const dht_lookup_size = 2 // This should be at least 1, below 2 is impractical
const dht_bucket_number = 8*NodeIDLen // This shouldn't be changed const dht_bucket_number = 8 * NodeIDLen // This shouldn't be changed
type dhtInfo struct { type dhtInfo struct {
// TODO save their nodeID so we don't need to rehash if we need it again // TODO save their nodeID so we don't need to rehash if we need it again
@ -104,9 +105,13 @@ func (t *dht) handleReq(req *dhtReq) {
func (t *dht) handleRes(res *dhtRes) { func (t *dht) handleRes(res *dhtRes) {
reqs, isIn := t.reqs[res.key] reqs, isIn := t.reqs[res.key]
if !isIn { return } if !isIn {
return
}
_, isIn = reqs[res.dest] _, isIn = reqs[res.dest]
if !isIn { return } if !isIn {
return
}
rinfo := dhtInfo{ rinfo := dhtInfo{
key: res.key, key: res.key,
coords: res.coords, coords: res.coords,
@ -115,14 +120,20 @@ func (t *dht) handleRes(res *dhtRes) {
} }
// 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())
if !isOK { return } if !isOK {
return
}
b := t.getBucket(bidx) b := t.getBucket(bidx)
for _, oldinfo := range b.infos { for _, oldinfo := range b.infos {
if oldinfo.key == rinfo.key {rinfo.send = oldinfo.send } if oldinfo.key == rinfo.key {
rinfo.send = oldinfo.send
}
} }
// Insert into table // Insert into table
t.insert(&rinfo) t.insert(&rinfo)
if res.dest == *rinfo.getNodeID() { return } // No infinite recursions if res.dest == *rinfo.getNodeID() {
return
} // No infinite recursions
// ping the nodes we were told about // ping the nodes we were told about
if len(res.infos) > dht_lookup_size { if len(res.infos) > dht_lookup_size {
// Ignore any "extra" lookup results // Ignore any "extra" lookup results
@ -130,9 +141,13 @@ func (t *dht) handleRes(res *dhtRes) {
} }
for _, info := range res.infos { for _, info := range res.infos {
bidx, isOK := t.getBucketIndex(info.getNodeID()) bidx, isOK := t.getBucketIndex(info.getNodeID())
if !isOK { continue } if !isOK {
continue
}
b := t.getBucket(bidx) b := t.getBucket(bidx)
if b.contains(info) { continue } // wait for maintenance cycle to get them if b.contains(info) {
continue
} // wait for maintenance cycle to get them
t.ping(info, info.getNodeID()) t.ping(info, info.getNodeID())
} }
} }
@ -140,9 +155,11 @@ func (t *dht) handleRes(res *dhtRes) {
func (t *dht) lookup(nodeID *NodeID) []*dhtInfo { func (t *dht) lookup(nodeID *NodeID) []*dhtInfo {
// FIXME this allocates a bunch, sorts, and keeps the part it likes // FIXME this allocates a bunch, sorts, and keeps the part it likes
// It would be better to only track the part it likes to begin with // It would be better to only track the part it likes to begin with
addInfos := func (res []*dhtInfo, infos []*dhtInfo) ([]*dhtInfo) { addInfos := func(res []*dhtInfo, infos []*dhtInfo) []*dhtInfo {
for _, info := range infos { for _, info := range infos {
if info == nil { panic ("Should never happen!") } if info == nil {
panic("Should never happen!")
}
if true || dht_firstCloserThanThird(info.getNodeID(), nodeID, &t.nodeID) { if true || dht_firstCloserThanThird(info.getNodeID(), nodeID, &t.nodeID) {
res = append(res, info) res = append(res, info)
} }
@ -150,12 +167,12 @@ func (t *dht) lookup(nodeID *NodeID) []*dhtInfo {
return res return res
} }
var res []*dhtInfo var res []*dhtInfo
for bidx := 0 ; bidx < t.nBuckets() ; bidx++ { for bidx := 0; bidx < t.nBuckets(); bidx++ {
b := t.getBucket(bidx) b := t.getBucket(bidx)
res = addInfos(res, b.infos) res = addInfos(res, b.infos)
} }
doSort := func(infos []*dhtInfo) { doSort := func(infos []*dhtInfo) {
less := func (i, j int) bool { less := func(i, j int) bool {
return dht_firstCloserThanThird(infos[i].getNodeID(), return dht_firstCloserThanThird(infos[i].getNodeID(),
nodeID, nodeID,
infos[j].getNodeID()) infos[j].getNodeID())
@ -163,7 +180,9 @@ func (t *dht) lookup(nodeID *NodeID) []*dhtInfo {
sort.SliceStable(infos, less) sort.SliceStable(infos, less)
} }
doSort(res) doSort(res)
if len(res) > dht_lookup_size { res = res[:dht_lookup_size] } if len(res) > dht_lookup_size {
res = res[:dht_lookup_size]
}
return res return res
} }
@ -180,7 +199,9 @@ func (t *dht) insertIfNew(info *dhtInfo) {
// Insert a peer if and only if the bucket doesn't already contain it // Insert a peer if and only if the bucket doesn't already contain it
nodeID := info.getNodeID() nodeID := info.getNodeID()
bidx, isOK := t.getBucketIndex(nodeID) bidx, isOK := t.getBucketIndex(nodeID)
if !isOK { return } if !isOK {
return
}
b := t.getBucket(bidx) b := t.getBucket(bidx)
if !b.contains(info) { if !b.contains(info) {
// We've never heard this node before // We've never heard this node before
@ -199,25 +220,35 @@ func (t *dht) insert(info *dhtInfo) {
// Get the bucket for this node // Get the bucket for this node
nodeID := info.getNodeID() nodeID := info.getNodeID()
bidx, isOK := t.getBucketIndex(nodeID) bidx, isOK := t.getBucketIndex(nodeID)
if !isOK { return } if !isOK {
return
}
b := t.getBucket(bidx) b := t.getBucket(bidx)
// 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
b.infos = append(b.infos, info) b.infos = append(b.infos, info)
// Check if the next bucket is non-full and return early if it is // Check if the next bucket is non-full and return early if it is
if bidx+1 == t.nBuckets() { return } if bidx+1 == t.nBuckets() {
bnext := t.getBucket(bidx+1) return
if len(bnext.infos) < dht_bucket_size { return } }
bnext := t.getBucket(bidx + 1)
if len(bnext.infos) < dht_bucket_size {
return
}
// Shrink from the *front* to requied size // Shrink from the *front* to requied size
for len(b.infos) > dht_bucket_size { b.infos = b.infos[1:] } for len(b.infos) > dht_bucket_size {
b.infos = b.infos[1:]
}
} }
func (t *dht) getBucketIndex(nodeID *NodeID) (int, bool) { func (t *dht) getBucketIndex(nodeID *NodeID) (int, bool) {
for bidx := 0 ; bidx < t.nBuckets() ; bidx++ { for bidx := 0; bidx < t.nBuckets(); bidx++ {
them := nodeID[bidx/8] & (0x80 >> byte(bidx % 8)) them := nodeID[bidx/8] & (0x80 >> byte(bidx%8))
me := t.nodeID[bidx/8] & (0x80 >> byte(bidx % 8)) me := t.nodeID[bidx/8] & (0x80 >> byte(bidx%8))
if them != me { return bidx, true } if them != me {
return bidx, true
}
} }
return t.nBuckets(), false return t.nBuckets(), false
} }
@ -225,11 +256,17 @@ func (t *dht) getBucketIndex(nodeID *NodeID) (int, bool) {
func (b *bucket) contains(ninfo *dhtInfo) bool { func (b *bucket) contains(ninfo *dhtInfo) bool {
// Compares if key and coords match // Compares if key and coords match
for _, info := range b.infos { for _, info := range b.infos {
if info == nil { panic("Should never happen") } if info == nil {
panic("Should never happen")
}
if info.key == ninfo.key { if info.key == ninfo.key {
if len(info.coords) != len(ninfo.coords) { return false } if len(info.coords) != len(ninfo.coords) {
for idx := 0 ; idx < len(info.coords) ; idx++ { return false
if info.coords[idx] != ninfo.coords[idx] { return false } }
for idx := 0; idx < len(info.coords); idx++ {
if info.coords[idx] != ninfo.coords[idx] {
return false
}
} }
return true return true
} }
@ -238,10 +275,12 @@ func (b *bucket) contains(ninfo *dhtInfo) bool {
} }
func (b *bucket) drop(key *boxPubKey) { func (b *bucket) drop(key *boxPubKey) {
clean := func (infos []*dhtInfo) []*dhtInfo { clean := func(infos []*dhtInfo) []*dhtInfo {
cleaned := infos[:0] cleaned := infos[:0]
for _, info := range infos { for _, info := range infos {
if info.key == *key { continue } if info.key == *key {
continue
}
cleaned = append(cleaned, info) cleaned = append(cleaned, info)
} }
return cleaned return cleaned
@ -260,7 +299,7 @@ func (t *dht) sendReq(req *dhtReq, dest *dhtInfo) {
toKey: dest.key, toKey: dest.key,
fromKey: t.core.boxPub, fromKey: t.core.boxPub,
nonce: *nonce, nonce: *nonce,
payload:payload, payload: payload,
} }
packet := p.encode() packet := p.encode()
t.core.router.out(packet) t.core.router.out(packet)
@ -268,7 +307,9 @@ func (t *dht) sendReq(req *dhtReq, dest *dhtInfo) {
if !isIn { if !isIn {
t.reqs[dest.key] = make(map[NodeID]time.Time) t.reqs[dest.key] = make(map[NodeID]time.Time)
reqsToDest, isIn = t.reqs[dest.key] reqsToDest, isIn = t.reqs[dest.key]
if !isIn { panic("This should never happen") } if !isIn {
panic("This should never happen")
}
} }
reqsToDest[req.dest] = time.Now() reqsToDest[req.dest] = time.Now()
} }
@ -302,27 +343,35 @@ func (b *bucket) nextToPing() *dhtInfo {
// And time between traffic loss from short term congestion in the network // And time between traffic loss from short term congestion in the network
var toPing *dhtInfo var toPing *dhtInfo
for _, next := range b.infos { for _, next := range b.infos {
if time.Since(next.send) < 6*time.Second { continue } if time.Since(next.send) < 6*time.Second {
if toPing == nil || next.recv.Before(toPing.recv) { toPing = next } continue
}
if toPing == nil || next.recv.Before(toPing.recv) {
toPing = next
}
} }
return toPing return toPing
} }
func (t *dht) getTarget(bidx int) *NodeID { func (t *dht) getTarget(bidx int) *NodeID {
targetID := t.nodeID targetID := t.nodeID
targetID[bidx/8] ^= 0x80 >> byte(bidx % 8) targetID[bidx/8] ^= 0x80 >> byte(bidx%8)
return &targetID return &targetID
} }
func (t *dht) ping(info *dhtInfo, target *NodeID) { func (t *dht) ping(info *dhtInfo, target *NodeID) {
if info.pings > 2 { if info.pings > 2 {
bidx, isOK := t.getBucketIndex(info.getNodeID()) bidx, isOK := t.getBucketIndex(info.getNodeID())
if !isOK { panic("This should never happen") } if !isOK {
panic("This should never happen")
}
b := t.getBucket(bidx) b := t.getBucket(bidx)
b.drop(&info.key) b.drop(&info.key)
return return
} }
if target == nil { target = &t.nodeID } if target == nil {
target = &t.nodeID
}
loc := t.core.switchTable.getLocator() loc := t.core.switchTable.getLocator()
coords := loc.getCoords() coords := loc.getCoords()
req := dhtReq{ req := dhtReq{
@ -339,28 +388,38 @@ func (t *dht) doMaintenance() {
// First clean up reqs // First clean up reqs
for key, reqs := range t.reqs { for key, reqs := range t.reqs {
for target, timeout := range reqs { for target, timeout := range reqs {
if time.Since(timeout) > time.Minute { delete(reqs, target) } if time.Since(timeout) > time.Minute {
delete(reqs, target)
}
}
if len(reqs) == 0 {
delete(t.reqs, key)
} }
if len(reqs) == 0 { delete(t.reqs, key) }
} }
// Ping the least recently contacted node // Ping the least recently contacted node
// This is to make sure we eventually notice when someone times out // This is to make sure we eventually notice when someone times out
var oldest *dhtInfo var oldest *dhtInfo
last := 0 last := 0
for bidx := 0 ; bidx < t.nBuckets() ; bidx++ { for bidx := 0; bidx < t.nBuckets(); bidx++ {
b := t.getBucket(bidx) b := t.getBucket(bidx)
if !b.isEmpty() { if !b.isEmpty() {
last = bidx last = bidx
toPing := b.nextToPing() toPing := b.nextToPing()
if toPing == nil { continue } // We've recently pinged everyone in b if toPing == nil {
continue
} // We've recently pinged everyone in b
if oldest == nil || toPing.recv.Before(oldest.recv) { if oldest == nil || toPing.recv.Before(oldest.recv) {
oldest = toPing oldest = toPing
} }
} }
} }
if oldest != nil { t.ping(oldest, nil) } // if the DHT isn't empty if oldest != nil {
t.ping(oldest, nil)
} // if the DHT isn't empty
// Refresh buckets // Refresh buckets
if t.offset > last { t.offset = 0 } if t.offset > last {
t.offset = 0
}
target := t.getTarget(t.offset) target := t.getTarget(t.offset)
for _, info := range t.lookup(target) { for _, info := range t.lookup(target) {
t.ping(info, target) t.ping(info, target)
@ -372,12 +431,13 @@ func (t *dht) doMaintenance() {
func dht_firstCloserThanThird(first *NodeID, func dht_firstCloserThanThird(first *NodeID,
second *NodeID, second *NodeID,
third *NodeID) bool { third *NodeID) bool {
for idx := 0 ; idx < NodeIDLen ; idx++ { for idx := 0; idx < NodeIDLen; idx++ {
f := first[idx] ^ second[idx] f := first[idx] ^ second[idx]
t := third[idx] ^ second[idx] t := third[idx] ^ second[idx]
if f == t { continue } if f == t {
continue
}
return f < t return f < t
} }
return false return false
} }

View File

@ -11,6 +11,7 @@ import "time"
import "sync" import "sync"
import "sync/atomic" import "sync/atomic"
import "math" import "math"
//import "fmt" //import "fmt"
type peers struct { type peers struct {
@ -58,6 +59,7 @@ type peer struct {
// Resets at the start of each tick // Resets at the start of each tick
throttle uint8 throttle uint8
} }
const peer_Throttle = 1 const peer_Throttle = 1
func (p *peer) getBandwidth() float64 { func (p *peer) getBandwidth() float64 {
@ -66,11 +68,13 @@ func (p *peer) getBandwidth() float64 {
} }
func (p *peer) updateBandwidth(bytes int, duration time.Duration) { func (p *peer) updateBandwidth(bytes int, duration time.Duration) {
if p == nil { return } if p == nil {
for ok := false ; !ok ; { return
}
for ok := false; !ok; {
oldBits := atomic.LoadUint64(&p.bandwidth) oldBits := atomic.LoadUint64(&p.bandwidth)
oldBandwidth := math.Float64frombits(oldBits) oldBandwidth := math.Float64frombits(oldBits)
bandwidth := oldBandwidth * 7 / 8 + float64(bytes)/duration.Seconds() bandwidth := oldBandwidth*7/8 + float64(bytes)/duration.Seconds()
bits := math.Float64bits(bandwidth) bits := math.Float64bits(bandwidth)
ok = atomic.CompareAndSwapUint64(&p.bandwidth, oldBits, bits) ok = atomic.CompareAndSwapUint64(&p.bandwidth, oldBits, bits)
} }
@ -90,8 +94,10 @@ func (ps *peers) newPeer(box *boxPubKey,
defer ps.mutex.Unlock() defer ps.mutex.Unlock()
oldPorts := ps.getPorts() oldPorts := ps.getPorts()
newPorts := make(map[switchPort]*peer) newPorts := make(map[switchPort]*peer)
for k,v := range oldPorts{ newPorts[k] = v } for k, v := range oldPorts {
for idx := switchPort(0) ; true ; idx++ { newPorts[k] = v
}
for idx := switchPort(0); true; idx++ {
if _, isIn := newPorts[idx]; !isIn { if _, isIn := newPorts[idx]; !isIn {
p.port = switchPort(idx) p.port = switchPort(idx)
newPorts[p.port] = &p newPorts[p.port] = &p
@ -108,11 +114,16 @@ func (p *peer) linkLoop(in <-chan []byte) {
for { for {
select { select {
case packet, ok := <-in: case packet, ok := <-in:
if !ok { return } if !ok {
return
}
p.handleLinkTraffic(packet) p.handleLinkTraffic(packet)
case <-ticker.C: { case <-ticker.C:
{
p.throttle = 0 p.throttle = 0
if p.port == 0 { continue } // Don't send announces on selfInterface if p.port == 0 {
continue
} // Don't send announces on selfInterface
// Maybe we shouldn't time out, and instead wait for a kill signal? // Maybe we shouldn't time out, and instead wait for a kill signal?
p.myMsg, p.mySigs = p.core.switchTable.createMessage(p.port) p.myMsg, p.mySigs = p.core.switchTable.createMessage(p.port)
p.sendSwitchAnnounce() p.sendSwitchAnnounce()
@ -121,33 +132,45 @@ func (p *peer) linkLoop(in <-chan []byte) {
} }
} }
func (p *peer) handlePacket(packet []byte, linkIn (chan<- []byte)) { func (p *peer) handlePacket(packet []byte, linkIn chan<- []byte) {
pType, pTypeLen := wire_decode_uint64(packet) pType, pTypeLen := wire_decode_uint64(packet)
if pTypeLen==0 { return } if pTypeLen == 0 {
switch (pType) { return
case wire_Traffic: p.handleTraffic(packet, pTypeLen) }
case wire_ProtocolTraffic: p.handleTraffic(packet, pTypeLen) switch pType {
case wire_LinkProtocolTraffic: { case wire_Traffic:
p.handleTraffic(packet, pTypeLen)
case wire_ProtocolTraffic:
p.handleTraffic(packet, pTypeLen)
case wire_LinkProtocolTraffic:
{
select { select {
case linkIn<-packet: case linkIn <- packet:
default: default:
} }
} }
default: /*panic(pType) ;*/ return default: /*panic(pType) ;*/
return
} }
} }
func (p *peer) handleTraffic(packet []byte, pTypeLen int) { func (p *peer) handleTraffic(packet []byte, pTypeLen int) {
ttl, ttlLen := wire_decode_uint64(packet[pTypeLen:]) ttl, ttlLen := wire_decode_uint64(packet[pTypeLen:])
ttlBegin := pTypeLen ttlBegin := pTypeLen
ttlEnd := pTypeLen+ttlLen ttlEnd := pTypeLen + ttlLen
coords, coordLen := wire_decode_coords(packet[ttlEnd:]) coords, coordLen := wire_decode_coords(packet[ttlEnd:])
coordEnd := ttlEnd+coordLen coordEnd := ttlEnd + coordLen
if coordEnd == len(packet) { return } // No payload if coordEnd == len(packet) {
return
} // No payload
toPort, newTTL := p.core.switchTable.lookup(coords, ttl) toPort, newTTL := p.core.switchTable.lookup(coords, ttl)
if toPort == p.port { return } // FIXME? shouldn't happen, does it? would loop if toPort == p.port {
return
} // FIXME? shouldn't happen, does it? would loop
to := p.core.peers.getPorts()[toPort] to := p.core.peers.getPorts()[toPort]
if to == nil { return } if to == nil {
return
}
newTTLSlice := wire_encode_uint64(newTTL) newTTLSlice := wire_encode_uint64(newTTL)
// This mutates the packet in-place if the length of the TTL changes! // This mutates the packet in-place if the length of the TTL changes!
shift := ttlLen - len(newTTLSlice) shift := ttlLen - len(newTTLSlice)
@ -178,17 +201,30 @@ func (p *peer) sendLinkPacket(packet []byte) {
func (p *peer) handleLinkTraffic(bs []byte) { func (p *peer) handleLinkTraffic(bs []byte) {
packet := wire_linkProtoTrafficPacket{} packet := wire_linkProtoTrafficPacket{}
// TODO throttle on returns? // TODO throttle on returns?
if !packet.decode(bs) { return } if !packet.decode(bs) {
if packet.toKey != p.core.boxPub { return } return
if packet.fromKey != p.box { return } }
if packet.toKey != p.core.boxPub {
return
}
if packet.fromKey != p.box {
return
}
payload, isOK := boxOpen(&p.shared, packet.payload, &packet.nonce) payload, isOK := boxOpen(&p.shared, packet.payload, &packet.nonce)
if !isOK { return } if !isOK {
return
}
pType, pTypeLen := wire_decode_uint64(payload) pType, pTypeLen := wire_decode_uint64(payload)
if pTypeLen == 0 { return } if pTypeLen == 0 {
return
}
switch pType { switch pType {
case wire_SwitchAnnounce: p.handleSwitchAnnounce(payload) case wire_SwitchAnnounce:
case wire_SwitchHopRequest: p.handleSwitchHopRequest(payload) p.handleSwitchAnnounce(payload)
case wire_SwitchHop: p.handleSwitchHop(payload) case wire_SwitchHopRequest:
p.handleSwitchHopRequest(payload)
case wire_SwitchHop:
p.handleSwitchHop(payload)
} }
} }
@ -197,12 +233,16 @@ func (p *peer) handleSwitchAnnounce(packet []byte) {
anc := msgAnnounce{} anc := msgAnnounce{}
//err := wire_decode_struct(packet, &anc) //err := wire_decode_struct(packet, &anc)
//if err != nil { return } //if err != nil { return }
if !anc.decode(packet) { return } if !anc.decode(packet) {
return
}
//if p.msgAnc != nil && anc.Seq != p.msgAnc.Seq { p.msgHops = nil } //if p.msgAnc != nil && anc.Seq != p.msgAnc.Seq { p.msgHops = nil }
if p.msgAnc == nil || if p.msgAnc == nil ||
anc.root != p.msgAnc.root || anc.root != p.msgAnc.root ||
anc.tstamp != p.msgAnc.tstamp || anc.tstamp != p.msgAnc.tstamp ||
anc.seq != p.msgAnc.seq { p.msgHops = nil } anc.seq != p.msgAnc.seq {
p.msgHops = nil
}
p.msgAnc = &anc p.msgAnc = &anc
p.processSwitchMessage() p.processSwitchMessage()
} }
@ -220,14 +260,28 @@ func (p *peer) requestHop(hop uint64) {
func (p *peer) handleSwitchHopRequest(packet []byte) { func (p *peer) handleSwitchHopRequest(packet []byte) {
//p.core.log.Println("DEBUG: handleSwitchHopRequest") //p.core.log.Println("DEBUG: handleSwitchHopRequest")
if p.throttle > peer_Throttle { return } if p.throttle > peer_Throttle {
if p.myMsg == nil { return } return
}
if p.myMsg == nil {
return
}
req := msgHopReq{} req := msgHopReq{}
if !req.decode(packet) { return } if !req.decode(packet) {
if req.root != p.myMsg.locator.root { return } return
if req.tstamp != p.myMsg.locator.tstamp { return } }
if req.seq != p.myMsg.seq { return } if req.root != p.myMsg.locator.root {
if uint64(len(p.myMsg.locator.coords)) <= req.hop { return } return
}
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 := msgHop{}
res.root = p.myMsg.locator.root res.root = p.myMsg.locator.root
res.tstamp = p.myMsg.locator.tstamp res.tstamp = p.myMsg.locator.tstamp
@ -244,21 +298,39 @@ func (p *peer) handleSwitchHopRequest(packet []byte) {
func (p *peer) handleSwitchHop(packet []byte) { func (p *peer) handleSwitchHop(packet []byte) {
//p.core.log.Println("DEBUG: handleSwitchHop") //p.core.log.Println("DEBUG: handleSwitchHop")
if p.throttle > peer_Throttle { return } if p.throttle > peer_Throttle {
if p.msgAnc == nil { return } return
}
if p.msgAnc == nil {
return
}
res := msgHop{} res := msgHop{}
if !res.decode(packet) { return } if !res.decode(packet) {
if res.root != p.msgAnc.root { return } return
if res.tstamp != p.msgAnc.tstamp { return } }
if res.seq != p.msgAnc.seq { return } if res.root != p.msgAnc.root {
if res.hop != uint64(len(p.msgHops)) { return } // always process in order 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 := switchLocator{coords: make([]switchPort, 0, len(p.msgHops)+1)}
loc.root = res.root loc.root = res.root
loc.tstamp = res.tstamp loc.tstamp = res.tstamp
for _, hop := range p.msgHops { loc.coords = append(loc.coords, hop.port) } for _, hop := range p.msgHops {
loc.coords = append(loc.coords, hop.port)
}
loc.coords = append(loc.coords, res.port) loc.coords = append(loc.coords, res.port)
thisHopKey := &res.root thisHopKey := &res.root
if res.hop != 0 { thisHopKey = &p.msgHops[res.hop-1].next } if res.hop != 0 {
thisHopKey = &p.msgHops[res.hop-1].next
}
bs := getBytesForSig(&res.next, &loc) bs := getBytesForSig(&res.next, &loc)
if p.core.sigs.check(thisHopKey, &res.sig, bs) { if p.core.sigs.check(thisHopKey, &res.sig, bs) {
p.msgHops = append(p.msgHops, &res) p.msgHops = append(p.msgHops, &res)
@ -270,23 +342,37 @@ func (p *peer) handleSwitchHop(packet []byte) {
func (p *peer) processSwitchMessage() { func (p *peer) processSwitchMessage() {
//p.core.log.Println("DEBUG: processSwitchMessage") //p.core.log.Println("DEBUG: processSwitchMessage")
if p.throttle > peer_Throttle { return } if p.throttle > peer_Throttle {
if p.msgAnc == nil { return } return
}
if p.msgAnc == nil {
return
}
if uint64(len(p.msgHops)) < p.msgAnc.len { if uint64(len(p.msgHops)) < p.msgAnc.len {
p.requestHop(uint64(len(p.msgHops))) p.requestHop(uint64(len(p.msgHops)))
return return
} }
p.throttle++ p.throttle++
if p.msgAnc.len != uint64(len(p.msgHops)) { return } if p.msgAnc.len != uint64(len(p.msgHops)) {
return
}
msg := switchMessage{} msg := switchMessage{}
coords := make([]switchPort, 0, len(p.msgHops)) coords := make([]switchPort, 0, len(p.msgHops))
sigs := make([]sigInfo, 0, len(p.msgHops)) sigs := make([]sigInfo, 0, len(p.msgHops))
for idx, hop := range p.msgHops { for idx, hop := range p.msgHops {
// Consistency checks, should be redundant (already checked these...) // Consistency checks, should be redundant (already checked these...)
if hop.root != p.msgAnc.root { return } if hop.root != p.msgAnc.root {
if hop.tstamp != p.msgAnc.tstamp { return } return
if hop.seq != p.msgAnc.seq { return } }
if hop.hop != uint64(idx) { return } if hop.tstamp != p.msgAnc.tstamp {
return
}
if hop.seq != p.msgAnc.seq {
return
}
if hop.hop != uint64(idx) {
return
}
coords = append(coords, hop.port) coords = append(coords, hop.port)
sigs = append(sigs, sigInfo{next: hop.next, sig: hop.sig}) sigs = append(sigs, sigInfo{next: hop.next, sig: hop.sig})
} }
@ -298,7 +384,9 @@ func (p *peer) processSwitchMessage() {
//msg.RSeq = p.msgAnc.RSeq //msg.RSeq = p.msgAnc.RSeq
//msg.Degree = p.msgAnc.Deg //msg.Degree = p.msgAnc.Deg
p.core.switchTable.handleMessage(&msg, p.port, sigs) p.core.switchTable.handleMessage(&msg, p.port, sigs)
if len(coords) == 0 { return } if len(coords) == 0 {
return
}
// Reuse locator, set the coords to the peer's coords, to use in dht // Reuse locator, set the coords to the peer's coords, to use in dht
msg.locator.coords = coords[:len(coords)-1] 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
@ -306,7 +394,7 @@ func (p *peer) processSwitchMessage() {
key: p.box, key: p.box,
coords: msg.locator.getCoords(), coords: msg.locator.getCoords(),
} }
p.core.dht.peers<-&dinfo p.core.dht.peers <- &dinfo
} }
func (p *peer) sendSwitchAnnounce() { func (p *peer) sendSwitchAnnounce() {
@ -323,7 +411,9 @@ func (p *peer) sendSwitchAnnounce() {
func (p *peer) getSig(hop uint64) sigInfo { func (p *peer) getSig(hop uint64) sigInfo {
//p.core.log.Println("DEBUG getSig:", len(p.mySigs), hop) //p.core.log.Println("DEBUG getSig:", len(p.mySigs), hop)
if hop < uint64(len(p.mySigs)) { return p.mySigs[hop] } if hop < uint64(len(p.mySigs)) {
return p.mySigs[hop]
}
bs := getBytesForSig(&p.sig, &p.myMsg.locator) bs := getBytesForSig(&p.sig, &p.myMsg.locator)
sig := sigInfo{} sig := sigInfo{}
sig.next = p.sig sig.next = p.sig
@ -342,4 +432,3 @@ func getBytesForSig(next *sigPubKey, loc *switchLocator) []byte {
//bs = append(next[:], bs...) //bs = append(next[:], bs...)
return bs return bs
} }

View File

@ -23,6 +23,7 @@ package yggdrasil
// The router then runs some sanity checks before passing it to the tun // The router then runs some sanity checks before passing it to the tun
import "time" import "time"
//import "fmt" //import "fmt"
//import "net" //import "net"
@ -40,9 +41,9 @@ func (r *router) init(core *Core) {
r.core = core r.core = core
r.addr = *address_addrForNodeID(&r.core.dht.nodeID) r.addr = *address_addrForNodeID(&r.core.dht.nodeID)
in := make(chan []byte, 1) // TODO something better than this... in := make(chan []byte, 1) // TODO something better than this...
p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub)//, out, in) p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub) //, out, in)
// TODO set in/out functions on the new peer... // TODO set in/out functions on the new peer...
p.out = func(packet []byte) { in<-packet } // FIXME in theory it blocks... p.out = func(packet []byte) { in <- packet } // FIXME in theory it blocks...
r.in = in r.in = in
// TODO? make caller responsible for go-ing if it needs to not block // TODO? make caller responsible for go-ing if it needs to not block
r.out = func(packet []byte) { p.handlePacket(packet, nil) } r.out = func(packet []byte) { p.handlePacket(packet, nil) }
@ -64,11 +65,16 @@ func (r *router) mainLoop() {
defer ticker.Stop() defer ticker.Stop()
for { for {
select { select {
case p := <-r.in: r.handleIn(p) case p := <-r.in:
case p := <-r.send: r.sendPacket(p) r.handleIn(p)
case info := <-r.core.dht.peers: r.core.dht.insert(info) //r.core.dht.insertIfNew(info) case p := <-r.send:
case <-r.reset: r.core.sessions.resetInits() r.sendPacket(p)
case <-ticker.C: { case info := <-r.core.dht.peers:
r.core.dht.insert(info) //r.core.dht.insertIfNew(info)
case <-r.reset:
r.core.sessions.resetInits()
case <-ticker.C:
{
// Any periodic maintenance stuff goes here // Any periodic maintenance stuff goes here
r.core.dht.doMaintenance() r.core.dht.doMaintenance()
util_getBytes() // To slowly drain things util_getBytes() // To slowly drain things
@ -78,30 +84,48 @@ func (r *router) mainLoop() {
} }
func (r *router) sendPacket(bs []byte) { func (r *router) sendPacket(bs []byte) {
if len(bs) < 40 { panic("Tried to send a packet shorter than a header...") } if len(bs) < 40 {
panic("Tried to send a packet shorter than a header...")
}
var sourceAddr address var sourceAddr address
var sourceSubnet subnet var sourceSubnet subnet
copy(sourceAddr[:], bs[8:]) copy(sourceAddr[:], bs[8:])
copy(sourceSubnet[:], bs[8:]) copy(sourceSubnet[:], bs[8:])
if !sourceAddr.isValid() && !sourceSubnet.isValid() { return } if !sourceAddr.isValid() && !sourceSubnet.isValid() {
return
}
var dest address var dest address
copy(dest[:], bs[24:]) copy(dest[:], bs[24:])
var snet subnet var snet subnet
copy(snet[:], bs[24:]) copy(snet[:], bs[24:])
if !dest.isValid() && !snet.isValid() { return } if !dest.isValid() && !snet.isValid() {
doSearch := func (packet []byte) { return
}
doSearch := func(packet []byte) {
var nodeID, mask *NodeID var nodeID, mask *NodeID
if dest.isValid() { nodeID, mask = dest.getNodeIDandMask() } if dest.isValid() {
if snet.isValid() { nodeID, mask = snet.getNodeIDandMask() } nodeID, mask = dest.getNodeIDandMask()
}
if snet.isValid() {
nodeID, mask = snet.getNodeIDandMask()
}
sinfo, isIn := r.core.searches.searches[*nodeID] sinfo, isIn := r.core.searches.searches[*nodeID]
if !isIn { sinfo = r.core.searches.createSearch(nodeID, mask) } if !isIn {
if packet != nil { sinfo.packet = packet } sinfo = r.core.searches.createSearch(nodeID, mask)
}
if packet != nil {
sinfo.packet = packet
}
r.core.searches.sendSearch(sinfo) r.core.searches.sendSearch(sinfo)
} }
var sinfo *sessionInfo var sinfo *sessionInfo
var isIn bool var isIn bool
if dest.isValid() { sinfo, isIn = r.core.sessions.getByTheirAddr(&dest) } if dest.isValid() {
if snet.isValid() { sinfo, isIn = r.core.sessions.getByTheirSubnet(&snet) } sinfo, isIn = r.core.sessions.getByTheirAddr(&dest)
}
if snet.isValid() {
sinfo, isIn = r.core.sessions.getByTheirSubnet(&snet)
}
switch { switch {
case !isIn || !sinfo.init: case !isIn || !sinfo.init:
// No or unintiialized session, so we need to search first // No or unintiialized session, so we need to search first
@ -113,7 +137,8 @@ func (r *router) sendPacket(bs []byte) {
doSearch(nil) doSearch(nil)
fallthrough fallthrough
//default: go func() { sinfo.send<-bs }() //default: go func() { sinfo.send<-bs }()
default: sinfo.send<-bs default:
sinfo.send <- bs
} }
} }
@ -121,70 +146,102 @@ func (r *router) recvPacket(bs []byte, theirAddr *address) {
// TODO pass their NodeID, check *that* instead // TODO pass their NodeID, check *that* instead
// Or store their address in the session?... // Or store their address in the session?...
//fmt.Println("Recv packet") //fmt.Println("Recv packet")
if theirAddr == nil { panic("Should not happen ever") } if theirAddr == nil {
if len(bs) < 24 { return } panic("Should not happen ever")
}
if len(bs) < 24 {
return
}
var source address var source address
copy(source[:], bs[8:]) copy(source[:], bs[8:])
var snet subnet var snet subnet
copy(snet[:], bs[8:]) copy(snet[:], bs[8:])
if !source.isValid() && !snet.isValid() { return } if !source.isValid() && !snet.isValid() {
return
}
//go func() { r.recv<-bs }() //go func() { r.recv<-bs }()
r.recv<-bs r.recv <- bs
} }
func (r *router) handleIn(packet []byte) { func (r *router) handleIn(packet []byte) {
pType, pTypeLen := wire_decode_uint64(packet) pType, pTypeLen := wire_decode_uint64(packet)
if pTypeLen == 0 { return } if pTypeLen == 0 {
return
}
switch pType { switch pType {
case wire_Traffic: r.handleTraffic(packet) case wire_Traffic:
case wire_ProtocolTraffic: r.handleProto(packet) r.handleTraffic(packet)
default: /*panic("Should not happen in testing") ;*/ return case wire_ProtocolTraffic:
r.handleProto(packet)
default: /*panic("Should not happen in testing") ;*/
return
} }
} }
func (r *router) handleTraffic(packet []byte) { func (r *router) handleTraffic(packet []byte) {
defer util_putBytes(packet) defer util_putBytes(packet)
p := wire_trafficPacket{} p := wire_trafficPacket{}
if !p.decode(packet) { return } if !p.decode(packet) {
return
}
sinfo, isIn := r.core.sessions.getSessionForHandle(&p.handle) sinfo, isIn := r.core.sessions.getSessionForHandle(&p.handle)
if !isIn { return } if !isIn {
return
}
//go func () { sinfo.recv<-&p }() //go func () { sinfo.recv<-&p }()
sinfo.recv<-&p sinfo.recv <- &p
} }
func (r *router) handleProto(packet []byte) { func (r *router) handleProto(packet []byte) {
// First parse the packet // First parse the packet
p := wire_protoTrafficPacket{} p := wire_protoTrafficPacket{}
if !p.decode(packet) { return } if !p.decode(packet) {
return
}
// Now try to open the payload // Now try to open the payload
var sharedKey *boxSharedKey var sharedKey *boxSharedKey
//var theirPermPub *boxPubKey //var theirPermPub *boxPubKey
if p.toKey == r.core.boxPub { if p.toKey == r.core.boxPub {
// Try to open using our permanent key // Try to open using our permanent key
sharedKey = r.core.sessions.getSharedKey(&r.core.boxPriv, &p.fromKey) sharedKey = r.core.sessions.getSharedKey(&r.core.boxPriv, &p.fromKey)
} else { return } } else {
return
}
bs, isOK := boxOpen(sharedKey, p.payload, &p.nonce) bs, isOK := boxOpen(sharedKey, p.payload, &p.nonce)
if !isOK { return } if !isOK {
return
}
// Now do something with the bytes in bs... // Now do something with the bytes in bs...
// send dht messages to dht, sessionRefresh to sessions, data to tun... // send dht messages to dht, sessionRefresh to sessions, data to tun...
// For data, should check that key and IP match... // For data, should check that key and IP match...
bsType, bsTypeLen := wire_decode_uint64(bs) bsType, bsTypeLen := wire_decode_uint64(bs)
if bsTypeLen == 0 { return } if bsTypeLen == 0 {
return
}
//fmt.Println("RECV bytes:", bs) //fmt.Println("RECV bytes:", bs)
switch bsType { switch bsType {
case wire_SessionPing: r.handlePing(bs, &p.fromKey) case wire_SessionPing:
case wire_SessionPong: r.handlePong(bs, &p.fromKey) r.handlePing(bs, &p.fromKey)
case wire_DHTLookupRequest: r.handleDHTReq(bs, &p.fromKey) case wire_SessionPong:
case wire_DHTLookupResponse: r.handleDHTRes(bs, &p.fromKey) r.handlePong(bs, &p.fromKey)
case wire_SearchRequest: r.handleSearchReq(bs) case wire_DHTLookupRequest:
case wire_SearchResponse: r.handleSearchRes(bs) r.handleDHTReq(bs, &p.fromKey)
default: /*panic("Should not happen in testing") ;*/ return case wire_DHTLookupResponse:
r.handleDHTRes(bs, &p.fromKey)
case wire_SearchRequest:
r.handleSearchReq(bs)
case wire_SearchResponse:
r.handleSearchRes(bs)
default: /*panic("Should not happen in testing") ;*/
return
} }
} }
func (r *router) handlePing(bs []byte, fromKey *boxPubKey) { func (r *router) handlePing(bs []byte, fromKey *boxPubKey) {
ping := sessionPing{} ping := sessionPing{}
if !ping.decode(bs) { return } if !ping.decode(bs) {
return
}
ping.sendPermPub = *fromKey ping.sendPermPub = *fromKey
r.core.sessions.handlePing(&ping) r.core.sessions.handlePing(&ping)
} }
@ -195,26 +252,38 @@ func (r *router) handlePong(bs []byte, fromKey *boxPubKey) {
func (r *router) handleDHTReq(bs []byte, fromKey *boxPubKey) { func (r *router) handleDHTReq(bs []byte, fromKey *boxPubKey) {
req := dhtReq{} req := dhtReq{}
if !req.decode(bs) { return } if !req.decode(bs) {
if req.key != *fromKey { return } return
}
if req.key != *fromKey {
return
}
r.core.dht.handleReq(&req) r.core.dht.handleReq(&req)
} }
func (r *router) handleDHTRes(bs []byte, fromKey *boxPubKey) { func (r *router) handleDHTRes(bs []byte, fromKey *boxPubKey) {
res := dhtRes{} res := dhtRes{}
if !res.decode(bs) { return } if !res.decode(bs) {
if res.key != *fromKey { return } return
}
if res.key != *fromKey {
return
}
r.core.dht.handleRes(&res) r.core.dht.handleRes(&res)
} }
func (r *router) handleSearchReq(bs []byte) { func (r *router) handleSearchReq(bs []byte) {
req := searchReq{} req := searchReq{}
if !req.decode(bs) { return } if !req.decode(bs) {
return
}
r.core.searches.handleSearchReq(&req) r.core.searches.handleSearchReq(&req)
} }
func (r *router) handleSearchRes(bs []byte) { func (r *router) handleSearchRes(bs []byte) {
res := searchRes{} res := searchRes{}
if !res.decode(bs) { return } if !res.decode(bs) {
return
}
r.core.searches.handleSearchRes(&res) r.core.searches.handleSearchRes(&res)
} }

View File

@ -17,6 +17,7 @@ package yggdrasil
// This hides bugs, which I don't want to do right now // This hides bugs, which I don't want to do right now
import "time" import "time"
//import "fmt" //import "fmt"
type searchInfo struct { type searchInfo struct {
@ -68,7 +69,9 @@ type searchRes struct {
func (s *searches) sendSearch(info *searchInfo) { func (s *searches) sendSearch(info *searchInfo) {
now := time.Now() now := time.Now()
if now.Sub(info.time) < time.Second { return } if now.Sub(info.time) < time.Second {
return
}
loc := s.core.switchTable.getLocator() loc := s.core.switchTable.getLocator()
coords := loc.getCoords() coords := loc.getCoords()
req := searchReq{ req := searchReq{
@ -94,7 +97,9 @@ func (s *searches) handleSearchReq(req *searchReq) {
break break
} }
} }
if !sent { s.sendSearchRes(req) } if !sent {
s.sendSearchRes(req)
}
} }
func (s *searches) forwardSearch(req *searchReq, next *dhtInfo) { func (s *searches) forwardSearch(req *searchReq, next *dhtInfo) {
@ -140,23 +145,29 @@ func (s *searches) sendSearchRes(req *searchReq) {
func (s *searches) handleSearchRes(res *searchRes) { func (s *searches) handleSearchRes(res *searchRes) {
info, isIn := s.searches[res.dest] info, isIn := s.searches[res.dest]
if !isIn { return } if !isIn {
return
}
them := getNodeID(&res.key) them := getNodeID(&res.key)
var destMasked NodeID var destMasked NodeID
var themMasked NodeID var themMasked NodeID
for idx := 0 ; idx < NodeIDLen ; idx++ { for idx := 0; idx < NodeIDLen; idx++ {
destMasked[idx] = info.dest[idx] & info.mask[idx] destMasked[idx] = info.dest[idx] & info.mask[idx]
themMasked[idx] = them[idx] & info.mask[idx] themMasked[idx] = them[idx] & info.mask[idx]
} }
//fmt.Println("DEBUG search res1:", themMasked, destMasked) //fmt.Println("DEBUG search res1:", themMasked, destMasked)
//fmt.Println("DEBUG search res2:", *them, *info.dest, *info.mask) //fmt.Println("DEBUG search res2:", *them, *info.dest, *info.mask)
if themMasked != destMasked { return } if themMasked != destMasked {
return
}
// They match, so create a session and send a sessionRequest // They match, so create a session and send a sessionRequest
sinfo, isIn := s.core.sessions.getByTheirPerm(&res.key) sinfo, isIn := s.core.sessions.getByTheirPerm(&res.key)
if !isIn { if !isIn {
sinfo = s.core.sessions.createSession(&res.key) sinfo = s.core.sessions.createSession(&res.key)
_, isIn := s.core.sessions.getByTheirPerm(&res.key) _, isIn := s.core.sessions.getByTheirPerm(&res.key)
if !isIn { panic("This should never happen") } if !isIn {
panic("This should never happen")
}
} }
// FIXME replay attacks could mess with coords? // FIXME replay attacks could mess with coords?
sinfo.coords = res.coords sinfo.coords = res.coords
@ -165,4 +176,3 @@ func (s *searches) handleSearchRes(res *searchRes) {
// Cleanup // Cleanup
delete(s.searches, res.dest) delete(s.searches, res.dest)
} }

View File

@ -41,8 +41,12 @@ type sessionPing struct {
// Returns true if the session was updated, false otherwise // Returns true if the session was updated, false otherwise
func (s *sessionInfo) update(p *sessionPing) bool { func (s *sessionInfo) update(p *sessionPing) bool {
if !(p.tstamp > s.tstamp) { return false } if !(p.tstamp > s.tstamp) {
if p.sendPermPub != s.theirPermPub { return false } // Shouldn't happen return false
}
if p.sendPermPub != s.theirPermPub {
return false
} // Shouldn't happen
if p.sendSesPub != s.theirSesPub { if p.sendSesPub != s.theirSesPub {
// FIXME need to protect against replay attacks // FIXME need to protect against replay attacks
// Put a sequence number or a timestamp or something in the pings? // Put a sequence number or a timestamp or something in the pings?
@ -99,28 +103,36 @@ func (ss *sessions) getSessionForHandle(handle *handle) (*sessionInfo, bool) {
func (ss *sessions) getByMySes(key *boxPubKey) (*sessionInfo, bool) { func (ss *sessions) getByMySes(key *boxPubKey) (*sessionInfo, bool) {
h, isIn := ss.byMySes[*key] h, isIn := ss.byMySes[*key]
if !isIn { return nil, false } if !isIn {
return nil, false
}
sinfo, isIn := ss.getSessionForHandle(h) sinfo, isIn := ss.getSessionForHandle(h)
return sinfo, isIn return sinfo, isIn
} }
func (ss *sessions) getByTheirPerm(key *boxPubKey) (*sessionInfo, bool) { func (ss *sessions) getByTheirPerm(key *boxPubKey) (*sessionInfo, bool) {
h, isIn := ss.byTheirPerm[*key] h, isIn := ss.byTheirPerm[*key]
if !isIn { return nil, false } if !isIn {
return nil, false
}
sinfo, isIn := ss.getSessionForHandle(h) sinfo, isIn := ss.getSessionForHandle(h)
return sinfo, isIn return sinfo, isIn
} }
func (ss *sessions) getByTheirAddr(addr *address) (*sessionInfo, bool) { func (ss *sessions) getByTheirAddr(addr *address) (*sessionInfo, bool) {
p, isIn := ss.addrToPerm[*addr] p, isIn := ss.addrToPerm[*addr]
if !isIn { return nil, false } if !isIn {
return nil, false
}
sinfo, isIn := ss.getByTheirPerm(p) sinfo, isIn := ss.getByTheirPerm(p)
return sinfo, isIn return sinfo, isIn
} }
func (ss *sessions) getByTheirSubnet(snet *subnet) (*sessionInfo, bool) { func (ss *sessions) getByTheirSubnet(snet *subnet) (*sessionInfo, bool) {
p, isIn := ss.subnetToPerm[*snet] p, isIn := ss.subnetToPerm[*snet]
if !isIn { return nil, false } if !isIn {
return nil, false
}
sinfo, isIn := ss.getByTheirPerm(p) sinfo, isIn := ss.getByTheirPerm(p)
return sinfo, isIn return sinfo, isIn
} }
@ -159,7 +171,9 @@ func (ss *sessions) createSession(theirPermKey *boxPubKey) *sessionInfo {
// Do some cleanup // Do some cleanup
// Time thresholds almost certainly could use some adjusting // Time thresholds almost certainly could use some adjusting
for _, s := range ss.sinfos { for _, s := range ss.sinfos {
if s.timedout() { s.close() } if s.timedout() {
s.close()
}
} }
ss.sinfos[sinfo.myHandle] = &sinfo ss.sinfos[sinfo.myHandle] = &sinfo
ss.byMySes[sinfo.mySesPub] = &sinfo.myHandle ss.byMySes[sinfo.mySesPub] = &sinfo.myHandle
@ -195,12 +209,16 @@ func (ss *sessions) getPing(sinfo *sessionInfo) sessionPing {
func (ss *sessions) getSharedKey(myPriv *boxPrivKey, func (ss *sessions) getSharedKey(myPriv *boxPrivKey,
theirPub *boxPubKey) *boxSharedKey { theirPub *boxPubKey) *boxSharedKey {
if skey, isIn := ss.permShared[*theirPub] ; isIn { return skey } if skey, isIn := ss.permShared[*theirPub]; isIn {
return skey
}
// First do some cleanup // First do some cleanup
const maxKeys = dht_bucket_number*dht_bucket_size const maxKeys = dht_bucket_number * dht_bucket_size
for key := range ss.permShared { for key := range ss.permShared {
// Remove a random key until the store is small enough // Remove a random key until the store is small enough
if len(ss.permShared) < maxKeys { break } if len(ss.permShared) < maxKeys {
break
}
delete(ss.permShared, key) delete(ss.permShared, key)
} }
ss.permShared[*theirPub] = getSharedKey(myPriv, theirPub) ss.permShared[*theirPub] = getSharedKey(myPriv, theirPub)
@ -233,19 +251,27 @@ func (ss *sessions) handlePing(ping *sessionPing) {
// Get the corresponding session (or create a new session) // Get the corresponding session (or create a new session)
sinfo, isIn := ss.getByTheirPerm(&ping.sendPermPub) sinfo, isIn := ss.getByTheirPerm(&ping.sendPermPub)
if !isIn || sinfo.timedout() { if !isIn || sinfo.timedout() {
if isIn { sinfo.close() } if isIn {
sinfo.close()
}
ss.createSession(&ping.sendPermPub) ss.createSession(&ping.sendPermPub)
sinfo, isIn = ss.getByTheirPerm(&ping.sendPermPub) sinfo, isIn = ss.getByTheirPerm(&ping.sendPermPub)
if !isIn { panic("This should not happen") } if !isIn {
panic("This should not happen")
}
} }
// Update the session // Update the session
if !sinfo.update(ping) { /*panic("Should not happen in testing")*/ ; return } if !sinfo.update(ping) { /*panic("Should not happen in testing")*/
if !ping.isPong{ ss.sendPingPong(sinfo, true) } return
}
if !ping.isPong {
ss.sendPingPong(sinfo, true)
}
if sinfo.packet != nil { if sinfo.packet != nil {
// send // send
var bs []byte var bs []byte
bs, sinfo.packet = sinfo.packet, nil bs, sinfo.packet = sinfo.packet, nil
go func() { sinfo.send<-bs }() go func() { sinfo.send <- bs }()
} }
} }
@ -254,8 +280,12 @@ func (n *boxNonce) minus(m *boxNonce) int64 {
for idx := range n { for idx := range n {
diff *= 256 diff *= 256
diff += int64(n[idx]) - int64(m[idx]) diff += int64(n[idx]) - int64(m[idx])
if diff > 64 { diff = 64 } if diff > 64 {
if diff < -64 { diff = -64 } diff = 64
}
if diff < -64 {
diff = -64
}
} }
return diff return diff
} }
@ -263,8 +293,10 @@ func (n *boxNonce) minus(m *boxNonce) int64 {
func (sinfo *sessionInfo) nonceIsOK(theirNonce *boxNonce) bool { func (sinfo *sessionInfo) nonceIsOK(theirNonce *boxNonce) bool {
// The bitmask is to allow for some non-duplicate out-of-order packets // The bitmask is to allow for some non-duplicate out-of-order packets
diff := theirNonce.minus(&sinfo.theirNonce) diff := theirNonce.minus(&sinfo.theirNonce)
if diff > 0 { return true } if diff > 0 {
return ^sinfo.nonceMask & (0x01 << uint64(-diff)) != 0 return true
}
return ^sinfo.nonceMask&(0x01<<uint64(-diff)) != 0
} }
func (sinfo *sessionInfo) updateNonce(theirNonce *boxNonce) { func (sinfo *sessionInfo) updateNonce(theirNonce *boxNonce) {
@ -281,7 +313,9 @@ func (sinfo *sessionInfo) updateNonce(theirNonce *boxNonce) {
} }
func (ss *sessions) resetInits() { func (ss *sessions) resetInits() {
for _, sinfo := range ss.sinfos { sinfo.init = false } for _, sinfo := range ss.sinfos {
sinfo.init = false
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -293,15 +327,27 @@ func (ss *sessions) resetInits() {
func (sinfo *sessionInfo) doWorker() { func (sinfo *sessionInfo) doWorker() {
for { for {
select { select {
case p, ok := <-sinfo.recv: if ok { sinfo.doRecv(p) } else { return } case p, ok := <-sinfo.recv:
case bs, ok := <-sinfo.send: if ok { sinfo.doSend(bs) } else { return } if ok {
sinfo.doRecv(p)
} else {
return
}
case bs, ok := <-sinfo.send:
if ok {
sinfo.doSend(bs)
} else {
return
}
} }
} }
} }
func (sinfo *sessionInfo) doSend(bs []byte) { func (sinfo *sessionInfo) doSend(bs []byte) {
defer util_putBytes(bs) defer util_putBytes(bs)
if !sinfo.init { return } // To prevent using empty session keys if !sinfo.init {
return
} // To prevent using empty session keys
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{
@ -317,11 +363,15 @@ func (sinfo *sessionInfo) doSend(bs []byte) {
func (sinfo *sessionInfo) doRecv(p *wire_trafficPacket) { func (sinfo *sessionInfo) doRecv(p *wire_trafficPacket) {
defer util_putBytes(p.payload) defer util_putBytes(p.payload)
if !sinfo.nonceIsOK(&p.nonce) { return } if !sinfo.nonceIsOK(&p.nonce) {
return
}
bs, isOK := boxOpen(&sinfo.sharedSesKey, p.payload, &p.nonce) bs, isOK := boxOpen(&sinfo.sharedSesKey, p.payload, &p.nonce)
if !isOK { util_putBytes(bs) ; return } if !isOK {
util_putBytes(bs)
return
}
sinfo.updateNonce(&p.nonce) sinfo.updateNonce(&p.nonce)
sinfo.time = time.Now() sinfo.time = time.Now()
sinfo.core.router.recvPacket(bs, &sinfo.theirAddr) sinfo.core.router.recvPacket(bs, &sinfo.theirAddr)
} }

View File

@ -22,9 +22,13 @@ func (m *sigManager) init() {
} }
func (m *sigManager) check(key *sigPubKey, sig *sigBytes, bs []byte) bool { func (m *sigManager) check(key *sigPubKey, sig *sigBytes, bs []byte) bool {
if m.isChecked(sig, bs) { return true } if m.isChecked(sig, bs) {
return true
}
verified := verify(key, bs, sig) verified := verify(key, bs, sig)
if verified { m.putChecked(sig, bs) } if verified {
m.putChecked(sig, bs)
}
return verified return verified
} }
@ -32,10 +36,16 @@ func (m *sigManager) isChecked(sig *sigBytes, bs []byte) bool {
m.mutex.RLock() m.mutex.RLock()
defer m.mutex.RUnlock() defer m.mutex.RUnlock()
k, isIn := m.checked[*sig] k, isIn := m.checked[*sig]
if !isIn { return false } if !isIn {
if len(bs) != len(k.bs) { return false } return false
for idx := 0 ; idx < len(bs) ; idx++ { }
if bs[idx] != k.bs[idx] { return false } if len(bs) != len(k.bs) {
return false
}
for idx := 0; idx < len(bs); idx++ {
if bs[idx] != k.bs[idx] {
return false
}
} }
k.time = time.Now() k.time = time.Now()
return true return true
@ -48,11 +58,12 @@ func (m *sigManager) putChecked(newsig *sigBytes, bs []byte) {
if time.Since(m.lastCleaned) > 60*time.Second { if time.Since(m.lastCleaned) > 60*time.Second {
// Since we have the write lock anyway, do some cleanup // Since we have the write lock anyway, do some cleanup
for s, k := range m.checked { for s, k := range m.checked {
if time.Since(k.time) > 60*time.Second { delete(m.checked, s) } if time.Since(k.time) > 60*time.Second {
delete(m.checked, s)
}
} }
m.lastCleaned = now m.lastCleaned = now
} }
k := knownSig{bs: bs, time: now} k := knownSig{bs: bs, time: now}
m.checked[*newsig] = k m.checked[*newsig] = k
} }

View File

@ -32,8 +32,10 @@ func firstIsBetter(first, second *sigPubKey) bool {
// Higher TreeID is better // Higher TreeID is better
ftid := getTreeID(first) ftid := getTreeID(first)
stid := getTreeID(second) stid := getTreeID(second)
for idx := 0 ; idx < len(ftid) ; idx++ { for idx := 0; idx < len(ftid); idx++ {
if ftid[idx] == stid[idx] { continue } if ftid[idx] == stid[idx] {
continue
}
return ftid[idx] > stid[idx] return ftid[idx] > stid[idx]
} }
// Edge case, when comparing identical IDs // Edge case, when comparing identical IDs
@ -55,17 +57,25 @@ func (l *switchLocator) dist(dest []byte) int {
offset := 0 offset := 0
fdc := 0 fdc := 0
for { for {
if fdc >= len(l.coords) { break } if fdc >= len(l.coords) {
break
}
coord, length := wire_decode_uint64(dest[offset:]) coord, length := wire_decode_uint64(dest[offset:])
if length == 0 { break } if length == 0 {
if l.coords[fdc] != switchPort(coord) { break } break
}
if l.coords[fdc] != switchPort(coord) {
break
}
fdc++ fdc++
offset += length offset += length
} }
dist := len(l.coords[fdc:]) dist := len(l.coords[fdc:])
for { for {
_, length := wire_decode_uint64(dest[offset:]) _, length := wire_decode_uint64(dest[offset:])
if length == 0 { break } if length == 0 {
break
}
dist++ dist++
offset += length offset += length
} }
@ -82,10 +92,16 @@ func (l *switchLocator) getCoords() []byte {
} }
func (x *switchLocator) isAncestorOf(y *switchLocator) bool { func (x *switchLocator) isAncestorOf(y *switchLocator) bool {
if x.root != y.root { return false } if x.root != y.root {
if len(x.coords) > len(y.coords) { return false } return false
}
if len(x.coords) > len(y.coords) {
return false
}
for idx := range x.coords { for idx := range x.coords {
if x.coords[idx] != y.coords[idx] { return false } if x.coords[idx] != y.coords[idx] {
return false
}
} }
return true return true
} }
@ -149,7 +165,7 @@ func (t *switchTable) init(core *Core, key sigPubKey) {
t.updater.Store(&sync.Once{}) t.updater.Store(&sync.Once{})
t.table.Store(lookupTable{elems: make(map[switchPort]tableElem)}) t.table.Store(lookupTable{elems: make(map[switchPort]tableElem)})
t.drop = make(map[sigPubKey]int64) t.drop = make(map[sigPubKey]int64)
doTicker := func () { doTicker := func() {
ticker := time.NewTicker(time.Second) ticker := time.NewTicker(time.Second)
defer ticker.Stop() defer ticker.Stop()
for { for {
@ -208,7 +224,7 @@ func (t *switchTable) cleanRoot() {
t.data.seq++ t.data.seq++
t.updater.Store(&sync.Once{}) t.updater.Store(&sync.Once{})
select { select {
case t.core.router.reset<-struct{}{}: case t.core.router.reset <- struct{}{}:
default: default:
} }
} }
@ -227,13 +243,17 @@ func (t *switchTable) cleanPeers() {
changed = true changed = true
} }
} }
if changed { t.updater.Store(&sync.Once{}) } if changed {
t.updater.Store(&sync.Once{})
}
} }
func (t *switchTable) cleanDropped() { func (t *switchTable) cleanDropped() {
// TODO only call this after root changes, not periodically // TODO only call this after root changes, not periodically
for root, _ := range t.drop { for root := range t.drop {
if !firstIsBetter(&root, &t.data.locator.root) { delete(t.drop, root) } if !firstIsBetter(&root, &t.data.locator.root) {
delete(t.drop, root)
}
} }
} }
@ -250,9 +270,13 @@ func (t *switchTable) handleMessage(msg *switchMessage, fromPort switchPort, sig
t.mutex.Lock() t.mutex.Lock()
defer t.mutex.Unlock() defer t.mutex.Unlock()
now := time.Now() now := time.Now()
if len(msg.locator.coords) == 0 { return } // Should always have >=1 links if len(msg.locator.coords) == 0 {
return
} // Should always have >=1 links
oldSender, isIn := t.data.peers[fromPort] oldSender, isIn := t.data.peers[fromPort]
if !isIn { oldSender.firstSeen = now } if !isIn {
oldSender.firstSeen = now
}
sender := peerInfo{key: msg.from, sender := peerInfo{key: msg.from,
locator: msg.locator, locator: msg.locator,
coords: msg.locator.coords[:len(msg.locator.coords)-1], coords: msg.locator.coords[:len(msg.locator.coords)-1],
@ -260,11 +284,17 @@ func (t *switchTable) handleMessage(msg *switchMessage, fromPort switchPort, sig
firstSeen: oldSender.firstSeen, firstSeen: oldSender.firstSeen,
port: fromPort, port: fromPort,
seq: msg.seq} seq: msg.seq}
equiv := func (x *switchLocator, y *switchLocator) bool { equiv := func(x *switchLocator, y *switchLocator) bool {
if x.root != y.root { return false } if x.root != y.root {
if len(x.coords) != len(y.coords) { return false } return false
}
if len(x.coords) != len(y.coords) {
return false
}
for idx := range x.coords { for idx := range x.coords {
if x.coords[idx] != y.coords[idx] { return false } if x.coords[idx] != y.coords[idx] {
return false
}
} }
return true return true
} }
@ -277,51 +307,63 @@ func (t *switchTable) handleMessage(msg *switchMessage, fromPort switchPort, sig
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(sigs)-1; idx++ {
if sigs[idx].next == t.core.sigPub { return false } if sigs[idx].next == t.core.sigPub {
return false
}
}
if msg.locator.root == t.core.sigPub {
return false
} }
if msg.locator.root == t.core.sigPub { return false }
return true return true
}() }()
sTime := now.Sub(sender.firstSeen) sTime := now.Sub(sender.firstSeen)
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(msg.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[msg.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 >= msg.locator.tstamp: // do nothing
case firstIsBetter(&msg.locator.root, &t.data.locator.root): updateRoot = true case firstIsBetter(&msg.locator.root, &t.data.locator.root):
updateRoot = true
case t.data.locator.root != msg.locator.root: // do nothing case t.data.locator.root != msg.locator.root: // do nothing
case t.data.locator.tstamp > msg.locator.tstamp: // do nothing case t.data.locator.tstamp > msg.locator.tstamp: // do nothing
case noParent: updateRoot = true case noParent:
case cost < pCost: updateRoot = true updateRoot = true
case cost < pCost:
updateRoot = true
case sender.port == t.parent && case sender.port == t.parent &&
(msg.locator.tstamp > t.data.locator.tstamp || (msg.locator.tstamp > t.data.locator.tstamp ||
!equiv(&msg.locator, &t.data.locator)): updateRoot = true !equiv(&msg.locator, &t.data.locator)):
updateRoot = true
} }
if updateRoot { if updateRoot {
if !equiv(&msg.locator, &t.data.locator) { if !equiv(&msg.locator, &t.data.locator) {
doUpdate = true doUpdate = true
t.data.seq++ t.data.seq++
select { select {
case t.core.router.reset<-struct{}{}: case t.core.router.reset <- struct{}{}:
default: default:
} }
//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 { t.time = now } if t.data.locator.tstamp != msg.locator.tstamp {
t.time = now
}
t.data.locator = msg.locator t.data.locator = msg.locator
t.parent = sender.port t.parent = sender.port
t.data.sigs = sigs 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)
} }
if doUpdate { t.updater.Store(&sync.Once{}) } if doUpdate {
t.updater.Store(&sync.Once{})
}
return return
} }
@ -344,7 +386,7 @@ func (t *switchTable) updateTable() {
//if !pinfo.forward { continue } //if !pinfo.forward { continue }
loc := pinfo.locator.clone() loc := pinfo.locator.clone()
loc.coords = loc.coords[:len(loc.coords)-1] // Remove the them->self link loc.coords = loc.coords[:len(loc.coords)-1] // Remove the them->self link
newTable.elems[pinfo.port] = tableElem { newTable.elems[pinfo.port] = tableElem{
locator: loc, locator: loc,
//degree: pinfo.degree, //degree: pinfo.degree,
firstSeen: pinfo.firstSeen, firstSeen: pinfo.firstSeen,
@ -358,7 +400,7 @@ func (t *switchTable) lookup(dest []byte, ttl uint64) (switchPort, uint64) {
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)
ports := t.core.peers.getPorts() ports := t.core.peers.getPorts()
getBandwidth := func (port switchPort) float64 { getBandwidth := func(port switchPort) float64 {
var bandwidth float64 var bandwidth float64
if p, isIn := ports[port]; isIn { if p, isIn := ports[port]; isIn {
bandwidth = p.getBandwidth() bandwidth = p.getBandwidth()
@ -367,15 +409,21 @@ func (t *switchTable) lookup(dest []byte, ttl uint64) (switchPort, uint64) {
} }
var best switchPort var best switchPort
myDist := table.self.dist(dest) //getDist(table.self.coords) myDist := table.self.dist(dest) //getDist(table.self.coords)
if !(uint64(myDist) < ttl) { return 0, 0 } if !(uint64(myDist) < ttl) {
return 0, 0
}
// score is in units of bandwidth / distance // score is in units of bandwidth / distance
bestScore := float64(-1) bestScore := float64(-1)
for port, info := range table.elems { for port, info := range table.elems {
if info.locator.root != table.self.root { continue } if info.locator.root != table.self.root {
continue
}
dist := info.locator.dist(dest) //getDist(info.locator.coords) dist := info.locator.dist(dest) //getDist(info.locator.coords)
if !(dist < myDist) { continue } if !(dist < myDist) {
continue
}
score := getBandwidth(port) score := getBandwidth(port)
score /= float64(1+dist) score /= float64(1 + dist)
if score > bestScore { if score > bestScore {
best = port best = port
bestScore = score bestScore = score
@ -395,4 +443,3 @@ type sigInfo struct {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -16,7 +16,7 @@ import "errors"
import "sync" import "sync"
import "fmt" import "fmt"
const tcp_msgSize = 2048+65535 // TODO figure out what makes sense const tcp_msgSize = 2048 + 65535 // TODO figure out what makes sense
type tcpInterface struct { type tcpInterface struct {
core *Core core *Core
@ -33,9 +33,13 @@ type tcpKeys struct {
func (iface *tcpInterface) init(core *Core, addr string) { func (iface *tcpInterface) init(core *Core, addr string) {
iface.core = core iface.core = core
tcpAddr, err := net.ResolveTCPAddr("tcp", addr) tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
iface.serv, err = net.ListenTCP("tcp", tcpAddr) iface.serv, err = net.ListenTCP("tcp", tcpAddr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
iface.calls = make(map[string]struct{}) iface.calls = make(map[string]struct{})
go iface.listener() go iface.listener()
} }
@ -45,7 +49,9 @@ func (iface *tcpInterface) listener() {
iface.core.log.Println("Listening on:", iface.serv.Addr().String()) iface.core.log.Println("Listening on:", iface.serv.Addr().String())
for { for {
sock, err := iface.serv.AcceptTCP() sock, err := iface.serv.AcceptTCP()
if err != nil { panic(err) } if err != nil {
panic(err)
}
go iface.handler(sock) go iface.handler(sock)
} }
} }
@ -67,7 +73,9 @@ func (iface *tcpInterface) call(saddr string) {
iface.mutex.Unlock() iface.mutex.Unlock()
if !quit { if !quit {
conn, err := net.DialTimeout("tcp", saddr, 6*time.Second) conn, err := net.DialTimeout("tcp", saddr, 6*time.Second)
if err != nil { return } if err != nil {
return
}
sock := conn.(*net.TCPConn) sock := conn.(*net.TCPConn)
iface.handler(sock) iface.handler(sock)
} }
@ -82,27 +90,41 @@ func (iface *tcpInterface) handler(sock *net.TCPConn) {
keys = append(keys, iface.core.boxPub[:]...) keys = append(keys, iface.core.boxPub[:]...)
keys = append(keys, iface.core.sigPub[:]...) keys = append(keys, iface.core.sigPub[:]...)
_, err := sock.Write(keys) _, err := sock.Write(keys)
if err != nil { return } if err != nil {
timeout := time.Now().Add(6*time.Second) return
}
timeout := time.Now().Add(6 * time.Second)
sock.SetReadDeadline(timeout) sock.SetReadDeadline(timeout)
n, err := sock.Read(keys) n, err := sock.Read(keys)
if err != nil { return } if err != nil {
if n < len(keys) { /*panic("Partial key packet?") ;*/ return } return
}
if n < len(keys) { /*panic("Partial key packet?") ;*/
return
}
ks := tcpKeys{} ks := tcpKeys{}
if !tcp_chop_keys(&ks.box, &ks.sig, &keys) { /*panic("Invalid key packet?") ;*/ return } if !tcp_chop_keys(&ks.box, &ks.sig, &keys) { /*panic("Invalid key packet?") ;*/
return
}
// Quit the parent call if this is a connection to ourself // Quit the parent call if this is a connection to ourself
equiv := func(k1, k2 []byte) bool { equiv := func(k1, k2 []byte) bool {
for idx := range k1 { for idx := range k1 {
if k1[idx] != k2[idx] { return false } if k1[idx] != k2[idx] {
return false
}
} }
return true return true
} }
if equiv(ks.box[:], iface.core.boxPub[:]) { return } // testing if equiv(ks.box[:], iface.core.boxPub[:]) {
if equiv(ks.sig[:], iface.core.sigPub[:]) { return } return
} // testing
if equiv(ks.sig[:], iface.core.sigPub[:]) {
return
}
// 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) linkIn := make(chan []byte, 1)
p := iface.core.peers.newPeer(&ks.box, &ks.sig)//, in, out) p := iface.core.peers.newPeer(&ks.box, &ks.sig) //, in, out)
in := func(bs []byte) { in := func(bs []byte) {
p.handlePacket(bs, linkIn) p.handlePacket(bs, linkIn)
} }
@ -124,7 +146,9 @@ func (iface *tcpInterface) handler(sock *net.TCPConn) {
wire_encode_uint64(uint64(len(msg))), wire_encode_uint64(uint64(len(msg))),
msg} msg}
size := 0 size := 0
for _, bs := range buf { size += len(bs) } for _, bs := range buf {
size += len(bs)
}
start := time.Now() start := time.Now()
buf.WriteTo(sock) buf.WriteTo(sock)
timed := time.Since(start) timed := time.Since(start)
@ -140,9 +164,12 @@ func (iface *tcpInterface) handler(sock *net.TCPConn) {
// Keep trying to fill the stack (LIFO order) while sending // Keep trying to fill the stack (LIFO order) while sending
select { select {
case msg, ok := <-out: case msg, ok := <-out:
if !ok { return } if !ok {
return
}
put(msg) put(msg)
default: send() default:
send()
} }
} }
} }
@ -151,8 +178,10 @@ func (iface *tcpInterface) handler(sock *net.TCPConn) {
defer func() { recover() }() defer func() { recover() }()
for { for {
select { select {
case out<-msg: return case out <- msg:
default: util_putBytes(<-out) return
default:
util_putBytes(<-out)
} }
} }
} }
@ -163,7 +192,9 @@ func (iface *tcpInterface) handler(sock *net.TCPConn) {
p.core.peers.mutex.Lock() p.core.peers.mutex.Lock()
oldPorts := p.core.peers.getPorts() oldPorts := p.core.peers.getPorts()
newPorts := make(map[switchPort]*peer) newPorts := make(map[switchPort]*peer)
for k,v := range oldPorts{ newPorts[k] = v } for k, v := range oldPorts {
newPorts[k] = v
}
delete(newPorts, p.port) delete(newPorts, p.port)
p.core.peers.putPorts(newPorts) p.core.peers.putPorts(newPorts)
p.core.peers.mutex.Unlock() p.core.peers.mutex.Unlock()
@ -184,15 +215,21 @@ func (iface *tcpInterface) reader(sock *net.TCPConn, in func([]byte)) {
bs := make([]byte, 2*tcp_msgSize) bs := make([]byte, 2*tcp_msgSize)
frag := bs[:0] frag := bs[:0]
for { for {
timeout := time.Now().Add(6*time.Second) timeout := time.Now().Add(6 * time.Second)
sock.SetReadDeadline(timeout) sock.SetReadDeadline(timeout)
n, err := sock.Read(bs[len(frag):]) n, err := sock.Read(bs[len(frag):])
if err != nil || n == 0 { break } if err != nil || n == 0 {
break
}
frag = bs[:len(frag)+n] frag = bs[:len(frag)+n]
for { for {
msg, ok, err := tcp_chop_msg(&frag) msg, ok, err := tcp_chop_msg(&frag)
if err != nil { return } if err != nil {
if !ok { break } // We didn't get the whole message yet return
}
if !ok {
break
} // We didn't get the whole message yet
newMsg := append(util_getBytes(), msg...) newMsg := append(util_getBytes(), msg...)
in(newMsg) in(newMsg)
util_yield() util_yield()
@ -210,9 +247,13 @@ var tcp_msg = [...]byte{0xde, 0xad, 0xb1, 0x75} // "dead bits"
func tcp_chop_keys(box *boxPubKey, sig *sigPubKey, bs *[]byte) bool { func tcp_chop_keys(box *boxPubKey, sig *sigPubKey, bs *[]byte) bool {
// This one is pretty simple: we know how long the message should be // This one is pretty simple: we know how long the message should be
// So don't call this with a message that's too short // So don't call this with a message that's too short
if len(*bs) < len(tcp_key) + len(*box) + len(*sig) { return false } if len(*bs) < len(tcp_key)+len(*box)+len(*sig) {
return false
}
for idx := range tcp_key { for idx := range tcp_key {
if (*bs)[idx] != tcp_key[idx] { return false } if (*bs)[idx] != tcp_key[idx] {
return false
}
} }
(*bs) = (*bs)[len(tcp_key):] (*bs) = (*bs)[len(tcp_key):]
copy(box[:], *bs) copy(box[:], *bs)
@ -224,14 +265,18 @@ func tcp_chop_keys(box *boxPubKey, sig *sigPubKey, bs *[]byte) bool {
func tcp_chop_msg(bs *[]byte) ([]byte, bool, error) { func tcp_chop_msg(bs *[]byte) ([]byte, bool, error) {
// Returns msg, ok, err // Returns msg, ok, err
if len(*bs) < len(tcp_msg) { return nil, false, nil } if len(*bs) < len(tcp_msg) {
return nil, false, nil
}
for idx := range tcp_msg { for idx := range tcp_msg {
if (*bs)[idx] != tcp_msg[idx] { if (*bs)[idx] != tcp_msg[idx] {
return nil, false, errors.New("Bad message!") return nil, false, errors.New("Bad message!")
} }
} }
msgLen, msgLenLen := wire_decode_uint64((*bs)[len(tcp_msg):]) msgLen, msgLenLen := wire_decode_uint64((*bs)[len(tcp_msg):])
if msgLen > tcp_msgSize { return nil, false, errors.New("Oversized message!") } if msgLen > tcp_msgSize {
return nil, false, errors.New("Oversized message!")
}
msgBegin := len(tcp_msg) + msgLenLen msgBegin := len(tcp_msg) + msgLenLen
msgEnd := msgBegin + int(msgLen) msgEnd := msgBegin + int(msgLen)
if msgLenLen == 0 || len(*bs) < msgEnd { if msgLenLen == 0 || len(*bs) < msgEnd {
@ -243,4 +288,3 @@ func tcp_chop_msg(bs *[]byte) ([]byte, bool, error) {
(*bs) = (*bs)[msgEnd:] (*bs) = (*bs)[msgEnd:]
return msg, true, nil return msg, true, nil
} }

View File

@ -18,18 +18,12 @@ func (tun *tunDevice) init(core *Core) {
tun.core = core tun.core = core
} }
func (tun *tunDevice) setup(addr string, mtu int) error {
iface, err := water.New(water.Config{ DeviceType: water.TUN })
if err != nil { panic(err) }
tun.iface = iface
tun.mtu = mtu //1280 // Lets default to the smallest thing allowed for now
return tun.setupAddress(addr)
}
func (tun *tunDevice) write() error { func (tun *tunDevice) write() error {
for { for {
data := <-tun.recv data := <-tun.recv
if _, err := tun.iface.Write(data); err != nil { return err } if _, err := tun.iface.Write(data); err != nil {
return err
}
util_putBytes(data) util_putBytes(data)
} }
} }
@ -38,19 +32,20 @@ func (tun *tunDevice) read() error {
buf := make([]byte, tun.mtu) buf := make([]byte, tun.mtu)
for { for {
n, err := tun.iface.Read(buf) n, err := tun.iface.Read(buf)
if err != nil { return err } if err != nil {
if buf[0] & 0xf0 != 0x60 || return err
n != 256*int(buf[4]) + int(buf[5]) + IPv6_HEADER_LENGTH { }
if buf[0]&0xf0 != 0x60 ||
n != 256*int(buf[4])+int(buf[5])+IPv6_HEADER_LENGTH {
// Either not an IPv6 packet or not the complete packet for some reason // Either not an IPv6 packet or not the complete packet for some reason
//panic("Should not happen in testing") //panic("Should not happen in testing")
continue continue
} }
packet := append(util_getBytes(), buf[:n]...) packet := append(util_getBytes(), buf[:n]...)
tun.send<-packet tun.send <- packet
} }
} }
func (tun *tunDevice) close() error { func (tun *tunDevice) close() error {
return tun.iface.Close() return tun.iface.Close()
} }

View File

@ -7,6 +7,22 @@ import "fmt"
import "os/exec" import "os/exec"
import "strings" import "strings"
import water "github.com/songgao/water"
func (tun *tunDevice) setup(ifname string, addr string, mtu int) error {
config := water.Config{DeviceType: water.TUN}
if ifname != "" && ifname != "auto" {
config.Name = ifname
}
iface, err := water.New(config)
if err != nil {
panic(err)
}
tun.iface = iface
tun.mtu = mtu //1280 // Lets default to the smallest thing allowed for now
return tun.setupAddress(addr)
}
func (tun *tunDevice) setupAddress(addr string) error { func (tun *tunDevice) setupAddress(addr string) error {
// Set address // Set address
cmd := exec.Command("ip", "-f", "inet6", cmd := exec.Command("ip", "-f", "inet6",
@ -33,4 +49,3 @@ func (tun *tunDevice) setupAddress(addr string) error {
} }
return nil return nil
} }

View File

@ -2,11 +2,23 @@
package yggdrasil package yggdrasil
import water "github.com/songgao/water"
// This is to catch unsupported platforms // This is to catch unsupported platforms
// If your platform supports tun devices, you could try configuring it manually // If your platform supports tun devices, you could try configuring it manually
func (tun *tunDevice) setup(ifname string, addr string, mtu int) error {
config := water.Config{DeviceType: water.TUN}
iface, err := water.New(config)
if err != nil {
panic(err)
}
tun.iface = iface
tun.mtu = mtu //1280 // Lets default to the smallest thing allowed for now
return tun.setupAddress(addr)
}
func (tun *tunDevice) setupAddress(addr string) error { func (tun *tunDevice) setupAddress(addr string) error {
tun.core.log.Println("Platform not supported, you must set the address of", tun.iface.Name(), "to", addr) tun.core.log.Println("Platform not supported, you must set the address of", tun.iface.Name(), "to", addr)
return nil return nil
} }

View File

@ -42,16 +42,22 @@ type udpKeys struct {
func (iface *udpInterface) init(core *Core, addr string) { func (iface *udpInterface) init(core *Core, addr string) {
iface.core = core iface.core = core
udpAddr, err := net.ResolveUDPAddr("udp", addr) udpAddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
iface.sock, err = net.ListenUDP("udp", udpAddr) iface.sock, err = net.ListenUDP("udp", udpAddr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
iface.conns = make(map[connAddr]*connInfo) iface.conns = make(map[connAddr]*connInfo)
go iface.reader() go iface.reader()
} }
func (iface *udpInterface) sendKeys(addr connAddr) { func (iface *udpInterface) sendKeys(addr connAddr) {
udpAddr, err := net.ResolveUDPAddr("udp", string(addr)) udpAddr, err := net.ResolveUDPAddr("udp", string(addr))
if err != nil { panic(err) } if err != nil {
panic(err)
}
msg := []byte{} msg := []byte{}
msg = udp_encode(msg, 0, 0, 0, nil) msg = udp_encode(msg, 0, 0, 0, nil)
msg = append(msg, iface.core.boxPub[:]...) msg = append(msg, iface.core.boxPub[:]...)
@ -65,9 +71,9 @@ func udp_isKeys(msg []byte) bool {
} }
func (iface *udpInterface) startConn(info *connInfo) { func (iface *udpInterface) startConn(info *connInfo) {
ticker := time.NewTicker(6*time.Second) ticker := time.NewTicker(6 * time.Second)
defer ticker.Stop() defer ticker.Stop()
defer func () { defer func() {
// Cleanup // Cleanup
// FIXME this still leaks a peer struct // FIXME this still leaks a peer struct
iface.mutex.Lock() iface.mutex.Lock()
@ -76,7 +82,9 @@ func (iface *udpInterface) startConn(info *connInfo) {
iface.core.peers.mutex.Lock() iface.core.peers.mutex.Lock()
oldPorts := iface.core.peers.getPorts() oldPorts := iface.core.peers.getPorts()
newPorts := make(map[switchPort]*peer) newPorts := make(map[switchPort]*peer)
for k,v := range oldPorts{ newPorts[k] = v } for k, v := range oldPorts {
newPorts[k] = v
}
delete(newPorts, info.peer.port) delete(newPorts, info.peer.port)
iface.core.peers.putPorts(newPorts) iface.core.peers.putPorts(newPorts)
iface.core.peers.mutex.Unlock() iface.core.peers.mutex.Unlock()
@ -87,15 +95,19 @@ func (iface *udpInterface) startConn(info *connInfo) {
}() }()
for { for {
select { select {
case ks := <-info.keysIn: { case ks := <-info.keysIn:
{
// FIXME? need signatures/sequence-numbers or something // FIXME? need signatures/sequence-numbers or something
// Spoofers could lock out a peer with fake/bad keys // Spoofers could lock out a peer with fake/bad keys
if ks.box == info.peer.box && ks.sig == info.peer.sig { if ks.box == info.peer.box && ks.sig == info.peer.sig {
info.timeout = 0 info.timeout = 0
} }
} }
case <-ticker.C: { case <-ticker.C:
if info.timeout > 10 { return } {
if info.timeout > 10 {
return
}
info.timeout++ info.timeout++
iface.sendKeys(info.addr) iface.sendKeys(info.addr)
} }
@ -108,17 +120,25 @@ func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) {
var ks udpKeys var ks udpKeys
_, _, _, bs := udp_decode(msg) _, _, _, bs := udp_decode(msg)
switch { switch {
case !wire_chop_slice(ks.box[:], &bs): return case !wire_chop_slice(ks.box[:], &bs):
case !wire_chop_slice(ks.sig[:], &bs): return return
case !wire_chop_slice(ks.sig[:], &bs):
return
}
if ks.box == iface.core.boxPub {
return
}
if ks.sig == iface.core.sigPub {
return
} }
if ks.box == iface.core.boxPub { return }
if ks.sig == iface.core.sigPub { return }
iface.mutex.RLock() iface.mutex.RLock()
conn, isIn := iface.conns[addr] conn, isIn := iface.conns[addr]
iface.mutex.RUnlock() // TODO? keep the lock longer?... iface.mutex.RUnlock() // TODO? keep the lock longer?...
if !isIn { if !isIn {
udpAddr, err := net.ResolveUDPAddr("udp", string(addr)) udpAddr, err := net.ResolveUDPAddr("udp", string(addr))
if err != nil { panic(err) } if err != nil {
panic(err)
}
conn = &connInfo{ conn = &connInfo{
addr: connAddr(addr), addr: connAddr(addr),
peer: iface.core.peers.newPeer(&ks.box, &ks.sig), peer: iface.core.peers.newPeer(&ks.box, &ks.sig),
@ -167,24 +187,27 @@ func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) {
inBuf = inBuf[:0] inBuf = inBuf[:0]
conn.countIn = count conn.countIn = count
} }
if chunk <= chunks && chunk == inChunks + 1 { if chunk <= chunks && chunk == inChunks+1 {
//iface.core.log.Println("GOING:", addr, chunks, chunk, count, len(payload)) //iface.core.log.Println("GOING:", addr, chunks, chunk, count, len(payload))
inChunks += 1 inChunks += 1
inBuf = append(inBuf, payload...) inBuf = append(inBuf, payload...)
if chunks != chunk { return } if chunks != chunk {
return
}
msg := append(util_getBytes(), inBuf...) msg := append(util_getBytes(), inBuf...)
conn.peer.handlePacket(msg, conn.linkIn) conn.peer.handlePacket(msg, conn.linkIn)
//iface.core.log.Println("DONE:", addr, chunks, chunk, count, len(payload)) //iface.core.log.Println("DONE:", addr, chunks, chunk, count, len(payload))
} }
} }
conn.peer.out = func (msg []byte) { conn.peer.out = func(msg []byte) {
defer func() { recover() }() defer func() { recover() }()
select { select {
case conn.out<-msg: case conn.out <- msg:
default: util_putBytes(msg) default:
util_putBytes(msg)
} }
} }
go func () { go func() {
//var chunks [][]byte //var chunks [][]byte
var out []byte var out []byte
for msg := range conn.out { for msg := range conn.out {
@ -195,9 +218,11 @@ func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) {
} }
chunks = append(chunks, bs) chunks = append(chunks, bs)
//iface.core.log.Println("DEBUG: out chunks:", len(chunks), len(msg)) //iface.core.log.Println("DEBUG: out chunks:", len(chunks), len(msg))
if len(chunks) > 255 { continue } if len(chunks) > 255 {
continue
}
start := time.Now() start := time.Now()
for idx,bs := range chunks { for idx, bs := range chunks {
nChunks, nChunk, count := uint8(len(chunks)), uint8(idx)+1, conn.countOut nChunks, nChunk, count := uint8(len(chunks)), uint8(idx)+1, conn.countOut
out = udp_encode(out[:0], nChunks, nChunk, count, bs) out = udp_encode(out[:0], nChunks, nChunk, count, bs)
//iface.core.log.Println("DEBUG out:", nChunks, nChunk, count, len(bs)) //iface.core.log.Println("DEBUG out:", nChunks, nChunk, count, len(bs))
@ -225,7 +250,7 @@ func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) {
func() { func() {
defer func() { recover() }() defer func() { recover() }()
select { select {
case conn.keysIn<-&ks: case conn.keysIn <- &ks:
default: default:
} }
}() }()
@ -245,8 +270,13 @@ func (iface *udpInterface) reader() {
//iface.core.log.Println("Starting read") //iface.core.log.Println("Starting read")
n, udpAddr, err := iface.sock.ReadFromUDP(bs) n, udpAddr, err := iface.sock.ReadFromUDP(bs)
//iface.core.log.Println("Read", n, udpAddr.String(), err) //iface.core.log.Println("Read", n, udpAddr.String(), err)
if err != nil { panic(err) ; break } if err != nil {
if n > 1500 { panic(n) } panic(err)
break
}
if n > 1500 {
panic(n)
}
//msg := append(util_getBytes(), bs[:n]...) //msg := append(util_getBytes(), bs[:n]...)
msg := bs[:n] msg := bs[:n]
addr := connAddr(udpAddr.String()) addr := connAddr(udpAddr.String())
@ -272,4 +302,3 @@ func udp_decode(bs []byte) (chunks, chunk, count uint8, payload []byte) {
func udp_encode(out []byte, chunks, chunk, count uint8, payload []byte) []byte { func udp_encode(out []byte, chunks, chunk, count uint8, payload []byte) []byte {
return append(append(out, chunks, chunk, count), payload...) return append(append(out, chunks, chunk, count), payload...)
} }

View File

@ -4,18 +4,19 @@ package yggdrasil
import "fmt" import "fmt"
import "runtime" import "runtime"
//import "sync" //import "sync"
func Util_testAddrIDMask() { func Util_testAddrIDMask() {
for idx := 0 ; idx < 16 ; idx++ { for idx := 0; idx < 16; idx++ {
var orig NodeID var orig NodeID
orig[8] = 42 orig[8] = 42
for bidx := 0 ; bidx < idx ; bidx++ { for bidx := 0; bidx < idx; bidx++ {
orig[bidx/8] |= (0x80 >> uint8(bidx % 8)) orig[bidx/8] |= (0x80 >> uint8(bidx%8))
} }
addr := address_addrForNodeID(&orig) addr := address_addrForNodeID(&orig)
nid, mask := addr.getNodeIDandMask() nid, mask := addr.getNodeIDandMask()
for b := 0 ; b < len(mask) ; b++ { for b := 0; b < len(mask); b++ {
nid[b] &= mask[b] nid[b] &= mask[b]
orig[b] &= mask[b] orig[b] &= mask[b]
} }
@ -65,15 +66,16 @@ func util_initByteStore() {
func util_getBytes() []byte { func util_getBytes() []byte {
select { select {
case bs := <-byteStore: return bs[:0] case bs := <-byteStore:
default: return nil return bs[:0]
default:
return nil
} }
} }
func util_putBytes(bs []byte) { func util_putBytes(bs []byte) {
select { select {
case byteStore<-bs: case byteStore <- bs:
default: default:
} }
} }

View File

@ -31,14 +31,14 @@ func wire_encode_uint64(elem uint64) []byte {
// Occasionally useful for appending to an existing slice (if there's room) // Occasionally useful for appending to an existing slice (if there's room)
func wire_put_uint64(elem uint64, out []byte) []byte { func wire_put_uint64(elem uint64, out []byte) []byte {
bs := make([]byte, 0, 10) bs := make([]byte, 0, 10)
bs = append(bs, byte(elem & 0x7f)) bs = append(bs, byte(elem&0x7f))
for e := elem >> 7 ; e > 0 ; e >>= 7 { for e := elem >> 7; e > 0; e >>= 7 {
bs = append(bs, byte(e | 0x80)) bs = append(bs, byte(e|0x80))
} }
// Now reverse bytes, because we set them in the wrong order // Now reverse bytes, because we set them in the wrong order
// TODO just put them in the right place the first time... // TODO just put them in the right place the first time...
last := len(bs)-1 last := len(bs) - 1
for idx := 0 ; idx < len(bs)/2 ; idx++ { for idx := 0; idx < len(bs)/2; idx++ {
bs[idx], bs[last-idx] = bs[last-idx], bs[idx] bs[idx], bs[last-idx] = bs[last-idx], bs[idx]
} }
return append(out, bs...) return append(out, bs...)
@ -53,7 +53,9 @@ func wire_decode_uint64(bs []byte) (uint64, int) {
elem <<= 7 elem <<= 7
elem |= uint64(b & 0x7f) elem |= uint64(b & 0x7f)
length++ length++
if b & 0x80 == 0 { break } if b&0x80 == 0 {
break
}
} }
return elem, length return elem, length
} }
@ -72,14 +74,16 @@ func wire_intToUint(i int64) uint64 {
func wire_intFromUint(u uint64) int64 { func wire_intFromUint(u uint64) int64 {
var i int64 var i int64
i = int64(u >> 1) i = int64(u >> 1)
if u & 0x01 != 0 { i *= -1 } if u&0x01 != 0 {
i *= -1
}
return i return i
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Takes coords, returns coords prefixed with encoded coord length // Takes coords, returns coords prefixed with encoded coord length
func wire_encode_coords(coords []byte) ([]byte) { func wire_encode_coords(coords []byte) []byte {
coordLen := wire_encode_uint64(uint64(len(coords))) coordLen := wire_encode_uint64(uint64(len(coords)))
bs := make([]byte, 0, len(coordLen)+len(coords)) bs := make([]byte, 0, len(coordLen)+len(coords))
bs = append(bs, coordLen...) bs = append(bs, coordLen...)
@ -87,7 +91,7 @@ func wire_encode_coords(coords []byte) ([]byte) {
return bs return bs
} }
func wire_put_coords(coords []byte, bs []byte) ([]byte) { func wire_put_coords(coords []byte, bs []byte) []byte {
bs = wire_put_uint64(uint64(len(coords)), bs) bs = wire_put_uint64(uint64(len(coords)), bs)
bs = append(bs, coords...) bs = append(bs, coords...)
return bs return bs
@ -97,10 +101,12 @@ func wire_put_coords(coords []byte, bs []byte) ([]byte) {
// Returns a slice of coords and the number of bytes read // Returns a slice of coords and the number of bytes read
func wire_decode_coords(packet []byte) ([]byte, int) { func wire_decode_coords(packet []byte) ([]byte, int) {
coordLen, coordBegin := wire_decode_uint64(packet) coordLen, coordBegin := wire_decode_uint64(packet)
coordEnd := coordBegin+int(coordLen) coordEnd := coordBegin + int(coordLen)
//if coordBegin == 0 { panic("No coords found") } // Testing //if coordBegin == 0 { panic("No coords found") } // Testing
//if coordEnd > len(packet) { panic("Packet too short") } // Testing //if coordEnd > len(packet) { panic("Packet too short") } // Testing
if coordBegin == 0 || coordEnd > len(packet) { return nil, 0 } if coordBegin == 0 || coordEnd > len(packet) {
return nil, 0
}
return packet[coordBegin:coordEnd], coordEnd return packet[coordBegin:coordEnd], coordEnd
} }
@ -132,12 +138,18 @@ func (m *msgAnnounce) decode(bs []byte) bool {
var pType uint64 var pType uint64
var tstamp uint64 var tstamp uint64
switch { switch {
case !wire_chop_uint64(&pType, &bs): return false case !wire_chop_uint64(&pType, &bs):
case pType != wire_SwitchAnnounce: return false return false
case !wire_chop_slice(m.root[:], &bs): return false case pType != wire_SwitchAnnounce:
case !wire_chop_uint64(&tstamp, &bs): return false return false
case !wire_chop_uint64(&m.seq, &bs): return false case !wire_chop_slice(m.root[:], &bs):
case !wire_chop_uint64(&m.len, &bs): return false return false
case !wire_chop_uint64(&tstamp, &bs):
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.Deg, &bs): return false //case !wire_chop_uint64(&m.Deg, &bs): return false
//case !wire_chop_uint64(&m.RSeq, &bs): return false //case !wire_chop_uint64(&m.RSeq, &bs): return false
} }
@ -165,12 +177,18 @@ func (m *msgHopReq) decode(bs []byte) bool {
var pType uint64 var pType uint64
var tstamp uint64 var tstamp uint64
switch { switch {
case !wire_chop_uint64(&pType, &bs): return false case !wire_chop_uint64(&pType, &bs):
case pType != wire_SwitchHopRequest: return false return false
case !wire_chop_slice(m.root[:], &bs): return false case pType != wire_SwitchHopRequest:
case !wire_chop_uint64(&tstamp, &bs): return false return false
case !wire_chop_uint64(&m.seq, &bs): return false case !wire_chop_slice(m.root[:], &bs):
case !wire_chop_uint64(&m.hop, &bs): return false 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) m.tstamp = wire_intFromUint(tstamp)
return true return true
@ -202,15 +220,24 @@ func (m *msgHop) decode(bs []byte) bool {
var pType uint64 var pType uint64
var tstamp uint64 var tstamp uint64
switch { switch {
case !wire_chop_uint64(&pType, &bs): return false case !wire_chop_uint64(&pType, &bs):
case pType != wire_SwitchHop: return false return false
case !wire_chop_slice(m.root[:], &bs): return false case pType != wire_SwitchHop:
case !wire_chop_uint64(&tstamp, &bs): return false return false
case !wire_chop_uint64(&m.seq, &bs): return false case !wire_chop_slice(m.root[:], &bs):
case !wire_chop_uint64(&m.hop, &bs): return false return false
case !wire_chop_uint64((*uint64)(&m.port), &bs): return false case !wire_chop_uint64(&tstamp, &bs):
case !wire_chop_slice(m.next[:], &bs): return false return false
case !wire_chop_slice(m.sig[:], &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) m.tstamp = wire_intFromUint(tstamp)
return true return true
@ -227,7 +254,9 @@ func wire_encode_locator(loc *switchLocator) []byte {
} }
func wire_chop_slice(toSlice []byte, fromSlice *[]byte) bool { func wire_chop_slice(toSlice []byte, fromSlice *[]byte) bool {
if len(*fromSlice) < len(toSlice) { return false } if len(*fromSlice) < len(toSlice) {
return false
}
copy(toSlice, *fromSlice) copy(toSlice, *fromSlice)
*fromSlice = (*fromSlice)[len(toSlice):] *fromSlice = (*fromSlice)[len(toSlice):]
return true return true
@ -235,7 +264,9 @@ func wire_chop_slice(toSlice []byte, fromSlice *[]byte) bool {
func wire_chop_coords(toCoords *[]byte, fromSlice *[]byte) bool { func wire_chop_coords(toCoords *[]byte, fromSlice *[]byte) bool {
coords, coordLen := wire_decode_coords(*fromSlice) coords, coordLen := wire_decode_coords(*fromSlice)
if coordLen == 0 { return false } if coordLen == 0 {
return false
}
*toCoords = append((*toCoords)[:0], coords...) *toCoords = append((*toCoords)[:0], coords...)
*fromSlice = (*fromSlice)[coordLen:] *fromSlice = (*fromSlice)[coordLen:]
return true return true
@ -243,7 +274,9 @@ func wire_chop_coords(toCoords *[]byte, fromSlice *[]byte) bool {
func wire_chop_uint64(toUInt64 *uint64, fromSlice *[]byte) bool { func wire_chop_uint64(toUInt64 *uint64, fromSlice *[]byte) bool {
dec, decLen := wire_decode_uint64(*fromSlice) dec, decLen := wire_decode_uint64(*fromSlice)
if decLen == 0 { return false } if decLen == 0 {
return false
}
*toUInt64 = dec *toUInt64 = dec
*fromSlice = (*fromSlice)[decLen:] *fromSlice = (*fromSlice)[decLen:]
return true return true
@ -277,12 +310,18 @@ func (p *wire_trafficPacket) encode() []byte {
func (p *wire_trafficPacket) decode(bs []byte) bool { func (p *wire_trafficPacket) decode(bs []byte) bool {
var pType uint64 var pType uint64
switch { switch {
case !wire_chop_uint64(&pType, &bs): return false case !wire_chop_uint64(&pType, &bs):
case pType != wire_Traffic: return false return false
case !wire_chop_uint64(&p.ttl, &bs): return false case pType != wire_Traffic:
case !wire_chop_coords(&p.coords, &bs): return false return false
case !wire_chop_slice(p.handle[:], &bs): return false case !wire_chop_uint64(&p.ttl, &bs):
case !wire_chop_slice(p.nonce[:], &bs): return false return false
case !wire_chop_coords(&p.coords, &bs):
return false
case !wire_chop_slice(p.handle[:], &bs):
return false
case !wire_chop_slice(p.nonce[:], &bs):
return false
} }
p.payload = append(util_getBytes(), bs...) p.payload = append(util_getBytes(), bs...)
return true return true
@ -309,16 +348,23 @@ func (p *wire_protoTrafficPacket) encode() []byte {
return bs return bs
} }
func(p *wire_protoTrafficPacket) decode(bs []byte) bool { func (p *wire_protoTrafficPacket) decode(bs []byte) bool {
var pType uint64 var pType uint64
switch { switch {
case !wire_chop_uint64(&pType, &bs): return false case !wire_chop_uint64(&pType, &bs):
case pType != wire_ProtocolTraffic: return false return false
case !wire_chop_uint64(&p.ttl, &bs): return false case pType != wire_ProtocolTraffic:
case !wire_chop_coords(&p.coords, &bs): return false return false
case !wire_chop_slice(p.toKey[:], &bs): return false case !wire_chop_uint64(&p.ttl, &bs):
case !wire_chop_slice(p.fromKey[:], &bs): return false return false
case !wire_chop_slice(p.nonce[:], &bs): return false case !wire_chop_coords(&p.coords, &bs):
return false
case !wire_chop_slice(p.toKey[:], &bs):
return false
case !wire_chop_slice(p.fromKey[:], &bs):
return false
case !wire_chop_slice(p.nonce[:], &bs):
return false
} }
p.payload = bs p.payload = bs
return true return true
@ -340,14 +386,19 @@ func (p *wire_linkProtoTrafficPacket) encode() []byte {
return bs return bs
} }
func(p *wire_linkProtoTrafficPacket) decode(bs []byte) bool { func (p *wire_linkProtoTrafficPacket) decode(bs []byte) bool {
var pType uint64 var pType uint64
switch { switch {
case !wire_chop_uint64(&pType, &bs): return false case !wire_chop_uint64(&pType, &bs):
case pType != wire_LinkProtocolTraffic: return false return false
case !wire_chop_slice(p.toKey[:], &bs): return false case pType != wire_LinkProtocolTraffic:
case !wire_chop_slice(p.fromKey[:], &bs): return false return false
case !wire_chop_slice(p.nonce[:], &bs): return false case !wire_chop_slice(p.toKey[:], &bs):
return false
case !wire_chop_slice(p.fromKey[:], &bs):
return false
case !wire_chop_slice(p.nonce[:], &bs):
return false
} }
p.payload = bs p.payload = bs
return true return true
@ -376,16 +427,24 @@ func (p *sessionPing) decode(bs []byte) bool {
var pType uint64 var pType uint64
var tstamp uint64 var tstamp uint64
switch { switch {
case !wire_chop_uint64(&pType, &bs): return false case !wire_chop_uint64(&pType, &bs):
case pType != wire_SessionPing && pType != wire_SessionPong: return false return false
case pType != wire_SessionPing && pType != wire_SessionPong:
return false
//p.sendPermPub used in top level (crypto), so skipped here //p.sendPermPub used in top level (crypto), so skipped here
case !wire_chop_slice(p.handle[:], &bs): return false case !wire_chop_slice(p.handle[:], &bs):
case !wire_chop_slice(p.sendSesPub[:], &bs): return false return false
case !wire_chop_uint64(&tstamp, &bs): return false case !wire_chop_slice(p.sendSesPub[:], &bs):
case !wire_chop_coords(&p.coords, &bs): return false return false
case !wire_chop_uint64(&tstamp, &bs):
return false
case !wire_chop_coords(&p.coords, &bs):
return false
} }
p.tstamp = wire_intFromUint(tstamp) p.tstamp = wire_intFromUint(tstamp)
if pType == wire_SessionPong { p.isPong = true } if pType == wire_SessionPong {
p.isPong = true
}
return true return true
} }
@ -403,12 +462,18 @@ func (r *dhtReq) encode() []byte {
func (r *dhtReq) decode(bs []byte) bool { func (r *dhtReq) decode(bs []byte) bool {
var pType uint64 var pType uint64
switch { switch {
case !wire_chop_uint64(&pType, &bs): return false case !wire_chop_uint64(&pType, &bs):
case pType != wire_DHTLookupRequest: return false return false
case !wire_chop_slice(r.key[:], &bs): return false case pType != wire_DHTLookupRequest:
case !wire_chop_coords(&r.coords, &bs): return false return false
case !wire_chop_slice(r.dest[:], &bs): return false case !wire_chop_slice(r.key[:], &bs):
default: return true return false
case !wire_chop_coords(&r.coords, &bs):
return false
case !wire_chop_slice(r.dest[:], &bs):
return false
default:
return true
} }
} }
@ -429,17 +494,24 @@ func (r *dhtRes) encode() []byte {
func (r *dhtRes) decode(bs []byte) bool { func (r *dhtRes) decode(bs []byte) bool {
var pType uint64 var pType uint64
switch { switch {
case !wire_chop_uint64(&pType, &bs): return false case !wire_chop_uint64(&pType, &bs):
case pType != wire_DHTLookupResponse: return false return false
case !wire_chop_slice(r.key[:], &bs): return false case pType != wire_DHTLookupResponse:
case !wire_chop_coords(&r.coords, &bs): return false return false
case !wire_chop_slice(r.dest[:], &bs): return false case !wire_chop_slice(r.key[:], &bs):
return false
case !wire_chop_coords(&r.coords, &bs):
return false
case !wire_chop_slice(r.dest[:], &bs):
return false
} }
for len(bs) > 0 { for len(bs) > 0 {
info := dhtInfo{} info := dhtInfo{}
switch { switch {
case !wire_chop_slice(info.key[:], &bs): return false case !wire_chop_slice(info.key[:], &bs):
case !wire_chop_coords(&info.coords, &bs): return false return false
case !wire_chop_coords(&info.coords, &bs):
return false
} }
r.infos = append(r.infos, &info) r.infos = append(r.infos, &info)
} }
@ -460,12 +532,18 @@ func (r *searchReq) encode() []byte {
func (r *searchReq) decode(bs []byte) bool { func (r *searchReq) decode(bs []byte) bool {
var pType uint64 var pType uint64
switch { switch {
case !wire_chop_uint64(&pType, &bs): return false case !wire_chop_uint64(&pType, &bs):
case pType != wire_SearchRequest: return false return false
case !wire_chop_slice(r.key[:], &bs): return false case pType != wire_SearchRequest:
case !wire_chop_coords(&r.coords, &bs): return false return false
case !wire_chop_slice(r.dest[:], &bs): return false case !wire_chop_slice(r.key[:], &bs):
default: return true return false
case !wire_chop_coords(&r.coords, &bs):
return false
case !wire_chop_slice(r.dest[:], &bs):
return false
default:
return true
} }
} }
@ -481,12 +559,17 @@ func (r *searchRes) encode() []byte {
func (r *searchRes) decode(bs []byte) bool { func (r *searchRes) decode(bs []byte) bool {
var pType uint64 var pType uint64
switch { switch {
case !wire_chop_uint64(&pType, &bs): return false case !wire_chop_uint64(&pType, &bs):
case pType != wire_SearchResponse: return false return false
case !wire_chop_slice(r.key[:], &bs): return false case pType != wire_SearchResponse:
case !wire_chop_coords(&r.coords, &bs): return false return false
case !wire_chop_slice(r.dest[:], &bs): return false case !wire_chop_slice(r.key[:], &bs):
default: return true return false
case !wire_chop_coords(&r.coords, &bs):
return false
case !wire_chop_slice(r.dest[:], &bs):
return false
default:
return true
} }
} }

View File

@ -25,7 +25,7 @@ import . "yggdrasil"
* It can generate a new config (--genconf) * It can generate a new config (--genconf)
* It can read a config from stdin (--useconf) * It can read a config from stdin (--useconf)
* It can run with an automatic config (--autoconf) * It can run with an automatic config (--autoconf)
*/ */
type nodeConfig struct { type nodeConfig struct {
Listen string Listen string
@ -35,6 +35,7 @@ type nodeConfig struct {
SigPub string SigPub string
SigPriv string SigPriv string
Multicast bool Multicast bool
IfName string
} }
type node struct { type node struct {
@ -44,20 +45,30 @@ type node struct {
func (n *node) init(cfg *nodeConfig, logger *log.Logger) { func (n *node) init(cfg *nodeConfig, logger *log.Logger) {
boxPub, err := hex.DecodeString(cfg.BoxPub) boxPub, err := hex.DecodeString(cfg.BoxPub)
if err != nil { panic(err) } if err != nil {
panic(err)
}
boxPriv, err := hex.DecodeString(cfg.BoxPriv) boxPriv, err := hex.DecodeString(cfg.BoxPriv)
if err != nil { panic(err) } if err != nil {
panic(err)
}
sigPub, err := hex.DecodeString(cfg.SigPub) sigPub, err := hex.DecodeString(cfg.SigPub)
if err != nil { panic(err) } if err != nil {
panic(err)
}
sigPriv, err := hex.DecodeString(cfg.SigPriv) sigPriv, err := hex.DecodeString(cfg.SigPriv)
if err != nil { panic(err) } if err != nil {
panic(err)
}
n.core.DEBUG_init(boxPub, boxPriv, sigPub, sigPriv) n.core.DEBUG_init(boxPub, boxPriv, sigPub, sigPriv)
n.core.DEBUG_setLogger(logger) n.core.DEBUG_setLogger(logger)
logger.Println("Starting interface...") logger.Println("Starting interface...")
n.core.DEBUG_setupAndStartGlobalUDPInterface(cfg.Listen) n.core.DEBUG_setupAndStartGlobalUDPInterface(cfg.Listen)
logger.Println("Started interface") logger.Println("Started interface")
go func () { go func() {
if len(cfg.Peers) == 0 { return } if len(cfg.Peers) == 0 {
return
}
for { for {
for _, p := range cfg.Peers { for _, p := range cfg.Peers {
n.core.DEBUG_maybeSendUDPKeys(p) n.core.DEBUG_maybeSendUDPKeys(p)
@ -80,13 +91,16 @@ func generateConfig() *nodeConfig {
cfg.SigPriv = hex.EncodeToString(spriv[:]) cfg.SigPriv = hex.EncodeToString(spriv[:])
cfg.Peers = []string{} cfg.Peers = []string{}
cfg.Multicast = true cfg.Multicast = true
cfg.IfName = "auto"
return &cfg return &cfg
} }
func doGenconf() string { func doGenconf() string {
cfg := generateConfig() cfg := generateConfig()
bs, err := json.MarshalIndent(cfg, "", " ") bs, err := json.MarshalIndent(cfg, "", " ")
if err != nil { panic(err) } if err != nil {
panic(err)
}
return string(bs) return string(bs)
} }
@ -94,21 +108,34 @@ var multicastAddr = "[ff02::114]:9001"
func (n *node) listen() { func (n *node) listen() {
groupAddr, err := net.ResolveUDPAddr("udp6", multicastAddr) groupAddr, err := net.ResolveUDPAddr("udp6", multicastAddr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
bs := make([]byte, 2048) bs := make([]byte, 2048)
for { for {
nBytes, rcm, fromAddr, err := n.sock.ReadFrom(bs) nBytes, rcm, fromAddr, err := n.sock.ReadFrom(bs)
if err != nil { panic(err) } if err != nil {
panic(err)
}
//if rcm == nil { continue } // wat //if rcm == nil { continue } // wat
//fmt.Println("DEBUG:", "packet from:", fromAddr.String()) //fmt.Println("DEBUG:", "packet from:", fromAddr.String())
if !rcm.Dst.IsLinkLocalMulticast() { continue } if !rcm.Dst.IsLinkLocalMulticast() {
if !rcm.Dst.Equal(groupAddr.IP) { continue } continue
}
if !rcm.Dst.Equal(groupAddr.IP) {
continue
}
anAddr := string(bs[:nBytes]) anAddr := string(bs[:nBytes])
addr, err := net.ResolveUDPAddr("udp6", anAddr) addr, err := net.ResolveUDPAddr("udp6", anAddr)
if err != nil { panic(err) ; continue } // Panic for testing, remove later if err != nil {
panic(err)
continue
} // Panic for testing, remove later
from := fromAddr.(*net.UDPAddr) from := fromAddr.(*net.UDPAddr)
//fmt.Println("DEBUG:", "heard:", addr.IP.String(), "from:", from.IP.String()) //fmt.Println("DEBUG:", "heard:", addr.IP.String(), "from:", from.IP.String())
if addr.IP.String() != from.IP.String() { continue } if addr.IP.String() != from.IP.String() {
continue
}
addr.Zone = from.Zone addr.Zone = from.Zone
saddr := addr.String() saddr := addr.String()
//if _, isIn := n.peers[saddr]; isIn { continue } //if _, isIn := n.peers[saddr]; isIn { continue }
@ -120,25 +147,39 @@ func (n *node) listen() {
func (n *node) announce() { func (n *node) announce() {
groupAddr, err := net.ResolveUDPAddr("udp6", multicastAddr) groupAddr, err := net.ResolveUDPAddr("udp6", multicastAddr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
udpaddr := n.core.DEBUG_getGlobalUDPAddr() udpaddr := n.core.DEBUG_getGlobalUDPAddr()
anAddr, err := net.ResolveUDPAddr("udp6", udpaddr.String()) anAddr, err := net.ResolveUDPAddr("udp6", udpaddr.String())
if err != nil { panic(err) } if err != nil {
panic(err)
}
destAddr, err := net.ResolveUDPAddr("udp6", multicastAddr) destAddr, err := net.ResolveUDPAddr("udp6", multicastAddr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
for { for {
ifaces, err := net.Interfaces() ifaces, err := net.Interfaces()
if err != nil { panic(err) } if err != nil {
panic(err)
}
for _, iface := range ifaces { for _, iface := range ifaces {
n.sock.JoinGroup(&iface, groupAddr) n.sock.JoinGroup(&iface, groupAddr)
//err := n.sock.JoinGroup(&iface, groupAddr) //err := n.sock.JoinGroup(&iface, groupAddr)
//if err != nil { panic(err) } //if err != nil { panic(err) }
addrs, err := iface.Addrs() addrs, err := iface.Addrs()
if err != nil { panic(err) } if err != nil {
panic(err)
}
for _, addr := range addrs { for _, addr := range addrs {
addrIP, _, _ := net.ParseCIDR(addr.String()) addrIP, _, _ := net.ParseCIDR(addr.String())
if addrIP.To4() != nil { continue } // IPv6 only if addrIP.To4() != nil {
if !addrIP.IsLinkLocalUnicast() { continue } continue
} // IPv6 only
if !addrIP.IsLinkLocalUnicast() {
continue
}
anAddr.IP = addrIP anAddr.IP = addrIP
anAddr.Zone = iface.Name anAddr.Zone = iface.Name
destAddr.Zone = iface.Name destAddr.Zone = iface.Name
@ -161,17 +202,26 @@ func main() {
flag.Parse() flag.Parse()
var cfg *nodeConfig var cfg *nodeConfig
switch { switch {
case *autoconf: cfg = generateConfig() case *autoconf:
cfg = generateConfig()
case *useconf: case *useconf:
config, err := ioutil.ReadAll(os.Stdin) config, err := ioutil.ReadAll(os.Stdin)
if err != nil { panic(err) } if err != nil {
panic(err)
}
decoder := json.NewDecoder(bytes.NewReader(config)) decoder := json.NewDecoder(bytes.NewReader(config))
err = decoder.Decode(&cfg) err = decoder.Decode(&cfg)
if err != nil { panic(err) } if err != nil {
case *genconf: fmt.Println(doGenconf()) panic(err)
default: flag.PrintDefaults() }
case *genconf:
fmt.Println(doGenconf())
default:
flag.PrintDefaults()
}
if cfg == nil {
return
} }
if cfg == nil { return }
logger := log.New(os.Stdout, "", log.Flags()) logger := log.New(os.Stdout, "", log.Flags())
if *pprof { if *pprof {
runtime.SetBlockProfileRate(1) runtime.SetBlockProfileRate(1)
@ -182,8 +232,8 @@ func main() {
n := node{} n := node{}
n.init(cfg, logger) n.init(cfg, logger)
logger.Println("Starting tun...") logger.Println("Starting tun...")
n.core.DEBUG_startTun() // 1280, the smallest supported MTU n.core.DEBUG_startTun(cfg.IfName) // 1280, the smallest supported MTU
//n.core.DEBUG_startTunWithMTU(65535) // Largest supported MTU //n.core.DEBUG_startTunWithMTU(cfg.IfName, 65535) // Largest supported MTU
defer func() { defer func() {
logger.Println("Closing...") logger.Println("Closing...")
n.core.DEBUG_stopTun() n.core.DEBUG_stopTun()
@ -191,13 +241,19 @@ func main() {
logger.Println("Started...") logger.Println("Started...")
if cfg.Multicast { if cfg.Multicast {
addr, err := net.ResolveUDPAddr("udp", multicastAddr) addr, err := net.ResolveUDPAddr("udp", multicastAddr)
if err != nil { panic(err) } if err != nil {
panic(err)
}
listenString := fmt.Sprintf("[::]:%v", addr.Port) listenString := fmt.Sprintf("[::]:%v", addr.Port)
conn, err := net.ListenPacket("udp6", listenString) conn, err := net.ListenPacket("udp6", listenString)
if err != nil { panic(err) } if err != nil {
panic(err)
}
//defer conn.Close() // Let it close on its own when the application exits //defer conn.Close() // Let it close on its own when the application exits
n.sock = ipv6.NewPacketConn(conn) n.sock = ipv6.NewPacketConn(conn)
if err = n.sock.SetControlMessage(ipv6.FlagDst, true) ; err != nil { panic(err) } if err = n.sock.SetControlMessage(ipv6.FlagDst, true); err != nil {
panic(err)
}
go n.listen() go n.listen()
go n.announce() go n.announce()
} }
@ -207,4 +263,3 @@ func main() {
<-c <-c
logger.Println("Stopping...") logger.Println("Stopping...")
} }