From 99b29f63c27ae0ec298f8095bc7f67aabe4da967 Mon Sep 17 00:00:00 2001 From: Robert Middleton Date: Sun, 25 Feb 2024 12:39:42 -0500 Subject: [PATCH] Added callback for determining buffer size When sending a datagram packet, we are now able to query how large the sending buffer is. If there is not enough space for us to send the full datagram, we automatically send back an error message. See: #3 --- GUI/lcc/lccqioconnection.cpp | 2 +- LCC/lcc-common-internal.h | 1 + LCC/lcc-common.h | 2 ++ LCC/lcc-datagram.c | 19 +++++++++++++++++++ LCC/lcc.c | 3 ++- LCC/lcc.h | 12 +++++++++--- LCC/test/test-alias.c | 4 ++-- LCC/test/test-common.c | 2 +- 8 files changed, 37 insertions(+), 8 deletions(-) diff --git a/GUI/lcc/lccqioconnection.cpp b/GUI/lcc/lccqioconnection.cpp index f2f4629..0a7b59a 100644 --- a/GUI/lcc/lccqioconnection.cpp +++ b/GUI/lcc/lccqioconnection.cpp @@ -14,7 +14,7 @@ LCCQIoConnection::LCCQIoConnection(QObject *parent) : LCCConnection(parent) m_lccGrid = lcc_gridconnect_new(); lcc_context_set_userdata(m_lcc, this); - lcc_context_set_write_function(m_lcc, LCCQIoConnection::writeLCCFrameCB); + lcc_context_set_write_function(m_lcc, LCCQIoConnection::writeLCCFrameCB, NULL); lcc_gridconnect_set_userdata(m_lccGrid, this); lcc_gridconnect_set_frame_parsed(m_lccGrid, LCCQIoConnection::gridconnectLCCFrameParsedCB); } diff --git a/LCC/lcc-common-internal.h b/LCC/lcc-common-internal.h index a4394b6..2b99466 100644 --- a/LCC/lcc-common-internal.h +++ b/LCC/lcc-common-internal.h @@ -106,6 +106,7 @@ struct lcc_context{ }; int16_t node_alias; lcc_write_fn write_function; + lcc_write_buffer_available write_buffer_avail_function; void* user_data; // Simple node information diff --git a/LCC/lcc-common.h b/LCC/lcc-common.h index e69a5f6..3e2ea53 100644 --- a/LCC/lcc-common.h +++ b/LCC/lcc-common.h @@ -51,6 +51,8 @@ enum lcc_producer_state{ */ typedef int(*lcc_write_fn)(struct lcc_context*, struct lcc_can_frame*); +typedef int(*lcc_write_buffer_available)(struct lcc_context*); + /** * A function that will be called when an event that we are interested in comes in. */ diff --git a/LCC/lcc-datagram.c b/LCC/lcc-datagram.c index b98c651..55bf530 100644 --- a/LCC/lcc-datagram.c +++ b/LCC/lcc-datagram.c @@ -73,11 +73,22 @@ int lcc_datagram_load_and_send(struct lcc_datagram_context* ctx, void* data, int data_len){ struct lcc_can_frame frame; + uint16_t buffer_size = UINT16_MAX; if(ctx == NULL || data_len < 0 || data_len > 72){ return LCC_ERROR_INVALID_ARG; } + if(ctx->parent->write_buffer_avail_function){ + buffer_size = ctx->parent->write_buffer_avail_function(ctx->parent); + } + + // A bit of a catch-22 here: + // if our buffer is not large enough, we can't actually send an error code + if(buffer_size == 0){ + return LCC_ERROR_TX; + } + if(data_len <= 8){ // There's just one frame for us to send, so let's send it. lcc_set_lcb_variable_field(&frame, ctx->parent, alias); @@ -93,6 +104,14 @@ int lcc_datagram_load_and_send(struct lcc_datagram_context* ctx, if(data_len % 8 != 0){ numPackets++; } + + if(buffer_size < numPackets){ + // We don't have enough buffer to send this data. + // Since we know we are sending a datagram, we can automatically send a 'datagram rejected' message + // with the appropriate error code + return lcc_datagram_respond_rejected(ctx, alias, LCC_ERRCODE_BUFFER_UNAVAILABLE, NULL); + } + for(int x = 0; x < numPackets; x++){ lcc_set_lcb_variable_field(&frame, ctx->parent, alias); if(x == 0){ diff --git a/LCC/lcc.c b/LCC/lcc.c index 733c62c..62a85b0 100644 --- a/LCC/lcc.c +++ b/LCC/lcc.c @@ -170,12 +170,13 @@ int lcc_context_incoming_frame(struct lcc_context* ctx, struct lcc_can_frame* fr return LCC_OK; } -int lcc_context_set_write_function(struct lcc_context* ctx, lcc_write_fn write_fn){ +int lcc_context_set_write_function(struct lcc_context* ctx, lcc_write_fn write_fn, lcc_write_buffer_available write_buffer_avail_fn){ if( !write_fn || !ctx ){ return LCC_ERROR_INVALID_ARG; } ctx->write_function = write_fn; + ctx->write_buffer_avail_function = write_buffer_avail_fn; return LCC_OK; } diff --git a/LCC/lcc.h b/LCC/lcc.h index 1a848f9..f04b8cb 100644 --- a/LCC/lcc.h +++ b/LCC/lcc.h @@ -33,11 +33,17 @@ void lcc_context_free(struct lcc_context* ctx); int lcc_context_incoming_frame(struct lcc_context* ctx, struct lcc_can_frame* frame); /** - * Set a function that will be called in order to write a CAN frame out on the bus - * @param write_fn + * Set functions that handle writing a CAN frame out on the bus. + * + * @param write_fn The function that will write out CAN frames to the bus + * @param write_buffer_avail_fn A function that will return how many CAN frames can be queued up to be sent. + * If there is not enough space to queue up CAN frames for a specific message, the message will not be queued. + * This parameter may be NULL, in which case the size is not checked. This is currently only relevant for datagram messages, + * as it is possible to determine how many frames we need before we try to send them. + * * @return */ -int lcc_context_set_write_function(struct lcc_context* ctx, lcc_write_fn write_fn); +int lcc_context_set_write_function(struct lcc_context* ctx, lcc_write_fn write_fn, lcc_write_buffer_available write_buffer_avail_fn); /** * Set the unique identifier of this node. diff --git a/LCC/test/test-alias.c b/LCC/test/test-alias.c index cc12eea..ad98831 100644 --- a/LCC/test/test-alias.c +++ b/LCC/test/test-alias.c @@ -37,8 +37,8 @@ static int alias_collision(){ return 1; } - lcc_context_set_write_function( both_ctx[0], write_fun ); - lcc_context_set_write_function( both_ctx[1], write_fun ); + lcc_context_set_write_function( both_ctx[0], write_fun, NULL ); + lcc_context_set_write_function( both_ctx[1], write_fun, NULL ); stat = lcc_context_generate_alias( both_ctx[0] ); if(stat != LCC_OK){ diff --git a/LCC/test/test-common.c b/LCC/test/test-common.c index 14f3b00..8c2daab 100644 --- a/LCC/test/test-common.c +++ b/LCC/test/test-common.c @@ -48,7 +48,7 @@ struct lcc_context** lcctest_create_contexts(int num){ for(int x = 0; x < num; x++){ all_ctx[x] = lcc_context_new(); - lcc_context_set_write_function(all_ctx[x], write_fun); + lcc_context_set_write_function(all_ctx[x], write_fun, NULL); lcc_context_set_unique_identifer(all_ctx[x], unique_id++); }