github.com/yggdrasil-network/yggdrasil-go@v0.5.6/src/admin/options.go (about) 1 package admin 2 3 import ( 4 "crypto/ed25519" 5 "encoding/hex" 6 "encoding/json" 7 "net" 8 "sync" 9 "time" 10 11 "github.com/Arceliar/ironwood/network" 12 13 "github.com/yggdrasil-network/yggdrasil-go/src/address" 14 ) 15 16 func (c *AdminSocket) _applyOption(opt SetupOption) { 17 switch v := opt.(type) { 18 case ListenAddress: 19 c.config.listenaddr = v 20 case LogLookups: 21 c.logLookups() 22 } 23 } 24 25 type SetupOption interface { 26 isSetupOption() 27 } 28 29 type ListenAddress string 30 31 func (a ListenAddress) isSetupOption() {} 32 33 type LogLookups struct{} 34 35 func (l LogLookups) isSetupOption() {} 36 37 func (a *AdminSocket) logLookups() { 38 type resi struct { 39 Address string `json:"addr"` 40 Key string `json:"key"` 41 Path []uint64 `json:"path"` 42 Time int64 `json:"time"` 43 } 44 type res struct { 45 Infos []resi `json:"infos"` 46 } 47 type info struct { 48 path []uint64 49 time time.Time 50 } 51 type edk [ed25519.PublicKeySize]byte 52 infos := make(map[edk]info) 53 var m sync.Mutex 54 a.core.PacketConn.PacketConn.Debug.SetDebugLookupLogger(func(l network.DebugLookupInfo) { 55 var k edk 56 copy(k[:], l.Key[:]) 57 m.Lock() 58 infos[k] = info{path: l.Path, time: time.Now()} 59 m.Unlock() 60 }) 61 _ = a.AddHandler( 62 "lookups", "Dump a record of lookups received in the past hour", []string{}, 63 func(in json.RawMessage) (interface{}, error) { 64 m.Lock() 65 rs := make([]resi, 0, len(infos)) 66 for k, v := range infos { 67 if time.Since(v.time) > 24*time.Hour { 68 // TODO? automatic cleanup, so we don't need to call lookups periodically to prevent leaks 69 delete(infos, k) 70 } 71 a := address.AddrForKey(ed25519.PublicKey(k[:])) 72 addr := net.IP(a[:]).String() 73 rs = append(rs, resi{Address: addr, Key: hex.EncodeToString(k[:]), Path: v.path, Time: v.time.Unix()}) 74 } 75 m.Unlock() 76 return &res{Infos: rs}, nil 77 }, 78 ) 79 }