From 13111095b0da649be3ff66dd22d71151a846fb7b Mon Sep 17 00:00:00 2001 From: Arnaud Date: Tue, 16 Sep 2025 15:45:11 +0200 Subject: [PATCH] Add debug feature --- examples/golang/codex.go | 65 ++++++++++++++++--- .../requests/node_info_request.nim | 32 ++++++++- library/libcodex.h | 5 ++ library/libcodex.nim | 17 +++++ 4 files changed, 109 insertions(+), 10 deletions(-) diff --git a/examples/golang/codex.go b/examples/golang/codex.go index e620bce5..ea95e9e0 100644 --- a/examples/golang/codex.go +++ b/examples/golang/codex.go @@ -84,6 +84,10 @@ package main return codex_repo(codexCtx, (CodexCallback) callback, resp); } + static int cGoCodexDebug(void* codexCtx, void* resp) { + return codex_debug(codexCtx, (CodexCallback) callback, resp); + } + static int cGoCodexStart(void* codexCtx, void* resp) { return codex_start(codexCtx, (CodexCallback) callback, resp); } @@ -180,6 +184,27 @@ type CodexConfig struct { LogFile string `json:"log-file,omitempty"` } +type RestNode struct { + NodeId string `json:"nodeId"` + PeerId string `json:"peerId"` + Record string `json:"record"` + Address *string `json:"address"` // Use pointer for nullable + Seen bool `json:"seen"` +} + +type RestRoutingTable struct { + LocalNode RestNode `json:"localNode"` + Nodes []RestNode `json:"nodes"` +} + +type CodexDebugInfo struct { + ID string `json:"id"` + Addrs []string `json:"addrs"` + Spr string `json:"spr"` + AnnounceAddresses []string `json:"announceAddresses"` + Table RestRoutingTable `json:"table"` +} + type CodexNode struct { ctx unsafe.Pointer } @@ -330,6 +355,26 @@ func (self *CodexNode) CodexRepo() (string, error) { return bridge.wait() } +func (self *CodexNode) CodexDebug() (CodexDebugInfo, error) { + var info CodexDebugInfo + + bridge := newBridgeCtx() + defer bridge.free() + + if C.cGoCodexDebug(self.ctx, bridge.resp) != C.RET_OK { + return info, bridge.CallError("cGoCodexDebug") + } + + value, err := bridge.wait() + if err != nil { + return info, err + } + + err = json.Unmarshal([]byte(value), &info) + + return info, err +} + func (self *CodexNode) CodexStart() error { bridge := newBridgeCtx() defer bridge.free() @@ -404,8 +449,6 @@ func main() { LogLevel: Info, } - log.Println("Creating Codex...") - node, err := CodexNew(config) if err != nil { log.Fatal("Error happened:", err.Error()) @@ -415,8 +458,6 @@ func main() { // node.CodexSetEventCallback() - log.Println("Getting version...") - version, err := node.CodexVersion() if err != nil { log.Fatal("Error happened:", err.Error()) @@ -424,8 +465,6 @@ func main() { log.Println("Codex version:", version) - log.Println("Getting revision...") - revision, err := node.CodexRevision() if err != nil { log.Fatal("Error happened:", err.Error()) @@ -433,8 +472,6 @@ func main() { log.Println("Codex revision:", revision) - log.Println("Getting repo...") - repo, err := node.CodexRepo() if err != nil { log.Fatal("Error happened:", err.Error()) @@ -452,6 +489,18 @@ func main() { log.Println("Codex started...") + debug, err := node.CodexDebug() + if err != nil { + log.Fatal("Error happened:", err.Error()) + } + + pretty, err := json.MarshalIndent(debug, "", " ") + if err != nil { + log.Fatal("Error happened:", err.Error()) + } + + log.Println(string(pretty)) + // Wait for a SIGINT or SIGTERM signal ch := make(chan os.Signal, 1) signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) diff --git a/library/codex_thread_requests/requests/node_info_request.nim b/library/codex_thread_requests/requests/node_info_request.nim index c252aba2..cece26da 100644 --- a/library/codex_thread_requests/requests/node_info_request.nim +++ b/library/codex_thread_requests/requests/node_info_request.nim @@ -4,12 +4,16 @@ import std/[options] import chronos import chronicles import confutils +import codexdht/discv5/spr import ../../../codex/conf +import ../../../codex/rest/json +import ../../../codex/node -from ../../../codex/codex import CodexServer +from ../../../codex/codex import CodexServer, config, node type NodeInfoMsgType* = enum REPO + DEBUG type NodeInfoRequest* = object operation: NodeInfoMsgType @@ -29,6 +33,24 @@ proc getRepo( ): Future[Result[string, string]] {.async: (raises: []).} = return ok($(codex[].config.dataDir)) +proc getDebug( + codex: ptr CodexServer +): Future[Result[string, string]] {.async: (raises: []).} = + let node = codex[].node + let table = RestRoutingTable.init(node.discovery.protocol.routingTable) + + let json = + %*{ + "id": $node.switch.peerInfo.peerId, + "addrs": node.switch.peerInfo.addrs.mapIt($it), + "spr": + if node.discovery.dhtRecord.isSome: node.discovery.dhtRecord.get.toURI else: "", + "announceAddresses": node.discovery.announceAddrs, + "table": table, + } + + return ok($json) + proc process*( self: ptr NodeInfoRequest, codex: ptr CodexServer ): Future[Result[string, string]] {.async: (raises: []).} = @@ -39,7 +61,13 @@ proc process*( of REPO: let res = (await getRepo(codex)) if res.isErr: - error "INFO failed", error = res.error + error "REPO failed", error = res.error + return err($res.error) + return res + of DEBUG: + let res = (await getDebug(codex)) + if res.isErr: + error "DEBUG failed", error = res.error return err($res.error) return res diff --git a/library/libcodex.h b/library/libcodex.h index 7e255a56..e8dd5a25 100644 --- a/library/libcodex.h +++ b/library/libcodex.h @@ -45,6 +45,11 @@ int codex_repo( CodexCallback callback, void* userData); +int codex_debug( + void* ctx, + CodexCallback callback, + void* userData); + int codex_start(void* ctx, CodexCallback callback, void* userData); diff --git a/library/libcodex.nim b/library/libcodex.nim index 067a88bc..6627672c 100644 --- a/library/libcodex.nim +++ b/library/libcodex.nim @@ -146,6 +146,23 @@ proc codex_repo( return RET_OK +proc codex_debug( + ctx: ptr CodexContext, callback: CodexCallback, userData: pointer +): cint {.dynlib, exportc.} = + initializeLibrary() + checkLibcodexParams(ctx, callback, userData) + + let reqContent = NodeInfoRequest.createShared(NodeInfoMsgType.DEBUG) + + codex_context.sendRequestToCodexThread( + ctx, RequestType.INFO, reqContent, callback, userData + ).isOkOr: + let msg = "libcodex error: " & $error + callback(RET_ERR, unsafeAddr msg[0], cast[csize_t](len(msg)), userData) + return RET_ERR + + return RET_OK + proc codex_destroy( ctx: ptr CodexContext, callback: CodexCallback, userData: pointer ): cint {.dynlib, exportc.} =