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

View File

@ -2,6 +2,7 @@ package config
// 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 {
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."` 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."` 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."` 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. // object for each Yggdrasil node you plan to run.
type Core struct { type Core struct {
// This is the main data structure that holds everything else for a node // This is the main data structure that holds everything else for a node
boxPub boxPubKey boxPub boxPubKey
boxPriv boxPrivKey boxPriv boxPrivKey
sigPub sigPubKey sigPub sigPubKey
sigPriv sigPrivKey sigPriv sigPrivKey
switchTable switchTable friendlyName string
peers peers switchTable switchTable
sigs sigManager peers peers
sessions sessions sigs sigManager
router router sessions sessions
dht dht router router
tun tunDevice dht dht
admin admin tun tunDevice
searches searches admin admin
multicast multicast searches searches
tcp tcpInterface multicast multicast
log *log.Logger tcp tcpInterface
ifceExpr []*regexp.Regexp // the zone of link-local IPv6 peers must match this log *log.Logger
ifceExpr []*regexp.Regexp // the zone of link-local IPv6 peers must match this
} }
func (c *Core) init(bpub *boxPubKey, func (c *Core) init(bpub *boxPubKey,
bpriv *boxPrivKey, bpriv *boxPrivKey,
spub *sigPubKey, spub *sigPubKey,
spriv *sigPrivKey) { spriv *sigPrivKey,
friendlyname string) {
// TODO separate init and start functions // TODO separate init and start functions
// Init sets up structs // Init sets up structs
// Start launches goroutines that depend on structs being set up // 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.boxPub, c.boxPriv = *bpub, *bpriv
c.sigPub, c.sigPriv = *spub, *spriv c.sigPub, c.sigPriv = *spub, *spriv
c.friendlyName = friendlyname
c.admin.core = c c.admin.core = c
c.sigs.init() c.sigs.init()
c.searches.init(c) c.searches.init(c)
@ -61,6 +64,14 @@ func (c *Core) init(bpub *boxPubKey,
c.tun.init(c) 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 // Starts up Yggdrasil using the provided NodeConfig, and outputs debug logging
// through the provided log.Logger. The started stack will include TCP and UDP // through the provided log.Logger. The started stack will include TCP and UDP
// sockets, a multicast discovery socket, an admin socket, router, switch and // 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(sigPub[:], sigPubHex)
copy(sigPriv[:], sigPrivHex) copy(sigPriv[:], sigPrivHex)
c.init(&boxPub, &boxPriv, &sigPub, &sigPriv) c.init(&boxPub, &boxPriv, &sigPub, &sigPriv, nc.FriendlyName)
c.admin.init(c, nc.AdminListen) c.admin.init(c, nc.AdminListen)
if err := c.tcp.init(c, nc.Listen, nc.ReadTimeout); err != nil { 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 bytesSent uint64 // To track bandwidth usage for getPeers
bytesRecvd 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 // BUG: sync/atomic, 32 bit platforms need the above to be the first element
core *Core core *Core
port switchPort port switchPort
box boxPubKey box boxPubKey
sig sigPubKey sig sigPubKey
shared boxSharedKey shared boxSharedKey
linkShared boxSharedKey linkShared boxSharedKey
firstSeen time.Time // To track uptime for getPeers endpoint string
linkOut (chan []byte) // used for protocol traffic (to bypass queues) friendlyName string
doSend (chan struct{}) // tell the linkLoop to send a switchMsg firstSeen time.Time // To track uptime for getPeers
dinfo *dhtInfo // used to keep the DHT working linkOut (chan []byte) // used for protocol traffic (to bypass queues)
out func([]byte) // Set up by whatever created the peers struct, used to send packets to other nodes doSend (chan struct{}) // tell the linkLoop to send a switchMsg
close func() // Called when a peer is removed, to close the underlying connection, or via admin api 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. // 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() now := time.Now()
p := peer{box: *box, p := peer{box: *box,
sig: *sig, sig: *sig,
shared: *getSharedKey(&ps.core.boxPriv, box), shared: *getSharedKey(&ps.core.boxPriv, box),
linkShared: *linkShared, linkShared: *linkShared,
firstSeen: now, endpoint: endpoint,
doSend: make(chan struct{}, 1), friendlyName: friendlyname,
core: ps.core} firstSeen: now,
doSend: make(chan struct{}, 1),
core: ps.core}
ps.mutex.Lock() ps.mutex.Lock()
defer ps.mutex.Unlock() defer ps.mutex.Unlock()
oldPorts := ps.getPorts() oldPorts := ps.getPorts()

View File

@ -47,7 +47,7 @@ func (r *router) init(core *Core) {
r.core = core r.core = core
r.addr = *address_addrForNodeID(&r.core.dht.nodeID) r.addr = *address_addrForNodeID(&r.core.dht.nodeID)
in := make(chan []byte, 32) // TODO something better than this... 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) { p.out = func(packet []byte) {
// This is to make very sure it never blocks // This is to make very sure it never blocks
select { 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 // Note that multiple connections to the same node are allowed
// E.g. over different interfaces // 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) p.linkOut = make(chan []byte, 1)
in := func(bs []byte) { in := func(bs []byte) {
p.handlePacket(bs) p.handlePacket(bs)

View File

@ -155,6 +155,12 @@ func main() {
minutes := uint(preformatted.(float64)/60) % 60 minutes := uint(preformatted.(float64)/60) % 60
hours := uint(preformatted.(float64) / 60 / 60) hours := uint(preformatted.(float64) / 60 / 60)
formatted = fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds) 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: default:
formatted = fmt.Sprint(preformatted) formatted = fmt.Sprint(preformatted)
} }