168 lines
5.9 KiB
C
168 lines
5.9 KiB
C
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#include "esp_err.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define SESSION_BROKER_MAX_CLIENTS 8U
|
|
#define SESSION_BROKER_CLIENT_NAME_MAX 23U
|
|
#define SESSION_BROKER_OUTPUT_SIZE 4096U
|
|
#define SESSION_BROKER_EVENT_QUEUE_LENGTH 16U
|
|
|
|
typedef uint32_t session_broker_client_id_t;
|
|
|
|
/* ID zero is reserved for "no client" and, specifically, "no writer". */
|
|
#define SESSION_BROKER_NO_CLIENT ((session_broker_client_id_t)0U)
|
|
|
|
typedef enum {
|
|
SESSION_BROKER_CLIENT_CONSOLE = 0,
|
|
SESSION_BROKER_CLIENT_USB,
|
|
SESSION_BROKER_CLIENT_WEB,
|
|
SESSION_BROKER_CLIENT_SSH,
|
|
SESSION_BROKER_CLIENT_INTERNAL,
|
|
} session_broker_client_type_t;
|
|
|
|
typedef enum {
|
|
SESSION_BROKER_EVENT_CONNECT = 0,
|
|
SESSION_BROKER_EVENT_DISCONNECT,
|
|
SESSION_BROKER_EVENT_WRITER_GRANTED,
|
|
SESSION_BROKER_EVENT_WRITER_RELEASED,
|
|
SESSION_BROKER_EVENT_WRITER_REVOKED,
|
|
SESSION_BROKER_EVENT_WRITER_DENIED,
|
|
} session_broker_event_type_t;
|
|
|
|
/*
|
|
* Events contain no pointers, so transports can encode them without lifetime
|
|
* concerns. sequence is broker-global and strictly increases per event.
|
|
* client_id identifies the subject; writer_id is the writer after the event.
|
|
*/
|
|
typedef struct {
|
|
uint64_t sequence;
|
|
session_broker_event_type_t type;
|
|
session_broker_client_id_t client_id;
|
|
session_broker_client_id_t writer_id;
|
|
} session_broker_event_t;
|
|
|
|
typedef struct {
|
|
/* UART bytes considered for delivery while this client was connected. */
|
|
uint64_t uart_rx_bytes;
|
|
uint64_t output_queued_bytes;
|
|
uint64_t output_read_bytes;
|
|
uint64_t output_dropped_bytes;
|
|
uint64_t tx_accepted_bytes;
|
|
uint64_t tx_rejected_bytes;
|
|
uint64_t connections;
|
|
uint64_t writer_requests;
|
|
uint64_t writer_grants;
|
|
uint64_t writer_releases;
|
|
uint64_t writer_revocations;
|
|
uint64_t writer_denials;
|
|
uint64_t writer_changes;
|
|
uint64_t events_queued;
|
|
uint64_t events_popped;
|
|
uint64_t event_drops;
|
|
} session_broker_client_counters_t;
|
|
|
|
typedef struct {
|
|
uint64_t uart_rx_bytes;
|
|
/* UART RX drained when there were no connected observers. */
|
|
uint64_t unobserved_rx_bytes;
|
|
/* Queue/read/drop totals count one copy per client observer. */
|
|
uint64_t output_queued_bytes;
|
|
uint64_t output_read_bytes;
|
|
uint64_t output_dropped_bytes;
|
|
uint64_t tx_accepted_bytes;
|
|
uint64_t tx_rejected_bytes;
|
|
uint64_t connections;
|
|
uint64_t disconnections;
|
|
uint64_t writer_requests;
|
|
uint64_t writer_grants;
|
|
uint64_t writer_releases;
|
|
uint64_t writer_revocations;
|
|
uint64_t writer_denials;
|
|
uint64_t writer_changes;
|
|
uint64_t events_generated;
|
|
uint64_t events_queued;
|
|
uint64_t events_popped;
|
|
uint64_t event_drops;
|
|
} session_broker_global_counters_t;
|
|
|
|
typedef struct {
|
|
session_broker_client_id_t id;
|
|
session_broker_client_type_t type;
|
|
char name[SESSION_BROKER_CLIENT_NAME_MAX + 1U];
|
|
bool is_writer;
|
|
size_t output_bytes_pending;
|
|
uint32_t events_pending;
|
|
session_broker_client_counters_t counters;
|
|
} session_broker_client_snapshot_t;
|
|
|
|
typedef struct {
|
|
session_broker_client_id_t writer_id;
|
|
uint32_t connected_clients;
|
|
uint64_t latest_event_sequence;
|
|
session_broker_global_counters_t counters;
|
|
} session_broker_global_snapshot_t;
|
|
|
|
/*
|
|
* Allocates all eight output streams and event queues, then starts the
|
|
* permanent broker task. The serial service must already be initialized
|
|
* before the first client connects.
|
|
*/
|
|
esp_err_t session_broker_init(void);
|
|
|
|
esp_err_t session_broker_connect(session_broker_client_type_t type,
|
|
const char *name,
|
|
session_broker_client_id_t *client_id);
|
|
esp_err_t session_broker_disconnect(session_broker_client_id_t client_id);
|
|
|
|
/*
|
|
* There is exactly one writer lease. Requests are granted only while idle;
|
|
* a competing request emits WRITER_DENIED. Force with ID zero revokes the
|
|
* current writer without assigning a replacement.
|
|
*/
|
|
esp_err_t session_broker_request_writer(session_broker_client_id_t client_id);
|
|
esp_err_t session_broker_release_writer(session_broker_client_id_t client_id);
|
|
esp_err_t session_broker_force_writer(session_broker_client_id_t client_id);
|
|
/* Revoke only if the expected client still owns the writer lease. */
|
|
esp_err_t session_broker_force_release_writer(session_broker_client_id_t expected_writer_id);
|
|
session_broker_client_id_t session_broker_get_writer_id(void);
|
|
|
|
/*
|
|
* Binary-transparent, zero-time data operations. write is accepted only from
|
|
* the current writer. read has one logical caller per connected transport.
|
|
* Partial transfers are normal and are reported through the output count.
|
|
*/
|
|
esp_err_t session_broker_write(session_broker_client_id_t client_id,
|
|
const uint8_t *data,
|
|
size_t size,
|
|
size_t *accepted);
|
|
esp_err_t session_broker_read(session_broker_client_id_t client_id,
|
|
uint8_t *data,
|
|
size_t size,
|
|
size_t *received);
|
|
esp_err_t session_broker_pop_event(session_broker_client_id_t client_id,
|
|
session_broker_event_t *event);
|
|
|
|
esp_err_t session_broker_get_client_snapshot(session_broker_client_id_t client_id,
|
|
session_broker_client_snapshot_t *snapshot);
|
|
esp_err_t session_broker_get_global_snapshot(session_broker_global_snapshot_t *snapshot);
|
|
|
|
/* Returns the number copied. Pass NULL with capacity zero to count clients. */
|
|
size_t session_broker_list_clients(session_broker_client_snapshot_t *clients,
|
|
size_t capacity);
|
|
|
|
/* Counter clearing does not reset client IDs, queued data, or event sequence. */
|
|
esp_err_t session_broker_clear_counters(void);
|
|
esp_err_t session_broker_clear_client_counters(session_broker_client_id_t client_id);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|