91 lines
3.7 KiB
C++
91 lines
3.7 KiB
C++
/*
|
|
* BastionGuard™ Secure Connection
|
|
* Copyright (C) 2025–2026 Calogero Scarnà
|
|
* GPL-3.0
|
|
*
|
|
* Protocollo wire daemon ↔ UI.
|
|
*
|
|
* Trasporto: Unix domain socket (SOCK_STREAM).
|
|
* Framing: 4 byte little-endian length (uint32) + payload JSON UTF-8.
|
|
* Nessun terminatore, nessun escape: la lunghezza e' l'unico marker.
|
|
*
|
|
* La UI e' sempre il server. Il daemon si connette come client.
|
|
*
|
|
* Ogni messaggio ha due campi obbligatori:
|
|
* "type": stringa, identifica il tipo di messaggio
|
|
* "id": uint64, correlazione per richieste/risposte
|
|
*
|
|
* Direzione daemon → UI:
|
|
* hello -> primo messaggio, { type, id, daemon_version }
|
|
* ping -> heartbeat, { type, id, stats: {...} }
|
|
* ask_rule -> richiede decisione utente, { type, id, connection: {...} }
|
|
* La UI risponde con ask_rule_reply con stesso id.
|
|
* alert -> notifica informativa, { type, id, level, what, text, connection? }
|
|
*
|
|
* Direzione UI → daemon:
|
|
* pong -> risposta a ping, { type, id }
|
|
* ask_rule_reply -> risposta a ask_rule, { type, id, action, duration, rule_name? }
|
|
* notification -> notifica runtime, { type, id, kind, data? }
|
|
* kind ∈ { stop, reload_rules, change_config, enable_interception,
|
|
* disable_interception, log_level, ... }
|
|
*/
|
|
|
|
#pragma once
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
#include <optional>
|
|
|
|
namespace bsc::proto {
|
|
|
|
// Path di default del socket Unix della UI.
|
|
inline constexpr const char* kDefaultSocketPath = "/tmp/bsd-daemon.sock";
|
|
|
|
// Tipi di messaggi.
|
|
namespace msg {
|
|
inline constexpr std::string_view kHello = "hello";
|
|
inline constexpr std::string_view kPing = "ping";
|
|
inline constexpr std::string_view kPong = "pong";
|
|
inline constexpr std::string_view kAskRule = "ask_rule";
|
|
inline constexpr std::string_view kAskRuleReply = "ask_rule_reply";
|
|
inline constexpr std::string_view kAlert = "alert";
|
|
inline constexpr std::string_view kNotification = "notification";
|
|
} // namespace msg
|
|
|
|
// Risoluzione socketPath: accetta sia "/tmp/foo.sock" sia "unix:///tmp/foo.sock".
|
|
inline std::string resolve_socket_path(std::string uri) {
|
|
static const std::string prefix = "unix://";
|
|
if (uri.rfind(prefix, 0) == 0) uri = uri.substr(prefix.size());
|
|
return uri;
|
|
}
|
|
|
|
// Codifica un payload JSON in un frame [uint32 LE length][payload]. Inserisce
|
|
// nel vettore `out` senza allocare di piu'.
|
|
inline void frame_encode(std::string_view payload, std::vector<std::uint8_t>& out) {
|
|
const std::uint32_t len = static_cast<std::uint32_t>(payload.size());
|
|
out.resize(4 + payload.size());
|
|
out[0] = static_cast<std::uint8_t>(len & 0xff);
|
|
out[1] = static_cast<std::uint8_t>((len >> 8) & 0xff);
|
|
out[2] = static_cast<std::uint8_t>((len >> 16) & 0xff);
|
|
out[3] = static_cast<std::uint8_t>((len >> 24) & 0xff);
|
|
std::memcpy(out.data() + 4, payload.data(), payload.size());
|
|
}
|
|
|
|
// Legge 4 byte di lunghezza dal buffer. Restituisce -1 se il buffer non ha
|
|
// almeno 4 byte.
|
|
inline std::int64_t frame_peek_length(const std::uint8_t* buf, std::size_t len) {
|
|
if (len < 4) return -1;
|
|
return static_cast<std::uint32_t>(buf[0])
|
|
| (static_cast<std::uint32_t>(buf[1]) << 8)
|
|
| (static_cast<std::uint32_t>(buf[2]) << 16)
|
|
| (static_cast<std::uint32_t>(buf[3]) << 24);
|
|
}
|
|
|
|
// Dimensione massima accettabile di un frame (DoS guard). 4 MiB e' ampiamente
|
|
// sufficiente per i messaggi del protocollo: AskRule col process tree piu'
|
|
// grande mai visto sta sotto i 64 KiB.
|
|
inline constexpr std::size_t kMaxFrameSize = 4u * 1024u * 1024u;
|
|
|
|
} // namespace bsc::proto
|