diff --git a/CHANGELOG.md b/CHANGELOG.md index bbae2114..b5213378 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - FileSystem: Added support for erase and write operation - Code improvement: Change multiple local variables to single structure - Delete `lwesp_datetime_t` and use generic `struct tm` instead +- Conn and netconn: Add validation counter to ensure netconn object matches connection object and that there was no connection close/re-open in between ## 1.1.2-dev diff --git a/lwesp/src/api/lwesp_netconn.c b/lwesp/src/api/lwesp_netconn.c index 6cf97bf3..bc8c1326 100644 --- a/lwesp/src/api/lwesp_netconn.c +++ b/lwesp/src/api/lwesp_netconn.c @@ -62,13 +62,14 @@ * \brief Sequential API structure */ typedef struct lwesp_netconn { - struct lwesp_netconn* next; /*!< Linked list entry */ + struct lwesp_netconn* next; /*!< Linked list entry */ - lwesp_netconn_type_t type; /*!< Netconn type */ - lwesp_port_t listen_port; /*!< Port on which we are listening */ + lwesp_netconn_type_t type; /*!< Netconn type */ + lwesp_port_t listen_port; /*!< Port on which we are listening */ - size_t rcv_packets; /*!< Number of received packets so far on this connection */ - lwesp_conn_p conn; /*!< Pointer to actual connection */ + size_t rcv_packets; /*!< Number of received packets so far on this connection */ + lwesp_conn_p conn; /*!< Pointer to actual connection */ + uint16_t conn_val_id; /*!< Connection validation ID that changes between every connection active/closed operation */ lwesp_sys_mbox_t mbox_accept; /*!< List of active connections waiting to be processed */ lwesp_sys_mbox_t mbox_receive; /*!< Message queue for receive mbox */ @@ -146,13 +147,14 @@ netconn_evt(lwesp_evt_t* evt) { * A new connection has been active * and should be handled by netconn API */ - case LWESP_EVT_CONN_ACTIVE: { /* A new connection active is active */ - if (lwesp_conn_is_client(conn)) { /* Was connection started by us? */ - nc = lwesp_conn_get_arg(conn); /* Argument should be already set */ + case LWESP_EVT_CONN_ACTIVE: { /* A new connection active is active */ + if (lwesp_conn_is_client(conn)) { /* Was connection started by us? */ + nc = lwesp_conn_get_arg(conn); /* Argument should be already set */ if (nc != NULL) { - nc->conn = conn; /* Save actual connection */ + nc->conn = conn; /* Save actual connection */ + nc->conn_val_id = conn->val_id; /* Get value ID */ } else { - close = 1; /* Close this connection, invalid netconn */ + close = 1; /* Close this connection, invalid netconn */ } /* Is the connection server type and we have known listening API? */ @@ -167,6 +169,7 @@ netconn_evt(lwesp_evt_t* evt) { if (nc != NULL) { nc->conn = conn; /* Set connection handle */ + nc->conn_val_id = conn->val_id; lwesp_conn_set_arg(conn, nc); /* Set argument for connection */ /* @@ -213,7 +216,7 @@ netconn_evt(lwesp_evt_t* evt) { #endif /* !LWESP_CFG_CONN_MANUAL_TCP_RECEIVE */ lwesp_pbuf_ref(pbuf); /* Increase reference counter */ - if (nc == NULL || !lwesp_sys_mbox_isvalid(&nc->mbox_receive) + if (nc == NULL || nc->conn_val_id != conn->val_id || !lwesp_sys_mbox_isvalid(&nc->mbox_receive) || !lwesp_sys_mbox_putnow(&nc->mbox_receive, pbuf)) { LWESP_DEBUGF(LWESP_CFG_DBG_NETCONN, "[LWESP NETCONN] Ignoring more data for receive!\r\n"); lwesp_pbuf_free(pbuf); /* Free pbuf */ @@ -242,7 +245,7 @@ netconn_evt(lwesp_evt_t* evt) { * In case we have a netconn available, * simply write pointer to received variable to indicate closed state */ - if (nc != NULL && lwesp_sys_mbox_isvalid(&nc->mbox_receive)) { + if (nc != NULL && nc->conn_val_id == conn->val_id && lwesp_sys_mbox_isvalid(&nc->mbox_receive)) { if (lwesp_sys_mbox_putnow(&nc->mbox_receive, (void*)&recv_closed)) { ++nc->mbox_receive_entries; } @@ -370,6 +373,17 @@ lwesp_netconn_delete(lwesp_netconn_p nc) { } } } + if (nc->conn != NULL) { + /* + * First delete the connection argument, + * then close the connection. + */ + lwesp_conn_set_arg(nc->conn, NULL); + if (lwesp_conn_is_active(nc->conn)) { + lwesp_conn_close(nc->conn, 1); + } + nc->conn = NULL; + } lwesp_core_unlock(); lwesp_mem_free_s((void**)&nc); diff --git a/lwesp/src/include/lwesp/lwesp_private.h b/lwesp/src/include/lwesp/lwesp_private.h index 3e3de5e5..3fbb31e7 100644 --- a/lwesp/src/include/lwesp/lwesp_private.h +++ b/lwesp/src/include/lwesp/lwesp_private.h @@ -184,7 +184,7 @@ typedef struct lwesp_conn { lwesp_evt_fn evt_func; /*!< Callback function for connection */ void* arg; /*!< User custom argument */ - uint8_t val_id; /*!< Validation ID number. It is increased each time + uint16_t val_id; /*!< Validation ID number. It is increased each time a new connection is established. It protects sending data to wrong connection in case we have data in send queue, @@ -399,7 +399,7 @@ typedef struct lwesp_msg { struct { lwesp_conn_t* conn; /*!< Pointer to connection to close */ - uint8_t val_id; /*!< Connection current validation ID when command was sent to queue */ + uint16_t val_id; /*!< Connection current validation ID when command was sent to queue */ } conn_close; /*!< Close connection */ struct { @@ -415,7 +415,7 @@ typedef struct lwesp_msg { lwesp_port_t remote_port; /*!< Remote port address for UDP connection */ uint8_t fau; /*!< Free after use flag to free memory after data are sent (or not) */ size_t* bw; /*!< Number of bytes written so far */ - uint8_t val_id; /*!< Connection current validation ID when command was sent to queue */ + uint16_t val_id; /*!< Connection current validation ID when command was sent to queue */ } conn_send; /*!< Structure to send data on connection */ #if LWESP_CFG_CONN_MANUAL_TCP_RECEIVE diff --git a/lwesp/src/lwesp/lwesp_conn.c b/lwesp/src/lwesp/lwesp_conn.c index bd409c86..59f0fb0d 100644 --- a/lwesp/src/lwesp/lwesp_conn.c +++ b/lwesp/src/lwesp/lwesp_conn.c @@ -176,9 +176,9 @@ lwespi_conn_check_available_rx_data(void) { * \param[in] conn: Connection handle * \return Connection current validation ID */ -uint8_t +uint16_t lwespi_conn_get_val_id(lwesp_conn_p conn) { - uint8_t val_id; + uint16_t val_id; lwesp_core_lock(); val_id = conn->val_id; lwesp_core_unlock(); diff --git a/lwesp/src/lwesp/lwesp_int.c b/lwesp/src/lwesp/lwesp_int.c index 3479ce72..5fcc0892 100644 --- a/lwesp/src/lwesp/lwesp_int.c +++ b/lwesp/src/lwesp/lwesp_int.c @@ -123,6 +123,7 @@ static const char* flash_partitions[] = { }; #endif +static uint16_t conn_val_id; static lwesp_recv_t recv_buff; static lwespr_t lwespi_process_sub_cmd(lwesp_msg_t* msg, lwesp_status_flags_t* stat); @@ -1145,13 +1146,15 @@ lwespi_parse_received(lwesp_recv_t* rcv) { lwesp_mem_free_s((void**)&conn->buff.buff); } } else if (!esp.m.link_conn.failed && !conn->status.f.active) { - id = conn->val_id; LWESP_MEMSET(conn, 0x00, sizeof(*conn)); /* Reset connection parameters */ conn->num = esp.m.link_conn.num; /* Set connection number */ conn->status.f.active = !esp.m.link_conn.failed; /* Check if connection active */ - conn->val_id = ++id; /* Set new validation ID */ + conn->val_id = ++conn_val_id; /* Set new validation ID */ + if (conn->val_id == 0) { /* Conn ID == 0 is invalid */ + conn->val_id = ++conn_val_id; + } - conn->type = esp.m.link_conn.type; /* Set connection type */ + conn->type = esp.m.link_conn.type; /* Set connection type */ LWESP_MEMCPY(&conn->remote_ip, &esp.m.link_conn.remote_ip, sizeof(conn->remote_ip)); conn->remote_port = esp.m.link_conn.remote_port; conn->local_port = esp.m.link_conn.local_port;