diff --git a/cmd/genkeys/main.go b/cmd/genkeys/main.go index cfab7ec1..fc0a1f02 100644 --- a/cmd/genkeys/main.go +++ b/cmd/genkeys/main.go @@ -54,9 +54,7 @@ func main() { if isBetter(currentBest, newKey.id[:]) || len(currentBest) == 0 { currentBest = newKey.id for _, channel := range threadChannels { - select { - case channel <- newKey.id: - } + channel <- newKey.id } fmt.Println("--------------------------------------------------------------------------------") switch { diff --git a/cmd/yggdrasil/main.go b/cmd/yggdrasil/main.go index 14b76c34..18b37d5a 100644 --- a/cmd/yggdrasil/main.go +++ b/cmd/yggdrasil/main.go @@ -106,7 +106,7 @@ func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *config if err != nil { panic(err) } - json.Unmarshal(confJson, &cfg) + _ = json.Unmarshal(confJson, &cfg) // Overlay our newly mapped configuration onto the autoconf node config that // we generated above. if err = mapstructure.Decode(dat, &cfg); err != nil { @@ -285,25 +285,29 @@ func main() { n.multicast = &multicast.Multicast{} n.tuntap = &tuntap.TunAdapter{} // Start the admin socket - n.admin.Init(&n.core, n.state, logger, nil) - if err := n.admin.Start(); err != nil { + if err := n.admin.Init(&n.core, n.state, logger, nil); err != nil { + logger.Errorln("An error occured initialising the admin module:", err) + } else if err := n.admin.Start(); err != nil { logger.Errorln("An error occurred starting admin socket:", err) } n.admin.SetupAdminHandlers(n.admin.(*admin.AdminSocket)) // Start the multicast interface - n.multicast.Init(&n.core, n.state, logger, nil) - if err := n.multicast.Start(); err != nil { + if err := n.multicast.Init(&n.core, n.state, logger, nil); err != nil { + logger.Errorln("An error occured initialising the multicast module:", err) + } else if err := n.multicast.Start(); err != nil { logger.Errorln("An error occurred starting multicast:", err) } n.multicast.SetupAdminHandlers(n.admin.(*admin.AdminSocket)) // Start the TUN/TAP interface if listener, err := n.core.ConnListen(); err == nil { if dialer, err := n.core.ConnDialer(); err == nil { - n.tuntap.Init(&n.core, n.state, logger, tuntap.TunOptions{Listener: listener, Dialer: dialer}) - if err := n.tuntap.Start(); err != nil { + if err := n.tuntap.Init(&n.core, n.state, logger, tuntap.TunOptions{Listener: listener, Dialer: dialer}); err != nil { + logger.Errorln("An error occured initialising the TUN module:", err) + } else if err := n.tuntap.Start(); err != nil { logger.Errorln("An error occurred starting TUN/TAP:", err) + } else { + n.tuntap.SetupAdminHandlers(n.admin.(*admin.AdminSocket)) } - n.tuntap.SetupAdminHandlers(n.admin.(*admin.AdminSocket)) } else { logger.Errorln("Unable to get Dialer:", err) } @@ -346,9 +350,9 @@ exit: } func (n *node) shutdown() { - n.admin.Stop() - n.multicast.Stop() - n.tuntap.Stop() + _ = n.admin.Stop() + _ = n.multicast.Stop() + _ = n.tuntap.Stop() n.core.Stop() } diff --git a/cmd/yggdrasilctl/main.go b/cmd/yggdrasilctl/main.go index 38d935a6..f7f4a69f 100644 --- a/cmd/yggdrasilctl/main.go +++ b/cmd/yggdrasilctl/main.go @@ -47,8 +47,11 @@ func run() int { fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [options] command [key=value] [key=value] ...\n\n", os.Args[0]) fmt.Println("Options:") flag.PrintDefaults() - fmt.Println("\nPlease note that options must always specified BEFORE the command\non the command line or they will be ignored.\n") - fmt.Println("Commands:\n - Use \"list\" for a list of available commands\n") + fmt.Println() + fmt.Println("Please note that options must always specified BEFORE the command\non the command line or they will be ignored.") + fmt.Println() + fmt.Println("Commands:\n - Use \"list\" for a list of available commands") + fmt.Println() fmt.Println("Examples:") fmt.Println(" - ", os.Args[0], "list") fmt.Println(" - ", os.Args[0], "getPeers") diff --git a/cmd/yggdrasilsim/dial.go b/cmd/yggdrasilsim/dial.go index c7892d40..70ae5049 100644 --- a/cmd/yggdrasilsim/dial.go +++ b/cmd/yggdrasilsim/dial.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "sort" "time" @@ -29,7 +30,7 @@ func dialTest(sendNode, recvNode *simNode) { mask[idx] = 0xff } for { - c, err := sendNode.dialer.DialByNodeIDandMask(nil, &recvNode.nodeID, &mask) + c, err := sendNode.dialer.DialByNodeIDandMask(context.TODO(), &recvNode.nodeID, &mask) if c != nil { c.Close() return diff --git a/cmd/yggdrasilsim/node.go b/cmd/yggdrasilsim/node.go index 65e6a805..0861f49e 100644 --- a/cmd/yggdrasilsim/node.go +++ b/cmd/yggdrasilsim/node.go @@ -20,7 +20,9 @@ type simNode struct { func newNode(id int) *simNode { n := simNode{id: id} - n.core.Start(config.GenerateConfig(), log.New(ioutil.Discard, "", 0)) + if _, err := n.core.Start(config.GenerateConfig(), log.New(ioutil.Discard, "", 0)); err != nil { + panic(err) + } n.nodeID = *n.core.NodeID() n.dialer, _ = n.core.ConnDialer() n.listener, _ = n.core.ConnListen() diff --git a/cmd/yggdrasilsim/store.go b/cmd/yggdrasilsim/store.go index 6fce81a4..f678ced2 100644 --- a/cmd/yggdrasilsim/store.go +++ b/cmd/yggdrasilsim/store.go @@ -2,19 +2,21 @@ package main type nodeStore map[int]*simNode -func makeStoreSingle() nodeStore { - s := make(nodeStore) - s[0] = newNode(0) - return s -} - func linkNodes(a *simNode, b *simNode) { la := a.core.NewSimlink() lb := b.core.NewSimlink() - la.SetDestination(lb) - lb.SetDestination(la) - la.Start() - lb.Start() + if err := la.SetDestination(lb); err != nil { + panic(err) + } + if err := lb.SetDestination(la); err != nil { + panic(err) + } + if err := la.Start(); err != nil { + panic(err) + } + if err := lb.Start(); err != nil { + panic(err) + } } func makeStoreSquareGrid(sideLength int) nodeStore { diff --git a/misc/sim/treesim.go b/misc/sim/treesim.go deleted file mode 100644 index 22cf881f..00000000 --- a/misc/sim/treesim.go +++ /dev/null @@ -1,459 +0,0 @@ -// +build !lint - -package main - -import ( - "bufio" - "flag" - "fmt" - "os" - "runtime" - "runtime/pprof" - "strconv" - "strings" - "time" - - "github.com/gologme/log" - - . "github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil" - - . "github.com/yggdrasil-network/yggdrasil-go/src/crypto" -) - -//////////////////////////////////////////////////////////////////////////////// - -type Node struct { - index int - core Core - send chan<- []byte - recv <-chan []byte -} - -func (n *Node) init(index int) { - n.index = index - n.core.Init() - n.send = n.core.DEBUG_getSend() - n.recv = n.core.DEBUG_getRecv() - n.core.DEBUG_simFixMTU() -} - -func (n *Node) printTraffic() { - for { - packet := <-n.recv - fmt.Println(n.index, packet) - //panic("Got a packet") - } -} - -func (n *Node) startPeers() { - //for _, p := range n.core.Peers.Ports { - // go p.MainLoop() - //} - //go n.printTraffic() - //n.core.Peers.DEBUG_startPeers() -} - -func linkNodes(m, n *Node) { - // Don't allow duplicates - if m.core.DEBUG_getPeers().DEBUG_hasPeer(n.core.DEBUG_getSigningPublicKey()) { - return - } - // Create peers - // Buffering reduces packet loss in the sim - // This slightly speeds up testing (fewer delays before retrying a ping) - pLinkPub, pLinkPriv := m.core.DEBUG_newBoxKeys() - qLinkPub, qLinkPriv := m.core.DEBUG_newBoxKeys() - p := m.core.DEBUG_getPeers().DEBUG_newPeer(n.core.DEBUG_getEncryptionPublicKey(), - n.core.DEBUG_getSigningPublicKey(), *m.core.DEBUG_getSharedKey(pLinkPriv, qLinkPub)) - q := n.core.DEBUG_getPeers().DEBUG_newPeer(m.core.DEBUG_getEncryptionPublicKey(), - m.core.DEBUG_getSigningPublicKey(), *n.core.DEBUG_getSharedKey(qLinkPriv, pLinkPub)) - DEBUG_simLinkPeers(p, q) - return -} - -func makeStoreSquareGrid(sideLength int) map[int]*Node { - store := make(map[int]*Node) - nNodes := sideLength * sideLength - idxs := make([]int, 0, nNodes) - // TODO shuffle nodeIDs - for idx := 1; idx <= nNodes; idx++ { - idxs = append(idxs, idx) - } - for _, idx := range idxs { - node := &Node{} - node.init(idx) - store[idx] = node - } - for idx := 0; idx < nNodes; idx++ { - if (idx % sideLength) != 0 { - linkNodes(store[idxs[idx]], store[idxs[idx-1]]) - } - if idx >= sideLength { - linkNodes(store[idxs[idx]], store[idxs[idx-sideLength]]) - } - } - //for _, node := range store { node.initPorts() } - return store -} - -func makeStoreStar(nNodes int) map[int]*Node { - store := make(map[int]*Node) - center := &Node{} - center.init(0) - store[0] = center - for idx := 1; idx < nNodes; idx++ { - node := &Node{} - node.init(idx) - store[idx] = node - linkNodes(center, node) - } - return store -} - -func loadGraph(path string) map[int]*Node { - f, err := os.Open(path) - if err != nil { - panic(err) - } - defer f.Close() - store := make(map[int]*Node) - s := bufio.NewScanner(f) - for s.Scan() { - line := s.Text() - nodeIdxstrs := strings.Split(line, " ") - nodeIdx0, _ := strconv.Atoi(nodeIdxstrs[0]) - nodeIdx1, _ := strconv.Atoi(nodeIdxstrs[1]) - if store[nodeIdx0] == nil { - node := &Node{} - node.init(nodeIdx0) - store[nodeIdx0] = node - } - if store[nodeIdx1] == nil { - node := &Node{} - node.init(nodeIdx1) - store[nodeIdx1] = node - } - linkNodes(store[nodeIdx0], store[nodeIdx1]) - } - //for _, node := range store { node.initPorts() } - return store -} - -//////////////////////////////////////////////////////////////////////////////// - -func startNetwork(store map[[32]byte]*Node) { - for _, node := range store { - node.startPeers() - } -} - -func getKeyedStore(store map[int]*Node) map[[32]byte]*Node { - newStore := make(map[[32]byte]*Node) - for _, node := range store { - newStore[node.core.DEBUG_getSigningPublicKey()] = node - } - return newStore -} - -func testPaths(store map[[32]byte]*Node) bool { - nNodes := len(store) - count := 0 - for _, source := range store { - count++ - fmt.Printf("Testing paths from node %d / %d (%d)\n", count, nNodes, source.index) - for _, dest := range store { - //if source == dest { continue } - destLoc := dest.core.DEBUG_getLocator() - coords := destLoc.DEBUG_getCoords() - temp := 0 - ttl := ^uint64(0) - oldTTL := ttl - for here := source; here != dest; { - temp++ - if temp > 4096 { - fmt.Println("Loop?") - time.Sleep(time.Second) - return false - } - nextPort := here.core.DEBUG_switchLookup(coords) - // First check if "here" is accepting packets from the previous node - // TODO explain how this works - ports := here.core.DEBUG_getPeers().DEBUG_getPorts() - nextPeer := ports[nextPort] - if nextPeer == nil { - fmt.Println("Peer associated with next port is nil") - return false - } - next := store[nextPeer.DEBUG_getSigKey()] - /* - if next == here { - //for idx, link := range here.links { - // fmt.Println("DUMP:", idx, link.nodeID) - //} - if nextPort != 0 { panic("This should not be") } - fmt.Println("Failed to route:", source.index, here.index, dest.index, oldTTL, ttl) - //here.table.DEBUG_dumpTable() - //fmt.Println("Ports:", here.nodeID, here.ports) - return false - panic(fmt.Sprintln("Routing Loop:", - source.index, - here.index, - dest.index)) - } - */ - if temp > 4090 { - fmt.Println("DEBUG:", - source.index, source.core.DEBUG_getLocator(), - here.index, here.core.DEBUG_getLocator(), - dest.index, dest.core.DEBUG_getLocator()) - //here.core.DEBUG_getSwitchTable().DEBUG_dumpTable() - } - if here != source { - // This is sufficient to check for routing loops or blackholes - //break - } - if here == next { - fmt.Println("Drop:", source.index, here.index, dest.index, oldTTL) - return false - } - here = next - } - } - } - return true -} - -func stressTest(store map[[32]byte]*Node) { - fmt.Println("Stress testing network...") - nNodes := len(store) - dests := make([][]byte, 0, nNodes) - for _, dest := range store { - loc := dest.core.DEBUG_getLocator() - coords := loc.DEBUG_getCoords() - dests = append(dests, coords) - } - lookups := 0 - start := time.Now() - for _, source := range store { - for _, coords := range dests { - source.core.DEBUG_switchLookup(coords) - lookups++ - } - } - timed := time.Since(start) - fmt.Printf("%d lookups in %s (%f lookups per second)\n", - lookups, - timed, - float64(lookups)/timed.Seconds()) -} - -func pingNodes(store map[[32]byte]*Node) { - fmt.Println("Sending pings...") - nNodes := len(store) - count := 0 - equiv := func(a []byte, b []byte) bool { - if len(a) != len(b) { - return false - } - for idx := 0; idx < len(a); idx++ { - if a[idx] != b[idx] { - return false - } - } - return true - } - for _, source := range store { - count++ - //if count > 16 { break } - fmt.Printf("Sending packets from node %d/%d (%d)\n", count, nNodes, source.index) - sourceKey := source.core.DEBUG_getEncryptionPublicKey() - payload := sourceKey[:] - sourceAddr := source.core.DEBUG_getAddr()[:] - sendTo := func(bs []byte, destAddr []byte) { - packet := make([]byte, 40+len(bs)) - copy(packet[8:24], sourceAddr) - copy(packet[24:40], destAddr) - copy(packet[40:], bs) - packet[0] = 6 << 4 - source.send <- packet - } - destCount := 0 - for _, dest := range store { - destCount += 1 - fmt.Printf("%d Nodes, %d Send, %d Recv\n", nNodes, count, destCount) - if dest == source { - fmt.Println("Skipping self") - continue - } - destAddr := dest.core.DEBUG_getAddr()[:] - ticker := time.NewTicker(150 * time.Millisecond) - sendTo(payload, destAddr) - for loop := true; loop; { - select { - case packet := <-dest.recv: - { - if equiv(payload, packet[len(packet)-len(payload):]) { - loop = false - } - } - case <-ticker.C: - sendTo(payload, destAddr) - //dumpDHTSize(store) // note that this uses racey functions to read things... - } - } - ticker.Stop() - } - //break // Only try sending pings from 1 node - // This is because, for some reason, stopTun() doesn't always close it - // And if two tuns are up, bad things happen (sends via wrong interface) - } - fmt.Println("Finished pinging nodes") -} - -func pingBench(store map[[32]byte]*Node) { - fmt.Println("Benchmarking pings...") - nPings := 0 - payload := make([]byte, 1280+40) // MTU + ipv6 header - var timed time.Duration - //nNodes := len(store) - count := 0 - for _, source := range store { - count++ - //fmt.Printf("Sending packets from node %d/%d (%d)\n", count, nNodes, source.index) - getPing := func(key [32]byte, decodedCoords []byte) []byte { - // TODO write some function to do this the right way, put... somewhere... - coords := DEBUG_wire_encode_coords(decodedCoords) - packet := make([]byte, 0, len(key)+len(coords)+len(payload)) - packet = append(packet, key[:]...) - packet = append(packet, coords...) - packet = append(packet, payload[:]...) - return packet - } - for _, dest := range store { - key := dest.core.DEBUG_getEncryptionPublicKey() - loc := dest.core.DEBUG_getLocator() - coords := loc.DEBUG_getCoords() - ping := getPing(key, coords) - // TODO make sure the session is open first - start := time.Now() - for i := 0; i < 1000000; i++ { - source.send <- ping - nPings++ - } - timed += time.Since(start) - break - } - break - } - fmt.Printf("Sent %d pings in %s (%f per second)\n", - nPings, - timed, - float64(nPings)/timed.Seconds()) -} - -func dumpStore(store map[NodeID]*Node) { - for _, node := range store { - fmt.Println("DUMPSTORE:", node.index, node.core.DEBUG_getLocator()) - node.core.DEBUG_getSwitchTable().DEBUG_dumpTable() - } -} - -func dumpDHTSize(store map[[32]byte]*Node) { - var min, max, sum int - for _, node := range store { - num := node.core.DEBUG_getDHTSize() - min = num - max = num - break - } - for _, node := range store { - num := node.core.DEBUG_getDHTSize() - if num < min { - min = num - } - if num > max { - max = num - } - sum += num - } - avg := float64(sum) / float64(len(store)) - fmt.Printf("DHT min %d / avg %f / max %d\n", min, avg, max) -} - -func (n *Node) startTCP(listen string) { - n.core.DEBUG_setupAndStartGlobalTCPInterface(listen) -} - -func (n *Node) connectTCP(remoteAddr string) { - n.core.AddPeer(remoteAddr, remoteAddr) -} - -//////////////////////////////////////////////////////////////////////////////// - -var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`") -var memprofile = flag.String("memprofile", "", "write memory profile to this file") - -func main() { - flag.Parse() - if *cpuprofile != "" { - f, err := os.Create(*cpuprofile) - if err != nil { - panic(fmt.Sprintf("could not create CPU profile: ", err)) - } - if err := pprof.StartCPUProfile(f); err != nil { - panic(fmt.Sprintf("could not start CPU profile: ", err)) - } - defer pprof.StopCPUProfile() - } - if *memprofile != "" { - f, err := os.Create(*memprofile) - if err != nil { - panic(fmt.Sprintf("could not create memory profile: ", err)) - } - defer func() { pprof.WriteHeapProfile(f); f.Close() }() - } - fmt.Println("Test") - Util_testAddrIDMask() - idxstore := makeStoreSquareGrid(4) - //idxstore := makeStoreStar(256) - //idxstore := loadGraph("misc/sim/hype-2016-09-19.list") - //idxstore := loadGraph("misc/sim/fc00-2017-08-12.txt") - //idxstore := loadGraph("skitter") - kstore := getKeyedStore(idxstore) - //* - logger := log.New(os.Stderr, "", log.Flags()) - for _, n := range kstore { - n.core.DEBUG_setLogger(logger) - } - //*/ - startNetwork(kstore) - //time.Sleep(10*time.Second) - // Note that testPaths only works if pressure is turned off - // Otherwise congestion can lead to routing loops? - for finished := false; !finished; { - finished = testPaths(kstore) - } - pingNodes(kstore) - //pingBench(kstore) // Only after disabling debug output - //stressTest(kstore) - //time.Sleep(120 * time.Second) - dumpDHTSize(kstore) // note that this uses racey functions to read things... - if false { - // This connects the sim to the local network - for _, node := range kstore { - node.startTCP("localhost:0") - node.connectTCP("localhost:12345") - break // just 1 - } - for _, node := range kstore { - go func() { - // Just dump any packets sent to this node - for range node.recv { - } - }() - } - var block chan struct{} - <-block - } - runtime.GC() -} diff --git a/src/admin/admin.go b/src/admin/admin.go index bdb7cd3a..5571702a 100644 --- a/src/admin/admin.go +++ b/src/admin/admin.go @@ -42,15 +42,14 @@ type handler struct { } // AddHandler is called for each admin function to add the handler and help documentation to the API. -func (a *AdminSocket) AddHandler(name string, args []string, handlerfunc func(Info) (Info, error)) error { +func (a *AdminSocket) AddHandler(name string, args []string, handlerfunc func(Info) (Info, error)) { if _, ok := a.handlers[strings.ToLower(name)]; ok { - return errors.New("handler already exists") + panic(fmt.Sprintf("admin handler %q already exists", name)) } a.handlers[strings.ToLower(name)] = handler{ args: args, handler: handlerfunc, } - return nil } // Init runs the initial admin setup. @@ -75,9 +74,13 @@ func (a *AdminSocket) UpdateConfig(config *config.NodeConfig) { if a.listenaddr != config.AdminListen { a.listenaddr = config.AdminListen if a.IsStarted() { - a.Stop() + if err := a.Stop(); err != nil { + a.log.Errorln("Failed to stop admin module:", err) + } + } + if err := a.Start(); err != nil { + a.log.Errorln("Failed to restart admin module:", err) } - a.Start() } } @@ -227,11 +230,6 @@ func (a *AdminSocket) SetupAdminHandlers(na *AdminSocket) { }, }, errors.New("Failed to remove peer") } - return Info{ - "not_removed": []string{ - in["uri"].(string), - }, - }, errors.New("Failed to remove peer") }) a.AddHandler("getAllowedEncryptionPublicKeys", []string{}, func(in Info) (Info, error) { return Info{"allowed_box_pubs": a.core.GetAllowedEncryptionPublicKeys()}, nil diff --git a/src/multicast/multicast.go b/src/multicast/multicast.go index 430e9374..4dd33a11 100644 --- a/src/multicast/multicast.go +++ b/src/multicast/multicast.go @@ -91,6 +91,7 @@ func (m *Multicast) _start() error { m.sock = ipv6.NewPacketConn(conn) if err = m.sock.SetControlMessage(ipv6.FlagDst, true); err != nil { // Windows can't set this flag, so we need to handle it in other ways + m.log.Warnln("m.sock.SetControlMessage(ipv6.FlagDst) error:", err) } m.isOpen = true @@ -294,7 +295,10 @@ func (m *Multicast) _announce() { continue } // Join the multicast group - m.sock.JoinGroup(&iface, groupAddr) + if err := m.sock.JoinGroup(&iface, groupAddr); err != nil { + m.log.Errorln("Failed to join multicast group on", iface.Name, "due to error:", err) + continue + } // Try and see if we already have a TCP listener for this interface var info *listenerInfo if nfo, ok := m.listeners[iface.Name]; !ok || nfo.listener.Listener == nil { @@ -325,7 +329,9 @@ func (m *Multicast) _announce() { a.Zone = "" destAddr.Zone = iface.Name msg := []byte(a.String()) - m.sock.WriteTo(msg, nil, destAddr) + if _, err = m.sock.WriteTo(msg, nil, destAddr); err != nil { + m.log.Errorln("Failed to send multicast beacon on", iface.Name, "due to error:", err) + } } if info.interval.Seconds() < 15 { info.interval += time.Second diff --git a/src/multicast/multicast_darwin.go b/src/multicast/multicast_darwin.go index ceff5b44..e7075c0a 100644 --- a/src/multicast/multicast_darwin.go +++ b/src/multicast/multicast_darwin.go @@ -29,8 +29,6 @@ import ( "golang.org/x/sys/unix" ) -var awdlGoroutineStarted bool - func (m *Multicast) _multicastStarted() { if !m.isOpen { return diff --git a/src/tuntap/ckr.go b/src/tuntap/ckr.go index fdb2bbdc..240b7139 100644 --- a/src/tuntap/ckr.go +++ b/src/tuntap/ckr.go @@ -93,8 +93,8 @@ func (c *cryptokey) configure() { // Wipe the caches c.mutexcaches.Lock() - c.ipv4cache = make(map[address.Address]cryptokey_route, 0) - c.ipv6cache = make(map[address.Address]cryptokey_route, 0) + c.ipv4cache = make(map[address.Address]cryptokey_route) + c.ipv6cache = make(map[address.Address]cryptokey_route) c.mutexcaches.Unlock() } diff --git a/src/tuntap/conn.go b/src/tuntap/conn.go index ddd89e9b..4824f01b 100644 --- a/src/tuntap/conn.go +++ b/src/tuntap/conn.go @@ -35,7 +35,7 @@ func (s *tunConn) _close_from_tun() { delete(s.tun.addrToConn, s.addr) delete(s.tun.subnetToConn, s.snet) func() { - defer func() { recover() }() + defer func() { _ = recover() }() close(s.stop) // Closes reader/writer goroutines }() } @@ -114,7 +114,7 @@ func (s *tunConn) _read(bs []byte) (err error) { func (s *tunConn) writeFrom(from phony.Actor, bs []byte) { s.Act(from, func() { - s._write(bs) + _ = s._write(bs) }) } diff --git a/src/tuntap/icmpv6.go b/src/tuntap/icmpv6.go index 67c10e54..afdec5fc 100644 --- a/src/tuntap/icmpv6.go +++ b/src/tuntap/icmpv6.go @@ -17,8 +17,6 @@ import ( "golang.org/x/net/ipv6" ) -const len_ETHER = 14 - type ICMPv6 struct { tun *TunAdapter } diff --git a/src/tuntap/iface.go b/src/tuntap/iface.go index 86c3f838..a0be341b 100644 --- a/src/tuntap/iface.go +++ b/src/tuntap/iface.go @@ -28,14 +28,13 @@ func (w *tunWriter) writeFrom(from phony.Actor, b []byte) { // write is pretty loose with the memory safety rules, e.g. it assumes it can // read w.tun.iface.IsTap() safely func (w *tunWriter) _write(b []byte) { - var written int var err error n := len(b) if n == 0 { return } temp := append(w.buf[:TUN_OFFSET_BYTES], b...) - written, err = w.tun.iface.Write(temp, TUN_OFFSET_BYTES) + _, err = w.tun.iface.Write(temp, TUN_OFFSET_BYTES) if err != nil { w.tun.Act(w, func() { if !w.tun.isOpen { @@ -43,10 +42,6 @@ func (w *tunWriter) _write(b []byte) { } }) } - if written != n+TUN_OFFSET_BYTES { - // FIXME some platforms return the wrong number of bytes written, causing error spam - //w.tun.log.Errorln("TUN iface write mismatch:", written, "bytes written vs", n+TUN_OFFSET_BYTES, "bytes given") - } } type tunReader struct { diff --git a/src/tuntap/tun.go b/src/tuntap/tun.go index 656ecca7..6da7ce6d 100644 --- a/src/tuntap/tun.go +++ b/src/tuntap/tun.go @@ -42,13 +42,11 @@ type TunAdapter struct { reader tunReader config *config.NodeState log *log.Logger - reconfigure chan chan error listener *yggdrasil.Listener dialer *yggdrasil.Dialer addr address.Address subnet address.Subnet ckr cryptokey - icmpv6 ICMPv6 mtu MTU iface tun.Device phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below @@ -170,7 +168,7 @@ func (tun *TunAdapter) _start() error { } tun.core.SetMaximumSessionMTU(tun.MTU()) tun.isOpen = true - go tun.handler() + go tun.handler() // nolint:errcheck tun.reader.Act(nil, tun.reader._read) // Start the reader tun.ckr.init(tun) return nil @@ -274,7 +272,7 @@ func (tun *TunAdapter) _wrap(conn *yggdrasil.Conn) (c *tunConn, err error) { // Set the read callback and start the timeout conn.SetReadCallback(func(bs []byte) { s.Act(conn, func() { - s._read(bs) + _ = s._read(bs) }) }) s.Act(nil, s.stillAlive) diff --git a/src/tuntap/tun_darwin.go b/src/tuntap/tun_darwin.go index b984e164..e80638f4 100644 --- a/src/tuntap/tun_darwin.go +++ b/src/tuntap/tun_darwin.go @@ -41,8 +41,8 @@ const ( ) type in6_addrlifetime struct { - ia6t_expire float64 - ia6t_preferred float64 + ia6t_expire float64 // nolint:unused nolint:structcheck + ia6t_preferred float64 // nolint:unused nolint:structcheck ia6t_vltime uint32 ia6t_pltime uint32 } @@ -50,16 +50,16 @@ type in6_addrlifetime struct { type sockaddr_in6 struct { sin6_len uint8 sin6_family uint8 - sin6_port uint8 - sin6_flowinfo uint32 + sin6_port uint8 // nolint:unused nolint:structcheck + sin6_flowinfo uint32 // nolint:unused nolint:structcheck sin6_addr [8]uint16 - sin6_scope_id uint32 + sin6_scope_id uint32 // nolint:unused nolint:structcheck } type in6_aliasreq struct { ifra_name [16]byte ifra_addr sockaddr_in6 - ifra_dstaddr sockaddr_in6 + ifra_dstaddr sockaddr_in6 // nolint:unused nolint:structcheck ifra_prefixmask sockaddr_in6 ifra_flags uint32 ifra_lifetime in6_addrlifetime diff --git a/src/util/cancellation.go b/src/util/cancellation.go index 7fc83147..5987add9 100644 --- a/src/util/cancellation.go +++ b/src/util/cancellation.go @@ -24,7 +24,7 @@ var CancellationTimeoutError = errors.New("timeout") // CancellationFinalizer is set as a finalizer when creating a new cancellation with NewCancellation(), and generally shouldn't be needed by the user, but is included in case other implementations of the same interface want to make use of it. func CancellationFinalizer(c Cancellation) { - c.Cancel(CancellationFinalized) + _ = c.Cancel(CancellationFinalized) } type cancellation struct { @@ -76,7 +76,7 @@ func CancellationChild(parent Cancellation) Cancellation { select { case <-child.Finished(): case <-parent.Finished(): - child.Cancel(parent.Error()) + _ = child.Cancel(parent.Error()) } }() return child @@ -91,7 +91,7 @@ func CancellationWithTimeout(parent Cancellation, timeout time.Duration) Cancell select { case <-child.Finished(): case <-timer.C: - child.Cancel(CancellationTimeoutError) + _ = child.Cancel(CancellationTimeoutError) } }() return child @@ -99,5 +99,5 @@ func CancellationWithTimeout(parent Cancellation, timeout time.Duration) Cancell // CancellationWithTimeout returns a ChildCancellation that will automatically be Cancelled with a CancellationTimeoutError after the specified deadline. func CancellationWithDeadline(parent Cancellation, deadline time.Time) Cancellation { - return CancellationWithTimeout(parent, deadline.Sub(time.Now())) + return CancellationWithTimeout(parent, time.Until(deadline)) } diff --git a/src/yggdrasil/api.go b/src/yggdrasil/api.go index c800cb0d..f26222de 100644 --- a/src/yggdrasil/api.go +++ b/src/yggdrasil/api.go @@ -211,7 +211,7 @@ func (c *Core) GetSessions() []Session { MTU: sinfo._getMTU(), BytesSent: sinfo.bytesSent, BytesRecvd: sinfo.bytesRecvd, - Uptime: time.Now().Sub(sinfo.timeOpened), + Uptime: time.Since(sinfo.timeOpened), WasMTUFixed: sinfo.wasMTUFixed, } copy(session.PublicKey[:], sinfo.theirPermPub[:]) @@ -340,7 +340,7 @@ func (c *Core) MyNodeInfo() NodeInfoPayload { // SetNodeInfo sets the local nodeinfo. Note that nodeinfo can be any value or // struct, it will be serialised into JSON automatically. func (c *Core) SetNodeInfo(nodeinfo interface{}, nodeinfoprivacy bool) { - c.router.nodeinfo.setNodeInfo(nodeinfo, nodeinfoprivacy) + _ = c.router.nodeinfo.setNodeInfo(nodeinfo, nodeinfoprivacy) } // GetMaximumSessionMTU returns the maximum allowed session MTU size. @@ -371,7 +371,7 @@ func (c *Core) SetMaximumSessionMTU(mtu MTU) { func (c *Core) GetNodeInfo(key crypto.BoxPubKey, coords []uint64, nocache bool) (NodeInfoPayload, error) { response := make(chan *NodeInfoPayload, 1) c.router.nodeinfo.addCallback(key, func(nodeinfo *NodeInfoPayload) { - defer func() { recover() }() + defer func() { _ = recover() }() select { case response <- nodeinfo: default: diff --git a/src/yggdrasil/conn.go b/src/yggdrasil/conn.go index 81b5b8d3..7f066c82 100644 --- a/src/yggdrasil/conn.go +++ b/src/yggdrasil/conn.go @@ -113,7 +113,7 @@ func (c *Conn) search() error { // Somehow this was called multiple times, TODO don't let that happen if sinfo != nil { // Need to clean up to avoid a session leak - sinfo.cancel.Cancel(nil) + _ = sinfo.cancel.Cancel(nil) sinfo.sessions.removeSession(sinfo) } default: @@ -149,11 +149,10 @@ func (c *Conn) _doSearch() { s := fmt.Sprintf("conn=%p", c) routerWork := func() { // Check to see if there is a search already matching the destination - sinfo, isIn := c.core.router.searches.searches[*c.nodeID] - if !isIn { + if _, isIn := c.core.router.searches.searches[*c.nodeID]; !isIn { // Nothing was found, so create a new search searchCompleted := func(sinfo *sessionInfo, e error) {} - sinfo = c.core.router.searches.newIterSearch(c.nodeID, c.nodeMask, searchCompleted) + sinfo := c.core.router.searches.newIterSearch(c.nodeID, c.nodeMask, searchCompleted) c.core.log.Debugf("%s DHT search started: %p", s, sinfo) // Start the search sinfo.startSearch() @@ -217,7 +216,7 @@ func (c *Conn) readNoCopy() ([]byte, error) { var doCancel bool phony.Block(c, func() { cancel, doCancel = c._getDeadlineCancellation(c.readDeadline) }) if doCancel { - defer cancel.Cancel(nil) + defer cancel.Cancel(nil) // nolint:errcheck } // Wait for some traffic to come through from the session select { @@ -295,7 +294,7 @@ func (c *Conn) writeNoCopy(msg FlowKeyMessage) error { var doCancel bool phony.Block(c, func() { cancel, doCancel = c._getDeadlineCancellation(c.writeDeadline) }) if doCancel { - defer cancel.Cancel(nil) + defer cancel.Cancel(nil) // nolint:errcheck } var err error select { @@ -369,8 +368,8 @@ func (c *Conn) RemoteAddr() net.Addr { // that synchronous Read and Write operations can block for. If no deadline is // configured, Read and Write operations can potentially block indefinitely. func (c *Conn) SetDeadline(t time.Time) error { - c.SetReadDeadline(t) - c.SetWriteDeadline(t) + _ = c.SetReadDeadline(t) + _ = c.SetWriteDeadline(t) return nil } diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index 4ac678df..9953729b 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -197,7 +197,9 @@ func (c *Core) _stop() { if c.addPeerTimer != nil { c.addPeerTimer.Stop() } - c.links.stop() + if err := c.links.stop(); err != nil { + c.log.Warnln("Error stopping links:", err) + } /* FIXME this deadlocks, need a waitgroup or something to coordinate shutdown for _, peer := range c.GetPeers() { c.DisconnectPeer(peer.Port) diff --git a/src/yggdrasil/core_test.go b/src/yggdrasil/core_test.go index 5f302c23..31c22af9 100644 --- a/src/yggdrasil/core_test.go +++ b/src/yggdrasil/core_test.go @@ -1,3 +1,5 @@ +// +build debug + package yggdrasil import ( diff --git a/src/yggdrasil/dialer.go b/src/yggdrasil/dialer.go index 9f58d305..502c6970 100644 --- a/src/yggdrasil/dialer.go +++ b/src/yggdrasil/dialer.go @@ -21,7 +21,7 @@ type Dialer struct { // "curve25519" or "nodeid" and the second parameter should contain a // hexadecimal representation of the target. It uses DialContext internally. func (d *Dialer) Dial(network, address string) (net.Conn, error) { - return d.DialContext(nil, network, address) + return d.DialContext(context.TODO(), network, address) } // DialContext is used internally by Dial, and should only be used with a diff --git a/src/yggdrasil/link.go b/src/yggdrasil/link.go index 5222644b..6a01f7e1 100644 --- a/src/yggdrasil/link.go +++ b/src/yggdrasil/link.go @@ -140,23 +140,6 @@ func (l *links) call(uri string, sintf string) error { return nil } -func (l *links) listen(uri string) error { - u, err := url.Parse(uri) - if err != nil { - return fmt.Errorf("listener %s is not correctly formatted (%s)", uri, err) - } - switch u.Scheme { - case "tcp": - _, err := l.tcp.listen(u.Host, nil) - return err - case "tls": - _, err := l.tcp.listen(u.Host, l.tcp.tls.forListener) - return err - default: - return errors.New("unknown listen scheme: " + u.Scheme) - } -} - func (l *links) create(msgIO linkMsgIO, name, linkType, local, remote string, incoming, force bool, options linkOptions) (*link, error) { // Technically anything unique would work for names, but let's pick something human readable, just for debugging intf := link{ @@ -191,7 +174,7 @@ func (intf *link) handler() error { // TODO split some of this into shorter functions, so it's easier to read, and for the FIXME duplicate peer issue mentioned later go func() { for bss := range intf.writer.worker { - intf.msgIO.writeMsgs(bss) + _, _ = intf.msgIO.writeMsgs(bss) } }() defer intf.writer.Act(nil, func() { @@ -231,13 +214,13 @@ func (intf *link) handler() error { // check - in future versions we really should check a signature or something like that. if pinned := intf.options.pinnedCurve25519Keys; pinned != nil { if _, allowed := pinned[meta.box]; !allowed { - intf.links.core.log.Errorf("Failed to connect to node: %q sent curve25519 key that does not match pinned keys", intf.name) + intf.links.core.log.Errorf("Failed to connect to node: %q sent curve25519 key that does not match pinned keys", intf.name()) return fmt.Errorf("failed to connect: host sent curve25519 key that does not match pinned keys") } } if pinned := intf.options.pinnedEd25519Keys; pinned != nil { if _, allowed := pinned[meta.sig]; !allowed { - intf.links.core.log.Errorf("Failed to connect to node: %q sent ed25519 key that does not match pinned keys", intf.name) + intf.links.core.log.Errorf("Failed to connect to node: %q sent ed25519 key that does not match pinned keys", intf.name()) return fmt.Errorf("failed to connect: host sent ed25519 key that does not match pinned keys") } } @@ -256,7 +239,7 @@ func (intf *link) handler() error { intf.links.mutex.Unlock() // FIXME we should really return an error and let the caller block instead // That lets them do things like close connections on its own, avoid printing a connection message in the first place, etc. - intf.links.core.log.Debugln("DEBUG: found existing interface for", intf.name) + intf.links.core.log.Debugln("DEBUG: found existing interface for", intf.name()) intf.msgIO.close() if !intf.incoming { // Block outgoing connection attempts until the existing connection closes @@ -272,7 +255,7 @@ func (intf *link) handler() error { intf.links.mutex.Unlock() close(intf.closed) }() - intf.links.core.log.Debugln("DEBUG: registered interface for", intf.name) + intf.links.core.log.Debugln("DEBUG: registered interface for", intf.name()) } intf.links.mutex.Unlock() // Create peer diff --git a/src/yggdrasil/listener.go b/src/yggdrasil/listener.go index 74ef3e88..46dcca33 100644 --- a/src/yggdrasil/listener.go +++ b/src/yggdrasil/listener.go @@ -28,7 +28,7 @@ func (l *Listener) Accept() (net.Conn, error) { // Close will stop the listener func (l *Listener) Close() (err error) { defer func() { - recover() + _ = recover() err = errors.New("already closed") }() if l.core.router.sessions.listener == l { diff --git a/src/yggdrasil/nodeinfo.go b/src/yggdrasil/nodeinfo.go index 30db03c5..260deae1 100644 --- a/src/yggdrasil/nodeinfo.go +++ b/src/yggdrasil/nodeinfo.go @@ -156,14 +156,6 @@ func (m *nodeinfo) _addCachedNodeInfo(key crypto.BoxPubKey, payload NodeInfoPayl } } -// Get a nodeinfo entry from the cache -func (m *nodeinfo) _getCachedNodeInfo(key crypto.BoxPubKey) (NodeInfoPayload, error) { - if nodeinfo, ok := m.cache[key]; ok { - return nodeinfo.payload, nil - } - return NodeInfoPayload{}, errors.New("No cache entry found") -} - // Handles a nodeinfo request/response - called from the router func (m *nodeinfo) handleNodeInfo(from phony.Actor, nodeinfo *nodeinfoReqRes) { m.Act(from, func() { diff --git a/src/yggdrasil/peer.go b/src/yggdrasil/peer.go index f04ab280..3f4911c0 100644 --- a/src/yggdrasil/peer.go +++ b/src/yggdrasil/peer.go @@ -87,7 +87,6 @@ type peer struct { sig crypto.SigPubKey shared crypto.BoxSharedKey linkShared crypto.BoxSharedKey - endpoint string firstSeen time.Time // To track uptime for getPeers dinfo *dhtInfo // used to keep the DHT working // The below aren't actually useful internally, they're just gathered for getPeers statistics @@ -186,18 +185,6 @@ func (ps *peers) sendSwitchMsgs(from phony.Actor) { }) } -func (ps *peers) updateDHT(from phony.Actor) { - ps.Act(from, func() { - for _, peer := range ps.ports { - p := peer - if p.port == 0 { - continue - } - p.Act(ps, p._updateDHT) - } - }) -} - // This must be launched in a separate goroutine by whatever sets up the peer struct. func (p *peer) start() { // Just for good measure, immediately send a switch message to this peer when we start diff --git a/src/yggdrasil/router.go b/src/yggdrasil/router.go index d387346e..e739bc2a 100644 --- a/src/yggdrasil/router.go +++ b/src/yggdrasil/router.go @@ -66,7 +66,9 @@ func (r *router) init(core *Core) { } r.nodeinfo.init(r.core) r.core.config.Mutex.RLock() - r.nodeinfo.setNodeInfo(r.core.config.Current.NodeInfo, r.core.config.Current.NodeInfoPrivacy) + if err := r.nodeinfo.setNodeInfo(r.core.config.Current.NodeInfo, r.core.config.Current.NodeInfoPrivacy); err != nil { + r.core.log.Errorln("Error setting NodeInfo:", err) + } r.core.config.Mutex.RUnlock() r.dht.init(r) r.searches.init(r) diff --git a/src/yggdrasil/session.go b/src/yggdrasil/session.go index 360f2a1b..309ca2ed 100644 --- a/src/yggdrasil/session.go +++ b/src/yggdrasil/session.go @@ -94,7 +94,7 @@ func (s *sessionInfo) _update(p *sessionPing) bool { s.time = time.Now() s.tstamp = p.Tstamp s.reset = false - defer func() { recover() }() // Recover if the below panics + defer func() { _ = recover() }() // Recover if the below panics select { case <-s.init: default: @@ -285,20 +285,22 @@ func (ss *sessions) getSharedKey(myPriv *crypto.BoxPrivKey, theirPub *crypto.BoxPubKey) *crypto.BoxSharedKey { return crypto.GetSharedKey(myPriv, theirPub) // FIXME concurrency issues with the below, so for now we just burn the CPU every time - if skey, isIn := ss.permShared[*theirPub]; isIn { - return skey - } - // First do some cleanup - const maxKeys = 1024 - for key := range ss.permShared { - // Remove a random key until the store is small enough - if len(ss.permShared) < maxKeys { - break + /* + if skey, isIn := ss.permShared[*theirPub]; isIn { + return skey } - delete(ss.permShared, key) - } - ss.permShared[*theirPub] = crypto.GetSharedKey(myPriv, theirPub) - return ss.permShared[*theirPub] + // First do some cleanup + const maxKeys = 1024 + for key := range ss.permShared { + // Remove a random key until the store is small enough + if len(ss.permShared) < maxKeys { + break + } + delete(ss.permShared, key) + } + ss.permShared[*theirPub] = crypto.GetSharedKey(myPriv, theirPub) + return ss.permShared[*theirPub] + */ } // Sends a session ping by calling sendPingPong in ping mode. diff --git a/src/yggdrasil/simlink.go b/src/yggdrasil/simlink.go index 9be6b306..15d5f816 100644 --- a/src/yggdrasil/simlink.go +++ b/src/yggdrasil/simlink.go @@ -2,6 +2,7 @@ package yggdrasil import ( "errors" + "github.com/Arceliar/phony" ) @@ -31,7 +32,7 @@ func (s *Simlink) _sendMetaBytes(bs []byte) error { } func (s *Simlink) close() error { - defer func() { recover() }() + defer func() { _ = recover() }() close(s.rch) return nil } @@ -46,7 +47,7 @@ func (s *Simlink) writeMsgs(msgs [][]byte) (int, error) { bs := append([]byte(nil), msg...) phony.Block(s, func() { s.dest.Act(s, func() { - defer func() { recover() }() + defer func() { _ = recover() }() s.dest.rch <- bs }) }) @@ -84,7 +85,7 @@ func (s *Simlink) Start() error { err = errors.New("already started") } else { s.started = true - go s.link.handler() + go s.link.handler() // nolint:errcheck } }) return err diff --git a/src/yggdrasil/stream.go b/src/yggdrasil/stream.go index afa97c76..9a7f73c2 100644 --- a/src/yggdrasil/stream.go +++ b/src/yggdrasil/stream.go @@ -53,13 +53,11 @@ func (s *stream) writeMsgs(bss [][]byte) (int, error) { // readMsg reads a message from the stream, accounting for stream padding, and is *not* thread safe. func (s *stream) readMsg() ([]byte, error) { - for { - bs, err := s.readMsgFromBuffer() - if err != nil { - return nil, fmt.Errorf("message error: %v", err) - } - return bs, err + bs, err := s.readMsgFromBuffer() + if err != nil { + return nil, fmt.Errorf("message error: %v", err) } + return bs, err } // Writes metadata bytes without stream padding, meant to be temporary diff --git a/src/yggdrasil/switch.go b/src/yggdrasil/switch.go index 2f4f3194..1e372709 100644 --- a/src/yggdrasil/switch.go +++ b/src/yggdrasil/switch.go @@ -117,28 +117,10 @@ func (l *switchLocator) getCoords() []byte { return bs } -// Returns true if this locator represents an ancestor of the locator given as an argument. -// Ancestor means that it's the parent node, or the parent of parent, and so on... -func (x *switchLocator) isAncestorOf(y *switchLocator) bool { - if x.root != y.root { - return false - } - if len(x.coords) > len(y.coords) { - return false - } - for idx := range x.coords { - if x.coords[idx] != y.coords[idx] { - return false - } - } - return true -} - // Information about a peer, used by the switch to build the tree and eventually make routing decisions. type peerInfo struct { key crypto.SigPubKey // ID of this peer locator switchLocator // Should be able to respond with signatures upon request - degree uint64 // Self-reported degree time time.Time // Time this node was last seen faster map[switchPort]uint64 // Counter of how often a node is faster than the current parent, penalized extra if slower port switchPort // Interface number of this peer @@ -177,7 +159,6 @@ type switchData struct { // To be read/written with atomic.Value Store/Load calls locator switchLocator peers map[switchPort]peerInfo - msg *switchMsg } // All the information stored by the switch. @@ -474,10 +455,7 @@ func (t *switchTable) _handleMsg(msg *switchMsg, fromPort switchPort, reprocessi return false } } - if sender.locator.root == t.core.sigPub { - return false - } - return true + return sender.locator.root == t.core.sigPub }() dropTstamp, isIn := t.drop[sender.locator.root] // Decide if we need to update info about the root or change parents. diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index ad9d872e..96d80128 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -30,7 +30,6 @@ import ( ) const default_timeout = 6 * time.Second -const tcp_ping_interval = (default_timeout * 2 / 3) // The TCP listener and information about active TCP connections, to avoid duplication. type tcp struct { @@ -67,7 +66,7 @@ type tcpOptions struct { } func (l *TcpListener) Stop() { - defer func() { recover() }() + defer func() { _ = recover() }() close(l.stop) } @@ -75,25 +74,14 @@ func (l *TcpListener) Stop() { func (t *tcp) setExtraOptions(c net.Conn) { switch sock := c.(type) { case *net.TCPConn: - sock.SetNoDelay(true) + if err := sock.SetNoDelay(true); err != nil { + t.links.core.log.Errorln("Error setting no-delay:", err) + } // TODO something for socks5 default: } } -// Returns the address of the listener. -func (t *tcp) getAddr() *net.TCPAddr { - // TODO: Fix this, because this will currently only give a single address - // to multicast.go, which obviously is not great, but right now multicast.go - // doesn't have the ability to send more than one address in a packet either - t.mutex.Lock() - defer t.mutex.Unlock() - for _, l := range t.listeners { - return l.Listener.Addr().(*net.TCPAddr) - } - return nil -} - // Initializes the struct. func (t *tcp) init(l *links) error { t.links = l diff --git a/src/yggdrasil/wire.go b/src/yggdrasil/wire.go index 9746d46e..eda43ed7 100644 --- a/src/yggdrasil/wire.go +++ b/src/yggdrasil/wire.go @@ -42,15 +42,6 @@ func wire_put_uint64(e uint64, out []byte) []byte { return append(out, b[i:]...) } -// Returns the length of a wire encoded uint64 of this value. -func wire_uint64_len(elem uint64) int { - l := 1 - for e := elem >> 7; e > 0; e >>= 7 { - l++ - } - return l -} - // Decode uint64 from a []byte slice. // Returns the decoded uint64 and the number of bytes used. func wire_decode_uint64(bs []byte) (uint64, int) {