5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-11-25 23:01:38 +00:00

Add some simple functions for Swift bindings (iOS)

This commit is contained in:
Neil Alexander 2019-01-01 23:25:20 +00:00
parent d08a3c6643
commit 53aeca8fa2
No known key found for this signature in database
GPG Key ID: A02A2019A2BB0944
4 changed files with 113 additions and 64 deletions

View File

@ -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)

View File

@ -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
}

View File

@ -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

51
src/yggdrasil/ios.go Normal file
View File

@ -0,0 +1,51 @@
// +build mobile
package yggdrasil
import (
"log"
"os"
"regexp"
"github.com/yggdrasil-network/yggdrasil-go/src/config"
)
// This file is meant to "plug the gap" for Gomobile support, as Gomobile
// will not create headers for Swift/Obj-C if they have complex (read: non-
// native) types. Therefore for iOS we will expose some nice simple functions
// to do what we need to do.
func (c *Core) StartAutoconfigure() error {
logger := log.New(os.Stdout, "", 0)
//logger.Println("Created logger")
//c := Core{}
//logger.Println("Created Core")
nc := config.GenerateConfig(true)
//logger.Println("Generated config")
nc.IfName = "none"
nc.AdminListen = "tcp://[::]:9001"
nc.Peers = []string{}
//logger.Println("Set some config options")
ifceExpr, err := regexp.Compile(".*")
if err == nil {
c.ifceExpr = append(c.ifceExpr, ifceExpr)
}
//logger.Println("Added multicast interface")
if err := c.Start(nc, logger); err != nil {
return err
}
//logger.Println("Started")
address := c.GetAddress()
subnet := c.GetSubnet()
logger.Printf("Your IPv6 address is %s", address.String())
logger.Printf("Your IPv6 subnet is %s", subnet.String())
return nil
}
func (c *Core) GetAddressString() string {
return c.GetAddress().String()
}
func (c *Core) GetSubetString() string {
return c.GetSubnet().String()
}