mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 03:05:07 +03:00 
			
		
		
		
	Wrap the metadata with a mutex to guarantee thread safety across core/router/sessions
This commit is contained in:
		
							parent
							
								
									97464feba9
								
							
						
					
					
						commit
						042a3400fe
					
				
					 4 changed files with 40 additions and 14 deletions
				
			
		| 
						 | 
				
			
			@ -80,11 +80,6 @@ func GetBuildVersion() string {
 | 
			
		|||
	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
 | 
			
		||||
// through the provided log.Logger. The started stack will include TCP and UDP
 | 
			
		||||
// 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)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
// useful if you want to redirect the output later.
 | 
			
		||||
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.subnet = *address_subnetForNodeID(&r.core.dht.nodeID)
 | 
			
		||||
	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)
 | 
			
		||||
	r.core.sessions.myMetadataMutex.RUnlock()
 | 
			
		||||
	p.out = func(packet []byte) {
 | 
			
		||||
		// This is to make very sure it never blocks
 | 
			
		||||
		select {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ package yggdrasil
 | 
			
		|||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -128,7 +129,8 @@ type sessions struct {
 | 
			
		|||
	sessionFirewallWhitelist            []string
 | 
			
		||||
	sessionFirewallBlacklist            []string
 | 
			
		||||
	// Metadata for this node
 | 
			
		||||
	myMetadata metadata
 | 
			
		||||
	myMetadata      metadata
 | 
			
		||||
	myMetadataMutex sync.RWMutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Initializes the session struct.
 | 
			
		||||
| 
						 | 
				
			
			@ -143,8 +145,17 @@ func (ss *sessions) init(core *Core) {
 | 
			
		|||
	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) {
 | 
			
		||||
	ss.myMetadataMutex.Lock()
 | 
			
		||||
	defer ss.myMetadataMutex.Unlock()
 | 
			
		||||
	ss.myMetadata = meta
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -485,18 +496,23 @@ func (ss *sessions) handlePing(ping *sessionPing) {
 | 
			
		|||
		bs, sinfo.packet = sinfo.packet, nil
 | 
			
		||||
		ss.core.router.sendPacket(bs)
 | 
			
		||||
	}
 | 
			
		||||
	if time.Since(sinfo.metaResTime).Minutes() > 15 {
 | 
			
		||||
		if time.Since(sinfo.metaReqTime).Minutes() > 1 {
 | 
			
		||||
			ss.sendMeta(sinfo, false)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// This requests metadata from the remote side fairly quickly after
 | 
			
		||||
	// establishing the session, and if other time constraints apply (no more
 | 
			
		||||
	// 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) {
 | 
			
		||||
	ss.myMetadataMutex.RLock()
 | 
			
		||||
	meta := sessionMeta{
 | 
			
		||||
		IsResponse: isResponse,
 | 
			
		||||
		Metadata:   ss.myMetadata,
 | 
			
		||||
	}
 | 
			
		||||
	ss.myMetadataMutex.RUnlock()
 | 
			
		||||
	bs := meta.encode()
 | 
			
		||||
	shared := ss.getSharedKey(&ss.core.boxPriv, &sinfo.theirPermPub)
 | 
			
		||||
	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 {
 | 
			
		||||
	var pTypeVal uint64
 | 
			
		||||
	if p.IsResponse {
 | 
			
		||||
| 
						 | 
				
			
			@ -370,7 +370,7 @@ func (p *sessionMeta) encode() []byte {
 | 
			
		|||
	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 {
 | 
			
		||||
	var pType uint64
 | 
			
		||||
	switch {
 | 
			
		||||
| 
						 | 
				
			
			@ -380,6 +380,9 @@ func (p *sessionMeta) decode(bs []byte) bool {
 | 
			
		|||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if p.IsResponse = pType == wire_SessionMetaResponse; p.IsResponse {
 | 
			
		||||
		if len(bs) == 0 {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		p.Metadata = make(metadata, len(bs))
 | 
			
		||||
		if !wire_chop_slice(p.Metadata[:], &bs) {
 | 
			
		||||
			return false
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue