From 5a3600278f7be5f2fd8b34baa32598c8cfda67b7 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Tue, 19 May 2026 14:15:26 +0400 Subject: [PATCH] Add nph formating --- .dockerignore | 4 ++ README.md | 8 +++ libplum.nimble | 3 ++ libplum/libplum.nim | 119 ++++++++++++++++++++++++-------------------- libplum/plum.nim | 53 ++++++++++---------- tests/test_plum.nim | 29 +++++++---- 6 files changed, 126 insertions(+), 90 deletions(-) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..208f92e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +vendor/libplum/build/ +tests/test_plum +nimcache/ +.git/ diff --git a/README.md b/README.md index 76290f5..4c1012f 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,14 @@ Three env vars control verbosity: TEST_VERBOSE=1 MINIUPNPD_VERBOSE=1 LIBPLUM_VERBOSE=1 nimble testIntegration ``` +## Development + +Format the code with [nph](https://github.com/arnetheduck/nph): + +```bash +nimble format +``` + ## License Licensed and distributed under either of diff --git a/libplum.nimble b/libplum.nimble index 29244e9..ab798d8 100644 --- a/libplum.nimble +++ b/libplum.nimble @@ -19,6 +19,9 @@ proc compileStaticLibraries() = exec("cmake --build build") cpFile("build/libplum.a", "libplum.a") +task format, "format Nim code using nph": + exec "nph libplum/ tests/" + task buildBundledLibs, "build bundled libraries": compileStaticLibraries() diff --git a/libplum/libplum.nim b/libplum/libplum.nim index cfa67f4..8de5c8b 100644 --- a/libplum/libplum.nim +++ b/libplum/libplum.nim @@ -19,11 +19,13 @@ const # Nim has no equivalent, so the generated C code drops the `const`, causing # a type mismatch warning in GCC 15+. This pragma suppresses that warning # only in this translation unit and is valid for both C and C++. -{.emit: """ +{. + emit: """ #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wno-incompatible-pointer-types" #endif -""".} +""" +.} when defined(windows): {.passl: "-lws2_32 -liphlpapi -lbcrypt".} @@ -31,69 +33,74 @@ else: {.passl: "-lpthread".} const - PLUM_ERR_SUCCESS* = cint(0) - PLUM_ERR_INVALID* = cint(-1) - PLUM_ERR_FAILED* = cint(-2) + PLUM_ERR_SUCCESS* = cint(0) + PLUM_ERR_INVALID* = cint(-1) + PLUM_ERR_FAILED* = cint(-2) PLUM_ERR_NOT_AVAIL* = cint(-3) - PLUM_MAX_HOST_LEN* = 256 + PLUM_MAX_HOST_LEN* = 256 PLUM_MAX_ADDRESS_LEN* = 64 - + # Import plum enums with cint size type - plum_log_level_t* {.importc: "plum_log_level_t", header: "plum.h", - size: sizeof(cint).} = enum + plum_log_level_t* {. + importc: "plum_log_level_t", header: "plum.h", size: sizeof(cint) + .} = enum PLUM_LOG_LEVEL_VERBOSE = 0 - PLUM_LOG_LEVEL_DEBUG = 1 - PLUM_LOG_LEVEL_INFO = 2 - PLUM_LOG_LEVEL_WARN = 3 - PLUM_LOG_LEVEL_ERROR = 4 - PLUM_LOG_LEVEL_FATAL = 5 - PLUM_LOG_LEVEL_NONE = 6 + PLUM_LOG_LEVEL_DEBUG = 1 + PLUM_LOG_LEVEL_INFO = 2 + PLUM_LOG_LEVEL_WARN = 3 + PLUM_LOG_LEVEL_ERROR = 4 + PLUM_LOG_LEVEL_FATAL = 5 + PLUM_LOG_LEVEL_NONE = 6 - plum_ip_protocol_t* {.importc: "plum_ip_protocol_t", header: "plum.h", - size: sizeof(cint).} = enum + plum_ip_protocol_t* {. + importc: "plum_ip_protocol_t", header: "plum.h", size: sizeof(cint) + .} = enum PLUM_IP_PROTOCOL_TCP = 0 PLUM_IP_PROTOCOL_UDP = 1 - plum_state_t* {.importc: "plum_state_t", header: "plum.h", - size: sizeof(cint).} = enum - PLUM_STATE_DESTROYED = 0 - PLUM_STATE_PENDING = 1 - PLUM_STATE_SUCCESS = 2 - PLUM_STATE_FAILURE = 3 + plum_state_t* {.importc: "plum_state_t", header: "plum.h", size: sizeof(cint).} = enum + PLUM_STATE_DESTROYED = 0 + PLUM_STATE_PENDING = 1 + PLUM_STATE_SUCCESS = 2 + PLUM_STATE_FAILURE = 3 PLUM_STATE_DESTROYING = 4 - plum_mapping_protocol_t* {.importc: "plum_mapping_protocol_t", header: "plum.h", - size: sizeof(cint).} = enum + plum_mapping_protocol_t* {. + importc: "plum_mapping_protocol_t", header: "plum.h", size: sizeof(cint) + .} = enum PLUM_MAPPING_PROTOCOL_UNKNOWN = 0 - PLUM_MAPPING_PROTOCOL_PCP = 1 - PLUM_MAPPING_PROTOCOL_NATPMP = 2 - PLUM_MAPPING_PROTOCOL_UPNP = 3 - PLUM_MAPPING_PROTOCOL_DIRECT = 4 - + PLUM_MAPPING_PROTOCOL_PCP = 1 + PLUM_MAPPING_PROTOCOL_NATPMP = 2 + PLUM_MAPPING_PROTOCOL_UPNP = 3 + PLUM_MAPPING_PROTOCOL_DIRECT = 4 + # Define the callback to receive the plum logs plum_log_callback_t* = proc(level: plum_log_level_t, message: cstring) {.cdecl.} # Define the config struct, passed by copy (usual for struct). plum_config_t* {.importc: "plum_config_t", header: "plum.h", bycopy.} = object - log_level* {.importc: "log_level".}: plum_log_level_t - log_callback* {.importc: "log_callback".}: plum_log_callback_t - dummytls_domain* {.importc: "dummytls_domain".}: cstring - discover_timeout* {.importc: "discover_timeout".}: cint # msecs, 0 means use default (10000) - mapping_timeout* {.importc: "mapping_timeout".}: cint # msecs, 0 means use default (10000) - recheck_period* {.importc: "recheck_period".}: cint # msecs, 0 means use default (300000) + log_level* {.importc: "log_level".}: plum_log_level_t + log_callback* {.importc: "log_callback".}: plum_log_callback_t + dummytls_domain* {.importc: "dummytls_domain".}: cstring + discover_timeout* {.importc: "discover_timeout".}: cint + # msecs, 0 means use default (10000) + mapping_timeout* {.importc: "mapping_timeout".}: cint + # msecs, 0 means use default (10000) + recheck_period* {.importc: "recheck_period".}: cint + # msecs, 0 means use default (300000) # Define the mapping struct, passed by copy (usual for struct). # The user_ptr is a pointer to the MappingHandle in order to receive the result plum_mapping_t* {.importc: "plum_mapping_t", header: "plum.h", bycopy.} = object - protocol* {.importc: "protocol".}: plum_ip_protocol_t + protocol* {.importc: "protocol".}: plum_ip_protocol_t mapping_protocol* {.importc: "mapping_protocol".}: plum_mapping_protocol_t - internal_port* {.importc: "internal_port".}: uint16 - external_port* {.importc: "external_port".}: uint16 - external_host* {.importc: "external_host".}: array[PLUM_MAX_HOST_LEN, char] - user_ptr* {.importc: "user_ptr".}: pointer + internal_port* {.importc: "internal_port".}: uint16 + external_port* {.importc: "external_port".}: uint16 + external_host* {.importc: "external_host".}: array[PLUM_MAX_HOST_LEN, char] + user_ptr* {.importc: "user_ptr".}: pointer # Define the callback to receive the mapping result plum_mapping_callback_t* = @@ -101,22 +108,24 @@ type # Import plum functions -proc plum_init*(config: ptr plum_config_t): cint - {.importc: "plum_init", header: "plum.h".} +proc plum_init*( + config: ptr plum_config_t +): cint {.importc: "plum_init", header: "plum.h".} -proc plum_cleanup*(): cint - {.importc: "plum_cleanup", header: "plum.h".} +proc plum_cleanup*(): cint {.importc: "plum_cleanup", header: "plum.h".} -proc plum_create_mapping*(mapping: ptr plum_mapping_t, - callback: plum_mapping_callback_t): cint - {.importc: "plum_create_mapping", header: "plum.h".} +proc plum_create_mapping*( + mapping: ptr plum_mapping_t, callback: plum_mapping_callback_t +): cint {.importc: "plum_create_mapping", header: "plum.h".} -proc plum_query_mapping*(id: cint, state: ptr plum_state_t, - mapping: ptr plum_mapping_t): cint - {.importc: "plum_query_mapping", header: "plum.h".} +proc plum_query_mapping*( + id: cint, state: ptr plum_state_t, mapping: ptr plum_mapping_t +): cint {.importc: "plum_query_mapping", header: "plum.h".} -proc plum_destroy_mapping*(id: cint): cint - {.importc: "plum_destroy_mapping", header: "plum.h".} +proc plum_destroy_mapping*( + id: cint +): cint {.importc: "plum_destroy_mapping", header: "plum.h".} -proc plum_get_local_address*(buffer: cstring, size: csize_t): cint - {.importc: "plum_get_local_address", header: "plum.h".} +proc plum_get_local_address*( + buffer: cstring, size: csize_t +): cint {.importc: "plum_get_local_address", header: "plum.h".} diff --git a/libplum/plum.nim b/libplum/plum.nim index f925a38..cdcadeb 100644 --- a/libplum/plum.nim +++ b/libplum/plum.nim @@ -12,11 +12,13 @@ import chronos/threadsync import results import ./libplum -{.emit: """ +{. + emit: """ #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wincompatible-pointer-types" #endif -""".} +""" +.} export results @@ -28,18 +30,18 @@ type UDP = PLUM_IP_PROTOCOL_UDP.int PlumState* = enum - Destroyed = PLUM_STATE_DESTROYED.int - Pending = PLUM_STATE_PENDING.int - Success = PLUM_STATE_SUCCESS.int - Failure = PLUM_STATE_FAILURE.int + Destroyed = PLUM_STATE_DESTROYED.int + Pending = PLUM_STATE_PENDING.int + Success = PLUM_STATE_SUCCESS.int + Failure = PLUM_STATE_FAILURE.int Destroying = PLUM_STATE_DESTROYING.int MappingProtocol* = enum Unknown = PLUM_MAPPING_PROTOCOL_UNKNOWN.int - PCP = PLUM_MAPPING_PROTOCOL_PCP.int - NatPmp = PLUM_MAPPING_PROTOCOL_NATPMP.int - UPnP = PLUM_MAPPING_PROTOCOL_UPNP.int - Direct = PLUM_MAPPING_PROTOCOL_DIRECT.int + PCP = PLUM_MAPPING_PROTOCOL_PCP.int + NatPmp = PLUM_MAPPING_PROTOCOL_NATPMP.int + UPnP = PLUM_MAPPING_PROTOCOL_UPNP.int + Direct = PLUM_MAPPING_PROTOCOL_DIRECT.int PlumMapping* = object protocol*: PlumProtocol @@ -52,8 +54,7 @@ type id*: cint mapping*: PlumMapping - PlumStateCallback* = - proc(state: PlumState, mapping: PlumMapping) {.callback.} + PlumStateCallback* = proc(state: PlumState, mapping: PlumMapping) {.callback.} MappingHandle = ref object signal: ThreadSignalPtr @@ -76,9 +77,11 @@ type # libplum calls mappingCallback from its own C thread. Under refc, any thread # that touches Nim objects must register with the GC first. template foreignThreadGc(body: untyped) = - when declared(setupForeignThreadGc): setupForeignThreadGc() + when declared(setupForeignThreadGc): + setupForeignThreadGc() body - when declared(tearDownForeignThreadGc): tearDownForeignThreadGc() + when declared(tearDownForeignThreadGc): + tearDownForeignThreadGc() var activeMappingsLock: Lock var activeMappings {.guard: activeMappingsLock.}: Table[cint, MappingHandle] @@ -92,8 +95,9 @@ template withSafeLock(body: untyped) = withLock activeMappingsLock: body -proc mappingCallback(id: cint, state: plum_state_t, - raw: ptr plum_mapping_t) {.cdecl, raises: [].} = +proc mappingCallback( + id: cint, state: plum_state_t, raw: ptr plum_mapping_t +) {.cdecl, raises: [].} = ## Called from libplum's internal C thread on SUCCESS, FAILURE, and DESTROYED. foreignThreadGc: @@ -139,7 +143,7 @@ proc mappingCallback(id: cint, state: plum_state_t, mappingProtocol: MappingProtocol(raw[].mapping_protocol.int), internalPort: raw[].internal_port, externalPort: raw[].external_port, - externalHost: $cast[cstring](addr raw[].external_host) + externalHost: $cast[cstring](addr raw[].external_host), ) handle.onStateChange(plumState, mapping) @@ -147,7 +151,7 @@ proc init*( logLevel: plum_log_level_t = PLUM_LOG_LEVEL_NONE, discoverTimeout: int = 0, mappingTimeout: int = 0, - recheckPeriod: int = 0 + recheckPeriod: int = 0, ): Result[void, string] {.raises: [].} = ## init MUST be called to setup internal plum thread (plum_init). @@ -157,7 +161,7 @@ proc init*( dummytls_domain: nil, discover_timeout: discoverTimeout.cint, mapping_timeout: mappingTimeout.cint, - recheck_period: recheckPeriod.cint + recheck_period: recheckPeriod.cint, ) let res = plum_init(addr config) @@ -180,21 +184,18 @@ proc createMapping*( internalPort: uint16, externalPort: uint16 = 0, timeout: Duration = seconds(30), - onStateChange: PlumStateCallback = nil + onStateChange: PlumStateCallback = nil, ): Future[Result[MappingResult, string]] {.async: (raises: [CancelledError]).} = let signal = ThreadSignalPtr.new().valueOr: return err("plum: cannot create signal: " & $error) - let handle = MappingHandle( - signal: signal, - onStateChange: onStateChange - ) + let handle = MappingHandle(signal: signal, onStateChange: onStateChange) var req = plum_mapping_t( protocol: plum_ip_protocol_t(protocol.int), internal_port: internalPort, external_port: externalPort, - user_ptr: cast[pointer](handle) + user_ptr: cast[pointer](handle), ) # Avoid issue with refc. @@ -252,7 +253,7 @@ proc createMapping*( mappingProtocol: h.resolvedMappingProtocol, internalPort: h.resolvedInternalPort, externalPort: h.resolvedExternalPort, - externalHost: $cast[cstring](unsafeAddr h.resolvedExternalHost) + externalHost: $cast[cstring](unsafeAddr h.resolvedExternalHost), ) if resolvedState == Success: diff --git a/tests/test_plum.nim b/tests/test_plum.nim index cbd1d1f..fc302fc 100644 --- a/tests/test_plum.nim +++ b/tests/test_plum.nim @@ -41,14 +41,20 @@ const miniupnp_protocol {.strdefine.} = "" # must fall back to NAT-PMP on its own (tests the silent-timeout fallback fix). when miniupnp_protocol != "": const expectedMappingProtocol = - when miniupnp_protocol == "pcp": PCP - elif miniupnp_protocol == "natpmp": NatPmp - else: UPnP + when miniupnp_protocol == "pcp": + PCP + elif miniupnp_protocol == "natpmp": + NatPmp + else: + UPnP suite "plum - " & miniupnp_protocol & " using miniupnp": test "createMapping TCP and destroyMapping": - let logLevel = if getEnv("LIBPLUM_VERBOSE") == "1": PLUM_LOG_LEVEL_VERBOSE - else: PLUM_LOG_LEVEL_NONE + let logLevel = + if getEnv("LIBPLUM_VERBOSE") == "1": + PLUM_LOG_LEVEL_VERBOSE + else: + PLUM_LOG_LEVEL_NONE check init(discoverTimeout = 15000, logLevel = logLevel).isOk() let r = waitFor createMapping(TCP, 8101, timeout = seconds(40)) @@ -60,14 +66,18 @@ when miniupnp_protocol != "": check res.mapping.mappingProtocol == expectedMappingProtocol check hasMapping(res.id) if getEnv("TEST_VERBOSE") == "1": - echo miniupnp_protocol & " TCP: " & res.mapping.externalHost & ":" & $res.mapping.externalPort + echo miniupnp_protocol & " TCP: " & res.mapping.externalHost & ":" & + $res.mapping.externalPort destroyMapping(res.id) discard cleanup() test "createMapping UDP and destroying": - let logLevel = if getEnv("LIBPLUM_VERBOSE") == "1": PLUM_LOG_LEVEL_VERBOSE - else: PLUM_LOG_LEVEL_NONE + let logLevel = + if getEnv("LIBPLUM_VERBOSE") == "1": + PLUM_LOG_LEVEL_VERBOSE + else: + PLUM_LOG_LEVEL_NONE check init(discoverTimeout = 2000, logLevel = logLevel).isOk() let r = waitFor createMapping(UDP, 8090, timeout = seconds(40)) @@ -77,7 +87,8 @@ when miniupnp_protocol != "": check res.mapping.externalPort > 0 check res.mapping.mappingProtocol == expectedMappingProtocol if getEnv("TEST_VERBOSE") == "1": - echo miniupnp_protocol & " UDP: " & res.mapping.externalHost & ":" & $res.mapping.externalPort + echo miniupnp_protocol & " UDP: " & res.mapping.externalHost & ":" & + $res.mapping.externalPort destroyMapping(res.id) discard cleanup()