From 8232dddf1c45fa3ddf8de9be2001a3eb3cd9e45c Mon Sep 17 00:00:00 2001 From: Andriy Gelman Date: Mon, 4 Dec 2023 09:40:49 -0500 Subject: [PATCH] shell: telnet: Don't close the connection on EAGAIN error EAGAIN error is returned if the tcp window size is full. Retry sending the packet instead of closing the connection if this error occurs. Also the full payload may not be sent in a single call to net_context_send(). Keep track of the number of bytes remaining and try to send the full payload. Signed-off-by: Andriy Gelman --- subsys/shell/backends/shell_telnet.c | 57 ++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/subsys/shell/backends/shell_telnet.c b/subsys/shell/backends/shell_telnet.c index a4dab627299..cd6f1184773 100644 --- a/subsys/shell/backends/shell_telnet.c +++ b/subsys/shell/backends/shell_telnet.c @@ -33,6 +33,8 @@ struct shell_telnet *sh_telnet; #define TELNET_MIN_COMMAND_LEN 2 #define TELNET_WILL_DO_COMMAND_LEN 3 +#define TELNET_RETRY_SEND_SLEEP_MS 50 + /* Basic TELNET implementation. */ static void telnet_end_client_connection(void) @@ -64,17 +66,29 @@ static void telnet_sent_cb(struct net_context *client, static void telnet_command_send_reply(uint8_t *msg, uint16_t len) { - int err; - if (sh_telnet->client_ctx == NULL) { return; } - err = net_context_send(sh_telnet->client_ctx, msg, len, telnet_sent_cb, - K_FOREVER, NULL); - if (err < 0) { - LOG_ERR("Failed to send command %d, shutting down", err); - telnet_end_client_connection(); + while (len > 0) { + int ret; + + ret = net_context_send(sh_telnet->client_ctx, msg, len, telnet_sent_cb, + K_FOREVER, NULL); + + if (ret == -EAGAIN) { + k_sleep(K_MSEC(TELNET_RETRY_SEND_SLEEP_MS)); + continue; + } + + if (ret < 0) { + LOG_ERR("Failed to send command %d, shutting down", ret); + telnet_end_client_connection(); + break; + } + + msg += ret; + len -= ret; } } @@ -175,7 +189,9 @@ static void telnet_reply_command(struct telnet_simple_command *cmd) static int telnet_send(void) { - int err; + int ret; + uint8_t *msg = sh_telnet->line_out.buf; + uint16_t len = sh_telnet->line_out.len; if (sh_telnet->line_out.len == 0) { return 0; @@ -185,13 +201,24 @@ static int telnet_send(void) return -ENOTCONN; } - err = net_context_send(sh_telnet->client_ctx, sh_telnet->line_out.buf, - sh_telnet->line_out.len, telnet_sent_cb, - K_FOREVER, NULL); - if (err < 0) { - LOG_ERR("Failed to send %d, shutting down", err); - telnet_end_client_connection(); - return err; + while (len > 0) { + ret = net_context_send(sh_telnet->client_ctx, msg, + len, telnet_sent_cb, + K_FOREVER, NULL); + + if (ret == -EAGAIN) { + k_sleep(K_MSEC(TELNET_RETRY_SEND_SLEEP_MS)); + continue; + } + + if (ret < 0) { + LOG_ERR("Failed to send %d, shutting down", ret); + telnet_end_client_connection(); + return ret; + } + + msg += ret; + len -= ret; } /* We reinitialize the line buffer */