diff --git a/build b/build index e463c852..a3a679f2 100755 --- a/build +++ b/build @@ -6,12 +6,13 @@ PKGVER=${PKGVER:-$(sh contrib/semver/version.sh --bare)} LDFLAGS="-X $PKGSRC.buildName=$PKGNAME -X $PKGSRC.buildVersion=$PKGVER" -while getopts "udtc:l:" option +while getopts "udmtc:l:" option do case "${option}" in u) UPX=true;; d) DEBUG=true;; + m) MOBILE=true;; t) TABLES=true;; c) GCFLAGS="$GCFLAGS $OPTARG";; l) LDFLAGS="$LDFLAGS $OPTARG";; @@ -25,7 +26,9 @@ fi for CMD in `ls cmd/` ; do echo "Building: $CMD" - if [ $DEBUG ]; then + if [ $MOBILE ]; then + go build -ldflags="$LDFLAGS" -gcflags="$GCFLAGS" -tags mobile -v ./cmd/$CMD + elif [ $DEBUG ]; then go build -ldflags="$LDFLAGS" -gcflags="$GCFLAGS" -tags debug -v ./cmd/$CMD else go build -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" -v ./cmd/$CMD diff --git a/src/yggdrasil/awdl.go b/src/yggdrasil/awdl.go new file mode 100644 index 00000000..b07c2fc7 --- /dev/null +++ b/src/yggdrasil/awdl.go @@ -0,0 +1,86 @@ +package yggdrasil + +import ( + "sync" + "github.com/yggdrasil-network/yggdrasil-go/src/crypto" +) + +type awdl struct { + core *Core + mutex sync.RWMutex // protects interfaces below + interfaces map[string]*awdlInterface +} + +type awdlInterface struct { + awdl *awdl + recv <-chan []byte // traffic received from the network + send chan<- []byte // traffic to send to the network + shutdown chan bool + peer *peer +} + +func (l *awdl) init(c *Core) error { + l.core = c + l.mutex.Lock() + l.interfaces = make(map[string]*awdlInterface) + l.mutex.Unlock() + + return nil +} + +func (l *awdl) create(boxPubKey *crypto.BoxPubKey, sigPubKey *crypto.SigPubKey, name string) *awdlInterface { + shared := crypto.GetSharedKey(&l.core.boxPriv, boxPubKey) + intf := awdlInterface{ + recv: make(<-chan []byte), + send: make(chan<- []byte), + shutdown: make(chan bool), + peer: l.core.peers.newPeer(boxPubKey, sigPubKey, shared, name), + } + if intf.peer != nil { + l.mutex.Lock() + l.interfaces[name] = &intf + l.mutex.Unlock() + intf.peer.linkOut = make(chan []byte, 1) // protocol traffic + intf.peer.out = func(msg []byte) { + defer func() { recover() }() + intf.send <- msg + } + go intf.handler() + l.core.switchTable.idleIn <- intf.peer.port + return &intf + } + return nil +} + +func (l *awdl) getInterface(identity string) *awdlInterface { + l.mutex.RLock() + defer l.mutex.RUnlock() + if intf, ok := l.interfaces[identity]; ok { + return intf + } + return nil +} + +func (l *awdl) shutdown(identity string) { + if intf, ok := l.interfaces[identity]; ok { + intf.shutdown <- true + l.core.peers.removePeer(intf.peer.port) + l.mutex.Lock() + delete(l.interfaces, identity) + l.mutex.Unlock() + } +} + +func (ai *awdlInterface) handler() { + for { + select { + case p := <-ai.peer.linkOut: + ai.send <- p + case r := <-ai.recv: // traffic received from AWDL + ai.peer.handlePacket(r) + case <-ai.shutdown: + return + default: + } + } +} diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index e38274fa..b99d1f2b 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -35,6 +35,7 @@ type Core struct { multicast multicast nodeinfo nodeinfo tcp tcpInterface + awdl awdl log *log.Logger ifceExpr []*regexp.Regexp // the zone of link-local IPv6 peers must match this } @@ -132,6 +133,11 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error { return err } + if err := c.awdl.init(c); err != nil { + c.log.Println("Failed to start AWDL interface") + return err + } + if nc.SwitchOptions.MaxTotalQueueSize >= SwitchQueueTotalMinSize { c.switchTable.queueTotalMaxSize = nc.SwitchOptions.MaxTotalQueueSize } diff --git a/src/yggdrasil/mobile.go b/src/yggdrasil/mobile.go index f579f532..36a98eab 100644 --- a/src/yggdrasil/mobile.go +++ b/src/yggdrasil/mobile.go @@ -11,6 +11,7 @@ import ( hjson "github.com/hjson/hjson-go" "github.com/mitchellh/mapstructure" "github.com/yggdrasil-network/yggdrasil-go/src/config" + "github.com/yggdrasil-network/yggdrasil-go/src/crypto" "github.com/yggdrasil-network/yggdrasil-go/src/util" ) @@ -91,3 +92,11 @@ func (c *Core) RouterSendPacket(buf []byte) error { c.router.tun.send <- packet return nil } + +func (c *Core) AWDLCreateInterface(boxPubKey []byte, sigPubKey []byte, name string) { + var box crypto.BoxPubKey + var sig crypto.SigPubKey + copy(box[:crypto.BoxPubKeyLen], boxPubKey[:]) + copy(sig[:crypto.SigPubKeyLen], sigPubKey[:]) + c.awdl.create(&box, &sig, name) +}