Files
logos-protocol/cpp/implementations/plain/incoming_call_handler.h
Dario Lipicar 29afbac532 Extract the Logos protocol layer from logos-cpp-sdk (lp_* C ABI + protocol semver) (#2)
* Extract the Logos protocol layer from logos-cpp-sdk

Transports (plain TCP/TLS, qt_local, qt_remote/QRO, mock), token manager,
consumer core (LogosAPIClient/LogosAPIConsumer incl. the capability
auto-requestModule flow), ModuleProxy, the abstract LogosProviderObject
interface, and the canonical QVariant<->JSON conversion — now behind the
language-neutral lp_* C ABI (logos_protocol.h) carrying the protocol
semver (LOGOS_PROTOCOL_VERSION_*, lp_protocol_version()).

Bytes crossing the ABI use the lossless {"_bytes": base64url} tagging
(NUL-safe), matching the plain wire encoding.

Provider lp_* surface is compiled groundwork; serving lands with module
authoring.

* consumer: typed requestModule for the capability flow

Port of logos-cpp-sdk master f5a127dd ('use updated capability module',
cpp-sdk#85, Iuri Matias) — the touched files (logos_api_client.cpp,
logos_api_consumer.{h,cpp}) moved into this repo in the P1 extraction.
The capability auto-requestModule path now calls a typed std::string
helper on the consumer (which acquires the capability object directly)
instead of a stringly invokeRemoteMethod round-trip. 111/111 tests.
2026-06-12 18:59:01 -03:00

61 lines
2.5 KiB
C++

#ifndef LOGOS_PLAIN_INCOMING_CALL_HANDLER_H
#define LOGOS_PLAIN_INCOMING_CALL_HANDLER_H
#include "rpc_message.h"
#include <functional>
namespace logos::plain {
// -----------------------------------------------------------------------------
// IncomingCallHandler — provider-side dispatch hook.
//
// rpc_connection hands inbound Call / Methods / Subscribe / Unsubscribe /
// Token messages to a handler that the Qt-boundary layer implements. The
// handler is what talks to the published QObject (ModuleProxy); this
// interface deliberately speaks only plain C++ types so the wire stack
// stays Qt-free.
//
// The reply callbacks can be invoked synchronously (from inside the
// handler) or asynchronously from a different thread — rpc_connection
// serializes the actual frame write internally.
// -----------------------------------------------------------------------------
class IncomingCallHandler {
public:
virtual ~IncomingCallHandler() = default;
using CallReply = std::function<void(ResultMessage)>;
using MethodsReply = std::function<void(MethodsResultMessage)>;
using EventSink = std::function<void(EventMessage)>;
virtual void onCall(const CallMessage& req, CallReply reply) = 0;
virtual void onMethods(const MethodsMessage& req, MethodsReply reply) = 0;
// `sink` stays alive until onUnsubscribe fires or the connection
// dies. The handler must call `sink(evt)` on every matching emission.
//
// `connectionId` is an opaque per-connection token (the rpc layer
// passes the connection's `this` pointer). The handler keys sinks
// by it so a subsequent onUnsubscribe / onConnectionClosed can
// remove only the sinks belonging to that connection — sub/unsub
// frames don't carry a subscriber identifier on the wire.
virtual void onSubscribe(const SubscribeMessage& req, EventSink sink,
const void* connectionId) = 0;
virtual void onUnsubscribe(const UnsubscribeMessage& req,
const void* connectionId) = 0;
// Called when a connection is torn down (graceful close or error)
// so the handler can drop any sinks still keyed to it. Without
// this, a dropped client leaks subscriptions and the host keeps
// fanning events into dead sinks.
virtual void onConnectionClosed(const void* connectionId) = 0;
virtual void onToken(const TokenMessage& req) = 0;
};
} // namespace logos::plain
#endif // LOGOS_PLAIN_INCOMING_CALL_HANDLER_H