diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go index e773630..7c9ed1b 100644 --- a/src/yggdrasil/admin.go +++ b/src/yggdrasil/admin.go @@ -829,16 +829,13 @@ func (a *admin) admin_getMeta(keyString, coordString string) (metadataPayload, e } response := make(chan *metadataPayload, 1) sendMetaRequest := func() { - a.core.metadata.callbacks[key] = metadataCallback{ - created: time.Now(), - call: func(meta *metadataPayload) { - defer func() { recover() }() - select { - case response <- meta: - default: - } - }, - } + a.core.metadata.addCallback(key, func(meta *metadataPayload) { + defer func() { recover() }() + select { + case response <- meta: + default: + } + }) a.core.metadata.sendMetadata(key, coords, false) } a.core.router.doAdmin(sendMetaRequest) diff --git a/src/yggdrasil/metadata.go b/src/yggdrasil/metadata.go index 7f607ed..19393b1 100644 --- a/src/yggdrasil/metadata.go +++ b/src/yggdrasil/metadata.go @@ -10,7 +10,9 @@ type metadata struct { myMetadata metadataPayload myMetadataMutex sync.RWMutex callbacks map[boxPubKey]metadataCallback + callbacksMutex sync.Mutex cache map[boxPubKey]metadataPayload + cacheMutex sync.RWMutex } type metadataPayload []byte @@ -38,8 +40,20 @@ func (m *metadata) init(core *Core) { }() } +// 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, + } +} + // Handles the callback, if there is one func (m *metadata) callback(sender boxPubKey, meta metadataPayload) { + m.callbacksMutex.Lock() + defer m.callbacksMutex.Unlock() if callback, ok := m.callbacks[sender]; ok { callback.call(&meta) delete(m.callbacks, sender) @@ -60,10 +74,28 @@ func (m *metadata) setMetadata(meta metadataPayload) { m.myMetadata = meta } +// 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{} +} + // Handles a meta request/response. func (m *metadata) handleMetadata(meta *sessionMeta) { if meta.IsResponse { - m.core.metadata.callback(meta.SendPermPub, meta.Metadata) + m.callback(meta.SendPermPub, meta.Metadata) + m.addCachedMetadata(meta.SendPermPub, meta.Metadata) } else { m.sendMetadata(meta.SendPermPub, meta.SendCoords, true) }