5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-11-15 15:30:29 +00:00
yggdrasil-go/src/yggdrasil/metadata.go

125 lines
3.0 KiB
Go
Raw Normal View History

2018-12-15 00:48:27 +00:00
package yggdrasil
import (
"sync"
"time"
)
type metadata struct {
core *Core
myMetadata metadataPayload
myMetadataMutex sync.RWMutex
callbacks map[boxPubKey]metadataCallback
2018-12-15 10:39:31 +00:00
callbacksMutex sync.Mutex
2018-12-15 00:48:27 +00:00
cache map[boxPubKey]metadataPayload
2018-12-15 10:39:31 +00:00
cacheMutex sync.RWMutex
2018-12-15 00:48:27 +00:00
}
type metadataPayload []byte
type metadataCallback struct {
call func(meta *metadataPayload)
created time.Time
}
// Initialises the metadata cache/callback stuff
func (m *metadata) init(core *Core) {
m.core = core
m.callbacks = make(map[boxPubKey]metadataCallback)
m.cache = make(map[boxPubKey]metadataPayload)
go func() {
for {
for boxPubKey, callback := range m.callbacks {
if time.Since(callback.created) > time.Minute {
delete(m.callbacks, boxPubKey)
}
}
time.Sleep(time.Second * 5)
}
}()
}
2018-12-15 10:39:31 +00:00
// Add a callback
func (m *metadata) addCallback(sender boxPubKey, call func(meta *metadataPayload)) {
m.callbacksMutex.Lock()
defer m.callbacksMutex.Unlock()
m.callbacks[sender] = metadataCallback{
created: time.Now(),
call: call,
}
}
2018-12-15 00:48:27 +00:00
// Handles the callback, if there is one
func (m *metadata) callback(sender boxPubKey, meta metadataPayload) {
2018-12-15 10:39:31 +00:00
m.callbacksMutex.Lock()
defer m.callbacksMutex.Unlock()
2018-12-15 00:48:27 +00:00
if callback, ok := m.callbacks[sender]; ok {
callback.call(&meta)
delete(m.callbacks, sender)
}
}
// Get the metadata
func (m *metadata) getMetadata() metadataPayload {
m.myMetadataMutex.RLock()
defer m.myMetadataMutex.RUnlock()
return m.myMetadata
}
// Set the metadata
func (m *metadata) setMetadata(meta metadataPayload) {
m.myMetadataMutex.Lock()
defer m.myMetadataMutex.Unlock()
m.myMetadata = meta
}
2018-12-15 10:39:31 +00:00
// Add metadata into the cache for a node
func (m *metadata) addCachedMetadata(key boxPubKey, payload metadataPayload) {
m.cacheMutex.Lock()
defer m.cacheMutex.Unlock()
m.cache[key] = payload
}
// Get a metadata entry from the cache
func (m *metadata) getCachedMetadata(key boxPubKey) metadataPayload {
m.cacheMutex.RLock()
defer m.cacheMutex.RUnlock()
if meta, ok := m.cache[key]; ok {
return meta
}
return metadataPayload{}
}
2018-12-15 00:48:27 +00:00
// Handles a meta request/response.
func (m *metadata) handleMetadata(meta *sessionMeta) {
if meta.IsResponse {
2018-12-15 10:39:31 +00:00
m.callback(meta.SendPermPub, meta.Metadata)
m.addCachedMetadata(meta.SendPermPub, meta.Metadata)
2018-12-15 00:48:27 +00:00
} else {
m.sendMetadata(meta.SendPermPub, meta.SendCoords, true)
}
}
// Send metadata request or response
func (m *metadata) sendMetadata(key boxPubKey, coords []byte, isResponse bool) {
table := m.core.switchTable.table.Load().(lookupTable)
meta := sessionMeta{
SendCoords: table.self.getCoords(),
IsResponse: isResponse,
Metadata: m.core.metadata.getMetadata(),
}
bs := meta.encode()
shared := m.core.sessions.getSharedKey(&m.core.boxPriv, &key)
payload, nonce := boxSeal(shared, bs, nil)
p := wire_protoTrafficPacket{
Coords: coords,
ToKey: key,
FromKey: m.core.boxPub,
Nonce: *nonce,
Payload: payload,
}
packet := p.encode()
m.core.router.out(packet)
}