5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-11-10 06:20:26 +00:00

Working metadata exchange

This commit is contained in:
Neil Alexander 2018-12-12 19:51:28 +00:00
parent 6200136fce
commit 97464feba9
No known key found for this signature in database
GPG Key ID: A02A2019A2BB0944
7 changed files with 22 additions and 58 deletions

View File

@ -2,7 +2,6 @@ package config
// NodeConfig defines all configuration values needed to run a signle yggdrasil node
type NodeConfig struct {
Metadata Metadata `comment:"Optional node metadata. Entirely optional but visible to all\npeers and nodes with open sessions."`
Listen string `comment:"Listen address for peer connections. Default is to listen for all\nTCP connections over IPv4 and IPv6 with a random port."`
AdminListen string `comment:"Listen address for admin connections. Default is to listen for local\nconnections either on TCP/9001 or a UNIX socket depending on your\nplatform. Use this value for yggdrasilctl -endpoint=X. To disable\nthe admin socket, use the value \"none\" instead."`
Peers []string `comment:"List of connection strings for static peers in URI format, e.g.\ntcp://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j."`
@ -20,6 +19,7 @@ type NodeConfig struct {
SessionFirewall SessionFirewall `comment:"The session firewall controls who can send/receive network traffic\nto/from. This is useful if you want to protect this node without\nresorting to using a real firewall. This does not affect traffic\nbeing routed via this node to somewhere else. Rules are prioritised as\nfollows: blacklist, whitelist, always allow outgoing, direct, remote."`
TunnelRouting TunnelRouting `comment:"Allow tunneling non-Yggdrasil traffic over Yggdrasil. This effectively\nallows you to use Yggdrasil to route to, or to bridge other networks,\nsimilar to a VPN tunnel. Tunnelling works between any two nodes and\ndoes not require them to be directly peered."`
SwitchOptions SwitchOptions `comment:"Advanced options for tuning the switch. Normally you will not need\nto edit these options."`
Metadata interface{} `comment:"Optional node metadata. Entirely optional but visible to all\npeers and nodes with open sessions."`
//Net NetConfig `comment:"Extended options for connecting to peers over other networks."`
}
@ -52,10 +52,3 @@ type TunnelRouting struct {
type SwitchOptions struct {
MaxTotalQueueSize uint64 `comment:"Maximum size of all switch queues combined (in bytes)."`
}
// Optional metadata - format subject to change
type Metadata struct {
Name string
Location string
Contact string
}

View File

@ -574,9 +574,6 @@ func (a *admin) getData_getSelf() *admin_nodeInfo {
{"ip", a.core.GetAddress().String()},
{"subnet", a.core.GetSubnet().String()},
{"coords", fmt.Sprint(coords)},
{"name", a.core.metadata.name},
{"location", a.core.metadata.location},
{"contact", a.core.metadata.contact},
}
if name := GetBuildName(); name != "unknown" {
self = append(self, admin_pair{"build_name", name})

View File

@ -23,7 +23,6 @@ type Core struct {
boxPriv boxPrivKey
sigPub sigPubKey
sigPriv sigPrivKey
metadata metadata
switchTable switchTable
peers peers
sessions sessions
@ -41,8 +40,7 @@ type Core struct {
func (c *Core) init(bpub *boxPubKey,
bpriv *boxPrivKey,
spub *sigPubKey,
spriv *sigPrivKey,
metadata metadata) {
spriv *sigPrivKey) {
// TODO separate init and start functions
// Init sets up structs
// Start launches goroutines that depend on structs being set up
@ -53,7 +51,6 @@ func (c *Core) init(bpub *boxPubKey,
}
c.boxPub, c.boxPriv = *bpub, *bpriv
c.sigPub, c.sigPriv = *spub, *spriv
c.metadata = metadata
c.admin.core = c
c.searches.init(c)
c.dht.init(c)
@ -85,7 +82,7 @@ func GetBuildVersion() string {
// Gets the friendly name of this node, as specified in the NodeConfig.
func (c *Core) GetMeta() metadata {
return c.metadata
return c.sessions.myMetadata
}
// Starts up Yggdrasil using the provided NodeConfig, and outputs debug logging
@ -129,13 +126,7 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
copy(sigPub[:], sigPubHex)
copy(sigPriv[:], sigPrivHex)
meta := metadata{
name: nc.Metadata.Name,
location: nc.Metadata.Location,
contact: nc.Metadata.Contact,
}
c.init(&boxPub, &boxPriv, &sigPub, &sigPriv, meta)
c.init(&boxPub, &boxPriv, &sigPub, &sigPriv)
c.admin.init(c, nc.AdminListen)
if err := c.tcp.init(c, nc.Listen, nc.ReadTimeout); err != nil {
@ -152,6 +143,7 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
return err
}
c.sessions.setMetadata(metadata("HIYA, THIS IS METADATA"))
c.sessions.setSessionFirewallState(nc.SessionFirewall.Enable)
c.sessions.setSessionFirewallDefaults(
nc.SessionFirewall.AllowFromDirect,

View File

@ -1,7 +0,0 @@
package yggdrasil
type metadata struct {
name string
location string
contact string
}

View File

@ -58,7 +58,7 @@ func (r *router) init(core *Core) {
r.addr = *address_addrForNodeID(&r.core.dht.nodeID)
r.subnet = *address_subnetForNodeID(&r.core.dht.nodeID)
in := make(chan []byte, 32) // TODO something better than this...
p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub, &boxSharedKey{}, "(self)", r.core.metadata)
p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub, &boxSharedKey{}, "(self)", r.core.sessions.myMetadata)
p.out = func(packet []byte) {
// This is to make very sure it never blocks
select {
@ -483,7 +483,6 @@ func (r *router) handleMeta(bs []byte, fromKey *boxPubKey) {
return
}
req.SendPermPub = *fromKey
r.core.log.Printf("handleMeta: %+v\n", req)
r.core.sessions.handleMeta(&req)
}

View File

@ -64,6 +64,8 @@ type sessionMeta struct {
Metadata metadata
}
type metadata []byte
// Updates session info in response to a ping, after checking that the ping is OK.
// Returns true if the session was updated, or false otherwise.
func (s *sessionInfo) update(p *sessionPing) bool {
@ -125,6 +127,8 @@ type sessions struct {
sessionFirewallAlwaysAllowsOutbound bool
sessionFirewallWhitelist []string
sessionFirewallBlacklist []string
// Metadata for this node
myMetadata metadata
}
// Initializes the session struct.
@ -139,6 +143,11 @@ func (ss *sessions) init(core *Core) {
ss.lastCleanup = time.Now()
}
// Enable or disable the session firewall
func (ss *sessions) setMetadata(meta metadata) {
ss.myMetadata = meta
}
// Enable or disable the session firewall
func (ss *sessions) setSessionFirewallState(enabled bool) {
ss.sessionFirewallEnabled = enabled
@ -486,11 +495,7 @@ func (ss *sessions) handlePing(ping *sessionPing) {
func (ss *sessions) sendMeta(sinfo *sessionInfo, isResponse bool) {
meta := sessionMeta{
IsResponse: isResponse,
Metadata: metadata{
name: "some.name.com", //[]byte(ss.core.friendlyName)[0:len(ss.core.friendlyName):32],
location: "Some Place",
contact: "someone@somewhere.com",
},
Metadata: ss.myMetadata,
}
bs := meta.encode()
shared := ss.getSharedKey(&ss.core.boxPriv, &sinfo.theirPermPub)
@ -504,10 +509,7 @@ func (ss *sessions) sendMeta(sinfo *sessionInfo, isResponse bool) {
}
packet := p.encode()
ss.core.router.out(packet)
if isResponse {
ss.core.log.Println("Sent meta response to", sinfo.theirAddr)
} else {
ss.core.log.Println("Sent meta request to", sinfo.theirAddr)
if !isResponse {
sinfo.metaReqTime = time.Now()
}
}
@ -526,14 +528,9 @@ func (ss *sessions) handleMeta(meta *sessionMeta) {
return
}
if meta.IsResponse {
ss.core.log.Println("Received meta response", string(meta.Metadata.name), "from", sinfo.theirAddr)
sinfo.theirMetadata = meta.Metadata
sinfo.metaResTime = time.Now()
ss.core.log.Println("- name:", meta.Metadata.name)
ss.core.log.Println("- contact:", meta.Metadata.contact)
ss.core.log.Println("- location:", meta.Metadata.location)
} else {
ss.core.log.Println("Received meta request", string(meta.Metadata.name), "from", sinfo.theirAddr)
ss.sendMeta(sinfo, true)
}
}

View File

@ -364,10 +364,8 @@ func (p *sessionMeta) encode() []byte {
pTypeVal = wire_SessionMetaRequest
}
bs := wire_encode_uint64(pTypeVal)
if p.IsResponse {
bs = append(bs, p.Metadata.name...)
bs = append(bs, p.Metadata.location...)
bs = append(bs, p.Metadata.contact...)
if pTypeVal == wire_SessionMetaResponse {
bs = append(bs, p.Metadata...)
}
return bs
}
@ -381,14 +379,9 @@ func (p *sessionMeta) decode(bs []byte) bool {
case pType != wire_SessionMetaRequest && pType != wire_SessionMetaResponse:
return false
}
p.IsResponse = pType == wire_SessionMetaResponse
if p.IsResponse {
switch {
case !wire_chop_slice([]byte(p.Metadata.name), &bs):
return false
case !wire_chop_slice([]byte(p.Metadata.location), &bs):
return false
case !wire_chop_slice([]byte(p.Metadata.contact), &bs):
if p.IsResponse = pType == wire_SessionMetaResponse; p.IsResponse {
p.Metadata = make(metadata, len(bs))
if !wire_chop_slice(p.Metadata[:], &bs) {
return false
}
}