Skip to content

Commit 1886d8c

Browse files
mniestrojjukkar
authored andcommitted
drivers: wifi: esp: rework +IPD handling
Split +IPD message handling into smaller logical functions, so it is much easier to follow code and further improve it. Make sure to do as much parsing work as possible, before accessing esp_socket object. This will allow to introduce thread-safety locking just in the critical parts in subsequent commits. Prefer early return from function over goto to return instruction, whenever cleanup code is not needed. Signed-off-by: Marcin Niestroj <[email protected]>
1 parent d60bd57 commit 1886d8c

File tree

1 file changed

+78
-52
lines changed

1 file changed

+78
-52
lines changed

drivers/wifi/esp/esp.c

Lines changed: 78 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -442,70 +442,101 @@ struct net_pkt *esp_prepare_pkt(struct esp_data *dev, struct net_buf *src,
442442
*/
443443
#define MIN_IPD_LEN (sizeof("+IPD,I,0E") - 1)
444444
#define MAX_IPD_LEN (sizeof("+IPD,I,4294967295E") - 1)
445-
MODEM_CMD_DIRECT_DEFINE(on_cmd_ipd)
446-
{
447-
char *endptr, end, ipd_buf[MAX_IPD_LEN + 1];
448-
int data_offset, data_len, ret;
449-
size_t match_len, frags_len;
450-
struct esp_socket *sock;
451-
struct esp_data *dev;
452-
struct net_pkt *pkt;
453-
uint8_t link_id;
454445

455-
dev = CONTAINER_OF(data, struct esp_data, cmd_handler_data);
446+
static int cmd_ipd_parse_hdr(struct net_buf *buf, uint16_t len,
447+
uint8_t *link_id,
448+
int *data_offset, int *data_len,
449+
char *end)
450+
{
451+
char *endptr, ipd_buf[MAX_IPD_LEN + 1];
452+
size_t frags_len;
453+
size_t match_len;
456454

457-
frags_len = net_buf_frags_len(data->rx_buf);
455+
frags_len = net_buf_frags_len(buf);
458456

459457
/* Wait until minimum cmd length is available */
460458
if (frags_len < MIN_IPD_LEN) {
461-
ret = -EAGAIN;
462-
goto out;
459+
return -EAGAIN;
463460
}
464461

465462
match_len = net_buf_linearize(ipd_buf, MAX_IPD_LEN,
466-
data->rx_buf, 0, MAX_IPD_LEN);
463+
buf, 0, MAX_IPD_LEN);
467464

468465
ipd_buf[match_len] = 0;
469466
if (ipd_buf[len] != ',' || ipd_buf[len + 2] != ',') {
470467
LOG_ERR("Invalid IPD: %s", log_strdup(ipd_buf));
471-
ret = len;
472-
goto out;
468+
return -EBADMSG;
473469
}
474470

475-
link_id = ipd_buf[len + 1] - '0';
476-
sock = esp_socket_from_link_id(dev, link_id);
477-
if (sock == NULL) {
478-
LOG_ERR("No socket for link %d", link_id);
479-
ret = len;
480-
goto out;
471+
*link_id = ipd_buf[len + 1] - '0';
472+
473+
*data_len = strtol(&ipd_buf[len + 3], &endptr, 10);
474+
475+
if (endptr == &ipd_buf[len + 3] ||
476+
(*endptr == 0 && match_len >= MAX_IPD_LEN)) {
477+
LOG_ERR("Invalid IPD len: %s", log_strdup(ipd_buf));
478+
return -EBADMSG;
479+
} else if (*endptr == 0) {
480+
return -EAGAIN;
481481
}
482482

483+
*end = *endptr;
484+
*data_offset = (endptr - ipd_buf) + 1;
485+
486+
return 0;
487+
}
488+
489+
static int cmd_ipd_check_hdr_end(struct esp_socket *sock, char actual)
490+
{
491+
char expected;
492+
483493
/* When using passive mode, the +IPD command ends with \r\n */
484494
if (ESP_PROTO_PASSIVE(sock->ip_proto)) {
485-
end = '\r';
495+
expected = '\r';
486496
} else {
487-
end = ':';
497+
expected = ':';
488498
}
489499

490-
data_len = strtol(&ipd_buf[len + 3], &endptr, 10);
491-
if (endptr == &ipd_buf[len + 3] ||
492-
(*endptr == 0 && match_len >= MAX_IPD_LEN)) {
493-
/* Invalid */
494-
LOG_ERR("Invalid IPD len: %s", log_strdup(ipd_buf));
495-
ret = len;
496-
goto out;
497-
} else if (*endptr == 0) {
498-
ret = -EAGAIN;
499-
goto out;
500-
} else if (*endptr != end) {
501-
LOG_ERR("Invalid cmd end 0x%02x, expected 0x%02x", *endptr,
502-
end);
503-
ret = len;
504-
goto out;
500+
if (expected != actual) {
501+
LOG_ERR("Invalid cmd end 0x%02x, expected 0x%02x", actual,
502+
expected);
503+
return -EBADMSG;
505504
}
506505

507-
*endptr = 0;
508-
data_offset = strlen(ipd_buf) + 1;
506+
return 0;
507+
}
508+
509+
MODEM_CMD_DIRECT_DEFINE(on_cmd_ipd)
510+
{
511+
struct esp_data *dev = CONTAINER_OF(data, struct esp_data,
512+
cmd_handler_data);
513+
struct esp_socket *sock;
514+
int data_offset, data_len;
515+
struct net_pkt *pkt;
516+
uint8_t link_id;
517+
char cmd_end;
518+
int err;
519+
520+
err = cmd_ipd_parse_hdr(data->rx_buf, len, &link_id, &data_offset,
521+
&data_len, &cmd_end);
522+
if (err) {
523+
if (err == -EAGAIN) {
524+
return -EAGAIN;
525+
}
526+
527+
return len;
528+
}
529+
530+
sock = esp_socket_from_link_id(dev, link_id);
531+
if (!sock) {
532+
LOG_ERR("No socket for link %d", link_id);
533+
return len;
534+
}
535+
536+
err = cmd_ipd_check_hdr_end(sock, cmd_end);
537+
if (err) {
538+
return len;
539+
}
509540

510541
/*
511542
* When using passive TCP, the data itself is not included in the +IPD
@@ -514,22 +545,18 @@ MODEM_CMD_DIRECT_DEFINE(on_cmd_ipd)
514545
if (ESP_PROTO_PASSIVE(sock->ip_proto)) {
515546
sock->bytes_avail = data_len;
516547
k_work_submit_to_queue(&dev->workq, &sock->recvdata_work);
517-
ret = data_offset;
518-
goto out;
548+
return data_offset;
519549
}
520550

521551
/* Do we have the whole message? */
522-
if (data_offset + data_len > frags_len) {
523-
ret = -EAGAIN;
524-
goto out;
552+
if (data_offset + data_len > net_buf_frags_len(data->rx_buf)) {
553+
return -EAGAIN;
525554
}
526555

527-
ret = data_offset + data_len; /* Skip */
528-
529556
if ((sock->flags & (ESP_SOCK_CONNECTED | ESP_SOCK_CLOSE_PENDING)) !=
530557
ESP_SOCK_CONNECTED) {
531-
LOG_DBG("Received data on closed link %d", link_id);
532-
goto out;
558+
LOG_DBG("Received data on closed link %d", sock->link_id);
559+
return data_offset + data_len;
533560
}
534561

535562
pkt = esp_prepare_pkt(dev, data->rx_buf, data_offset, data_len);
@@ -546,8 +573,7 @@ MODEM_CMD_DIRECT_DEFINE(on_cmd_ipd)
546573
submit_work:
547574
k_work_submit_to_queue(&dev->workq, &sock->recv_work);
548575

549-
out:
550-
return ret;
576+
return data_offset + data_len;
551577
}
552578

553579
MODEM_CMD_DEFINE(on_cmd_busy_sending)

0 commit comments

Comments
 (0)