Add FriendlyName option, show friendly name and real endpoint in admin socket/yggdrasilctl

This commit is contained in:
Neil Alexander 2018-10-21 17:57:48 +01:00
parent a9f72a6ee1
commit b809adf981
No known key found for this signature in database
GPG Key ID: A02A2019A2BB0944
7 changed files with 67 additions and 40 deletions

View File

@ -470,6 +470,7 @@ func (a *admin) getData_getSelf() *admin_nodeInfo {
{"ip", a.core.GetAddress().String()},
{"subnet", a.core.GetSubnet().String()},
{"coords", fmt.Sprint(coords)},
{"friendly_name", a.core.friendlyName},
}
return &self
}
@ -492,6 +493,8 @@ func (a *admin) getData_getPeers() []admin_nodeInfo {
{"uptime", int(time.Since(p.firstSeen).Seconds())},
{"bytes_sent", atomic.LoadUint64(&p.bytesSent)},
{"bytes_recvd", atomic.LoadUint64(&p.bytesRecvd)},
{"endpoint", p.endpoint},
{"friendly_name", p.friendlyName},
}
peerInfos = append(peerInfos, info)
}
@ -516,6 +519,8 @@ func (a *admin) getData_getSwitchPeers() []admin_nodeInfo {
{"port", elem.port},
{"bytes_sent", atomic.LoadUint64(&peer.bytesSent)},
{"bytes_recvd", atomic.LoadUint64(&peer.bytesRecvd)},
{"endpoint", peer.endpoint},
{"friendly_name", peer.friendlyName},
}
peerInfos = append(peerInfos, info)
}

View File

@ -2,6 +2,7 @@ package config
// NodeConfig defines all configuration values needed to run a signle yggdrasil node
type NodeConfig struct {
FriendlyName string `comment:"Friendly name for this node. It is visible to direct peers."`
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."`
Peers []string `comment:"List of connection strings for static peers in URI format, i.e.\ntcp://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j."`

View File

@ -16,29 +16,31 @@ import (
// object for each Yggdrasil node you plan to run.
type Core struct {
// This is the main data structure that holds everything else for a node
boxPub boxPubKey
boxPriv boxPrivKey
sigPub sigPubKey
sigPriv sigPrivKey
switchTable switchTable
peers peers
sigs sigManager
sessions sessions
router router
dht dht
tun tunDevice
admin admin
searches searches
multicast multicast
tcp tcpInterface
log *log.Logger
ifceExpr []*regexp.Regexp // the zone of link-local IPv6 peers must match this
boxPub boxPubKey
boxPriv boxPrivKey
sigPub sigPubKey
sigPriv sigPrivKey
friendlyName string
switchTable switchTable
peers peers
sigs sigManager
sessions sessions
router router
dht dht
tun tunDevice
admin admin
searches searches
multicast multicast
tcp tcpInterface
log *log.Logger
ifceExpr []*regexp.Regexp // the zone of link-local IPv6 peers must match this
}
func (c *Core) init(bpub *boxPubKey,
bpriv *boxPrivKey,
spub *sigPubKey,
spriv *sigPrivKey) {
spriv *sigPrivKey,
friendlyname string) {
// TODO separate init and start functions
// Init sets up structs
// Start launches goroutines that depend on structs being set up
@ -49,6 +51,7 @@ func (c *Core) init(bpub *boxPubKey,
}
c.boxPub, c.boxPriv = *bpub, *bpriv
c.sigPub, c.sigPriv = *spub, *spriv
c.friendlyName = friendlyname
c.admin.core = c
c.sigs.init()
c.searches.init(c)
@ -61,6 +64,14 @@ func (c *Core) init(bpub *boxPubKey,
c.tun.init(c)
}
// Gets the friendly name of this node, as specified in the NodeConfig.
func (c *Core) GetFriendlyName() string {
if c.friendlyName == "" {
return "(none)"
}
return c.friendlyName
}
// Starts up Yggdrasil using the provided NodeConfig, and outputs debug logging
// through the provided log.Logger. The started stack will include TCP and UDP
// sockets, a multicast discovery socket, an admin socket, router, switch and
@ -94,7 +105,7 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
copy(sigPub[:], sigPubHex)
copy(sigPriv[:], sigPrivHex)
c.init(&boxPub, &boxPriv, &sigPub, &sigPriv)
c.init(&boxPub, &boxPriv, &sigPub, &sigPriv, nc.FriendlyName)
c.admin.init(c, nc.AdminListen)
if err := c.tcp.init(c, nc.Listen, nc.ReadTimeout); err != nil {

View File

@ -79,30 +79,34 @@ type peer struct {
bytesSent uint64 // To track bandwidth usage for getPeers
bytesRecvd uint64 // To track bandwidth usage for getPeers
// BUG: sync/atomic, 32 bit platforms need the above to be the first element
core *Core
port switchPort
box boxPubKey
sig sigPubKey
shared boxSharedKey
linkShared boxSharedKey
firstSeen time.Time // To track uptime for getPeers
linkOut (chan []byte) // used for protocol traffic (to bypass queues)
doSend (chan struct{}) // tell the linkLoop to send a switchMsg
dinfo *dhtInfo // used to keep the DHT working
out func([]byte) // Set up by whatever created the peers struct, used to send packets to other nodes
close func() // Called when a peer is removed, to close the underlying connection, or via admin api
core *Core
port switchPort
box boxPubKey
sig sigPubKey
shared boxSharedKey
linkShared boxSharedKey
endpoint string
friendlyName string
firstSeen time.Time // To track uptime for getPeers
linkOut (chan []byte) // used for protocol traffic (to bypass queues)
doSend (chan struct{}) // tell the linkLoop to send a switchMsg
dinfo *dhtInfo // used to keep the DHT working
out func([]byte) // Set up by whatever created the peers struct, used to send packets to other nodes
close func() // Called when a peer is removed, to close the underlying connection, or via admin api
}
// Creates a new peer with the specified box, sig, and linkShared keys, using the lowest unocupied port number.
func (ps *peers) newPeer(box *boxPubKey, sig *sigPubKey, linkShared *boxSharedKey) *peer {
func (ps *peers) newPeer(box *boxPubKey, sig *sigPubKey, linkShared *boxSharedKey, endpoint string, friendlyname string) *peer {
now := time.Now()
p := peer{box: *box,
sig: *sig,
shared: *getSharedKey(&ps.core.boxPriv, box),
linkShared: *linkShared,
firstSeen: now,
doSend: make(chan struct{}, 1),
core: ps.core}
sig: *sig,
shared: *getSharedKey(&ps.core.boxPriv, box),
linkShared: *linkShared,
endpoint: endpoint,
friendlyName: friendlyname,
firstSeen: now,
doSend: make(chan struct{}, 1),
core: ps.core}
ps.mutex.Lock()
defer ps.mutex.Unlock()
oldPorts := ps.getPorts()

View File

@ -47,7 +47,7 @@ func (r *router) init(core *Core) {
r.core = core
r.addr = *address_addrForNodeID(&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{})
p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub, &boxSharedKey{}, "(self)", r.core.GetFriendlyName())
p.out = func(packet []byte) {
// This is to make very sure it never blocks
select {

View File

@ -287,7 +287,7 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
}()
// Note that multiple connections to the same node are allowed
// E.g. over different interfaces
p := iface.core.peers.newPeer(&info.box, &info.sig, getSharedKey(myLinkPriv, &meta.link))
p := iface.core.peers.newPeer(&info.box, &info.sig, getSharedKey(myLinkPriv, &meta.link), sock.RemoteAddr().String(), "(none)")
p.linkOut = make(chan []byte, 1)
in := func(bs []byte) {
p.handlePacket(bs)

View File

@ -155,6 +155,12 @@ func main() {
minutes := uint(preformatted.(float64)/60) % 60
hours := uint(preformatted.(float64) / 60 / 60)
formatted = fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
case "friendly_name":
if len(preformatted.(string)) > 32 {
formatted = fmt.Sprintf("%s...", preformatted.(string)[:32])
} else {
formatted = preformatted.(string)
}
default:
formatted = fmt.Sprint(preformatted)
}