Skip to content
API Documentation
BastionGuard™
bsc::ui::UIClient::Impl Class Reference

Classes

struct  PendingAsk

Public Member Functions

 Impl (std::string uri)
 ~Impl ()
void start ()
void stop ()
bool is_connected () const noexcept
int connect_once () const
void reconnect_loop ()
bool write_frame (const std::string &payload)
bool read_exact (int fd, std::uint8_t *buf, std::size_t n)
void read_until_eof ()
void dispatch_incoming (const json &j)
bool send_hello ()
void flush_queued_alerts ()
bool send_or_queue_alert (const json &j)

Public Attributes

std::string socket_path_
std::atomic_bool running_ {false}
std::atomic_int fd_ {-1}
std::atomic_bool handshake_done_ {false}
std::thread reader_thread_
std::mutex write_mutex_
std::atomic_uint64_t next_id_ {1}
std::mutex pending_mutex_
std::unordered_map< std::uint64_t, std::shared_ptr< PendingAsk > > pending_asks_
std::mutex handler_mutex_
std::function< void(const NotificationEvent &)> notif_handler_
std::mutex alerts_mutex_
std::deque< std::string > queued_alerts_

Detailed Description

Definition at line 97 of file UIClient.cpp.

Constructor & Destructor Documentation

◆ Impl()

bsc::ui::UIClient::Impl::Impl ( std::string uri)
inlineexplicit

Definition at line 99 of file UIClient.cpp.

std::string resolve_socket_path(std::string uri)
Definition Wire.hpp:58

References socket_path_.

◆ ~Impl()

bsc::ui::UIClient::Impl::~Impl ( )
inline

Definition at line 102 of file UIClient.cpp.

102{ stop(); }

References stop().

Member Function Documentation

◆ connect_once()

int bsc::ui::UIClient::Impl::connect_once ( ) const
inline

Definition at line 171 of file UIClient.cpp.

171 {
172 int fd = ::socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
173 if (fd < 0) return -1;
174 sockaddr_un addr{};
175 addr.sun_family = AF_UNIX;
176 if (socket_path_.size() >= sizeof(addr.sun_path)) { ::close(fd); return -1; }
177 std::memcpy(addr.sun_path, socket_path_.c_str(), socket_path_.size());
178 if (::connect(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
179 ::close(fd);
180 return -1;
181 }
182 return fd;
183 }

References socket_path_.

Referenced by reconnect_loop().

◆ dispatch_incoming()

void bsc::ui::UIClient::Impl::dispatch_incoming ( const json & j)
inline

Definition at line 287 of file UIClient.cpp.

287 {
288 const std::string type = j.value("type", std::string{});
289 if (type == bsc::proto::msg::kPong) {
290 // Nothing to do: e' una conferma di heartbeat.
291 return;
292 }
293 if (type == bsc::proto::msg::kAskRuleReply) {
294 const auto id = j.value("id", std::uint64_t{0});
295 std::shared_ptr<PendingAsk> p;
296 {
297 std::lock_guard<std::mutex> lk(pending_mutex_);
298 auto it = pending_asks_.find(id);
299 if (it == pending_asks_.end()) return;
300 p = it->second;
301 }
302 {
303 std::lock_guard<std::mutex> l2(p->mu);
304 p->reply = j;
305 p->ready = true;
306 }
307 p->cv.notify_all();
308 return;
309 }
310 if (type == bsc::proto::msg::kNotification) {
311 NotificationEvent ev;
312 ev.id = j.value("id", std::uint64_t{0});
313 ev.type = j.value("kind", std::string{});
314 ev.data = j.value("data", std::string{});
315 if (j.contains("rules") && j["rules"].is_array()) {
316 for (const auto& r : j["rules"]) ev.rules.push_back(rule_from_json(r));
317 }
318 std::function<void(const NotificationEvent&)> cb;
319 {
320 std::lock_guard<std::mutex> lk(handler_mutex_);
321 cb = notif_handler_;
322 }
323 if (cb) cb(ev);
324 return;
325 }
327 "UIClient: messaggio di tipo sconosciuto: " + type);
328 }
void warning(const std::string &msg)
Definition Logger.cpp:22
static Logger & instance()
Definition Logger.cpp:11
std::unordered_map< std::uint64_t, std::shared_ptr< PendingAsk > > pending_asks_
Definition UIClient.cpp:126
std::function< void(const NotificationEvent &)> notif_handler_
Definition UIClient.cpp:130
constexpr std::string_view kAskRuleReply
Definition Wire.hpp:52
constexpr std::string_view kPong
Definition Wire.hpp:50
constexpr std::string_view kNotification
Definition Wire.hpp:54
bsc::rule::Rule rule_from_json(const json &j)
Definition UIClient.cpp:79

References bsc::ui::NotificationEvent::data, handler_mutex_, bsc::ui::NotificationEvent::id, bsc::logging::Logger::instance(), bsc::proto::msg::kAskRuleReply, bsc::proto::msg::kNotification, bsc::proto::msg::kPong, notif_handler_, pending_asks_, pending_mutex_, bsc::ui::NotificationEvent::rules, bsc::ui::NotificationEvent::type, and bsc::logging::Logger::warning().

Referenced by read_until_eof().

◆ flush_queued_alerts()

void bsc::ui::UIClient::Impl::flush_queued_alerts ( )
inline

Definition at line 341 of file UIClient.cpp.

341 {
342 std::deque<std::string> q;
343 {
344 std::lock_guard<std::mutex> lk(alerts_mutex_);
345 q.swap(queued_alerts_);
346 }
347 for (const auto& payload : q) {
348 if (!write_frame(payload)) {
349 // Rimetti in coda quello che non siamo riusciti a spedire
350 std::lock_guard<std::mutex> lk(alerts_mutex_);
351 queued_alerts_.push_front(payload);
352 break;
353 }
354 }
355 }
std::deque< std::string > queued_alerts_
Definition UIClient.cpp:134
bool write_frame(const std::string &payload)
Definition UIClient.cpp:228

References alerts_mutex_, queued_alerts_, and write_frame().

Referenced by reconnect_loop().

◆ is_connected()

bool bsc::ui::UIClient::Impl::is_connected ( ) const
inlinenoexcept

Definition at line 164 of file UIClient.cpp.

164 {
165 return fd_.load() >= 0 && handshake_done_.load();
166 }
std::atomic_int fd_
Definition UIClient.cpp:108
std::atomic_bool handshake_done_
Definition UIClient.cpp:109

References fd_, and handshake_done_.

Referenced by send_or_queue_alert().

◆ read_exact()

bool bsc::ui::UIClient::Impl::read_exact ( int fd,
std::uint8_t * buf,
std::size_t n )
inline

Definition at line 247 of file UIClient.cpp.

247 {
248 std::size_t got = 0;
249 while (got < n) {
250 ssize_t r = ::recv(fd, buf + got, n - got, 0);
251 if (r == 0) return false; // EOF
252 if (r < 0) {
253 if (errno == EINTR) continue;
254 return false;
255 }
256 got += static_cast<std::size_t>(r);
257 }
258 return true;
259 }

Referenced by read_until_eof().

◆ read_until_eof()

void bsc::ui::UIClient::Impl::read_until_eof ( )
inline

Definition at line 262 of file UIClient.cpp.

262 {
263 auto& log = bsc::logging::Logger::instance();
264 int fd = fd_.load();
265 while (fd >= 0 && running_) {
266 std::uint8_t len_buf[4];
267 if (!read_exact(fd, len_buf, 4)) break;
268 const std::int64_t len = bsc::proto::frame_peek_length(len_buf, 4);
269 if (len < 0 || static_cast<std::size_t>(len) > bsc::proto::kMaxFrameSize) {
270 log.warning("UIClient: frame invalido, chiudo connessione");
271 break;
272 }
273 std::vector<std::uint8_t> payload(static_cast<std::size_t>(len));
274 if (!read_exact(fd, payload.data(), payload.size())) break;
275
276 try {
277 json j = json::parse(payload.begin(), payload.end());
279 } catch (const std::exception& e) {
280 log.warning(std::string("UIClient: JSON invalido: ") + e.what());
281 }
282 fd = fd_.load();
283 }
284 }
std::atomic_bool running_
Definition UIClient.cpp:107
void dispatch_incoming(const json &j)
Definition UIClient.cpp:287
bool read_exact(int fd, std::uint8_t *buf, std::size_t n)
Definition UIClient.cpp:247
constexpr std::size_t kMaxFrameSize
Definition Wire.hpp:89
std::int64_t frame_peek_length(const std::uint8_t *buf, std::size_t len)
Definition Wire.hpp:78
nlohmann::json json
Definition UIClient.cpp:29

References dispatch_incoming(), fd_, bsc::proto::frame_peek_length(), bsc::logging::Logger::instance(), bsc::proto::kMaxFrameSize, read_exact(), and running_.

Referenced by reconnect_loop().

◆ reconnect_loop()

void bsc::ui::UIClient::Impl::reconnect_loop ( )
inline

Definition at line 185 of file UIClient.cpp.

185 {
186 auto& log = bsc::logging::Logger::instance();
187 bool previously_connected = false;
188 while (running_) {
189 int fd = connect_once();
190 if (fd < 0) {
191 if (previously_connected) {
192 log.warning("UI disconnessa, tento la riconnessione...");
193 previously_connected = false;
194 }
195 std::this_thread::sleep_for(std::chrono::seconds(1));
196 continue;
197 }
198
199 fd_ = fd;
200 handshake_done_ = false;
201
202 // Invia hello immediatamente
203 if (!send_hello()) {
204 ::close(fd);
205 fd_ = -1;
206 std::this_thread::sleep_for(std::chrono::seconds(1));
207 continue;
208 }
209
210 handshake_done_ = true;
211 previously_connected = true;
212 log.info("UI connessa su " + socket_path_);
214
215 // Loop di lettura finche' il socket non si chiude
217
218 // Disconnesso: pulisci
219 int old = fd_.exchange(-1);
220 if (old >= 0) ::close(old);
221 handshake_done_ = false;
222 }
223 }

References connect_once(), fd_, flush_queued_alerts(), handshake_done_, bsc::logging::Logger::instance(), read_until_eof(), running_, send_hello(), and socket_path_.

Referenced by start().

◆ send_hello()

bool bsc::ui::UIClient::Impl::send_hello ( )
inline

Definition at line 332 of file UIClient.cpp.

332 {
333 json j = {
334 {"type", bsc::proto::msg::kHello},
335 {"id", next_id_++},
336 {"daemon_version", "bsc-daemon-cpp"}
337 };
338 return write_frame(j.dump());
339 }
std::atomic_uint64_t next_id_
Definition UIClient.cpp:116
constexpr std::string_view kHello
Definition Wire.hpp:48

References bsc::proto::msg::kHello, next_id_, and write_frame().

Referenced by reconnect_loop().

◆ send_or_queue_alert()

bool bsc::ui::UIClient::Impl::send_or_queue_alert ( const json & j)
inline

Definition at line 358 of file UIClient.cpp.

358 {
359 const std::string payload = j.dump();
360 if (is_connected() && write_frame(payload)) return true;
361 std::lock_guard<std::mutex> lk(alerts_mutex_);
362 if (queued_alerts_.size() >= 128) queued_alerts_.pop_front();
363 queued_alerts_.push_back(payload);
364 return true;
365 }
bool is_connected() const noexcept
Definition UIClient.cpp:164

References alerts_mutex_, is_connected(), queued_alerts_, and write_frame().

◆ start()

void bsc::ui::UIClient::Impl::start ( )
inline

Definition at line 138 of file UIClient.cpp.

138 {
139 if (running_.exchange(true)) return;
140 reader_thread_ = std::thread([this]() { reconnect_loop(); });
141 }
std::thread reader_thread_
Definition UIClient.cpp:110

References reader_thread_, reconnect_loop(), and running_.

◆ stop()

void bsc::ui::UIClient::Impl::stop ( )
inline

Definition at line 143 of file UIClient.cpp.

143 {
144 running_ = false;
145 int fd = fd_.exchange(-1);
146 if (fd >= 0) {
147 ::shutdown(fd, SHUT_RDWR);
148 ::close(fd);
149 }
150 // Sblocca qualunque ask_rule bloccato
151 {
152 std::lock_guard<std::mutex> lk(pending_mutex_);
153 for (auto& [id, p] : pending_asks_) {
154 std::lock_guard<std::mutex> l2(p->mu);
155 p->ready = true;
156 p->reply = json::object(); // risposta vuota = timeout
157 p->cv.notify_all();
158 }
159 pending_asks_.clear();
160 }
161 if (reader_thread_.joinable()) reader_thread_.join();
162 }

References fd_, pending_asks_, pending_mutex_, reader_thread_, and running_.

Referenced by ~Impl().

◆ write_frame()

bool bsc::ui::UIClient::Impl::write_frame ( const std::string & payload)
inline

Definition at line 228 of file UIClient.cpp.

228 {
229 int fd = fd_.load();
230 if (fd < 0) return false;
231 std::vector<std::uint8_t> frame;
232 bsc::proto::frame_encode(payload, frame);
233 std::lock_guard<std::mutex> lk(write_mutex_);
234 std::size_t total = 0;
235 while (total < frame.size()) {
236 ssize_t n = ::send(fd, frame.data() + total, frame.size() - total, MSG_NOSIGNAL);
237 if (n < 0) {
238 if (errno == EINTR) continue;
239 return false;
240 }
241 total += static_cast<std::size_t>(n);
242 }
243 return true;
244 }
void frame_encode(std::string_view payload, std::vector< std::uint8_t > &out)
Definition Wire.hpp:66

References fd_, bsc::proto::frame_encode(), and write_mutex_.

Referenced by flush_queued_alerts(), send_hello(), and send_or_queue_alert().

Member Data Documentation

◆ alerts_mutex_

std::mutex bsc::ui::UIClient::Impl::alerts_mutex_

Definition at line 133 of file UIClient.cpp.

Referenced by flush_queued_alerts(), and send_or_queue_alert().

◆ fd_

std::atomic_int bsc::ui::UIClient::Impl::fd_ {-1}

Definition at line 108 of file UIClient.cpp.

Referenced by is_connected(), read_until_eof(), reconnect_loop(), stop(), and write_frame().

◆ handler_mutex_

std::mutex bsc::ui::UIClient::Impl::handler_mutex_

Definition at line 129 of file UIClient.cpp.

Referenced by dispatch_incoming().

◆ handshake_done_

std::atomic_bool bsc::ui::UIClient::Impl::handshake_done_ {false}

Definition at line 109 of file UIClient.cpp.

Referenced by is_connected(), and reconnect_loop().

◆ next_id_

std::atomic_uint64_t bsc::ui::UIClient::Impl::next_id_ {1}

Definition at line 116 of file UIClient.cpp.

Referenced by send_hello().

◆ notif_handler_

std::function<void(const NotificationEvent&)> bsc::ui::UIClient::Impl::notif_handler_

Definition at line 130 of file UIClient.cpp.

Referenced by dispatch_incoming().

◆ pending_asks_

std::unordered_map<std::uint64_t, std::shared_ptr<PendingAsk> > bsc::ui::UIClient::Impl::pending_asks_

Definition at line 126 of file UIClient.cpp.

Referenced by dispatch_incoming(), and stop().

◆ pending_mutex_

std::mutex bsc::ui::UIClient::Impl::pending_mutex_

Definition at line 125 of file UIClient.cpp.

Referenced by dispatch_incoming(), and stop().

◆ queued_alerts_

std::deque<std::string> bsc::ui::UIClient::Impl::queued_alerts_

Definition at line 134 of file UIClient.cpp.

Referenced by flush_queued_alerts(), and send_or_queue_alert().

◆ reader_thread_

std::thread bsc::ui::UIClient::Impl::reader_thread_

Definition at line 110 of file UIClient.cpp.

Referenced by start(), and stop().

◆ running_

std::atomic_bool bsc::ui::UIClient::Impl::running_ {false}

Definition at line 107 of file UIClient.cpp.

Referenced by read_until_eof(), reconnect_loop(), start(), and stop().

◆ socket_path_

std::string bsc::ui::UIClient::Impl::socket_path_

Definition at line 104 of file UIClient.cpp.

Referenced by connect_once(), Impl(), and reconnect_loop().

◆ write_mutex_

std::mutex bsc::ui::UIClient::Impl::write_mutex_

Definition at line 113 of file UIClient.cpp.

Referenced by write_frame().


The documentation for this class was generated from the following file:
  • BastionGuard/thirdparty/bastionguard-secure-connection/daemon/src/ui/UIClient.cpp