mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-26 08:21:36 +00:00
Wrap the metadata with a mutex to guarantee thread safety across core/router/sessions
This commit is contained in:
parent
97464feba9
commit
042a3400fe
@ -80,11 +80,6 @@ func GetBuildVersion() string {
|
|||||||
return buildVersion
|
return buildVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the friendly name of this node, as specified in the NodeConfig.
|
|
||||||
func (c *Core) GetMeta() metadata {
|
|
||||||
return c.sessions.myMetadata
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
||||||
@ -245,6 +240,16 @@ func (c *Core) GetSubnet() *net.IPNet {
|
|||||||
return &net.IPNet{IP: subnet, Mask: net.CIDRMask(64, 128)}
|
return &net.IPNet{IP: subnet, Mask: net.CIDRMask(64, 128)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets the node metadata.
|
||||||
|
func (c *Core) GetMetadata() metadata {
|
||||||
|
return c.sessions.getMetadata()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the node metadata.
|
||||||
|
func (c *Core) SetMetadata(meta metadata) {
|
||||||
|
c.sessions.setMetadata(meta)
|
||||||
|
}
|
||||||
|
|
||||||
// Sets the output logger of the Yggdrasil node after startup. This may be
|
// Sets the output logger of the Yggdrasil node after startup. This may be
|
||||||
// useful if you want to redirect the output later.
|
// useful if you want to redirect the output later.
|
||||||
func (c *Core) SetLogger(log *log.Logger) {
|
func (c *Core) SetLogger(log *log.Logger) {
|
||||||
|
@ -58,7 +58,9 @@ func (r *router) init(core *Core) {
|
|||||||
r.addr = *address_addrForNodeID(&r.core.dht.nodeID)
|
r.addr = *address_addrForNodeID(&r.core.dht.nodeID)
|
||||||
r.subnet = *address_subnetForNodeID(&r.core.dht.nodeID)
|
r.subnet = *address_subnetForNodeID(&r.core.dht.nodeID)
|
||||||
in := make(chan []byte, 32) // TODO something better than this...
|
in := make(chan []byte, 32) // TODO something better than this...
|
||||||
|
r.core.sessions.myMetadataMutex.RLock()
|
||||||
p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub, &boxSharedKey{}, "(self)", r.core.sessions.myMetadata)
|
p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub, &boxSharedKey{}, "(self)", r.core.sessions.myMetadata)
|
||||||
|
r.core.sessions.myMetadataMutex.RUnlock()
|
||||||
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 {
|
||||||
|
@ -7,6 +7,7 @@ package yggdrasil
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -129,6 +130,7 @@ type sessions struct {
|
|||||||
sessionFirewallBlacklist []string
|
sessionFirewallBlacklist []string
|
||||||
// Metadata for this node
|
// Metadata for this node
|
||||||
myMetadata metadata
|
myMetadata metadata
|
||||||
|
myMetadataMutex sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes the session struct.
|
// Initializes the session struct.
|
||||||
@ -143,8 +145,17 @@ func (ss *sessions) init(core *Core) {
|
|||||||
ss.lastCleanup = time.Now()
|
ss.lastCleanup = time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable or disable the session firewall
|
// Get the metadata
|
||||||
|
func (ss *sessions) getMetadata() metadata {
|
||||||
|
ss.myMetadataMutex.RLock()
|
||||||
|
defer ss.myMetadataMutex.RUnlock()
|
||||||
|
return ss.myMetadata
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the metadata
|
||||||
func (ss *sessions) setMetadata(meta metadata) {
|
func (ss *sessions) setMetadata(meta metadata) {
|
||||||
|
ss.myMetadataMutex.Lock()
|
||||||
|
defer ss.myMetadataMutex.Unlock()
|
||||||
ss.myMetadata = meta
|
ss.myMetadata = meta
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,18 +496,23 @@ func (ss *sessions) handlePing(ping *sessionPing) {
|
|||||||
bs, sinfo.packet = sinfo.packet, nil
|
bs, sinfo.packet = sinfo.packet, nil
|
||||||
ss.core.router.sendPacket(bs)
|
ss.core.router.sendPacket(bs)
|
||||||
}
|
}
|
||||||
if time.Since(sinfo.metaResTime).Minutes() > 15 {
|
// This requests metadata from the remote side fairly quickly after
|
||||||
if time.Since(sinfo.metaReqTime).Minutes() > 1 {
|
// establishing the session, and if other time constraints apply (no more
|
||||||
ss.sendMeta(sinfo, false)
|
// often than 15 minutes since receiving the last metadata)
|
||||||
}
|
//if time.Since(sinfo.metaResTime).Minutes() > 15 {
|
||||||
}
|
// if time.Since(sinfo.metaReqTime).Minutes() > 1 {
|
||||||
|
// ss.sendMeta(sinfo, false)
|
||||||
|
// }
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *sessions) sendMeta(sinfo *sessionInfo, isResponse bool) {
|
func (ss *sessions) sendMeta(sinfo *sessionInfo, isResponse bool) {
|
||||||
|
ss.myMetadataMutex.RLock()
|
||||||
meta := sessionMeta{
|
meta := sessionMeta{
|
||||||
IsResponse: isResponse,
|
IsResponse: isResponse,
|
||||||
Metadata: ss.myMetadata,
|
Metadata: ss.myMetadata,
|
||||||
}
|
}
|
||||||
|
ss.myMetadataMutex.RUnlock()
|
||||||
bs := meta.encode()
|
bs := meta.encode()
|
||||||
shared := ss.getSharedKey(&ss.core.boxPriv, &sinfo.theirPermPub)
|
shared := ss.getSharedKey(&ss.core.boxPriv, &sinfo.theirPermPub)
|
||||||
payload, nonce := boxSeal(shared, bs, nil)
|
payload, nonce := boxSeal(shared, bs, nil)
|
||||||
|
@ -355,7 +355,7 @@ func (p *sessionPing) decode(bs []byte) bool {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Encodes a sessionPing into its wire format.
|
// Encodes a sessionMeta into its wire format.
|
||||||
func (p *sessionMeta) encode() []byte {
|
func (p *sessionMeta) encode() []byte {
|
||||||
var pTypeVal uint64
|
var pTypeVal uint64
|
||||||
if p.IsResponse {
|
if p.IsResponse {
|
||||||
@ -370,7 +370,7 @@ func (p *sessionMeta) encode() []byte {
|
|||||||
return bs
|
return bs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decodes an encoded sessionPing into the struct, returning true if successful.
|
// Decodes an encoded sessionMeta into the struct, returning true if successful.
|
||||||
func (p *sessionMeta) decode(bs []byte) bool {
|
func (p *sessionMeta) decode(bs []byte) bool {
|
||||||
var pType uint64
|
var pType uint64
|
||||||
switch {
|
switch {
|
||||||
@ -380,6 +380,9 @@ func (p *sessionMeta) decode(bs []byte) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if p.IsResponse = pType == wire_SessionMetaResponse; p.IsResponse {
|
if p.IsResponse = pType == wire_SessionMetaResponse; p.IsResponse {
|
||||||
|
if len(bs) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
p.Metadata = make(metadata, len(bs))
|
p.Metadata = make(metadata, len(bs))
|
||||||
if !wire_chop_slice(p.Metadata[:], &bs) {
|
if !wire_chop_slice(p.Metadata[:], &bs) {
|
||||||
return false
|
return false
|
||||||
|
Loading…
Reference in New Issue
Block a user