aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Smeding <tom.smeding@gmail.com>2020-10-03 21:30:57 +0200
committerTom Smeding <tom.smeding@gmail.com>2020-10-03 21:30:57 +0200
commit08b2de406a45f98cc2b46a35719f4c9d1a87c1b5 (patch)
tree0c8b8cdfd2fbdab0cb630574e7572319e14a7c90
parentd096bb626f8dd78b6ba1ac9c2d19e567cb88827e (diff)
ssh/tomsg_clientlib: Fix stuck-data bug in tomsg_next_event
The issue was that I have too many buffering layers. The bug occurred when the sshnc layer had received some amount of data, some of which (but not all of which) was passed on to tomsg_clientlib via sshnc_maybe_recv in receive_more_data. If the data that _was_ passed on did not constitute a full event, tomsg_clientlib did not ask for more data from the sshnc layer; it would only get received the next time there was actual data on the _socket_, at which point poll(2) would ensure the whole chain gets looped through another time.
-rw-r--r--ssh/tomsg_clientlib.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/ssh/tomsg_clientlib.c b/ssh/tomsg_clientlib.c
index df22a1e..260b785 100644
--- a/ssh/tomsg_clientlib.c
+++ b/ssh/tomsg_clientlib.c
@@ -938,12 +938,18 @@ enum tomsg_retval tomsg_next_event(struct tomsg_client *client, struct tomsg_eve
enum tomsg_retval ret = find_handle_next_line(client, eventp);
if (ret != TOMSG_ERR_AGAIN) return ret;
- // Otherwise, try to receive more data.
- ret = receive_more_data(client);
- if (ret != TOMSG_OK) return ret;
-
- // And then handle any line that might be completed at this point.
- return find_handle_next_line(client, eventp);
+ // Otherwise, try to receive more data until either there is no more data
+ // anymore, or we have a complete event.
+ while (true) {
+ ret = receive_more_data(client);
+ if (ret != TOMSG_OK) return ret;
+
+ // Handle any line that might be completed at this point. If that
+ // produces an event or an error, return it; otherwise loop and receive
+ // more data.
+ ret = find_handle_next_line(client, eventp);
+ if (ret != TOMSG_ERR_AGAIN) return ret;
+ }
}
#define SEND_FMT0(client, tag, fmt) do { \