diff --git a/include/bravais.h b/include/bravais.h index f795dd6..ef3ed6f 100644 --- a/include/bravais.h +++ b/include/bravais.h @@ -33,6 +33,8 @@ typedef enum { BRAVAIS_ERR_MALFORMED = -3, BRAVAIS_ERR_OUT_OF_MEMORY = -4, BRAVAIS_ERR_UNSUPPORTED = -5, + BRAVAIS_ERR_AUTH = -6, + BRAVAIS_ERR_STATE = -7, BRAVAIS_ERR_UNKNOWN = -1000 } bravais_result_t; diff --git a/src/proto/conn.c b/src/proto/conn.c new file mode 100644 index 0000000..b500127 --- /dev/null +++ b/src/proto/conn.c @@ -0,0 +1,125 @@ +// conn.c +// Top-level connection object and the public API surface +// +// Lifecycle made but the data path is a stub for now. + +#include "proto/conn.h" +#include "util/hygiene.h" + +#include + +static void conn_log(const bravais_conn_t* conn, bravais_log_level_t level, const char* msg) { + if (!conn->config.logFn) { return; } + conn->config.logFn(conn->config.logUserData, level, msg); +} + +static bool config_is_valid(const bravais_config_t* config) { + if (!config) { return false; } + if (config->role != BRAVAIS_ROLE_INITIATOR && config->role != BRAVAIS_ROLE_RESPONDER) { return false; } + if (config->transportMode != BRAVAIS_TRANSPORT_RAW && config->transportMode != BRAVAIS_TRANSPORT_QUIC) { return false; } + + return true; +} + +void bravais_config_init(bravais_config_t* config) { + if (!config) { return; } + + config->role = BRAVAIS_ROLE_INITIATOR; + config->transportMode = BRAVAIS_TRANSPORT_RAW; + config->logFn = nullptr; + config->logUserData = nullptr; +} + +bravais_result_t bravais_conn_create(const bravais_config_t* config, bravais_conn_t** outConn) { + if (!outConn) { return BRAVAIS_ERR_INVALID_ARG; } + *outConn = nullptr; + + if (!config || !config_is_valid(config)) { return BRAVAIS_ERR_INVALID_ARG; } + + bravais_conn_t* newConn = (bravais_conn_t*)calloc(1, sizeof(*newConn)); + if (!newConn) { return BRAVAIS_ERR_OUT_OF_MEMORY; } + + newConn->config = *config; + newConn->state = BRAVAIS_CONN_STATE_IDLE; + + conn_log(newConn, BRAVAIS_LOG_LEVEL_DEBUG, "Connection created"); + *outConn = newConn; + + return BRAVAIS_OK; +} + +void bravais_conn_destroy(bravais_conn_t* conn) { + if (!conn) { return; } + + bravais_hygiene_zero(conn, sizeof(*conn)); + free(conn); + conn_log(conn, BRAVAIS_LOG_LEVEL_DEBUG, "Connection destroyed"); +} + +bravais_result_t bravais_recv_datagram(bravais_conn_t* conn, const uint8_t* buf, size_t bufLen, [[maybe_unused]] uint64_t nowMs) { + if (!conn || (!buf && bufLen != 0)) { + return BRAVAIS_ERR_INVALID_ARG; + } + return BRAVAIS_ERR_UNSUPPORTED; +} + +bravais_result_t bravais_send_packet(bravais_conn_t* conn, const uint8_t* buf, size_t bufLen, [[maybe_unused]] uint64_t nowMs) { + if (!conn || (!buf && bufLen != 0)) { + return BRAVAIS_ERR_INVALID_ARG; + } + + if (bufLen > BRAVAIS_MAX_PLAINTEXT_SIZE) { + return BRAVAIS_ERR_INVALID_ARG; + } + + return BRAVAIS_ERR_UNSUPPORTED; +} + +bravais_result_t bravais_poll_datagram(bravais_conn_t* conn, uint8_t* out, size_t* outLen, [[maybe_unused]] uint64_t nowMs) { + if (!conn || !out || !outLen) { + return BRAVAIS_ERR_INVALID_ARG; + } + + *outLen = 0; + + return BRAVAIS_ERR_UNSUPPORTED; +} + +bravais_result_t bravais_poll_plaintext(bravais_conn_t* conn, uint8_t* out, size_t* outLen, [[maybe_unused]] uint64_t nowMs) { + if (!conn || !out || !outLen) { + return BRAVAIS_ERR_INVALID_ARG; + } + + *outLen = 0; + + return BRAVAIS_EMPTY; +} + +uint64_t bravais_next_timeout([[maybe_unused]] const bravais_conn_t* conn) { + return UINT64_MAX; +} + +bravais_result_t bravais_on_timeout(bravais_conn_t* conn, [[maybe_unused]] uint64_t nowMs) { + if (!conn) { + return BRAVAIS_ERR_INVALID_ARG; + } + + return BRAVAIS_OK; +} + +const char* bravais_result_str(bravais_result_t result) { + switch (result) { + case BRAVAIS_OK: return "OK"; + case BRAVAIS_EMPTY: return "Nothing to emit right now"; + case BRAVAIS_ERR_INVALID_ARG: return "Invalid argument"; + case BRAVAIS_ERR_BUFFER_TOO_SMALL: return "Buffer too small"; + case BRAVAIS_ERR_MALFORMED: return "Malformed input"; + case BRAVAIS_ERR_OUT_OF_MEMORY: return "Out of memory"; + case BRAVAIS_ERR_UNSUPPORTED: return "Unsupported or unimplemented feature"; + case BRAVAIS_ERR_UNKNOWN: return "Unknown error"; + case BRAVAIS_ERR_AUTH: return "Authentication failed"; + case BRAVAIS_ERR_STATE: return "Invalid state for operation"; + + return "Unknown result"; + } +} diff --git a/src/proto/conn.h b/src/proto/conn.h new file mode 100644 index 0000000..46d076f --- /dev/null +++ b/src/proto/conn.h @@ -0,0 +1,23 @@ +// conn.h +// Connection internals for the lib +// +// Generally only included from proto/; others should use params instead for field access + +#ifndef BRAVAIS_CONN_H +#define BRAVAIS_CONN_H + +#include "bravais.h" + +typedef enum { + BRAVAIS_CONN_STATE_IDLE, + BRAVAIS_CONN_STATE_HANDSHAKE, + BRAVAIS_CONN_STATE_ESTABLISHED, + BRAVAIS_CONN_STATE_CLOSED +} bravais_conn_state_t; + +struct bravais_conn { + bravais_config_t config; + bravais_conn_state_t state; +}; + +#endif // BRAVAIS_CONN_H