mirror of
https://github.com/logos-messaging/logos-delivery.git
synced 2026-07-20 19:49:28 +00:00
Callers need to know whether a channel is open before create/send, and had no way to ask without inferring it from a "channel already exists" error. Exposed at both layers so FFI consumers get the same answer. "Exists" means currently held by the manager, i.e. between a successful createReliableChannel and closeChannel. Persisted SDS state outlives a close, so a closed channel reports false -- this is a liveness check, not a "was this channel ever created" check. Cherry-picked from chore/channel-exists, which forked before the nim-ffi 0.2.0 migration. The FFI proc is re-expressed in the typed model, which also lets it carry a real bool instead of a "true"/"false" string; the hand-written header hunk is dropped since that header is generated now. Closes #4039 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
88 lines
2.8 KiB
Nim
88 lines
2.8 KiB
Nim
import chronos, results, ffi
|
|
import
|
|
logos_delivery/waku/common/base64,
|
|
logos_delivery,
|
|
logos_delivery/channels/encryption/noop_encryption,
|
|
logos_delivery/waku/waku_core/topics/content_topic,
|
|
logos_delivery/api/types,
|
|
../declare_lib
|
|
|
|
# Typed CBOR request; `payload` is base64 for the same reason as SendRequest in
|
|
# messaging_api. Fields unexported to keep the export marker out of the bindings.
|
|
type ChannelSendRequest* {.ffi.} = object
|
|
payload: string
|
|
ephemeral: bool
|
|
|
|
proc installEncryption(mechanism: string): Result[void, string] =
|
|
## The Encrypt/Decrypt brokers dispatch to a single provider, so this installs
|
|
## it process-wide even though the mechanism is named per channel: channels
|
|
## created with different mechanisms would fight over it, last one winning.
|
|
## Traffic cannot flow until some provider is registered.
|
|
case mechanism
|
|
of "noop":
|
|
setNoopEncryption()
|
|
ok()
|
|
else:
|
|
err("unknown encryption mechanism '" & mechanism & "'; supported: noop")
|
|
|
|
proc logosdeliveryChannelCreate*(
|
|
lib: LogosDelivery,
|
|
channelIdStr: string,
|
|
contentTopicStr: string,
|
|
senderIdStr: string,
|
|
encryptionStr: string,
|
|
): Future[Result[string, string]] {.ffi.} =
|
|
requireChannels(lib, "ChannelCreate"):
|
|
return err(errMsg)
|
|
|
|
installEncryption(encryptionStr).isOkOr:
|
|
return err("ChannelCreate failed: " & error)
|
|
|
|
let id = lib.reliableChannelManager.createReliableChannel(
|
|
ChannelId(channelIdStr),
|
|
ContentTopic(contentTopicStr),
|
|
SdsParticipantID(senderIdStr),
|
|
).valueOr:
|
|
return err("ChannelCreate failed: " & $error)
|
|
|
|
return ok(string(id))
|
|
|
|
proc logosdeliveryChannelExists*(
|
|
lib: LogosDelivery, channelIdStr: string
|
|
): Future[Result[bool, string]] {.ffi.} =
|
|
## Whether the channel is currently held by the manager, i.e. between a
|
|
## successful create and close. A missing channel is `false`, not an error.
|
|
requireChannels(lib, "ChannelExists"):
|
|
return err(errMsg)
|
|
|
|
return ok(lib.reliableChannelManager.channelExists(ChannelId(channelIdStr)))
|
|
|
|
proc logosdeliveryChannelSend*(
|
|
lib: LogosDelivery, channelIdStr: string, req: ChannelSendRequest
|
|
): Future[Result[string, string]] {.ffi.} =
|
|
requireChannels(lib, "ChannelSend"):
|
|
return err(errMsg)
|
|
|
|
let payload = base64.decode(Base64String(req.payload)).valueOr:
|
|
return err("invalid payload format: " & error)
|
|
|
|
let requestId = (
|
|
await lib.reliableChannelManager.send(
|
|
ChannelId(channelIdStr), payload, req.ephemeral
|
|
)
|
|
).valueOr:
|
|
return err("ChannelSend failed: " & $error)
|
|
|
|
return ok($requestId)
|
|
|
|
proc logosdeliveryChannelClose*(
|
|
lib: LogosDelivery, channelIdStr: string
|
|
): Future[Result[string, string]] {.ffi.} =
|
|
requireChannels(lib, "ChannelClose"):
|
|
return err(errMsg)
|
|
|
|
(await lib.reliableChannelManager.closeChannel(ChannelId(channelIdStr))).isOkOr:
|
|
return err("ChannelClose failed: " & $error)
|
|
|
|
return ok("")
|