Files
logos-protocol/cpp/logos_transport_config_json.cpp
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

102 lines
3.0 KiB
C++

#include "logos_transport_config_json.h"
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace logos {
namespace {
const char* protocolToString(LogosProtocol p)
{
switch (p) {
case LogosProtocol::LocalSocket: return "local";
case LogosProtocol::Tcp: return "tcp";
case LogosProtocol::TcpSsl: return "tcp_ssl";
}
return "local";
}
LogosProtocol protocolFromString(const std::string& s)
{
if (s == "tcp") return LogosProtocol::Tcp;
if (s == "tcp_ssl") return LogosProtocol::TcpSsl;
return LogosProtocol::LocalSocket;
}
const char* codecToString(LogosWireCodec c)
{
switch (c) {
case LogosWireCodec::Cbor: return "cbor";
case LogosWireCodec::Json: return "json";
}
return "json";
}
LogosWireCodec codecFromString(const std::string& s)
{
if (s == "cbor") return LogosWireCodec::Cbor;
return LogosWireCodec::Json;
}
} // namespace
std::string transportSetToJsonString(const LogosTransportSet& set)
{
json arr = json::array();
for (const auto& cfg : set) {
json o;
o["protocol"] = protocolToString(cfg.protocol);
if (cfg.protocol != LogosProtocol::LocalSocket) {
o["host"] = cfg.host;
o["port"] = cfg.port;
o["codec"] = codecToString(cfg.codec);
}
if (cfg.protocol == LogosProtocol::TcpSsl) {
// Cert/key paths intentionally included — this serialization
// is the parent → child handoff so the child knows what
// files to load when binding its TLS listener.
if (!cfg.caFile.empty()) o["ca_file"] = cfg.caFile;
if (!cfg.certFile.empty()) o["cert_file"] = cfg.certFile;
if (!cfg.keyFile.empty()) o["key_file"] = cfg.keyFile;
o["verify_peer"] = cfg.verifyPeer;
}
arr.push_back(std::move(o));
}
return arr.dump(); // single-line, suitable for CLI / env-var passing
}
LogosTransportSet transportSetFromJsonString(const std::string& jsonStr)
{
LogosTransportSet out;
if (jsonStr.empty()) return out;
json arr;
try {
arr = json::parse(jsonStr);
} catch (const json::exception&) {
return out;
}
if (!arr.is_array()) return out;
for (const auto& o : arr) {
if (!o.is_object()) continue;
LogosTransportConfig cfg;
cfg.protocol = protocolFromString(o.value("protocol", std::string{"local"}));
cfg.host = o.value("host", std::string{"127.0.0.1"});
const int rawPort = o.value("port", 0);
if (rawPort < 0 || rawPort > 0xFFFF) continue;
cfg.port = static_cast<uint16_t>(rawPort);
cfg.codec = codecFromString(o.value("codec", std::string{"json"}));
cfg.caFile = o.value("ca_file", std::string{});
cfg.certFile = o.value("cert_file", std::string{});
cfg.keyFile = o.value("key_file", std::string{});
cfg.verifyPeer = o.value("verify_peer", true);
out.push_back(std::move(cfg));
}
return out;
}
} // namespace logos