aboutsummaryrefslogtreecommitdiff
path: root/proto/puzbusv1.c
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2024-05-20 10:25:21 +0200
committerlonkaars <loek@pipeframe.xyz>2024-05-20 10:25:21 +0200
commit9ff66bfe22c5f378584db2a57160d00b585a77ce (patch)
tree637bac57e8d0d75797fa29424f1a00aeedaaa2cc /proto/puzbusv1.c
parent2d3ba07806517f0d27b118df761675a05ab98fc7 (diff)
make puzbus slightly more robust
Diffstat (limited to 'proto/puzbusv1.c')
-rw-r--r--proto/puzbusv1.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/proto/puzbusv1.c b/proto/puzbusv1.c
index d6cd597..3be4939 100644
--- a/proto/puzbusv1.c
+++ b/proto/puzbusv1.c
@@ -7,21 +7,32 @@
#include "puzbusv1.h"
-bool pb_read(struct pb_msg* target, char* buf, size_t buf_sz) {
- // remaining bytes to be read to target->data; this is the only variable that
- // needs to persist between buffer blocks, and is therefore static
- static size_t rdata = 0;
+/**
+ * \brief Remaining bytes to be read to target->data
+ *
+ * This is the only variable that needs to persist between buffer blocks. It is
+ * declared in the global scope to allow resetting using the \c pb_read_reset()
+ * function.
+ *
+ * \note \p rdata may be reset by calling \c pb_read_reset()
+ */
+static size_t rdata = 0;
+int pb_read(struct pb_msg* target, char* buf, size_t buf_sz) {
// a new reader is used per buffer block passed to this function
mpack_reader_t reader;
mpack_reader_init_data(&reader, buf, buf_sz);
// at start of message
if (rdata == 0) {
- // NOTE: This approach will crash and burn when target->addr can be read
- // and target->length is past the end of the current buffer block. This is
- // a highly unlikely scenario, as pb_read is called for each chunk of a TCP
- // frame, and frames (should) include only one puzzle bus message.
+ // NOTE: The entire start of a message needs to be readable from the buffer
+ // at this point. When target->addr can be read and target->length is past
+ // the end of the current buffer block, this function will crash and burn.
+ // This is a highly unlikely scenario, as pb_read is called for each chunk
+ // of a TCP frame, and frames (should) include only one puzzle bus message.
+ // The check here is kind of optional.
+ if (buf_sz < 4) return -1;
+
target->addr = mpack_expect_u16(&reader);
target->length = rdata = mpack_expect_bin(&reader);
target->data = (char*) malloc(target->length);
@@ -35,7 +46,11 @@ bool pb_read(struct pb_msg* target, char* buf, size_t buf_sz) {
rdata -= to_read;
// if rdata = 0, the message was completely read
- return rdata == 0;
+ return rdata;
+}
+
+void pb_read_reset() {
+ rdata = 0;
}
bool pb_write(struct pb_msg* target, char** buf, size_t* buf_sz) {