aboutsummaryrefslogtreecommitdiff
path: root/client/libacron/README.md
diff options
context:
space:
mode:
authorTrumeet <yuuta@yuuta.moe>2022-08-09 17:15:45 -0700
committerTrumeet <yuuta@yuuta.moe>2022-08-09 17:15:45 -0700
commit7edaa14c2c822e5b776edaa6534753b258d29488 (patch)
tree7c6dba03c89d3d9745a40d03e5b45c1f9cdf3938 /client/libacron/README.md
parent1d42944d172cbc725cd025aea1c364c3f13a38e5 (diff)
downloadacron-7edaa14c2c822e5b776edaa6534753b258d29488.tar
acron-7edaa14c2c822e5b776edaa6534753b258d29488.tar.gz
acron-7edaa14c2c822e5b776edaa6534753b258d29488.tar.bz2
acron-7edaa14c2c822e5b776edaa6534753b258d29488.zip
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.
Diffstat (limited to 'client/libacron/README.md')
-rw-r--r--client/libacron/README.md58
1 files changed, 52 insertions, 6 deletions
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()`: