mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-26 06:01:37 +00:00
commit
cfcdf91444
@ -1,17 +1,19 @@
|
|||||||
package yggdrasil
|
package yggdrasil
|
||||||
|
|
||||||
import "net"
|
import (
|
||||||
import "os"
|
"encoding/hex"
|
||||||
import "encoding/hex"
|
"encoding/json"
|
||||||
import "encoding/json"
|
"errors"
|
||||||
import "errors"
|
"fmt"
|
||||||
import "fmt"
|
"net"
|
||||||
import "net/url"
|
"net/url"
|
||||||
import "sort"
|
"os"
|
||||||
import "strings"
|
"sort"
|
||||||
import "strconv"
|
"strconv"
|
||||||
import "sync/atomic"
|
"strings"
|
||||||
import "time"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// TODO: Add authentication
|
// TODO: Add authentication
|
||||||
|
|
||||||
@ -324,7 +326,6 @@ func (a *admin) handleRequest(conn net.Conn) {
|
|||||||
|
|
||||||
// Send the response back
|
// Send the response back
|
||||||
if err := encoder.Encode(&send); err != nil {
|
if err := encoder.Encode(&send); err != nil {
|
||||||
// fmt.Println("Admin socket JSON encode error:", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -640,7 +641,7 @@ func (a *admin) getResponse_dot() []byte {
|
|||||||
for _, info := range infos {
|
for _, info := range infos {
|
||||||
keys = append(keys, info.key)
|
keys = append(keys, info.key)
|
||||||
}
|
}
|
||||||
// TODO sort
|
// sort
|
||||||
less := func(i, j int) bool {
|
less := func(i, j int) bool {
|
||||||
return keys[i] < keys[j]
|
return keys[i] < keys[j]
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package yggdrasil
|
package yggdrasil
|
||||||
|
|
||||||
import "io/ioutil"
|
import (
|
||||||
import "log"
|
"encoding/hex"
|
||||||
import "regexp"
|
"fmt"
|
||||||
import "net"
|
"io/ioutil"
|
||||||
import "fmt"
|
"log"
|
||||||
import "encoding/hex"
|
"net"
|
||||||
import "yggdrasil/config"
|
"regexp"
|
||||||
|
|
||||||
|
"yggdrasil/config"
|
||||||
|
)
|
||||||
|
|
||||||
// The Core object represents the Yggdrasil node. You should create a Core
|
// The Core object represents the Yggdrasil node. You should create a Core
|
||||||
// object for each Yggdrasil node you plan to run.
|
// object for each Yggdrasil node you plan to run.
|
||||||
|
@ -10,10 +10,13 @@ It also defines NodeID and TreeID as hashes of keys, and wraps hash functions
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import "crypto/rand"
|
import (
|
||||||
import "crypto/sha512"
|
"crypto/rand"
|
||||||
import "golang.org/x/crypto/ed25519"
|
"crypto/sha512"
|
||||||
import "golang.org/x/crypto/nacl/box"
|
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
|
"golang.org/x/crypto/nacl/box"
|
||||||
|
)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -121,7 +124,6 @@ func boxOpen(shared *boxSharedKey,
|
|||||||
boxed []byte,
|
boxed []byte,
|
||||||
nonce *boxNonce) ([]byte, bool) {
|
nonce *boxNonce) ([]byte, bool) {
|
||||||
out := util_getBytes()
|
out := util_getBytes()
|
||||||
//return append(out, boxed...), true // XXX HACK to test without encryption
|
|
||||||
s := (*[boxSharedKeyLen]byte)(shared)
|
s := (*[boxSharedKeyLen]byte)(shared)
|
||||||
n := (*[boxNonceLen]byte)(nonce)
|
n := (*[boxNonceLen]byte)(nonce)
|
||||||
unboxed, success := box.OpenAfterPrecomputation(out, boxed, n, s)
|
unboxed, success := box.OpenAfterPrecomputation(out, boxed, n, s)
|
||||||
@ -134,7 +136,6 @@ func boxSeal(shared *boxSharedKey, unboxed []byte, nonce *boxNonce) ([]byte, *bo
|
|||||||
}
|
}
|
||||||
nonce.update()
|
nonce.update()
|
||||||
out := util_getBytes()
|
out := util_getBytes()
|
||||||
//return append(out, unboxed...), nonce // XXX HACK to test without encryption
|
|
||||||
s := (*[boxSharedKeyLen]byte)(shared)
|
s := (*[boxSharedKeyLen]byte)(shared)
|
||||||
n := (*[boxNonceLen]byte)(nonce)
|
n := (*[boxNonceLen]byte)(nonce)
|
||||||
boxed := box.SealAfterPrecomputation(out, unboxed, n, s)
|
boxed := box.SealAfterPrecomputation(out, unboxed, n, s)
|
||||||
|
@ -18,10 +18,10 @@ Slight changes *do* make it blackhole hard, bootstrapping isn't an easy problem
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import "sort"
|
import (
|
||||||
import "time"
|
"sort"
|
||||||
|
"time"
|
||||||
//import "fmt"
|
)
|
||||||
|
|
||||||
// Number of DHT buckets, equal to the number of bits in a NodeID.
|
// Number of DHT buckets, equal to the number of bits in a NodeID.
|
||||||
// Note that, in practice, nearly all of these will be empty.
|
// Note that, in practice, nearly all of these will be empty.
|
||||||
@ -236,7 +236,6 @@ func (t *dht) nBuckets() int {
|
|||||||
// Inserts a node into the DHT if they meet certain requirements.
|
// Inserts a node into the DHT if they meet certain requirements.
|
||||||
// In particular, they must either be a peer that's not already in the DHT, or else be someone we should insert into the DHT (see: shouldInsert).
|
// In particular, they must either be a peer that's not already in the DHT, or else be someone we should insert into the DHT (see: shouldInsert).
|
||||||
func (t *dht) insertIfNew(info *dhtInfo, isPeer bool) {
|
func (t *dht) insertIfNew(info *dhtInfo, isPeer bool) {
|
||||||
//fmt.Println("DEBUG: dht insertIfNew:", info.getNodeID(), info.coords)
|
|
||||||
// Insert if no "other" entry already exists
|
// Insert if no "other" entry already exists
|
||||||
nodeID := info.getNodeID()
|
nodeID := info.getNodeID()
|
||||||
bidx, isOK := t.getBucketIndex(nodeID)
|
bidx, isOK := t.getBucketIndex(nodeID)
|
||||||
@ -256,7 +255,6 @@ func (t *dht) insertIfNew(info *dhtInfo, isPeer bool) {
|
|||||||
|
|
||||||
// Adds a node to the DHT, possibly removing another node in the process.
|
// Adds a node to the DHT, possibly removing another node in the process.
|
||||||
func (t *dht) insert(info *dhtInfo, isPeer bool) {
|
func (t *dht) insert(info *dhtInfo, isPeer bool) {
|
||||||
//fmt.Println("DEBUG: dht insert:", info.getNodeID(), info.coords)
|
|
||||||
// First update the time on this info
|
// First update the time on this info
|
||||||
info.recv = time.Now()
|
info.recv = time.Now()
|
||||||
// Get the bucket for this node
|
// Get the bucket for this node
|
||||||
|
@ -9,11 +9,14 @@ package yggdrasil
|
|||||||
// - Destination Unreachable messages, when a session prohibits
|
// - Destination Unreachable messages, when a session prohibits
|
||||||
// incoming traffic
|
// incoming traffic
|
||||||
|
|
||||||
import "net"
|
import (
|
||||||
import "golang.org/x/net/ipv6"
|
"encoding/binary"
|
||||||
import "golang.org/x/net/icmp"
|
"errors"
|
||||||
import "encoding/binary"
|
"net"
|
||||||
import "errors"
|
|
||||||
|
"golang.org/x/net/icmp"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
type macAddress [6]byte
|
type macAddress [6]byte
|
||||||
|
|
||||||
@ -239,10 +242,16 @@ func (i *icmpv6) create_icmpv6_tun(dst net.IP, src net.IP, mtype ipv6.ICMPType,
|
|||||||
// when the host operating system generates an NDP request for any address in
|
// when the host operating system generates an NDP request for any address in
|
||||||
// the fd00::/8 range, so that the operating system knows to route that traffic
|
// the fd00::/8 range, so that the operating system knows to route that traffic
|
||||||
// to the Yggdrasil TAP adapter.
|
// to the Yggdrasil TAP adapter.
|
||||||
// TODO: Make this respect the value of address_prefix in address.go
|
|
||||||
func (i *icmpv6) handle_ndp(in []byte) ([]byte, error) {
|
func (i *icmpv6) handle_ndp(in []byte) ([]byte, error) {
|
||||||
// Ignore NDP requests for anything outside of fd00::/8
|
// Ignore NDP requests for anything outside of fd00::/8
|
||||||
if in[8] != 0xFD {
|
var source address
|
||||||
|
copy(source[:], in[8:])
|
||||||
|
var snet subnet
|
||||||
|
copy(snet[:], in[8:])
|
||||||
|
switch {
|
||||||
|
case source.isValid():
|
||||||
|
case snet.isValid():
|
||||||
|
default:
|
||||||
return nil, errors.New("Not an NDP for fd00::/8")
|
return nil, errors.New("Not an NDP for fd00::/8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package yggdrasil
|
package yggdrasil
|
||||||
|
|
||||||
import "net"
|
import (
|
||||||
import "time"
|
"fmt"
|
||||||
import "fmt"
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
import "golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
type multicast struct {
|
type multicast struct {
|
||||||
core *Core
|
core *Core
|
||||||
@ -37,11 +39,9 @@ func (m *multicast) start() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
//defer conn.Close() // Let it close on its own when the application exits
|
|
||||||
m.sock = ipv6.NewPacketConn(conn)
|
m.sock = ipv6.NewPacketConn(conn)
|
||||||
if err = m.sock.SetControlMessage(ipv6.FlagDst, true); err != nil {
|
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
|
// Windows can't set this flag, so we need to handle it in other ways
|
||||||
//panic(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go m.listen()
|
go m.listen()
|
||||||
@ -95,8 +95,6 @@ func (m *multicast) announce() {
|
|||||||
for {
|
for {
|
||||||
for _, iface := range m.interfaces() {
|
for _, iface := range m.interfaces() {
|
||||||
m.sock.JoinGroup(&iface, groupAddr)
|
m.sock.JoinGroup(&iface, groupAddr)
|
||||||
//err := n.sock.JoinGroup(&iface, groupAddr)
|
|
||||||
//if err != nil { panic(err) }
|
|
||||||
addrs, err := iface.Addrs()
|
addrs, err := iface.Addrs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -133,8 +131,6 @@ func (m *multicast) listen() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
//if rcm == nil { continue } // wat
|
|
||||||
//fmt.Println("DEBUG:", "packet from:", fromAddr.String())
|
|
||||||
if rcm != nil {
|
if rcm != nil {
|
||||||
// Windows can't set the flag needed to return a non-nil value here
|
// Windows can't set the flag needed to return a non-nil value here
|
||||||
// So only make these checks if we get something useful back
|
// So only make these checks if we get something useful back
|
||||||
@ -149,19 +145,14 @@ func (m *multicast) listen() {
|
|||||||
anAddr := string(bs[:nBytes])
|
anAddr := string(bs[:nBytes])
|
||||||
addr, err := net.ResolveTCPAddr("tcp6", anAddr)
|
addr, err := net.ResolveTCPAddr("tcp6", anAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
|
||||||
continue
|
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())
|
|
||||||
if addr.IP.String() != from.IP.String() {
|
if addr.IP.String() != from.IP.String() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
addr.Zone = from.Zone
|
addr.Zone = from.Zone
|
||||||
saddr := addr.String()
|
saddr := addr.String()
|
||||||
//if _, isIn := n.peers[saddr]; isIn { continue }
|
|
||||||
//n.peers[saddr] = struct{}{}
|
|
||||||
m.core.tcp.connect(saddr)
|
m.core.tcp.connect(saddr)
|
||||||
//fmt.Println("DEBUG:", "added multicast peer:", saddr)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,21 +4,20 @@ package yggdrasil
|
|||||||
// Commented code should be removed
|
// Commented code should be removed
|
||||||
// Live code should be better commented
|
// Live code should be better commented
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
import "sync"
|
"sync"
|
||||||
import "sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
//import "fmt"
|
)
|
||||||
|
|
||||||
// The peers struct represents peers with an active connection.
|
// The peers struct represents peers with an active connection.
|
||||||
// Incomping packets are passed to the corresponding peer, which handles them somehow.
|
// Incomping packets are passed to the corresponding peer, which handles them somehow.
|
||||||
// In most cases, this involves passing the packet to the handler for outgoing traffic to another peer.
|
// In most cases, this involves passing the packet to the handler for outgoing traffic to another peer.
|
||||||
// In other cases, it's link protocol traffic used to build the spanning tree, in which case this checks signatures and passes the message along to the switch.
|
// In other cases, it's link protocol traffic used to build the spanning tree, in which case this checks signatures and passes the message along to the switch.
|
||||||
type peers struct {
|
type peers struct {
|
||||||
core *Core
|
core *Core
|
||||||
mutex sync.Mutex // Synchronize writes to atomic
|
mutex sync.Mutex // Synchronize writes to atomic
|
||||||
ports atomic.Value //map[Port]*peer, use CoW semantics
|
ports atomic.Value //map[Port]*peer, use CoW semantics
|
||||||
//ports map[Port]*peer
|
|
||||||
authMutex sync.RWMutex
|
authMutex sync.RWMutex
|
||||||
allowedEncryptionPublicKeys map[boxPubKey]struct{}
|
allowedEncryptionPublicKeys map[boxPubKey]struct{}
|
||||||
}
|
}
|
||||||
@ -198,7 +197,7 @@ func (p *peer) linkLoop() {
|
|||||||
// Called to handle incoming packets.
|
// Called to handle incoming packets.
|
||||||
// Passes the packet to a handler for that packet type.
|
// Passes the packet to a handler for that packet type.
|
||||||
func (p *peer) handlePacket(packet []byte) {
|
func (p *peer) handlePacket(packet []byte) {
|
||||||
// TODO See comment in sendPacket about atomics technically being done wrong
|
// FIXME this is off by stream padding and msg length overhead, should be done in tcp.go
|
||||||
atomic.AddUint64(&p.bytesRecvd, uint64(len(packet)))
|
atomic.AddUint64(&p.bytesRecvd, uint64(len(packet)))
|
||||||
pType, pTypeLen := wire_decode_uint64(packet)
|
pType, pTypeLen := wire_decode_uint64(packet)
|
||||||
if pTypeLen == 0 {
|
if pTypeLen == 0 {
|
||||||
@ -307,8 +306,6 @@ func (p *peer) sendSwitchMsg() {
|
|||||||
Sig: *sign(&p.core.sigPriv, bs),
|
Sig: *sign(&p.core.sigPriv, bs),
|
||||||
})
|
})
|
||||||
packet := msg.encode()
|
packet := msg.encode()
|
||||||
//p.core.log.Println("Encoded msg:", msg, "; bytes:", packet)
|
|
||||||
//fmt.Println("Encoded msg:", msg, "; bytes:", packet)
|
|
||||||
p.sendLinkPacket(packet)
|
p.sendLinkPacket(packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +316,6 @@ func (p *peer) handleSwitchMsg(packet []byte) {
|
|||||||
if !msg.decode(packet) {
|
if !msg.decode(packet) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//p.core.log.Println("Decoded msg:", msg, "; bytes:", packet)
|
|
||||||
if len(msg.Hops) < 1 {
|
if len(msg.Hops) < 1 {
|
||||||
p.core.peers.removePeer(p.port)
|
p.core.peers.removePeer(p.port)
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
package yggdrasil
|
package yggdrasil
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
import "log"
|
"errors"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
// Starts the function profiler. This is only supported when built with
|
// Starts the function profiler. This is only supported when built with
|
||||||
// '-tags build'.
|
// '-tags build'.
|
||||||
|
@ -22,12 +22,12 @@ package yggdrasil
|
|||||||
// The packet is passed to the session, which decrypts it, router.recvPacket
|
// The packet is passed to the session, which decrypts it, router.recvPacket
|
||||||
// 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 (
|
||||||
import "golang.org/x/net/icmp"
|
"time"
|
||||||
import "golang.org/x/net/ipv6"
|
|
||||||
|
|
||||||
//import "fmt"
|
"golang.org/x/net/icmp"
|
||||||
//import "net"
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
// The router struct has channels to/from the tun/tap device and a self peer (0), which is how messages are passed between this node and the peers/switch layer.
|
// The router struct has channels to/from the tun/tap device and a self peer (0), which is how messages are passed between this node and the peers/switch layer.
|
||||||
// The router's mainLoop goroutine is responsible for managing all information related to the dht, searches, and crypto sessions.
|
// The router's mainLoop goroutine is responsible for managing all information related to the dht, searches, and crypto sessions.
|
||||||
@ -101,7 +101,6 @@ func (r *router) mainLoop() {
|
|||||||
// Any periodic maintenance stuff goes here
|
// Any periodic maintenance stuff goes here
|
||||||
r.core.switchTable.doMaintenance()
|
r.core.switchTable.doMaintenance()
|
||||||
r.core.dht.doMaintenance()
|
r.core.dht.doMaintenance()
|
||||||
//r.core.peers.sendSwitchMsgs() // FIXME debugging
|
|
||||||
util_getBytes() // To slowly drain things
|
util_getBytes() // To slowly drain things
|
||||||
}
|
}
|
||||||
case f := <-r.admin:
|
case f := <-r.admin:
|
||||||
@ -243,7 +242,6 @@ func (r *router) sendPacket(bs []byte) {
|
|||||||
// Checks that the IP address is correct (matches the session) and passes the packet to the tun/tap.
|
// Checks that the IP address is correct (matches the session) and passes the packet to the tun/tap.
|
||||||
func (r *router) recvPacket(bs []byte, theirAddr *address, theirSubnet *subnet) {
|
func (r *router) recvPacket(bs []byte, theirAddr *address, theirSubnet *subnet) {
|
||||||
// Note: called directly by the session worker, not the router goroutine
|
// Note: called directly by the session worker, not the router goroutine
|
||||||
//fmt.Println("Recv packet")
|
|
||||||
if len(bs) < 24 {
|
if len(bs) < 24 {
|
||||||
util_putBytes(bs)
|
util_putBytes(bs)
|
||||||
return
|
return
|
||||||
@ -274,7 +272,7 @@ func (r *router) handleIn(packet []byte) {
|
|||||||
r.handleTraffic(packet)
|
r.handleTraffic(packet)
|
||||||
case wire_ProtocolTraffic:
|
case wire_ProtocolTraffic:
|
||||||
r.handleProto(packet)
|
r.handleProto(packet)
|
||||||
default: /*panic("Should not happen in testing") ;*/
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,7 +288,6 @@ func (r *router) handleTraffic(packet []byte) {
|
|||||||
if !isIn {
|
if !isIn {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//go func () { sinfo.recv<-&p }()
|
|
||||||
sinfo.recv <- &p
|
sinfo.recv <- &p
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +300,6 @@ func (r *router) handleProto(packet []byte) {
|
|||||||
}
|
}
|
||||||
// Now try to open the payload
|
// Now try to open the payload
|
||||||
var sharedKey *boxSharedKey
|
var sharedKey *boxSharedKey
|
||||||
//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)
|
||||||
@ -321,7 +317,6 @@ func (r *router) handleProto(packet []byte) {
|
|||||||
if bsTypeLen == 0 {
|
if bsTypeLen == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//fmt.Println("RECV bytes:", bs)
|
|
||||||
switch bsType {
|
switch bsType {
|
||||||
case wire_SessionPing:
|
case wire_SessionPing:
|
||||||
r.handlePing(bs, &p.FromKey)
|
r.handlePing(bs, &p.FromKey)
|
||||||
|
@ -11,10 +11,10 @@ package yggdrasil
|
|||||||
// A new search packet is sent immediately after receiving a response
|
// A new search packet is sent immediately after receiving a response
|
||||||
// A new search packet is sent periodically, once per second, in case a packet was dropped (this slowly causes the search to become parallel if the search doesn't timeout but also doesn't finish within 1 second for whatever reason)
|
// A new search packet is sent periodically, once per second, in case a packet was dropped (this slowly causes the search to become parallel if the search doesn't timeout but also doesn't finish within 1 second for whatever reason)
|
||||||
|
|
||||||
import "sort"
|
import (
|
||||||
import "time"
|
"sort"
|
||||||
|
"time"
|
||||||
//import "fmt"
|
)
|
||||||
|
|
||||||
// This defines the maximum number of dhtInfo that we keep track of for nodes to query in an ongoing search.
|
// This defines the maximum number of dhtInfo that we keep track of for nodes to query in an ongoing search.
|
||||||
const search_MAX_SEARCH_SIZE = 16
|
const search_MAX_SEARCH_SIZE = 16
|
||||||
|
@ -456,7 +456,6 @@ func (sinfo *sessionInfo) doRecv(p *wire_trafficPacket) {
|
|||||||
}
|
}
|
||||||
if newMTU < sinfo.myMTU {
|
if newMTU < sinfo.myMTU {
|
||||||
sinfo.myMTU = newMTU
|
sinfo.myMTU = newMTU
|
||||||
//sinfo.core.log.Println("DEBUG set MTU to:", sinfo.myMTU)
|
|
||||||
sinfo.core.sessions.sendPingPong(sinfo, false)
|
sinfo.core.sessions.sendPingPong(sinfo, false)
|
||||||
sinfo.mtuTime = time.Now()
|
sinfo.mtuTime = time.Now()
|
||||||
sinfo.wasMTUFixed = true
|
sinfo.wasMTUFixed = true
|
||||||
@ -470,7 +469,6 @@ func (sinfo *sessionInfo) doRecv(p *wire_trafficPacket) {
|
|||||||
if time.Since(sinfo.mtuTime) > time.Minute {
|
if time.Since(sinfo.mtuTime) > time.Minute {
|
||||||
sinfo.myMTU = uint16(sinfo.core.tun.mtu)
|
sinfo.myMTU = uint16(sinfo.core.tun.mtu)
|
||||||
sinfo.mtuTime = time.Now()
|
sinfo.mtuTime = time.Now()
|
||||||
//sinfo.core.log.Println("DEBUG: Reset MTU to:", sinfo.myMTU)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
go func() { sinfo.core.router.admin <- fixSessionMTU }()
|
go func() { sinfo.core.router.admin <- fixSessionMTU }()
|
||||||
|
@ -3,8 +3,10 @@ package yggdrasil
|
|||||||
// This is where we record which signatures we've previously checked
|
// This is where we record which signatures we've previously checked
|
||||||
// It's so we can avoid needlessly checking them again
|
// It's so we can avoid needlessly checking them again
|
||||||
|
|
||||||
import "sync"
|
import (
|
||||||
import "time"
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// This keeps track of what signatures have already been checked.
|
// This keeps track of what signatures have already been checked.
|
||||||
// It's used to skip expensive crypto operations, given that many signatures are likely to be the same for the average node's peers.
|
// It's used to skip expensive crypto operations, given that many signatures are likely to be the same for the average node's peers.
|
||||||
|
@ -11,12 +11,12 @@ package yggdrasil
|
|||||||
// TODO? use a pre-computed lookup table (python version had this)
|
// TODO? use a pre-computed lookup table (python version had this)
|
||||||
// A little annoying to do with constant changes from backpressure
|
// A little annoying to do with constant changes from backpressure
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
import "sort"
|
"sort"
|
||||||
import "sync"
|
"sync"
|
||||||
import "sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
//import "fmt"
|
)
|
||||||
|
|
||||||
const switch_timeout = time.Minute
|
const switch_timeout = time.Minute
|
||||||
const switch_updateInterval = switch_timeout / 2
|
const switch_updateInterval = switch_timeout / 2
|
||||||
@ -201,25 +201,19 @@ func (t *switchTable) cleanRoot() {
|
|||||||
// Get rid of the root if it looks like its timed out
|
// Get rid of the root if it looks like its timed out
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
doUpdate := false
|
doUpdate := false
|
||||||
//fmt.Println("DEBUG clean root:", now.Sub(t.time))
|
|
||||||
if now.Sub(t.time) > switch_timeout {
|
if now.Sub(t.time) > switch_timeout {
|
||||||
//fmt.Println("root timed out", t.data.locator)
|
|
||||||
dropped := t.data.peers[t.parent]
|
dropped := t.data.peers[t.parent]
|
||||||
dropped.time = t.time
|
dropped.time = t.time
|
||||||
t.drop[t.data.locator.root] = t.data.locator.tstamp
|
t.drop[t.data.locator.root] = t.data.locator.tstamp
|
||||||
doUpdate = true
|
doUpdate = true
|
||||||
//t.core.log.Println("DEBUG: switch root timeout", len(t.drop))
|
|
||||||
}
|
}
|
||||||
// Or, if we're better than our root, root ourself
|
// Or, if we're better than our root, root ourself
|
||||||
if firstIsBetter(&t.key, &t.data.locator.root) {
|
if firstIsBetter(&t.key, &t.data.locator.root) {
|
||||||
//fmt.Println("root is worse than us", t.data.locator.Root)
|
|
||||||
doUpdate = true
|
doUpdate = true
|
||||||
//t.core.log.Println("DEBUG: switch root replace with self", t.data.locator.Root)
|
|
||||||
}
|
}
|
||||||
// Or, if we are the root, possibly update our timestamp
|
// Or, if we are the root, possibly update our timestamp
|
||||||
if t.data.locator.root == t.key &&
|
if t.data.locator.root == t.key &&
|
||||||
now.Sub(t.time) > switch_updateInterval {
|
now.Sub(t.time) > switch_updateInterval {
|
||||||
//fmt.Println("root is self and old, updating", t.data.locator.Root)
|
|
||||||
doUpdate = true
|
doUpdate = true
|
||||||
}
|
}
|
||||||
if doUpdate {
|
if doUpdate {
|
||||||
@ -421,15 +415,12 @@ func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort) {
|
|||||||
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)
|
|
||||||
//fmt.Println("Switch update:", msg.Locator.Root, msg.Locator.Tstamp, msg.Locator.Coords)
|
|
||||||
}
|
}
|
||||||
if t.data.locator.tstamp != sender.locator.tstamp {
|
if t.data.locator.tstamp != sender.locator.tstamp {
|
||||||
t.time = now
|
t.time = now
|
||||||
}
|
}
|
||||||
t.data.locator = sender.locator
|
t.data.locator = sender.locator
|
||||||
t.parent = sender.port
|
t.parent = sender.port
|
||||||
//t.core.log.Println("Switch update:", msg.Locator.Root, msg.Locator.Tstamp, msg.Locator.Coords)
|
|
||||||
t.core.peers.sendSwitchMsgs()
|
t.core.peers.sendSwitchMsgs()
|
||||||
}
|
}
|
||||||
if doUpdate {
|
if doUpdate {
|
||||||
@ -504,6 +495,5 @@ func (t *switchTable) lookup(dest []byte) switchPort {
|
|||||||
bestCost = cost
|
bestCost = cost
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//t.core.log.Println("DEBUG: sending to", best, "cost", bestCost)
|
|
||||||
return best
|
return best
|
||||||
}
|
}
|
||||||
|
@ -14,13 +14,16 @@ package yggdrasil
|
|||||||
// It involves exchanging version numbers and crypto keys
|
// It involves exchanging version numbers and crypto keys
|
||||||
// See version.go for version metadata format
|
// See version.go for version metadata format
|
||||||
|
|
||||||
import "net"
|
import (
|
||||||
import "time"
|
"errors"
|
||||||
import "errors"
|
"fmt"
|
||||||
import "sync"
|
"net"
|
||||||
import "sync/atomic"
|
"sync"
|
||||||
import "fmt"
|
"sync/atomic"
|
||||||
import "golang.org/x/net/proxy"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/proxy"
|
||||||
|
)
|
||||||
|
|
||||||
const tcp_msgSize = 2048 + 65535 // TODO figure out what makes sense
|
const tcp_msgSize = 2048 + 65535 // TODO figure out what makes sense
|
||||||
|
|
||||||
@ -211,7 +214,7 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
|
|||||||
}
|
}
|
||||||
if equiv(info.box[:], iface.core.boxPub[:]) {
|
if equiv(info.box[:], iface.core.boxPub[:]) {
|
||||||
return
|
return
|
||||||
} // testing
|
}
|
||||||
if equiv(info.sig[:], iface.core.sigPub[:]) {
|
if equiv(info.sig[:], iface.core.sigPub[:]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -286,7 +289,6 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
|
|||||||
timer.Reset(timerInterval)
|
timer.Reset(timerInterval)
|
||||||
select {
|
select {
|
||||||
case _ = <-timer.C:
|
case _ = <-timer.C:
|
||||||
//iface.core.log.Println("DEBUG: sending keep-alive:", sock.RemoteAddr().String())
|
|
||||||
send(nil) // TCP keep-alive traffic
|
send(nil) // TCP keep-alive traffic
|
||||||
case msg := <-p.linkOut:
|
case msg := <-p.linkOut:
|
||||||
send(msg)
|
send(msg)
|
||||||
@ -352,14 +354,12 @@ func (iface *tcpInterface) reader(sock net.Conn, in func([]byte)) {
|
|||||||
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 {
|
if err != nil || n == 0 {
|
||||||
// iface.core.log.Println(err)
|
|
||||||
break
|
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 {
|
if err != nil {
|
||||||
// iface.core.log.Println(err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -2,8 +2,10 @@ package yggdrasil
|
|||||||
|
|
||||||
// This manages the tun driver to send/recv packets to/from applications
|
// This manages the tun driver to send/recv packets to/from applications
|
||||||
|
|
||||||
import "github.com/songgao/packets/ethernet"
|
import (
|
||||||
import "github.com/yggdrasil-network/water"
|
"github.com/songgao/packets/ethernet"
|
||||||
|
"github.com/yggdrasil-network/water"
|
||||||
|
)
|
||||||
|
|
||||||
const tun_IPv6_HEADER_LENGTH = 40
|
const tun_IPv6_HEADER_LENGTH = 40
|
||||||
const tun_ETHER_HEADER_LENGTH = 14
|
const tun_ETHER_HEADER_LENGTH = 14
|
||||||
@ -127,7 +129,7 @@ func (tun *tunDevice) read() error {
|
|||||||
|
|
||||||
// Closes the TUN/TAP adapter. This is only usually called when the Yggdrasil
|
// Closes the TUN/TAP adapter. This is only usually called when the Yggdrasil
|
||||||
// process stops. Typically this operation will happen quickly, but on macOS
|
// process stops. Typically this operation will happen quickly, but on macOS
|
||||||
// it can block until a read operation is completed.
|
// it can block until a read operation is completed.
|
||||||
func (tun *tunDevice) close() error {
|
func (tun *tunDevice) close() error {
|
||||||
if tun.iface == nil {
|
if tun.iface == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -2,16 +2,18 @@
|
|||||||
|
|
||||||
package yggdrasil
|
package yggdrasil
|
||||||
|
|
||||||
import "unsafe"
|
import (
|
||||||
import "syscall"
|
"encoding/binary"
|
||||||
import "strings"
|
"os/exec"
|
||||||
import "strconv"
|
"strconv"
|
||||||
import "encoding/binary"
|
"strings"
|
||||||
import "os/exec"
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
import "golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
import "github.com/yggdrasil-network/water"
|
"github.com/yggdrasil-network/water"
|
||||||
|
)
|
||||||
|
|
||||||
const SIOCSIFADDR_IN6 = (0x80000000) | ((288 & 0x1fff) << 16) | uint32(byte('i'))<<8 | 12
|
const SIOCSIFADDR_IN6 = (0x80000000) | ((288 & 0x1fff) << 16) | uint32(byte('i'))<<8 | 12
|
||||||
|
|
||||||
@ -74,7 +76,7 @@ type in6_ifreq_lifetime struct {
|
|||||||
// OpenBSD, NetBSD) an attempt is made to set the adapter properties by using
|
// OpenBSD, NetBSD) an attempt is made to set the adapter properties by using
|
||||||
// a system socket and making syscalls to the kernel. This is not refined though
|
// a system socket and making syscalls to the kernel. This is not refined though
|
||||||
// and often doesn't work (if at all), therefore if a call fails, it resorts
|
// and often doesn't work (if at all), therefore if a call fails, it resorts
|
||||||
// to calling "ifconfig" instead.
|
// to calling "ifconfig" instead.
|
||||||
func (tun *tunDevice) setup(ifname string, iftapmode bool, addr string, mtu int) error {
|
func (tun *tunDevice) setup(ifname string, iftapmode bool, addr string, mtu int) error {
|
||||||
var config water.Config
|
var config water.Config
|
||||||
if ifname[:4] == "auto" {
|
if ifname[:4] == "auto" {
|
||||||
|
@ -2,13 +2,16 @@ package yggdrasil
|
|||||||
|
|
||||||
// The darwin platform specific tun parts
|
// The darwin platform specific tun parts
|
||||||
|
|
||||||
import "unsafe"
|
import (
|
||||||
import "strings"
|
"encoding/binary"
|
||||||
import "strconv"
|
"strconv"
|
||||||
import "encoding/binary"
|
"strings"
|
||||||
import "golang.org/x/sys/unix"
|
"unsafe"
|
||||||
|
|
||||||
import water "github.com/yggdrasil-network/water"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
water "github.com/yggdrasil-network/water"
|
||||||
|
)
|
||||||
|
|
||||||
// Sane defaults for the Darwin/macOS platform. The "default" options may be
|
// Sane defaults for the Darwin/macOS platform. The "default" options may be
|
||||||
// may be replaced by the running configuration.
|
// may be replaced by the running configuration.
|
||||||
@ -69,7 +72,7 @@ type ifreq struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sets the IPv6 address of the utun adapter. On Darwin/macOS this is done using
|
// Sets the IPv6 address of the utun adapter. On Darwin/macOS this is done using
|
||||||
// a system socket and making direct syscalls to the kernel.
|
// a system socket and making direct syscalls to the kernel.
|
||||||
func (tun *tunDevice) setupAddress(addr string) error {
|
func (tun *tunDevice) setupAddress(addr string) error {
|
||||||
var fd int
|
var fd int
|
||||||
var err error
|
var err error
|
||||||
|
@ -2,13 +2,15 @@ package yggdrasil
|
|||||||
|
|
||||||
// The linux platform specific tun parts
|
// The linux platform specific tun parts
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
import "fmt"
|
"errors"
|
||||||
import "net"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
import water "github.com/yggdrasil-network/water"
|
"github.com/docker/libcontainer/netlink"
|
||||||
|
|
||||||
import "github.com/docker/libcontainer/netlink"
|
water "github.com/yggdrasil-network/water"
|
||||||
|
)
|
||||||
|
|
||||||
// Sane defaults for the Linux platform. The "default" options may be
|
// Sane defaults for the Linux platform. The "default" options may be
|
||||||
// may be replaced by the running configuration.
|
// may be replaced by the running configuration.
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
package yggdrasil
|
package yggdrasil
|
||||||
|
|
||||||
import water "github.com/yggdrasil-network/water"
|
import (
|
||||||
import "os/exec"
|
"fmt"
|
||||||
import "strings"
|
"os/exec"
|
||||||
import "fmt"
|
"strings"
|
||||||
|
|
||||||
|
water "github.com/yggdrasil-network/water"
|
||||||
|
)
|
||||||
|
|
||||||
// This is to catch Windows platforms
|
// This is to catch Windows platforms
|
||||||
|
|
||||||
|
@ -4,8 +4,6 @@ package yggdrasil
|
|||||||
|
|
||||||
import "runtime"
|
import "runtime"
|
||||||
|
|
||||||
//import "sync"
|
|
||||||
|
|
||||||
// A wrapper around runtime.Gosched() so it doesn't need to be imported elsewhere.
|
// A wrapper around runtime.Gosched() so it doesn't need to be imported elsewhere.
|
||||||
func util_yield() {
|
func util_yield() {
|
||||||
runtime.Gosched()
|
runtime.Gosched()
|
||||||
@ -21,20 +19,6 @@ func util_unlockthread() {
|
|||||||
runtime.UnlockOSThread()
|
runtime.UnlockOSThread()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used previously, but removed because casting to an interface{} allocates...
|
|
||||||
var byteStore sync.Pool = sync.Pool{
|
|
||||||
New: func () interface{} { return []byte(nil) },
|
|
||||||
}
|
|
||||||
|
|
||||||
func util_getBytes() []byte {
|
|
||||||
return byteStore.Get().([]byte)[:0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func util_putBytes(bs []byte) {
|
|
||||||
byteStore.Put(bs) // This is the part that allocates
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This is used to buffer recently used slices of bytes, to prevent allocations in the hot loops.
|
// This is used to buffer recently used slices of bytes, to prevent allocations in the hot loops.
|
||||||
// It's used like a sync.Pool, but with a fixed size and typechecked without type casts to/from interface{} (which were making the profiles look ugly).
|
// It's used like a sync.Pool, but with a fixed size and typechecked without type casts to/from interface{} (which were making the profiles look ugly).
|
||||||
var byteStore chan []byte
|
var byteStore chan []byte
|
||||||
|
Loading…
Reference in New Issue
Block a user