From 7edaa14c2c822e5b776edaa6534753b258d29488 Mon Sep 17 00:00:00 2001 From: Trumeet Date: Tue, 9 Aug 2022 17:15:45 -0700 Subject: fix(libacron): infinite loop when wic_parse returns 0 This is a rather complicated way to fix backlogging issues. It asks the client to pass partial buffer, and the client also must retry with NULL buffer if ac_receive returns AC_E_AGAIN. --- client/libacron/README.md | 58 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 6 deletions(-) (limited to 'client/libacron/README.md') diff --git a/client/libacron/README.md b/client/libacron/README.md index 14d37ad..736b44a 100644 --- a/client/libacron/README.md +++ b/client/libacron/README.md @@ -202,12 +202,22 @@ Then, the program can listen for responses or events. The client should do its own magic to receive from socket and supply `ac_receive` with a buffer and size. +Function `ac_receive` may only parse part of the buffer, so it is the client's responsibility to keep +track of the bytes read: + ```c ac_obj_t *obj = NULL; uint8_t buffer[1000U]; -size_t bytes; -/* TODO: recv() */ -while (!(r = ac_receive(connection, buffer, bytes, &obj))) { +size_t len; +size_t pos = 0; +size_t read; +/* TODO: recv(): reset pos to 0 and set len. */ +while (1) { + if ((r = ac_receive(connection, buffer, pos, len, &obj, &read))) { + /* Handle error. */ + break; + } + pos += read; /* The obj is now referencing to a library allocated event or response. */ /* Do things with the event or response. */ ac_obj_free(obj); @@ -220,9 +230,45 @@ while (!(r = ac_receive(connection, buffer, bytes, &obj))) { > `ac_receive` will backlog the additional parsed messages, and they will return the second time > calling `ac_receive` with buffer = bytes = 0. > -> This will happen only `ac_receive` returns zero with a non-NULL obj output. If that is true, -> the client must additionally call `ac_receive` infinite times with buffer = bytes = 0, until either -> `ac_receive` returns an error or obj output is NULL. +> This will happen only `ac_receive` returns `AC_E_AGAIN`. If that is true, the client must additionally +> call `ac_receive` infinite times with buffer = bytes = 0, until either `ac_receive` returns an error or +> returns `AC_E_OK`. See the code below: + +```c +ac_obj_t *obj = NULL; +uint8_t buffer[1000U]; +size_t len; +size_t pos = 0; +size_t read; +/* TODO: recv(): reset pos to 0 and set len. */ +bool again = false; +while (1) { + if ((r = ac_receive(connection, buffer, pos, len, &obj, &read))) { + if (r == AC_E_AGAIN) { + again = true; + } else { + /* Handle error. */ + break; + } + } + pos += read; + /* The obj is now referencing to a library allocated event or response. */ + /* Do things with the event or response. */ + ac_obj_free(obj); + /* Clear backlog */ + while (again) { + if ((r = ac_receive(connection, NULL, 0, 0, &obj, NULL))) { + if (r == AC_E_AGAIN) { + again = true; + } else { + /* Handle error. */ + break; + } + } + ac_obj_free(obj); + } +} +``` The program can make requests using `ac_request()`: -- cgit v1.2.3