Files
Ananta-ps/pkg/protocol/method_registry.go
T

90 lines
2.1 KiB
Go

package protocol
import (
"encoding/json"
"fmt"
"log"
"os"
"sync"
)
type MethodEntry struct {
Name string `json:"name"`
ID uint32 `json:"id"`
Hex string `json:"hex"`
}
type MethodIdCatalog struct {
ClientBuild uint32 `json:"clientBuild"`
Source string `json:"source"`
Methods []MethodEntry `json:"methods"`
}
var (
methodRegistryLock sync.RWMutex
idToNameMap = make(map[uint32]string)
nameToIdMap = make(map[string]uint32)
isRegistryLoaded bool
)
func init() {
for name, id := range canonicalMethodIDs {
nameToIdMap[name] = id
idToNameMap[id] = name
}
}
// LoadMethodCatalog loads the method catalog from a JSON file (e.g. data/client_data/MethodIds.json).
func LoadMethodCatalog(path string) error {
data, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("failed to read method catalog from %s: %w", path, err)
}
var catalog MethodIdCatalog
if err := json.Unmarshal(data, &catalog); err != nil {
return fmt.Errorf("failed to parse method catalog JSON: %w", err)
}
methodRegistryLock.Lock()
defer methodRegistryLock.Unlock()
for _, m := range catalog.Methods {
idToNameMap[m.ID] = m.Name
nameToIdMap[m.Name] = m.ID
}
isRegistryLoaded = true
log.Printf("[PROTOCOL] Loaded %d RPC method definitions from %s (Build %d)", len(catalog.Methods), path, catalog.ClientBuild)
return nil
}
// GetMethodName returns the friendly name of a Method ID, or a formatted fallback.
func GetMethodName(id uint32) string {
methodRegistryLock.RLock()
defer methodRegistryLock.RUnlock()
if name, ok := idToNameMap[id]; ok {
return name
}
return fmt.Sprintf("UnknownMethod_0x%08X(%d)", id, id)
}
// GetMethodID returns the numeric ID for a method name.
func GetMethodID(name string) (uint32, bool) {
methodRegistryLock.RLock()
defer methodRegistryLock.RUnlock()
id, ok := nameToIdMap[name]
return id, ok
}
// MethodGetMethodIDDefault resolves a verified name. Legacy callers still pass
// a fallback, but guessed IDs must never be sent to an unrelated client handler.
func MethodGetMethodIDDefault(name string, fallback uint32) uint32 {
if id, ok := GetMethodID(name); ok {
return id
}
return 0
}