From 5badda7c82961549ff02d4861df67af86188d924 Mon Sep 17 00:00:00 2001 From: Cococry Date: Wed, 29 Jul 2026 10:40:12 +0200 Subject: [PATCH] feat: S2C frame payload limits (EVENT_BATCH sent according to limits) --- faithd/src/client/client.c | 11 +++--- faithd/src/codec/protocol.c | 58 +++++++++++------------------- faithd/src/codec/protocol.h | 14 +++++--- faithd/src/commands/conversation.c | 2 ++ faithd/src/delivery/events.c | 37 +++++++++++++++---- 5 files changed, 67 insertions(+), 55 deletions(-) diff --git a/faithd/src/client/client.c b/faithd/src/client/client.c index ec0ae32..2ae1eaf 100644 --- a/faithd/src/client/client.c +++ b/faithd/src/client/client.c @@ -299,11 +299,11 @@ static faith_status_code_t read_frame_sync(SSL *ssl, faith_frame_t *out) { if (frame_size < FAITH_FRAME_METADATA_SIZE) return FAITH_ERR_BAD_FRAME; - if (frame_size > FAITH_MAX_FRAME_LEN) { + if (frame_size > FAITH_MAX_STC_FRAME_SIZE) { nob_log(ERROR, "Failed to read frame; Frame is too large, " "frame_size=%i MAX_FRAME_LEN=%i", - (int32_t)frame_size, (int32_t)FAITH_MAX_FRAME_LEN); + (int32_t)frame_size, (int32_t)FAITH_MAX_CTS_FRAME_SIZE); return FAITH_ERR_TOO_LARGE; } @@ -317,11 +317,11 @@ static faith_status_code_t read_frame_sync(SSL *ssl, faith_frame_t *out) { if (out->proto_ver != FAITH_PROTO_VERSION) return FAITH_ERR_UNSUPPORTED_VER; - if (out->payload_size > FAITH_MAX_PAYLOAD_SIZE) { + if (out->payload_size > FAITH_MAX_STC_PAYLOAD_SIZE) { nob_log(ERROR, "Failed to read frame; Frame is too large, " "frame_size=%u MAX_FRAME_LEN=%i", - out->payload_size, (int32_t)FAITH_MAX_FRAME_LEN); + out->payload_size, (int32_t)FAITH_MAX_CTS_FRAME_SIZE); return FAITH_ERR_TOO_LARGE; } @@ -1957,7 +1957,7 @@ static int read_identity(const char *path, client_side_identity_t *ident) { return 1; } -#define READ_IDENT "ident/23a2b2bf0b4457c86ad6127da2a1ae85.bin" +#define READ_IDENT "ident/e5dbc4ceaab6baee77881c9eb5307a68.bin" static faith_status_code_t client_new_identity(client_side_identity_t *o_ident) { if (!o_ident) @@ -1966,7 +1966,6 @@ client_new_identity(client_side_identity_t *o_ident) { /* Generate 128 bit random device & auth identities */ #ifdef READ_IDENT - char buf[33]; read_identity(READ_IDENT, o_ident); #else _FH_CHECK_RETURN(faith_random_bytes(o_ident->auth_id.bytes, diff --git a/faithd/src/codec/protocol.c b/faithd/src/codec/protocol.c index b737bf8..2439eac 100644 --- a/faithd/src/codec/protocol.c +++ b/faithd/src/codec/protocol.c @@ -18,12 +18,6 @@ faith_status_code_t faith_encode_frame(uint8_t *out_buf, size_t *out_size, const faith_body_size_t frame_size = FAITH_FRAME_METADATA_SIZE + in->payload_size; - if (in->payload_size > FAITH_MAX_PAYLOAD_SIZE) - goto payload_too_large; - - if (frame_size > FAITH_MAX_FRAME_LEN) - goto frame_too_large; - size_t offset = 0; FAITH_ENCODE_U32_BE_RETURN(out_buf, buf_cap_in_bytes, offset, @@ -43,21 +37,6 @@ faith_status_code_t faith_encode_frame(uint8_t *out_buf, size_t *out_size, FAITH_ENCODE_EPILOGUE(data_size, !=); return FAITH_OK; - -frame_too_large: - nob_log(ERROR, - "[%s] Failed to encode frame; Frame is too large, " - "frame_size=%u, MAX_FRAME_LEN=%i", - _MODULE_NAME, (uint32_t)frame_size, (int32_t)FAITH_MAX_FRAME_LEN); - return FAITH_ERR_TOO_LARGE; -payload_too_large: - nob_log(ERROR, - "[%s] Failed to encode frame; Payload is too large, " - "payload_size=%u, MAX_PAYLOAD_SIZE=%i", - - _MODULE_NAME, (uint32_t)in->payload_size, - (int32_t)FAITH_MAX_PAYLOAD_SIZE); - return FAITH_ERR_TOO_LARGE; } faith_status_code_t faith_decode_frame(const uint8_t *payload, @@ -87,20 +66,20 @@ faith_status_code_t faith_decode_frame(const uint8_t *payload, const size_t frame_payload_size = (size_t)frame_size - FAITH_FRAME_METADATA_SIZE; - if (frame_payload_size > FAITH_MAX_PAYLOAD_SIZE) { + if (frame_payload_size > FAITH_MAX_CTS_PAYLOAD_SIZE) { nob_log(ERROR, "[%s] Failed to parse frame from buffer; " "payload_size=%zu MAX_PAYLOAD_SIZE=%zu", - _MODULE_NAME, payload_size, (size_t)FAITH_MAX_PAYLOAD_SIZE); + _MODULE_NAME, payload_size, (size_t)FAITH_MAX_CTS_PAYLOAD_SIZE); return FAITH_ERR_TOO_LARGE; } - if (frame_size > FAITH_MAX_FRAME_LEN) { + if (frame_size > FAITH_MAX_CTS_FRAME_SIZE) { nob_log(ERROR, "[%s] Failed to parse frame from buffer; Frame is too large, " "frame_size=%i MAX_FRAME_LEN=%i", - _MODULE_NAME, (int32_t)frame_size, (int32_t)FAITH_MAX_FRAME_LEN); + _MODULE_NAME, (int32_t)frame_size, (int32_t)FAITH_MAX_CTS_FRAME_SIZE); return FAITH_ERR_TOO_LARGE; } @@ -762,13 +741,14 @@ faith_status_code_t faith_decode_event_body(const uint8_t *payload, } faith_status_code_t -faith_codec_event_batch_data_size(faith_envl_stc_event_t *events, - uint16_t n_events, - faith_body_size_t *o_size) { - if (!events || !o_size) +faith_codec_event_batch_data_size_fit(faith_envl_stc_event_t *events, + uint16_t n_events, + faith_body_size_t* o_events_data_size, + size_t *o_n_fitting, size_t cap) { + if (!events || !o_n_fitting) return FAITH_ERR_INVALID; - *o_size = 0; + *o_n_fitting = 0; if (n_events > FAITH_EVENT_BATCH_MAX_EVENTS) { nob_log(ERROR, @@ -778,7 +758,8 @@ faith_codec_event_batch_data_size(faith_envl_stc_event_t *events, return FAITH_ERR_INVALID; } - size_t total_data_size = 0; + size_t events_data_size = 0; + size_t n_fitting = 0; if (n_events != 0) { for (uint16_t i = 0; i < n_events; i++) { @@ -795,7 +776,7 @@ faith_codec_event_batch_data_size(faith_envl_stc_event_t *events, size_t encoded_elem_size = sizeof(uint16_t) + body_size; - if (encoded_elem_size > UINT32_MAX - total_data_size) { + if (encoded_elem_size > UINT32_MAX - events_data_size) { nob_log(ERROR, "[%s] Cannot encode EVENT_BATCH: adding event %" PRIu16 " would make the total event data exceed UINT32_MAX.", @@ -803,14 +784,17 @@ faith_codec_event_batch_data_size(faith_envl_stc_event_t *events, return FAITH_ERR_TOO_LARGE; } - total_data_size += encoded_elem_size; + + if (events_data_size + encoded_elem_size > cap) { + break; + } + events_data_size += encoded_elem_size; + n_fitting++; } } - if (total_data_size > SIZE_MAX - FAITH_ENVL_STC_EVENT_BATCH_BODY_SIZE_FIXED) - return FAITH_ERR_TOO_LARGE; - - *o_size = total_data_size; + *o_n_fitting = n_fitting; + *o_events_data_size = events_data_size; return FAITH_OK; } diff --git a/faithd/src/codec/protocol.h b/faithd/src/codec/protocol.h index d5974f5..90e4aa3 100644 --- a/faithd/src/codec/protocol.h +++ b/faithd/src/codec/protocol.h @@ -16,8 +16,8 @@ #include #include -#define FAITH_MAX_PAYLOAD_SIZE 256 -#define FAITH_MAX_FRAME_LEN 512 +#define FAITH_MAX_CTS_PAYLOAD_SIZE 256 +#define FAITH_MAX_CTS_FRAME_SIZE 512 #define FAITH_FRAME_LENGTH_SIZE sizeof(uint32_t) @@ -25,6 +25,10 @@ (_FAITH_BODY_SIZE(sizeof(uint16_t) /* protocol version */ + \ sizeof(uint16_t) /* message type */)) +#define FAITH_MAX_STC_PAYLOAD_SIZE (1024 * 1024 * 4) +#define FAITH_MAX_STC_FRAME_SIZE \ + (FAITH_FRAME_HEADER_SIZE + FAITH_MAX_STC_PAYLOAD_SIZE) + #define FAITH_FRAME_HEADER_SIZE \ (_FAITH_BODY_SIZE(FAITH_FRAME_LENGTH_SIZE + FAITH_FRAME_METADATA_SIZE)) @@ -151,9 +155,9 @@ faith_status_code_t faith_decode_event_body(const uint8_t *payload, faith_body_size_t payload_size, faith_envl_stc_event_t *out); -faith_status_code_t -faith_codec_event_batch_data_size(faith_envl_stc_event_t *events, - uint16_t n_events, faith_body_size_t *o_size); +faith_status_code_t faith_codec_event_batch_data_size_fit( + faith_envl_stc_event_t *events, uint16_t n_events, + faith_body_size_t *o_events_data_size, size_t *o_n_fitting, size_t cap); faith_status_code_t faith_encode_event_batch_body(uint8_t *out_buf, faith_body_size_t *out_size, diff --git a/faithd/src/commands/conversation.c b/faithd/src/commands/conversation.c index 79f2847..a509601 100644 --- a/faithd/src/commands/conversation.c +++ b/faithd/src/commands/conversation.c @@ -63,7 +63,9 @@ faith_status_code_t conv_handle_create_conversation( faith_event_conversation_created_t conv_created = {.conversation_id = conv_id}; + for(size_t i = 0; i < 100; i++) { _FH_CHECK_DEFER(send_conversation_created(s, cl, &conv_created, &create_conv_cmd.conversant_id)); + } *o_result = FAITH_COMMAND_RESULT_ACCEPTED; diff --git a/faithd/src/delivery/events.c b/faithd/src/delivery/events.c index e974522..6e3f79e 100644 --- a/faithd/src/delivery/events.c +++ b/faithd/src/delivery/events.c @@ -8,6 +8,8 @@ #define DIV_UP(x, y) (((x) + (y) - 1) / (y)) +#define _MODULE_NAME "delivery/events" + static faith_status_code_t queue_event_online_user(server_state_t *s, struct client_conn_t *cl, device_event_inbox_t *inbox, @@ -130,23 +132,44 @@ faith_status_code_t delivery_queue_pending_events(server_state_t *s, size_t n_events = arrlen(sess->inbox.events); - for (size_t offset = 0; offset < n_events; offset += 256) { + size_t n_fitting = 0; + for (size_t offset = 0; offset < n_events; offset += n_fitting) { size_t remaining = n_events - offset; faith_envl_stc_event_t *batch = &sess->inbox.events[offset]; - size_t in_batch = remaining < FAITH_EVENT_BATCH_MAX_EVENTS - ? remaining - : FAITH_EVENT_BATCH_MAX_EVENTS; + size_t n_in_batch = remaining < FAITH_EVENT_BATCH_MAX_EVENTS + ? remaining + : FAITH_EVENT_BATCH_MAX_EVENTS; + + const size_t batch_overhead = + FAITH_ENVL_STC_EVENT_BATCH_BODY_SIZE_FIXED + FAITH_ENVL_HEADER_SIZE; + + if (FAITH_MAX_STC_PAYLOAD_SIZE < batch_overhead) { + return FAITH_ERR_TOO_LARGE; + } + + const size_t max_events_data_size = + FAITH_MAX_STC_PAYLOAD_SIZE - batch_overhead; faith_body_size_t events_data_size = 0; - _FH_CHECK_RETURN( - faith_codec_event_batch_data_size(batch, in_batch, &events_data_size)); + n_fitting = 0; + + _FH_CHECK_RETURN(faith_codec_event_batch_data_size_fit( + batch, n_in_batch, &events_data_size, &n_fitting, + max_events_data_size)); + + if (n_fitting == 0 || n_fitting > n_in_batch) { + nob_log(ERROR, + "[%s] Event data is too large or codec returned invalid count.", + _MODULE_NAME); + return FAITH_ERR_TOO_LARGE; + } faith_envl_stc_event_batch_t batch_envl = {0}; batch_envl.events_data_size = events_data_size; batch_envl.events = batch; - batch_envl.n_events = (uint16_t)in_batch; + batch_envl.n_events = (uint16_t)n_fitting; _FH_CHECK_RETURN(queue_event_batch_envl(s, cl, &batch_envl)); }