From f96f08943c63e57a8afe35145207906b8cd4f628 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Wed, 17 Sep 2025 14:37:34 +0200 Subject: [PATCH] Add peer debug --- examples/golang/codex.go | 70 +++++++++++++++++-- .../requests/node_debug_request.nim | 39 ++++++++++- .../requests/node_p2p_request.nim | 2 +- library/libcodex.h | 6 ++ library/libcodex.nim | 17 +++++ 5 files changed, 125 insertions(+), 9 deletions(-) diff --git a/examples/golang/codex.go b/examples/golang/codex.go index 01a88a02..8d6ecabd 100644 --- a/examples/golang/codex.go +++ b/examples/golang/codex.go @@ -104,6 +104,10 @@ package main return codex_connect(codexCtx, peerId, peerAddresses, peerAddressesSize, (CodexCallback) callback, resp); } + static int cGoCodexPeerDebug(void* codexCtx, char* peerId, void* resp) { + return codex_peer_debug(codexCtx, peerId, (CodexCallback) callback, resp); + } + static int cGoCodexStart(void* codexCtx, void* resp) { return codex_start(codexCtx, (CodexCallback) callback, resp); } @@ -199,6 +203,15 @@ type CodexConfig struct { LogFile string `json:"log-file,omitempty"` } +type RestPeerRecord struct { + PeerId string `json:"peerId"` + SeqNo int `json:"seqNo"` + Addresses []string `json:"addresses,omitempty"` +} + +// peerId* {.serialize.}: PeerId +// seqNo* {.serialize.}: uint64 +// addresses* {.serialize.}: seq[AddressInfo] type RestNode struct { NodeId string `json:"nodeId"` PeerId string `json:"peerId"` @@ -434,20 +447,49 @@ func (self *CodexNode) CodexConnect(peerId string, peerAddresses []string) error var cPeerId = C.CString(peerId) defer C.free(unsafe.Pointer(cPeerId)) - var cAddresses = make([]*C.char, len(peerAddresses)) - for i, addr := range peerAddresses { - cAddresses[i] = C.CString(addr) - defer C.free(unsafe.Pointer(cAddresses[i])) - } + if len(peerAddresses) > 0 { + var cAddresses = make([]*C.char, len(peerAddresses)) + for i, addr := range peerAddresses { + cAddresses[i] = C.CString(addr) + defer C.free(unsafe.Pointer(cAddresses[i])) + } - if C.cGoCodexConnect(self.ctx, cPeerId, &cAddresses[0], C.uintptr_t(len(peerAddresses)), bridge.resp) != C.RET_OK { - return bridge.CallError("cGoCodexConnect") + if C.cGoCodexConnect(self.ctx, cPeerId, &cAddresses[0], C.uintptr_t(len(peerAddresses)), bridge.resp) != C.RET_OK { + return bridge.CallError("cGoCodexConnect") + } + } else { + if C.cGoCodexConnect(self.ctx, cPeerId, nil, 0, bridge.resp) != C.RET_OK { + return bridge.CallError("cGoCodexConnect") + } } _, err := bridge.wait() return err } +func (self *CodexNode) CodexPeerDebug(peerId string) (RestPeerRecord, error) { + var record RestPeerRecord + + bridge := newBridgeCtx() + defer bridge.free() + + var cPeerId = C.CString(peerId) + defer C.free(unsafe.Pointer(cPeerId)) + + if C.cGoCodexPeerDebug(self.ctx, cPeerId, bridge.resp) != C.RET_OK { + return record, bridge.CallError("cGoCodexPeerDebug") + } + + value, err := bridge.wait() + if err != nil { + return record, err + } + + err = json.Unmarshal([]byte(value), &record) + + return record, err +} + func (self *CodexNode) CodexStart() error { bridge := newBridgeCtx() defer bridge.free() @@ -593,6 +635,20 @@ func main() { log.Println("Codex Log Level set to TRACE") + // err = node.CodexConnect(peerId, []string{}) + // if err != nil { + // log.Fatal("Error happened:", err.Error()) + // } + + // log.Println("Codex connecting to self...") + + // val, err := node.CodexPeerDebug(peerId) + // if err != nil { + // log.Fatal("Error happened:", err.Error()) + // } + + // log.Println("Codex debugging self...", val) + // 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_debug_request.nim b/library/codex_thread_requests/requests/node_debug_request.nim index 17881f9f..f58c022c 100644 --- a/library/codex_thread_requests/requests/node_debug_request.nim +++ b/library/codex_thread_requests/requests/node_debug_request.nim @@ -4,6 +4,7 @@ import std/[options] import chronos import chronicles import codexdht/discv5/spr +import ../../alloc import ../../../codex/conf import ../../../codex/rest/json import ../../../codex/node @@ -12,16 +13,22 @@ from ../../../codex/codex import CodexServer, node type NodeDebugMsgType* = enum DEBUG + PEER type NodeDebugRequest* = object operation: NodeDebugMsgType + peerId: cstring -proc createShared*(T: type NodeDebugRequest, op: NodeDebugMsgType): ptr type T = +proc createShared*( + T: type NodeDebugRequest, op: NodeDebugMsgType, peerId: cstring = "" +): ptr type T = var ret = createShared(T) ret[].operation = op + ret[].peerId = peerId.alloc() return ret proc destroyShared(self: ptr NodeDebugRequest) = + deallocShared(self[].peerId) deallocShared(self) proc getDebug( @@ -42,6 +49,30 @@ proc getDebug( return ok($json) +proc getPeer( + codex: ptr CodexServer, peerId: cstring +): Future[Result[string, string]] {.async: (raises: []).} = + when codex_enable_api_debug_peers: + let node = codex[].node + let res = PeerId.init($peerId) + if res.isErr: + return err("Invalid peer ID " & $peerId & ": " & $res.error()) + + let id = res.get() + + try: + let peerRecord = await node.findPeer(id) + if peerRecord.isNone: + return err("Peer not found") + + return ok($ %RestPeerRecord.init(peerRecord.get())) + except CancelledError: + return err("Operation cancelled") + except CatchableError as e: + return err("Error when finding peer: " & e.msg) + else: + return err("Peer debug API is disabled") + proc process*( self: ptr NodeDebugRequest, codex: ptr CodexServer ): Future[Result[string, string]] {.async: (raises: []).} = @@ -55,5 +86,11 @@ proc process*( error "DEBUG failed", error = res.error return err($res.error) return res + of NodeDebugMsgType.PEER: + let res = (await getPeer(codex, self.peerId)) + if res.isErr: + error "PEER failed", error = res.error + return err($res.error) + return res return ok("") diff --git a/library/codex_thread_requests/requests/node_p2p_request.nim b/library/codex_thread_requests/requests/node_p2p_request.nim index 5291c138..eebe874b 100644 --- a/library/codex_thread_requests/requests/node_p2p_request.nim +++ b/library/codex_thread_requests/requests/node_p2p_request.nim @@ -3,8 +3,8 @@ import std/[options] import chronos import chronicles -import ../../alloc import libp2p +import ../../alloc import ../../../codex/node from ../../../codex/codex import CodexServer, node diff --git a/library/libcodex.h b/library/libcodex.h index 026a317c..621eebce 100644 --- a/library/libcodex.h +++ b/library/libcodex.h @@ -74,6 +74,12 @@ int codex_connect( CodexCallback callback, void* userData); +int codex_peer_debug( + void* ctx, + const char* peerId, + CodexCallback callback, + void* userData); + int codex_start(void* ctx, CodexCallback callback, void* userData); diff --git a/library/libcodex.nim b/library/libcodex.nim index a4402024..accb2632 100644 --- a/library/libcodex.nim +++ b/library/libcodex.nim @@ -248,6 +248,23 @@ proc codex_connect( return RET_OK +proc codex_peer_debug( + ctx: ptr CodexContext, peerId: cstring, callback: CodexCallback, userData: pointer +): cint {.dynlib, exportc.} = + initializeLibrary() + checkLibcodexParams(ctx, callback, userData) + + let reqContent = NodeDebugRequest.createShared(NodeDebugMsgType.PEER, peerId = peerId) + + codex_context.sendRequestToCodexThread( + ctx, RequestType.DEBUG, 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.} =