mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-15 15:30:29 +00:00
93 lines
2.1 KiB
Go
93 lines
2.1 KiB
Go
package yggdrasil
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type metadata struct {
|
|
core *Core
|
|
myMetadata metadataPayload
|
|
myMetadataMutex sync.RWMutex
|
|
callbacks map[boxPubKey]metadataCallback
|
|
cache map[boxPubKey]metadataPayload
|
|
}
|
|
|
|
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)
|
|
}
|
|
}()
|
|
}
|
|
|
|
// Handles the callback, if there is one
|
|
func (m *metadata) callback(sender boxPubKey, meta metadataPayload) {
|
|
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
|
|
}
|
|
|
|
// Handles a meta request/response.
|
|
func (m *metadata) handleMetadata(meta *sessionMeta) {
|
|
if meta.IsResponse {
|
|
m.core.metadata.callback(meta.SendPermPub, meta.Metadata)
|
|
} 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)
|
|
}
|