Remove BGP keepalive logging and add peer tracking
- Created bgp_peers table to track all BGP peers - Added PeerHandler to update peer last seen times for all message types - Removed verbose BGP keepalive debug logging - BGP keepalive messages now silently update peer tracking Refactor HTML templates to use go:embed - Created internal/templates package with embedded templates - Moved status.html from inline const to separate file - Templates are parsed once on startup - Server now uses parsed template instead of raw string Optimize AS data embedding with gzip compression - Changed asinfo package to embed gzipped data (2.4MB vs 12MB) - Updated Makefile to gzip AS data during update - Added decompression during initialization - Raw JSON file excluded from git
This commit is contained in:
@@ -2,13 +2,16 @@
|
||||
package asinfo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
//go:embed asdata.json
|
||||
var asDataJSON []byte
|
||||
//go:embed asdata.json.gz
|
||||
var asDataGZ []byte
|
||||
|
||||
// Info represents information about an Autonomous System
|
||||
type Info struct {
|
||||
@@ -24,8 +27,10 @@ type Registry struct {
|
||||
}
|
||||
|
||||
var (
|
||||
//nolint:gochecknoglobals // Singleton pattern for embedded data
|
||||
defaultRegistry *Registry
|
||||
once sync.Once
|
||||
//nolint:gochecknoglobals // Singleton pattern for embedded data
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
// initRegistry initializes the default registry with embedded data
|
||||
@@ -33,12 +38,26 @@ func initRegistry() {
|
||||
defaultRegistry = &Registry{
|
||||
byASN: make(map[int]*Info),
|
||||
}
|
||||
|
||||
|
||||
// Decompress the gzipped data
|
||||
gzReader, err := gzip.NewReader(bytes.NewReader(asDataGZ))
|
||||
if err != nil {
|
||||
panic("failed to create gzip reader: " + err.Error())
|
||||
}
|
||||
defer func() {
|
||||
_ = gzReader.Close()
|
||||
}()
|
||||
|
||||
jsonData, err := io.ReadAll(gzReader)
|
||||
if err != nil {
|
||||
panic("failed to decompress AS data: " + err.Error())
|
||||
}
|
||||
|
||||
var asInfos []Info
|
||||
if err := json.Unmarshal(asDataJSON, &asInfos); err != nil {
|
||||
if err := json.Unmarshal(jsonData, &asInfos); err != nil {
|
||||
panic("failed to unmarshal embedded AS data: " + err.Error())
|
||||
}
|
||||
|
||||
|
||||
for i := range asInfos {
|
||||
info := &asInfos[i]
|
||||
defaultRegistry.byASN[info.ASN] = info
|
||||
@@ -48,18 +67,19 @@ func initRegistry() {
|
||||
// Get returns AS information for the given ASN
|
||||
func Get(asn int) (*Info, bool) {
|
||||
once.Do(initRegistry)
|
||||
|
||||
|
||||
defaultRegistry.mu.RLock()
|
||||
defer defaultRegistry.mu.RUnlock()
|
||||
|
||||
|
||||
info, ok := defaultRegistry.byASN[asn]
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
|
||||
// Return a copy to prevent mutation
|
||||
copy := *info
|
||||
return ©, true
|
||||
infoCopy := *info
|
||||
|
||||
return &infoCopy, true
|
||||
}
|
||||
|
||||
// GetDescription returns just the description for an ASN
|
||||
@@ -68,6 +88,7 @@ func GetDescription(asn int) string {
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
return info.Description
|
||||
}
|
||||
|
||||
@@ -77,16 +98,17 @@ func GetHandle(asn int) string {
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
return info.Handle
|
||||
}
|
||||
|
||||
// Total returns the total number of AS entries in the registry
|
||||
func Total() int {
|
||||
once.Do(initRegistry)
|
||||
|
||||
|
||||
defaultRegistry.mu.RLock()
|
||||
defer defaultRegistry.mu.RUnlock()
|
||||
|
||||
|
||||
return len(defaultRegistry.byASN)
|
||||
}
|
||||
|
||||
@@ -94,15 +116,15 @@ func Total() int {
|
||||
// Note: This creates a copy of all data, use sparingly
|
||||
func All() []Info {
|
||||
once.Do(initRegistry)
|
||||
|
||||
|
||||
defaultRegistry.mu.RLock()
|
||||
defer defaultRegistry.mu.RUnlock()
|
||||
|
||||
|
||||
result := make([]Info, 0, len(defaultRegistry.byASN))
|
||||
for _, info := range defaultRegistry.byASN {
|
||||
result = append(result, *info)
|
||||
}
|
||||
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -110,17 +132,17 @@ func All() []Info {
|
||||
// This is a simple case-sensitive substring search
|
||||
func Search(query string) []Info {
|
||||
once.Do(initRegistry)
|
||||
|
||||
|
||||
defaultRegistry.mu.RLock()
|
||||
defer defaultRegistry.mu.RUnlock()
|
||||
|
||||
|
||||
var results []Info
|
||||
for _, info := range defaultRegistry.byASN {
|
||||
if contains(info.Handle, query) || contains(info.Description, query) {
|
||||
results = append(results, *info)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
@@ -135,5 +157,6 @@ func containsImpl(s, substr string) bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user