mirror of
https://github.com/logos-storage/nim-libplum.git
synced 2026-07-24 00:03:11 +00:00
feat: protocol filter (#15)
* Add Protocol filter * Temporary point on fork * Use ord instead of int
This commit is contained in:
parent
de15c06943
commit
fa8aadb591
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -1,4 +1,4 @@
|
||||
[submodule "vendor/libplum"]
|
||||
path = vendor/libplum
|
||||
url = https://github.com/paullouisageneau/libplum.git
|
||||
branch = master
|
||||
path = vendor/libplum
|
||||
url = https://github.com/2-towns/libplum.git
|
||||
branch = feat/protocol-filter
|
||||
|
||||
11
api.md
11
api.md
@ -26,6 +26,13 @@ type MappingProtocol* = enum
|
||||
Direct ## no mapping needed, local address is already public
|
||||
```
|
||||
|
||||
```nim
|
||||
type ProtocolFilter* {.pure.} = enum
|
||||
Any ## try all protocols (default)
|
||||
PCP ## PCP/NAT-PMP only
|
||||
UPnP ## UPnP only
|
||||
```
|
||||
|
||||
```nim
|
||||
type PlumMapping* = object
|
||||
protocol*: PlumProtocol ## IP protocol (TCP/UDP)
|
||||
@ -55,7 +62,8 @@ proc init*(
|
||||
logLevel: plum_log_level_t = PLUM_LOG_LEVEL_NONE,
|
||||
discoverTimeout: int = 0,
|
||||
mappingTimeout: int = 0,
|
||||
recheckPeriod: int = 0
|
||||
recheckPeriod: int = 0,
|
||||
protocol: ProtocolFilter = ProtocolFilter.Any
|
||||
): Result[void, string]
|
||||
```
|
||||
|
||||
@ -65,6 +73,7 @@ Initializes the library and starts the internal thread. Must be called before an
|
||||
- `discoverTimeout`: how long to probe for a NAT device, in ms (default: 10000)
|
||||
- `mappingTimeout`: how long to wait for a mapping response, in ms (default: 10000)
|
||||
- `recheckPeriod`: interval between periodic mapping rechecks, in ms (default: 300000)
|
||||
- `protocol`: restrict discovery to a single family (`ProtocolFilter.PCP` for PCP/NAT-PMP, `ProtocolFilter.UPnP` for UPnP); `ProtocolFilter.Any` tries all (default)
|
||||
|
||||
### cleanup
|
||||
|
||||
|
||||
@ -52,35 +52,40 @@ type
|
||||
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_VERBOSE
|
||||
PLUM_LOG_LEVEL_DEBUG
|
||||
PLUM_LOG_LEVEL_INFO
|
||||
PLUM_LOG_LEVEL_WARN
|
||||
PLUM_LOG_LEVEL_ERROR
|
||||
PLUM_LOG_LEVEL_FATAL
|
||||
PLUM_LOG_LEVEL_NONE
|
||||
|
||||
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_IP_PROTOCOL_TCP
|
||||
PLUM_IP_PROTOCOL_UDP
|
||||
|
||||
plum_protocol_t* {.importc: "plum_protocol_t", header: "plum.h", size: sizeof(cint).} = enum
|
||||
PLUM_PROTOCOL_ANY
|
||||
PLUM_PROTOCOL_PCP
|
||||
PLUM_PROTOCOL_UPNP
|
||||
|
||||
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_STATE_DESTROYED
|
||||
PLUM_STATE_PENDING
|
||||
PLUM_STATE_SUCCESS
|
||||
PLUM_STATE_FAILURE
|
||||
PLUM_STATE_DESTROYING
|
||||
|
||||
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_UNKNOWN
|
||||
PLUM_MAPPING_PROTOCOL_PCP
|
||||
PLUM_MAPPING_PROTOCOL_NATPMP
|
||||
PLUM_MAPPING_PROTOCOL_UPNP
|
||||
PLUM_MAPPING_PROTOCOL_DIRECT
|
||||
|
||||
# Define the callback to receive the plum logs
|
||||
plum_log_callback_t* = proc(level: plum_log_level_t, message: cstring) {.cdecl.}
|
||||
@ -96,6 +101,7 @@ type
|
||||
# msecs, 0 means use default (10000)
|
||||
recheck_period* {.importc: "recheck_period".}: cint
|
||||
# msecs, 0 means use default (300000)
|
||||
protocol* {.importc: "protocol".}: plum_protocol_t # PLUM_PROTOCOL_ANY means try all
|
||||
|
||||
# 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
|
||||
|
||||
@ -34,31 +34,36 @@ export results
|
||||
|
||||
type
|
||||
PlumProtocol* = enum
|
||||
TCP = PLUM_IP_PROTOCOL_TCP.int
|
||||
UDP = PLUM_IP_PROTOCOL_UDP.int
|
||||
TCP = ord(PLUM_IP_PROTOCOL_TCP)
|
||||
UDP = ord(PLUM_IP_PROTOCOL_UDP)
|
||||
|
||||
ProtocolFilter* {.pure.} = enum
|
||||
Any = ord(PLUM_PROTOCOL_ANY)
|
||||
PCP = ord(PLUM_PROTOCOL_PCP)
|
||||
UPnP = ord(PLUM_PROTOCOL_UPNP)
|
||||
|
||||
PlumLogLevel* {.pure.} = enum
|
||||
Verbose = PLUM_LOG_LEVEL_VERBOSE.int
|
||||
Debug = PLUM_LOG_LEVEL_DEBUG.int
|
||||
Info = PLUM_LOG_LEVEL_INFO.int
|
||||
Warn = PLUM_LOG_LEVEL_WARN.int
|
||||
Error = PLUM_LOG_LEVEL_ERROR.int
|
||||
Fatal = PLUM_LOG_LEVEL_FATAL.int
|
||||
None = PLUM_LOG_LEVEL_NONE.int
|
||||
Verbose = ord(PLUM_LOG_LEVEL_VERBOSE)
|
||||
Debug = ord(PLUM_LOG_LEVEL_DEBUG)
|
||||
Info = ord(PLUM_LOG_LEVEL_INFO)
|
||||
Warn = ord(PLUM_LOG_LEVEL_WARN)
|
||||
Error = ord(PLUM_LOG_LEVEL_ERROR)
|
||||
Fatal = ord(PLUM_LOG_LEVEL_FATAL)
|
||||
None = ord(PLUM_LOG_LEVEL_NONE)
|
||||
|
||||
PlumState* = enum
|
||||
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
|
||||
Destroyed = ord(PLUM_STATE_DESTROYED)
|
||||
Pending = ord(PLUM_STATE_PENDING)
|
||||
Success = ord(PLUM_STATE_SUCCESS)
|
||||
Failure = ord(PLUM_STATE_FAILURE)
|
||||
Destroying = ord(PLUM_STATE_DESTROYING)
|
||||
|
||||
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
|
||||
Unknown = ord(PLUM_MAPPING_PROTOCOL_UNKNOWN)
|
||||
PCP = ord(PLUM_MAPPING_PROTOCOL_PCP)
|
||||
NatPmp = ord(PLUM_MAPPING_PROTOCOL_NATPMP)
|
||||
UPnP = ord(PLUM_MAPPING_PROTOCOL_UPNP)
|
||||
Direct = ord(PLUM_MAPPING_PROTOCOL_DIRECT)
|
||||
|
||||
PlumMapping* = object
|
||||
protocol*: PlumProtocol
|
||||
@ -161,8 +166,11 @@ proc init*(
|
||||
discoverTimeout: int32 = 0,
|
||||
mappingTimeout: int32 = 0,
|
||||
recheckPeriod: int32 = 0,
|
||||
protocol: ProtocolFilter = ProtocolFilter.Any,
|
||||
): Result[void, string] =
|
||||
## init MUST be called to setup internal plum thread (plum_init).
|
||||
## protocol restricts discovery to a single family (PCP/NAT-PMP or UPnP);
|
||||
## ProtocolFilter.Any tries all.
|
||||
|
||||
var config = plum_config_t(
|
||||
log_level: plum_log_level_t(logLevel.int),
|
||||
@ -171,6 +179,7 @@ proc init*(
|
||||
discover_timeout: discoverTimeout.cint,
|
||||
mapping_timeout: mappingTimeout.cint,
|
||||
recheck_period: recheckPeriod.cint,
|
||||
protocol: plum_protocol_t(protocol.int),
|
||||
)
|
||||
|
||||
let res = plum_init(addr config)
|
||||
|
||||
@ -210,3 +210,40 @@ when miniupnp_protocol != "":
|
||||
# no destroyMapping on purpose: cleanup must release everything
|
||||
check cleanup().isOk()
|
||||
check activeMappingCount() == 0
|
||||
|
||||
# miniupnpd in the pcp container also serves UPnP, so a UPnP filter must
|
||||
# override the default PCP-first selection.
|
||||
when miniupnp_protocol == "pcp":
|
||||
test "protocol filter selects UPnP even when PCP is available":
|
||||
require init(
|
||||
discoverTimeout = discoverMs.int32,
|
||||
logLevel = logLevel,
|
||||
protocol = ProtocolFilter.UPnP,
|
||||
)
|
||||
.isOk()
|
||||
defer:
|
||||
discard cleanup()
|
||||
|
||||
let r = waitFor createMapping(TCP, 8111, timeout = mappingTimeout)
|
||||
require r.isOk()
|
||||
let res = r.value
|
||||
defer:
|
||||
destroyMapping(res.id)
|
||||
|
||||
check res.mapping.mappingProtocol == UPnP
|
||||
|
||||
# miniupnpd in the upnp container has PCP/NAT-PMP disabled, so a PCP filter
|
||||
# must not fall back to UPnP: the mapping cannot succeed.
|
||||
when miniupnp_protocol == "upnp":
|
||||
test "protocol filter PCP does not fall back to UPnP":
|
||||
require init(
|
||||
discoverTimeout = discoverMs.int32,
|
||||
logLevel = logLevel,
|
||||
protocol = ProtocolFilter.PCP,
|
||||
)
|
||||
.isOk()
|
||||
defer:
|
||||
discard cleanup()
|
||||
|
||||
let r = waitFor createMapping(TCP, 8112, timeout = mappingTimeout)
|
||||
check r.isErr()
|
||||
|
||||
2
vendor/libplum
vendored
2
vendor/libplum
vendored
@ -1 +1 @@
|
||||
Subproject commit e4be508aad4297b190498c7e26552e0f495a9aa1
|
||||
Subproject commit 3df6d2b2e37689c572b69af401a6922d9db67541
|
||||
Loading…
x
Reference in New Issue
Block a user