diff --git a/contrib/mobile/mobile.go b/contrib/mobile/mobile.go index ba7cfdf..fc85036 100644 --- a/contrib/mobile/mobile.go +++ b/contrib/mobile/mobile.go @@ -25,7 +25,7 @@ import ( // 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. type Yggdrasil struct { - core core.Core + core *core.Core iprwc *ipv6rwc.ReadWriteCloser config *config.NodeConfig multicast multicast.Multicast @@ -48,19 +48,42 @@ func (m *Yggdrasil) StartJSON(configjson []byte) error { if err := json.Unmarshal(configjson, &m.config); err != nil { return err } - m.config.IfName = "none" - if err := m.core.Start(m.config, logger); err != nil { - logger.Errorln("An error occured starting Yggdrasil:", err) - return err + // Setup the Yggdrasil node itself. + sk, err := hex.DecodeString(m.config.PrivateKey) + if err != nil { + panic(err) + } + options := []core.SetupOption{ + core.IfName("none"), + core.IfMTU(m.config.IfMTU), + } + for _, peer := range m.config.Peers { + options = append(options, core.Peer{URI: peer}) + } + for intf, peers := range m.config.InterfacePeers { + for _, peer := range peers { + options = append(options, core.Peer{URI: peer, SourceInterface: intf}) + } + } + for _, allowed := range m.config.AllowedPublicKeys { + k, err := hex.DecodeString(allowed) + if err != nil { + panic(err) + } + options = append(options, core.AllowedPublicKey(k[:])) + } + m.core, err = core.New(sk[:], options...) + if err != nil { + panic(err) } mtu := m.config.IfMTU - m.iprwc = ipv6rwc.NewReadWriteCloser(&m.core) + m.iprwc = ipv6rwc.NewReadWriteCloser(m.core) if m.iprwc.MaxMTU() < mtu { mtu = m.iprwc.MaxMTU() } m.iprwc.SetMTU(mtu) if len(m.config.MulticastInterfaces) > 0 { - if err := m.multicast.Init(&m.core, m.config, logger, nil); err != nil { + if err := m.multicast.Init(m.core, m.config, logger, nil); err != nil { logger.Errorln("An error occurred initialising multicast:", err) return err } @@ -139,18 +162,18 @@ func (m *Yggdrasil) GetCoordsString() string { func (m *Yggdrasil) GetPeersJSON() (result string) { peers := []struct { - core.Peer + core.PeerInfo IP string }{} for _, v := range m.core.GetPeers() { a := address.AddrForKey(v.Key) ip := net.IP(a[:]).String() peers = append(peers, struct { - core.Peer + core.PeerInfo IP string }{ - Peer: v, - IP: ip, + PeerInfo: v, + IP: ip, }) } if res, err := json.Marshal(peers); err == nil { diff --git a/go.mod b/go.mod index c93b8a0..11170a1 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/kardianos/minwinsvc v1.0.0 github.com/mitchellh/mapstructure v1.4.1 github.com/vishvananda/netlink v1.1.0 - golang.org/x/mobile v0.0.0-20220112015953-858099ff7816 + golang.org/x/mobile v0.0.0-20220722155234-aaac322e2105 golang.org/x/net v0.0.0-20211101193420-4a448f8816b3 golang.org/x/sys v0.0.0-20211102192858-4dd72447c267 golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b diff --git a/go.sum b/go.sum index c87112f..0fc5cad 100644 --- a/go.sum +++ b/go.sum @@ -52,6 +52,8 @@ golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+o golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20220112015953-858099ff7816 h1:jhDgkcu3yQ4tasBZ+1YwDmK7eFmuVf1w1k+NGGGxfmE= golang.org/x/mobile v0.0.0-20220112015953-858099ff7816/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ= +golang.org/x/mobile v0.0.0-20220722155234-aaac322e2105 h1:3vUV5x5+3LfQbgk7paCM6INOaJG9xXQbn79xoNkwfIk= +golang.org/x/mobile v0.0.0-20220722155234-aaac322e2105/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= diff --git a/src/core/api.go b/src/core/api.go index 30e7e0f..3ab26ee 100644 --- a/src/core/api.go +++ b/src/core/api.go @@ -2,6 +2,8 @@ package core import ( "crypto/ed25519" + "sync/atomic" + "time" //"encoding/hex" "encoding/json" @@ -19,14 +21,13 @@ import ( //"github.com/Arceliar/phony" ) -type Self struct { +type SelfInfo struct { Key ed25519.PublicKey Root ed25519.PublicKey Coords []uint64 } -/* -type Peer struct { +type PeerInfo struct { Key ed25519.PublicKey Root ed25519.PublicKey Coords []uint64 @@ -36,25 +37,24 @@ type Peer struct { TXBytes uint64 Uptime time.Duration } -*/ -type DHTEntry struct { +type DHTEntryInfo struct { Key ed25519.PublicKey Port uint64 Rest uint64 } -type PathEntry struct { +type PathEntryInfo struct { Key ed25519.PublicKey Path []uint64 } -type Session struct { +type SessionInfo struct { Key ed25519.PublicKey } -func (c *Core) GetSelf() Self { - var self Self +func (c *Core) GetSelf() SelfInfo { + var self SelfInfo s := c.PacketConn.PacketConn.Debug.GetSelf() self.Key = s.Key self.Root = s.Root @@ -62,9 +62,8 @@ func (c *Core) GetSelf() Self { return self } -/* -func (c *Core) GetPeers() []Peer { - var peers []Peer +func (c *Core) GetPeers() []PeerInfo { + var peers []PeerInfo names := make(map[net.Conn]string) c.links.mutex.Lock() for _, info := range c.links.links { @@ -73,7 +72,7 @@ func (c *Core) GetPeers() []Peer { c.links.mutex.Unlock() ps := c.PacketConn.PacketConn.Debug.GetPeers() for _, p := range ps { - var info Peer + var info PeerInfo info.Key = p.Key info.Root = p.Root info.Coords = p.Coords @@ -91,13 +90,12 @@ func (c *Core) GetPeers() []Peer { } return peers } -*/ -func (c *Core) GetDHT() []DHTEntry { - var dhts []DHTEntry +func (c *Core) GetDHT() []DHTEntryInfo { + var dhts []DHTEntryInfo ds := c.PacketConn.PacketConn.Debug.GetDHT() for _, d := range ds { - var info DHTEntry + var info DHTEntryInfo info.Key = d.Key info.Port = d.Port info.Rest = d.Rest @@ -106,11 +104,11 @@ func (c *Core) GetDHT() []DHTEntry { return dhts } -func (c *Core) GetPaths() []PathEntry { - var paths []PathEntry +func (c *Core) GetPaths() []PathEntryInfo { + var paths []PathEntryInfo ps := c.PacketConn.PacketConn.Debug.GetPaths() for _, p := range ps { - var info PathEntry + var info PathEntryInfo info.Key = p.Key info.Path = p.Path paths = append(paths, info) @@ -118,11 +116,11 @@ func (c *Core) GetPaths() []PathEntry { return paths } -func (c *Core) GetSessions() []Session { - var sessions []Session +func (c *Core) GetSessions() []SessionInfo { + var sessions []SessionInfo ss := c.PacketConn.Debug.GetSessions() for _, s := range ss { - var info Session + var info SessionInfo info.Key = s.Key sessions = append(sessions, info) } diff --git a/src/core/core.go b/src/core/core.go index df3888a..f41b653 100644 --- a/src/core/core.go +++ b/src/core/core.go @@ -15,7 +15,6 @@ import ( "github.com/Arceliar/phony" "github.com/gologme/log" - "github.com/yggdrasil-network/yggdrasil-go/src/crypto" "github.com/yggdrasil-network/yggdrasil-go/src/version" //"github.com/yggdrasil-network/yggdrasil-go/src/crypto" ) @@ -61,6 +60,9 @@ func New(secret ed25519.PrivateKey, opts ...SetupOption) (*Core, error) { if c.PacketConn, err = iwe.NewPacketConn(c.secret); err != nil { return nil, fmt.Errorf("error creating encryption: %w", err) } + c.config._peers = map[Peer]struct{}{} + c.config._listeners = map[ListenAddress]struct{}{} + c.config._allowedPublicKeys = map[[32]byte]struct{}{} for _, opt := range opts { c._applyOption(opt) } @@ -101,7 +103,7 @@ func (c *Core) _applyOption(opt SetupOption) { case IfMTU: c.config.ifmtu = v case AllowedPublicKey: - pk := crypto.SigPubKey{} + pk := [32]byte{} copy(pk[:], v) c.config._allowedPublicKeys[pk] = struct{}{} } diff --git a/src/core/core_test.go b/src/core/core_test.go index fcfe2e3..823e5e9 100644 --- a/src/core/core_test.go +++ b/src/core/core_test.go @@ -2,6 +2,7 @@ package core import ( "bytes" + "crypto/ed25519" "math/rand" "net/url" "os" @@ -9,21 +10,8 @@ import ( "time" "github.com/gologme/log" - - "github.com/yggdrasil-network/yggdrasil-go/src/config" - "github.com/yggdrasil-network/yggdrasil-go/src/defaults" ) -// GenerateConfig produces default configuration with suitable modifications for tests. -func GenerateConfig() *config.NodeConfig { - cfg := defaults.GenerateConfig() - cfg.AdminListen = "none" - cfg.Listen = []string{"tcp://127.0.0.1:0"} - cfg.IfName = "none" - - return cfg -} - // GetLoggerWithPrefix creates a new logger instance with prefix. // If verbose is set to true, three log levels are enabled: "info", "warn", "error". func GetLoggerWithPrefix(prefix string, verbose bool) *log.Logger { @@ -40,13 +28,18 @@ func GetLoggerWithPrefix(prefix string, verbose bool) *log.Logger { // CreateAndConnectTwo creates two nodes. nodeB connects to nodeA. // Verbosity flag is passed to logger. func CreateAndConnectTwo(t testing.TB, verbose bool) (nodeA *Core, nodeB *Core) { - nodeA = new(Core) - if err := nodeA.Start(GenerateConfig(), GetLoggerWithPrefix("A: ", verbose)); err != nil { + var err error + var skA, skB ed25519.PrivateKey + if _, skA, err = ed25519.GenerateKey(nil); err != nil { t.Fatal(err) } - - nodeB = new(Core) - if err := nodeB.Start(GenerateConfig(), GetLoggerWithPrefix("B: ", verbose)); err != nil { + if _, skB, err = ed25519.GenerateKey(nil); err != nil { + t.Fatal(err) + } + if nodeA, err = New(skA, ListenAddress("tcp://127.0.0.1:0"), IfName("none")); err != nil { + t.Fatal(err) + } + if nodeB, err = New(skB, ListenAddress("tcp://127.0.0.1:0"), IfName("none")); err != nil { t.Fatal(err) } diff --git a/src/core/link.go b/src/core/link.go index 0b7e50a..099a8af 100644 --- a/src/core/link.go +++ b/src/core/link.go @@ -17,6 +17,7 @@ import ( "sync/atomic" + "github.com/Arceliar/phony" "github.com/yggdrasil-network/yggdrasil-go/src/address" "github.com/yggdrasil-network/yggdrasil-go/src/util" "golang.org/x/net/proxy" @@ -62,7 +63,14 @@ func (l *links) init(c *Core) error { l.mutex.Unlock() l.stopped = make(chan struct{}) - if err := l.tcp.init(l); err != nil { + var listeners []ListenAddress + phony.Block(c, func() { + listeners = make([]ListenAddress, 0, len(c.config._listeners)) + for listener := range c.config._listeners { + listeners = append(listeners, listener) + } + }) + if err := l.tcp.init(l, listeners); err != nil { c.log.Errorln("Failed to start TCP interface") return err } @@ -71,10 +79,6 @@ func (l *links) init(c *Core) error { } func (l *links) call(u *url.URL, sintf string) error { - //u, err := url.Parse(uri) - //if err != nil { - // return fmt.Errorf("peer %s is not correctly formatted (%s)", uri, err) - //} tcpOpts := tcpOptions{} if pubkeys, ok := u.Query()["key"]; ok && len(pubkeys) > 0 { tcpOpts.pinnedEd25519Keys = make(map[keyArray]struct{})