diff --git a/library/libwaku.h b/library/libwaku.h index 5660e3a10..a0ccede92 100644 --- a/library/libwaku.h +++ b/library/libwaku.h @@ -181,6 +181,12 @@ int waku_peer_exchange_request(void* ctx, WakuCallBack callback, void* userData); +int waku_ping_peer(void* ctx, + const char* peerAddr, + int timeoutMs, + WakuCallBack callback, + void* userData); + #ifdef __cplusplus } #endif diff --git a/library/libwaku.nim b/library/libwaku.nim index 93d468f1e..3d591b712 100644 --- a/library/libwaku.nim +++ b/library/libwaku.nim @@ -22,6 +22,7 @@ import ./waku_thread/inter_thread_communication/requests/protocols/lightpush_request, ./waku_thread/inter_thread_communication/requests/debug_node_request, ./waku_thread/inter_thread_communication/requests/discovery_request, + ./waku_thread/inter_thread_communication/requests/ping_request, ./waku_thread/inter_thread_communication/waku_thread_request, ./alloc, ./callback @@ -672,5 +673,22 @@ proc waku_peer_exchange_request( ) .handleRes(callback, userData) +proc waku_ping_peer( + ctx: ptr WakuContext, + peerID: cstring, + timeoutMs: cuint, + callback: WakuCallBack, + userData: pointer, +): cint {.dynlib, exportc.} = + checkLibwakuParams(ctx, callback, userData) + + waku_thread + .sendRequestToWakuThread( + ctx, + RequestType.PING, + PingRequest.createShared(peerID, chronos.milliseconds(timeoutMs)), + ) + .handleRes(callback, userData) + ### End of exported procs ################################################################################ diff --git a/library/waku_thread/inter_thread_communication/requests/ping_request.nim b/library/waku_thread/inter_thread_communication/requests/ping_request.nim new file mode 100644 index 000000000..d9361b2c7 --- /dev/null +++ b/library/waku_thread/inter_thread_communication/requests/ping_request.nim @@ -0,0 +1,53 @@ +import std/json +import chronos, results +import libp2p/[protocols/ping, switch, multiaddress, multicodec] +import ../../../../waku/[factory/waku, waku_core/peers, node/waku_node], ../../../alloc + +type PingRequest* = object + peerAddr: cstring + timeout: Duration + +proc createShared*( + T: type PingRequest, peerAddr: cstring, timeout: Duration +): ptr type T = + var ret = createShared(T) + ret[].peerAddr = peerAddr.alloc() + ret[].timeout = timeout + return ret + +proc destroyShared(self: ptr PingRequest) = + deallocShared(self[].peerAddr) + deallocShared(self) + +proc process*( + self: ptr PingRequest, waku: ptr Waku +): Future[Result[string, string]] {.async.} = + defer: + destroyShared(self) + + let peerInfo = peers.parsePeerInfo($self[].peerAddr).valueOr: + return err("PingRequest failed to parse peer addr: " & $error) + + proc ping(): Future[Result[Duration, string]] {.async, gcsafe.} = + try: + let conn = await waku.node.switch.dial(peerInfo.peerId, peerInfo.addrs, PingCodec) + let pingRTT = await waku.node.libp2pPing.ping(conn) + if pingRTT == 0.nanos: + return err("could not ping peer: rtt-0") + return ok(pingRTT) + except CatchableError: + return err("could not ping peer: " & getCurrentExceptionMsg()) + + let pingFuture = ping() + let pingRTT: Duration = + if self[].timeout == chronos.milliseconds(0): # No timeout expected + (await pingFuture).valueOr: + return err(error) + else: + let timedOut = not (await pingFuture.withTimeout(self[].timeout)) + if timedOut: + return err("ping timed out") + pingFuture.read().valueOr: + return err(error) + + ok($(pingRTT.nanos)) diff --git a/library/waku_thread/inter_thread_communication/waku_thread_request.nim b/library/waku_thread/inter_thread_communication/waku_thread_request.nim index 4f1733047..63dacc06d 100644 --- a/library/waku_thread/inter_thread_communication/waku_thread_request.nim +++ b/library/waku_thread/inter_thread_communication/waku_thread_request.nim @@ -12,11 +12,13 @@ import ./requests/protocols/store_request, ./requests/protocols/lightpush_request, ./requests/debug_node_request, - ./requests/discovery_request + ./requests/discovery_request, + ./requests/ping_request type RequestType* {.pure.} = enum LIFECYCLE PEER_MANAGER + PING RELAY STORE DEBUG @@ -50,6 +52,8 @@ proc process*( cast[ptr NodeLifecycleRequest](request[].reqContent).process(waku) of PEER_MANAGER: cast[ptr PeerManagementRequest](request[].reqContent).process(waku[]) + of PING: + cast[ptr PingRequest](request[].reqContent).process(waku) of RELAY: cast[ptr RelayRequest](request[].reqContent).process(waku) of STORE: