mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2024-12-25 01:07:49 +00:00
Merge pull request #301 from neilalexander/ios
Boilerplate for iOS support
This commit is contained in:
commit
38209ee9b9
7
build
7
build
@ -6,12 +6,13 @@ PKGVER=${PKGVER:-$(sh contrib/semver/version.sh --bare)}
|
|||||||
|
|
||||||
LDFLAGS="-X $PKGSRC.buildName=$PKGNAME -X $PKGSRC.buildVersion=$PKGVER"
|
LDFLAGS="-X $PKGSRC.buildName=$PKGNAME -X $PKGSRC.buildVersion=$PKGVER"
|
||||||
|
|
||||||
while getopts "udtc:l:" option
|
while getopts "udmtc:l:" option
|
||||||
do
|
do
|
||||||
case "${option}"
|
case "${option}"
|
||||||
in
|
in
|
||||||
u) UPX=true;;
|
u) UPX=true;;
|
||||||
d) DEBUG=true;;
|
d) DEBUG=true;;
|
||||||
|
m) MOBILE=true;;
|
||||||
t) TABLES=true;;
|
t) TABLES=true;;
|
||||||
c) GCFLAGS="$GCFLAGS $OPTARG";;
|
c) GCFLAGS="$GCFLAGS $OPTARG";;
|
||||||
l) LDFLAGS="$LDFLAGS $OPTARG";;
|
l) LDFLAGS="$LDFLAGS $OPTARG";;
|
||||||
@ -25,7 +26,9 @@ fi
|
|||||||
for CMD in `ls cmd/` ; do
|
for CMD in `ls cmd/` ; do
|
||||||
echo "Building: $CMD"
|
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
|
go build -ldflags="$LDFLAGS" -gcflags="$GCFLAGS" -tags debug -v ./cmd/$CMD
|
||||||
else
|
else
|
||||||
go build -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" -v ./cmd/$CMD
|
go build -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" -v ./cmd/$CMD
|
||||||
|
@ -2,13 +2,11 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -23,7 +21,6 @@ import (
|
|||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
|
"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,52 +31,10 @@ type node struct {
|
|||||||
core Core
|
core Core
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generates default configuration. This is used when outputting the -genconf
|
|
||||||
// parameter and also when using -autoconf. The isAutoconf flag is used to
|
|
||||||
// determine whether the operating system should select a free port by itself
|
|
||||||
// (which guarantees that there will not be a conflict with any other services)
|
|
||||||
// or whether to generate a random port number. The only side effect of setting
|
|
||||||
// isAutoconf is that the TCP and UDP ports will likely end up with different
|
|
||||||
// port numbers.
|
|
||||||
func generateConfig(isAutoconf bool) *nodeConfig {
|
|
||||||
// Create a new core.
|
|
||||||
core := Core{}
|
|
||||||
// Generate encryption keys.
|
|
||||||
bpub, bpriv := core.NewEncryptionKeys()
|
|
||||||
spub, spriv := core.NewSigningKeys()
|
|
||||||
// Create a node configuration and populate it.
|
|
||||||
cfg := nodeConfig{}
|
|
||||||
if isAutoconf {
|
|
||||||
cfg.Listen = "[::]:0"
|
|
||||||
} else {
|
|
||||||
r1 := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
||||||
cfg.Listen = fmt.Sprintf("[::]:%d", r1.Intn(65534-32768)+32768)
|
|
||||||
}
|
|
||||||
cfg.AdminListen = defaults.GetDefaults().DefaultAdminListen
|
|
||||||
cfg.EncryptionPublicKey = hex.EncodeToString(bpub[:])
|
|
||||||
cfg.EncryptionPrivateKey = hex.EncodeToString(bpriv[:])
|
|
||||||
cfg.SigningPublicKey = hex.EncodeToString(spub[:])
|
|
||||||
cfg.SigningPrivateKey = hex.EncodeToString(spriv[:])
|
|
||||||
cfg.Peers = []string{}
|
|
||||||
cfg.InterfacePeers = map[string][]string{}
|
|
||||||
cfg.AllowedEncryptionPublicKeys = []string{}
|
|
||||||
cfg.MulticastInterfaces = []string{".*"}
|
|
||||||
cfg.IfName = defaults.GetDefaults().DefaultIfName
|
|
||||||
cfg.IfMTU = defaults.GetDefaults().DefaultIfMTU
|
|
||||||
cfg.IfTAPMode = defaults.GetDefaults().DefaultIfTAPMode
|
|
||||||
cfg.SessionFirewall.Enable = false
|
|
||||||
cfg.SessionFirewall.AllowFromDirect = true
|
|
||||||
cfg.SessionFirewall.AllowFromRemote = true
|
|
||||||
cfg.SwitchOptions.MaxTotalQueueSize = yggdrasil.SwitchQueueTotalMinSize
|
|
||||||
cfg.NodeInfoPrivacy = false
|
|
||||||
|
|
||||||
return &cfg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generates a new configuration and returns it in HJSON format. This is used
|
// Generates a new configuration and returns it in HJSON format. This is used
|
||||||
// with -genconf.
|
// with -genconf.
|
||||||
func doGenconf(isjson bool) string {
|
func doGenconf(isjson bool) string {
|
||||||
cfg := generateConfig(false)
|
cfg := config.GenerateConfig(false)
|
||||||
var bs []byte
|
var bs []byte
|
||||||
var err error
|
var err error
|
||||||
if isjson {
|
if isjson {
|
||||||
@ -114,19 +69,19 @@ func main() {
|
|||||||
case *autoconf:
|
case *autoconf:
|
||||||
// Use an autoconf-generated config, this will give us random keys and
|
// Use an autoconf-generated config, this will give us random keys and
|
||||||
// port numbers, and will use an automatically selected TUN/TAP interface.
|
// port numbers, and will use an automatically selected TUN/TAP interface.
|
||||||
cfg = generateConfig(true)
|
cfg = config.GenerateConfig(true)
|
||||||
case *useconffile != "" || *useconf:
|
case *useconffile != "" || *useconf:
|
||||||
// Use a configuration file. If -useconf, the configuration will be read
|
// Use a configuration file. If -useconf, the configuration will be read
|
||||||
// from stdin. If -useconffile, the configuration will be read from the
|
// from stdin. If -useconffile, the configuration will be read from the
|
||||||
// filesystem.
|
// filesystem.
|
||||||
var config []byte
|
var configjson []byte
|
||||||
var err error
|
var err error
|
||||||
if *useconffile != "" {
|
if *useconffile != "" {
|
||||||
// Read the file from the filesystem
|
// Read the file from the filesystem
|
||||||
config, err = ioutil.ReadFile(*useconffile)
|
configjson, err = ioutil.ReadFile(*useconffile)
|
||||||
} else {
|
} else {
|
||||||
// Read the file from stdin.
|
// Read the file from stdin.
|
||||||
config, err = ioutil.ReadAll(os.Stdin)
|
configjson, err = ioutil.ReadAll(os.Stdin)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -135,11 +90,11 @@ func main() {
|
|||||||
// throwing everywhere when it's converting things into UTF-16 for the hell
|
// throwing everywhere when it's converting things into UTF-16 for the hell
|
||||||
// of it - remove it and decode back down into UTF-8. This is necessary
|
// of it - remove it and decode back down into UTF-8. This is necessary
|
||||||
// because hjson doesn't know what to do with UTF-16 and will panic
|
// because hjson doesn't know what to do with UTF-16 and will panic
|
||||||
if bytes.Compare(config[0:2], []byte{0xFF, 0xFE}) == 0 ||
|
if bytes.Compare(configjson[0:2], []byte{0xFF, 0xFE}) == 0 ||
|
||||||
bytes.Compare(config[0:2], []byte{0xFE, 0xFF}) == 0 {
|
bytes.Compare(configjson[0:2], []byte{0xFE, 0xFF}) == 0 {
|
||||||
utf := unicode.UTF16(unicode.BigEndian, unicode.UseBOM)
|
utf := unicode.UTF16(unicode.BigEndian, unicode.UseBOM)
|
||||||
decoder := utf.NewDecoder()
|
decoder := utf.NewDecoder()
|
||||||
config, err = decoder.Bytes(config)
|
configjson, err = decoder.Bytes(configjson)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -148,9 +103,9 @@ func main() {
|
|||||||
// then parse the configuration we loaded above on top of it. The effect
|
// then parse the configuration we loaded above on top of it. The effect
|
||||||
// of this is that any configuration item that is missing from the provided
|
// of this is that any configuration item that is missing from the provided
|
||||||
// configuration will use a sane default.
|
// configuration will use a sane default.
|
||||||
cfg = generateConfig(false)
|
cfg = config.GenerateConfig(false)
|
||||||
var dat map[string]interface{}
|
var dat map[string]interface{}
|
||||||
if err := hjson.Unmarshal(config, &dat); err != nil {
|
if err := hjson.Unmarshal(configjson, &dat); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
confJson, err := json.Marshal(dat)
|
confJson, err := json.Marshal(dat)
|
||||||
|
@ -1,5 +1,15 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
|
||||||
|
)
|
||||||
|
|
||||||
// NodeConfig defines all configuration values needed to run a signle yggdrasil node
|
// NodeConfig defines all configuration values needed to run a signle yggdrasil node
|
||||||
type NodeConfig struct {
|
type NodeConfig struct {
|
||||||
Listen string `comment:"Listen address for peer connections. Default is to listen for all\nTCP connections over IPv4 and IPv6 with a random port."`
|
Listen string `comment:"Listen address for peer connections. Default is to listen for all\nTCP connections over IPv4 and IPv6 with a random port."`
|
||||||
@ -53,3 +63,45 @@ type TunnelRouting struct {
|
|||||||
type SwitchOptions struct {
|
type SwitchOptions struct {
|
||||||
MaxTotalQueueSize uint64 `comment:"Maximum size of all switch queues combined (in bytes)."`
|
MaxTotalQueueSize uint64 `comment:"Maximum size of all switch queues combined (in bytes)."`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generates default configuration. This is used when outputting the -genconf
|
||||||
|
// parameter and also when using -autoconf. The isAutoconf flag is used to
|
||||||
|
// determine whether the operating system should select a free port by itself
|
||||||
|
// (which guarantees that there will not be a conflict with any other services)
|
||||||
|
// or whether to generate a random port number. The only side effect of setting
|
||||||
|
// isAutoconf is that the TCP and UDP ports will likely end up with different
|
||||||
|
// port numbers.
|
||||||
|
func GenerateConfig(isAutoconf bool) *NodeConfig {
|
||||||
|
// Create a new core.
|
||||||
|
//core := Core{}
|
||||||
|
// Generate encryption keys.
|
||||||
|
bpub, bpriv := crypto.NewBoxKeys()
|
||||||
|
spub, spriv := crypto.NewSigKeys()
|
||||||
|
// Create a node configuration and populate it.
|
||||||
|
cfg := NodeConfig{}
|
||||||
|
if isAutoconf {
|
||||||
|
cfg.Listen = "[::]:0"
|
||||||
|
} else {
|
||||||
|
r1 := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
cfg.Listen = fmt.Sprintf("[::]:%d", r1.Intn(65534-32768)+32768)
|
||||||
|
}
|
||||||
|
cfg.AdminListen = defaults.GetDefaults().DefaultAdminListen
|
||||||
|
cfg.EncryptionPublicKey = hex.EncodeToString(bpub[:])
|
||||||
|
cfg.EncryptionPrivateKey = hex.EncodeToString(bpriv[:])
|
||||||
|
cfg.SigningPublicKey = hex.EncodeToString(spub[:])
|
||||||
|
cfg.SigningPrivateKey = hex.EncodeToString(spriv[:])
|
||||||
|
cfg.Peers = []string{}
|
||||||
|
cfg.InterfacePeers = map[string][]string{}
|
||||||
|
cfg.AllowedEncryptionPublicKeys = []string{}
|
||||||
|
cfg.MulticastInterfaces = []string{".*"}
|
||||||
|
cfg.IfName = defaults.GetDefaults().DefaultIfName
|
||||||
|
cfg.IfMTU = defaults.GetDefaults().DefaultIfMTU
|
||||||
|
cfg.IfTAPMode = defaults.GetDefaults().DefaultIfTAPMode
|
||||||
|
cfg.SessionFirewall.Enable = false
|
||||||
|
cfg.SessionFirewall.AllowFromDirect = true
|
||||||
|
cfg.SessionFirewall.AllowFromRemote = true
|
||||||
|
cfg.SwitchOptions.MaxTotalQueueSize = 4 * 1024 * 1024
|
||||||
|
cfg.NodeInfoPrivacy = false
|
||||||
|
|
||||||
|
return &cfg
|
||||||
|
}
|
||||||
|
@ -1,17 +1,8 @@
|
|||||||
package yggdrasil
|
package yggdrasil
|
||||||
|
|
||||||
// Defines the minimum required functions for an adapter type.
|
|
||||||
type AdapterInterface interface {
|
|
||||||
init(core *Core, send chan<- []byte, recv <-chan []byte)
|
|
||||||
read() error
|
|
||||||
write() error
|
|
||||||
close() error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defines the minimum required struct members for an adapter type (this is
|
// Defines the minimum required struct members for an adapter type (this is
|
||||||
// now the base type for tunAdapter in tun.go)
|
// now the base type for tunAdapter in tun.go)
|
||||||
type Adapter struct {
|
type Adapter struct {
|
||||||
AdapterInterface
|
|
||||||
core *Core
|
core *Core
|
||||||
send chan<- []byte
|
send chan<- []byte
|
||||||
recv <-chan []byte
|
recv <-chan []byte
|
||||||
|
147
src/yggdrasil/awdl.go
Normal file
147
src/yggdrasil/awdl.go
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
package yggdrasil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type awdl struct {
|
||||||
|
core *Core
|
||||||
|
mutex sync.RWMutex // protects interfaces below
|
||||||
|
interfaces map[string]*awdlInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
type awdlInterface struct {
|
||||||
|
awdl *awdl
|
||||||
|
fromAWDL chan []byte
|
||||||
|
toAWDL chan []byte
|
||||||
|
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(fromAWDL chan []byte, toAWDL chan []byte, boxPubKey *crypto.BoxPubKey, sigPubKey *crypto.SigPubKey, name string) (*awdlInterface, error) {
|
||||||
|
/*
|
||||||
|
myLinkPub, myLinkPriv := crypto.NewBoxKeys()
|
||||||
|
meta := version_getBaseMetadata()
|
||||||
|
meta.box = l.core.boxPub
|
||||||
|
meta.sig = l.core.sigPub
|
||||||
|
meta.link = *myLinkPub
|
||||||
|
metaBytes := meta.encode()
|
||||||
|
l.core.log.Println("toAWDL <- metaBytes")
|
||||||
|
toAWDL <- metaBytes
|
||||||
|
l.core.log.Println("metaBytes = <-fromAWDL")
|
||||||
|
metaBytes = <-fromAWDL
|
||||||
|
l.core.log.Println("version_metadata{}")
|
||||||
|
meta = version_metadata{}
|
||||||
|
if !meta.decode(metaBytes) || !meta.check() {
|
||||||
|
return nil, errors.New("Metadata decode failure")
|
||||||
|
}
|
||||||
|
base := version_getBaseMetadata()
|
||||||
|
if meta.ver > base.ver || meta.ver == base.ver && meta.minorVer > base.minorVer {
|
||||||
|
return nil, errors.New("Failed to connect to node: " + name + " version: " + fmt.Sprintf("%d.%d", meta.ver, meta.minorVer))
|
||||||
|
}
|
||||||
|
shared := crypto.GetSharedKey(myLinkPriv, &meta.link)
|
||||||
|
*/
|
||||||
|
shared := crypto.GetSharedKey(&l.core.boxPriv, boxPubKey)
|
||||||
|
intf := awdlInterface{
|
||||||
|
awdl: l,
|
||||||
|
fromAWDL: fromAWDL,
|
||||||
|
toAWDL: toAWDL,
|
||||||
|
shutdown: make(chan bool),
|
||||||
|
peer: l.core.peers.newPeer(boxPubKey, sigPubKey, shared, name),
|
||||||
|
//peer: l.core.peers.newPeer(&meta.box, &meta.sig, 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.toAWDL <- msg
|
||||||
|
} // called by peer.sendPacket()
|
||||||
|
l.core.switchTable.idleIn <- intf.peer.port // notify switch that we're idle
|
||||||
|
intf.peer.close = func() {
|
||||||
|
close(intf.fromAWDL)
|
||||||
|
close(intf.toAWDL)
|
||||||
|
}
|
||||||
|
go intf.handler()
|
||||||
|
go intf.peer.linkLoop()
|
||||||
|
return &intf, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("l.core.peers.newPeer failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
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) error {
|
||||||
|
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()
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return errors.New(fmt.Sprintf("Interface '%s' doesn't exist or already shutdown", identity))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ai *awdlInterface) handler() {
|
||||||
|
send := func(msg []byte) {
|
||||||
|
ai.toAWDL <- msg
|
||||||
|
atomic.AddUint64(&ai.peer.bytesSent, uint64(len(msg)))
|
||||||
|
util.PutBytes(msg)
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
timerInterval := tcp_ping_interval
|
||||||
|
timer := time.NewTimer(timerInterval)
|
||||||
|
defer timer.Stop()
|
||||||
|
select {
|
||||||
|
case p := <-ai.peer.linkOut:
|
||||||
|
send(p)
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
timer.Stop()
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
timer.Reset(timerInterval)
|
||||||
|
select {
|
||||||
|
case _ = <-timer.C:
|
||||||
|
send([]byte{})
|
||||||
|
case p := <-ai.peer.linkOut:
|
||||||
|
send(p)
|
||||||
|
continue
|
||||||
|
case r := <-ai.fromAWDL:
|
||||||
|
ai.peer.handlePacket(r)
|
||||||
|
ai.awdl.core.switchTable.idleIn <- ai.peer.port
|
||||||
|
case <-ai.shutdown:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,7 @@ type Core struct {
|
|||||||
multicast multicast
|
multicast multicast
|
||||||
nodeinfo nodeinfo
|
nodeinfo nodeinfo
|
||||||
tcp tcpInterface
|
tcp tcpInterface
|
||||||
|
awdl awdl
|
||||||
log *log.Logger
|
log *log.Logger
|
||||||
ifceExpr []*regexp.Regexp // the zone of link-local IPv6 peers must match this
|
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
|
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 {
|
if nc.SwitchOptions.MaxTotalQueueSize >= SwitchQueueTotalMinSize {
|
||||||
c.switchTable.queueTotalMaxSize = nc.SwitchOptions.MaxTotalQueueSize
|
c.switchTable.queueTotalMaxSize = nc.SwitchOptions.MaxTotalQueueSize
|
||||||
}
|
}
|
||||||
|
167
src/yggdrasil/mobile.go
Normal file
167
src/yggdrasil/mobile.go
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
// +build mobile
|
||||||
|
|
||||||
|
package yggdrasil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This file is meant to "plug the gap" for mobile support, as Gomobile will
|
||||||
|
// not create headers for Swift/Obj-C etc if they have complex (non-native)
|
||||||
|
// types. Therefore for iOS we will expose some nice simple functions. Note
|
||||||
|
// that in the case of iOS we handle reading/writing to/from TUN in Swift
|
||||||
|
// therefore we use the "dummy" TUN interface instead.
|
||||||
|
|
||||||
|
func (c *Core) StartAutoconfigure() error {
|
||||||
|
mobilelog := MobileLogger{}
|
||||||
|
logger := log.New(mobilelog, "", 0)
|
||||||
|
nc := config.GenerateConfig(true)
|
||||||
|
nc.IfName = "dummy"
|
||||||
|
nc.AdminListen = "tcp://localhost:9001"
|
||||||
|
nc.Peers = []string{}
|
||||||
|
if hostname, err := os.Hostname(); err == nil {
|
||||||
|
nc.NodeInfo = map[string]interface{}{"name": hostname}
|
||||||
|
}
|
||||||
|
ifceExpr, err := regexp.Compile(".*")
|
||||||
|
if err == nil {
|
||||||
|
c.ifceExpr = append(c.ifceExpr, ifceExpr)
|
||||||
|
}
|
||||||
|
if err := c.Start(nc, logger); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) StartJSON(configjson []byte) error {
|
||||||
|
mobilelog := MobileLogger{}
|
||||||
|
logger := log.New(mobilelog, "", 0)
|
||||||
|
nc := config.GenerateConfig(false)
|
||||||
|
var dat map[string]interface{}
|
||||||
|
if err := hjson.Unmarshal(configjson, &dat); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := mapstructure.Decode(dat, &nc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nc.IfName = "dummy"
|
||||||
|
for _, ll := range nc.MulticastInterfaces {
|
||||||
|
ifceExpr, err := regexp.Compile(ll)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
c.AddMulticastInterfaceExpr(ifceExpr)
|
||||||
|
}
|
||||||
|
if err := c.Start(nc, logger); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateConfigJSON() []byte {
|
||||||
|
nc := config.GenerateConfig(false)
|
||||||
|
nc.IfName = "dummy"
|
||||||
|
if json, err := json.Marshal(nc); err == nil {
|
||||||
|
return json
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) GetAddressString() string {
|
||||||
|
return c.GetAddress().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) GetSubnetString() string {
|
||||||
|
return c.GetSubnet().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) RouterRecvPacket() ([]byte, error) {
|
||||||
|
packet := <-c.router.tun.recv
|
||||||
|
return packet, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) RouterSendPacket(buf []byte) error {
|
||||||
|
packet := append(util.GetBytes(), buf[:]...)
|
||||||
|
c.router.tun.send <- packet
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) AWDLCreateInterface(boxPubKey string, sigPubKey string, name string) error {
|
||||||
|
fromAWDL := make(chan []byte, 32)
|
||||||
|
toAWDL := make(chan []byte, 32)
|
||||||
|
|
||||||
|
var boxPub crypto.BoxPubKey
|
||||||
|
var sigPub crypto.SigPubKey
|
||||||
|
boxPubHex, err := hex.DecodeString(boxPubKey)
|
||||||
|
if err != nil {
|
||||||
|
c.log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sigPubHex, err := hex.DecodeString(sigPubKey)
|
||||||
|
if err != nil {
|
||||||
|
c.log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
copy(boxPub[:], boxPubHex)
|
||||||
|
copy(sigPub[:], sigPubHex)
|
||||||
|
|
||||||
|
if intf, err := c.awdl.create(fromAWDL, toAWDL, &boxPub, &sigPub, name); err == nil {
|
||||||
|
if intf != nil {
|
||||||
|
c.log.Println(err)
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
c.log.Println("c.awdl.create didn't return an interface")
|
||||||
|
return errors.New("c.awdl.create didn't return an interface")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) AWDLCreateInterfaceFromContext(context []byte, name string) error {
|
||||||
|
if len(context) < crypto.BoxPubKeyLen+crypto.SigPubKeyLen {
|
||||||
|
return errors.New("Not enough bytes in context")
|
||||||
|
}
|
||||||
|
boxPubKey := hex.EncodeToString(context[:crypto.BoxPubKeyLen])
|
||||||
|
sigPubKey := hex.EncodeToString(context[crypto.BoxPubKeyLen:])
|
||||||
|
return c.AWDLCreateInterface(boxPubKey, sigPubKey, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) AWDLShutdownInterface(name string) error {
|
||||||
|
return c.awdl.shutdown(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) AWDLRecvPacket(identity string) ([]byte, error) {
|
||||||
|
if intf := c.awdl.getInterface(identity); intf != nil {
|
||||||
|
return <-intf.toAWDL, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("AWDLRecvPacket identity not known: " + identity)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) AWDLSendPacket(identity string, buf []byte) error {
|
||||||
|
packet := append(util.GetBytes(), buf[:]...)
|
||||||
|
if intf := c.awdl.getInterface(identity); intf != nil {
|
||||||
|
intf.fromAWDL <- packet
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("AWDLSendPacket identity not known: " + identity)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) AWDLConnectionContext() []byte {
|
||||||
|
var context []byte
|
||||||
|
context = append(context, c.boxPub[:]...)
|
||||||
|
context = append(context, c.sigPub[:]...)
|
||||||
|
return context
|
||||||
|
}
|
25
src/yggdrasil/mobile_ios.go
Normal file
25
src/yggdrasil/mobile_ios.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// +build mobile,darwin
|
||||||
|
|
||||||
|
package yggdrasil
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -x objective-c
|
||||||
|
#cgo LDFLAGS: -framework Foundation
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
void Log(const char *text) {
|
||||||
|
NSString *nss = [NSString stringWithUTF8String:text];
|
||||||
|
NSLog(@"%@", nss);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
type MobileLogger struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nsl MobileLogger) Write(p []byte) (n int, err error) {
|
||||||
|
p = append(p, 0)
|
||||||
|
cstr := (*C.char)(unsafe.Pointer(&p[0]))
|
||||||
|
C.Log(cstr)
|
||||||
|
return len(p), nil
|
||||||
|
}
|
@ -217,6 +217,7 @@ func (p *peer) handlePacket(packet []byte) {
|
|||||||
default:
|
default:
|
||||||
util.PutBytes(packet)
|
util.PutBytes(packet)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called to handle traffic or protocolTraffic packets.
|
// Called to handle traffic or protocolTraffic packets.
|
||||||
|
@ -47,12 +47,14 @@ func (tun *tunAdapter) init(core *Core, send chan<- []byte, recv <-chan []byte)
|
|||||||
// Starts the setup process for the TUN/TAP adapter, and if successful, starts
|
// Starts the setup process for the TUN/TAP adapter, and if successful, starts
|
||||||
// the read/write goroutines to handle packets on that interface.
|
// the read/write goroutines to handle packets on that interface.
|
||||||
func (tun *tunAdapter) start(ifname string, iftapmode bool, addr string, mtu int) error {
|
func (tun *tunAdapter) start(ifname string, iftapmode bool, addr string, mtu int) error {
|
||||||
if ifname == "none" {
|
if ifname != "none" {
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err := tun.setup(ifname, iftapmode, addr, mtu); err != nil {
|
if err := tun.setup(ifname, iftapmode, addr, mtu); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if ifname == "none" || ifname == "dummy" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
tun.mutex.Lock()
|
tun.mutex.Lock()
|
||||||
tun.isOpen = true
|
tun.isOpen = true
|
||||||
tun.mutex.Unlock()
|
tun.mutex.Unlock()
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build !mobile
|
||||||
|
|
||||||
package yggdrasil
|
package yggdrasil
|
||||||
|
|
||||||
// The darwin platform specific tun parts
|
// The darwin platform specific tun parts
|
||||||
|
19
src/yggdrasil/tun_dummy.go
Normal file
19
src/yggdrasil/tun_dummy.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// +build mobile
|
||||||
|
|
||||||
|
package yggdrasil
|
||||||
|
|
||||||
|
// This is to catch unsupported platforms
|
||||||
|
// If your platform supports tun devices, you could try configuring it manually
|
||||||
|
|
||||||
|
// Creates the TUN/TAP adapter, if supported by the Water library. Note that
|
||||||
|
// no guarantees are made at this point on an unsupported platform.
|
||||||
|
func (tun *tunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int) error {
|
||||||
|
tun.mtu = getSupportedMTU(mtu)
|
||||||
|
return tun.setupAddress(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't know how to set the IPv6 address on an unknown platform, therefore
|
||||||
|
// write about it to stdout and don't try to do anything further.
|
||||||
|
func (tun *tunAdapter) setupAddress(addr string) error {
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build !mobile
|
||||||
|
|
||||||
package yggdrasil
|
package yggdrasil
|
||||||
|
|
||||||
// The linux platform specific tun parts
|
// The linux platform specific tun parts
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// +build !linux,!darwin,!windows,!openbsd,!freebsd,!netbsd
|
// +build !linux,!darwin,!windows,!openbsd,!freebsd,!netbsd,!mobile
|
||||||
|
|
||||||
package yggdrasil
|
package yggdrasil
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user