mirror of
https://github.com/espressif/esp-modbus.git
synced 2026-08-03 20:24:09 +02:00
Merge branch 'bugfix/fix_slave_error_disconnected_node' into 'main'
fix slave close socket immediately on disconnect See merge request idf/esp-modbus!139
This commit is contained in:
@@ -268,7 +268,7 @@ int transaction_delete_expired(transaction_handle_t transaction, transaction_tic
|
||||
transaction_item_handle_t item, tmp;
|
||||
CRITICAL_SECTION_LOCK(transaction->lock);
|
||||
STAILQ_FOREACH_SAFE(item, transaction->list, next, tmp) {
|
||||
if (current_tick - item->tick > timeout) {
|
||||
if ((current_tick - item->tick > timeout) || atomic_load(&(item->state)) == EXPIRED) {
|
||||
STAILQ_REMOVE(transaction->list, item, transaction_item, next);
|
||||
free(item->buffer);
|
||||
transaction->size -= item->len;
|
||||
|
||||
@@ -637,12 +637,7 @@ void mb_drv_tcp_task(void *ctx)
|
||||
if (sock_id) {
|
||||
if (drv_obj->mb_node_open_count >= MB_MAX_FDS) {
|
||||
ESP_LOGE(TAG, "%p, unable to accept node, maximum is %u connections.", drv_obj, MB_MAX_FDS);
|
||||
#if LWIP_SO_LINGER
|
||||
struct linger sl;
|
||||
sl.l_onoff = 1; // non-zero value enables linger option in lwip
|
||||
sl.l_linger = 0; // timeout interval in seconds
|
||||
setsockopt(sock_id, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl));
|
||||
#endif // LWIP_SO_LINGER
|
||||
mb_set_linger(sock_id, 0);
|
||||
close(sock_id);
|
||||
} else {
|
||||
// Create new node info and open it
|
||||
@@ -685,12 +680,11 @@ void mb_drv_tcp_task(void *ctx)
|
||||
if (ret == ERR_CONN) {
|
||||
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", connection lost."), ctx, (int)node_ptr->fd,
|
||||
(int)node_ptr->sock_id, node_ptr->addr_info.ip_addr_str);
|
||||
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, node_ptr->index);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", critical read error=%d, errno=%u."), ctx, (int)node_ptr->fd,
|
||||
(int)node_ptr->sock_id, node_ptr->addr_info.ip_addr_str, (int)ret, (unsigned)errno);
|
||||
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, node_ptr->index);
|
||||
}
|
||||
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, node_ptr->index, ret);
|
||||
}
|
||||
}
|
||||
curr_fd++;
|
||||
|
||||
@@ -121,17 +121,36 @@ typedef struct _port_driver port_driver_t;
|
||||
|
||||
// Post event to event loop and unblocks the select through the eventfd to handle the event loop run,
|
||||
// So, the eventfd value keeps last event and its fd.
|
||||
#define DRIVER_SEND_EVENT(ctx, event, fd) (__extension__( \
|
||||
#define DRIVER_SEND_EVENT_MACRO(ctx, event, fd, value) (__extension__( \
|
||||
{ \
|
||||
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx); \
|
||||
mb_event_info_t (event_info##__FUNCTION__##__LINE__); \
|
||||
(event_info##__FUNCTION__##__LINE__).event_id = (int32_t)event; \
|
||||
(event_info##__FUNCTION__##__LINE__).opt_fd = fd; \
|
||||
(event_info##__FUNCTION__##__LINE__).opt_val = value; \
|
||||
((write_event((void *)drv_obj, &(event_info##__FUNCTION__##__LINE__)) > 0) \
|
||||
? ((event_info##__FUNCTION__##__LINE__)).event_id : UNDEF_FD); \
|
||||
} \
|
||||
))
|
||||
|
||||
#define PAR_CAT2(_1, _2) PAR_CAT_(_1, _2)
|
||||
#define PAR_CAT_(_1, _2) _1##_2
|
||||
|
||||
#define PAR_VA_NUM_ARGS(...) PAR_VA_NUM_ARGS_(__VA_ARGS__, 4, 3, 2, 1)
|
||||
#define PAR_VA_NUM_ARGS_(_1, _2, _3, _4, N, ...) N
|
||||
|
||||
// Initialization of event structure using variadic parameters
|
||||
#define DRIVER_SEND_EVENT(...) PAR_CAT2(DRIVER_SEND_EVENT_, PAR_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
#define DRIVER_SEND_EVENT_1(_1) \
|
||||
static_assert(0, "Number of parameters in this macro is incorrect.");
|
||||
#define DRIVER_SEND_EVENT_2(_1, _2) \
|
||||
DRIVER_SEND_EVENT_MACRO(_1, _2, -1, 0)
|
||||
#define DRIVER_SEND_EVENT_3(_1, _2, _3) \
|
||||
DRIVER_SEND_EVENT_MACRO(_1, _2, _3, 0)
|
||||
#define DRIVER_SEND_EVENT_4(_1, _2, _3, _4) \
|
||||
DRIVER_SEND_EVENT_MACRO(_1, _2, _3, _4)
|
||||
|
||||
#define MB_GET_NODE_STATE(pnode) (atomic_load(&((mb_node_info_t *)pnode)->addr_info.state))
|
||||
|
||||
#define MB_SET_NODE_STATE(pnode, node_state) do { \
|
||||
@@ -173,7 +192,8 @@ typedef struct {
|
||||
typedef union {
|
||||
struct {
|
||||
int32_t event_id; /*!< an event */
|
||||
int32_t opt_fd; /*!< fd option for an event */
|
||||
int16_t opt_fd; /*!< fd option for an event */
|
||||
int16_t opt_val; /*!< value option for an event */
|
||||
};
|
||||
uint64_t val;
|
||||
} mb_event_info_t;
|
||||
|
||||
@@ -531,12 +531,13 @@ MB_EVENT_HANDLER(mbm_on_error)
|
||||
mb_drv_clear_status_flag(ctx, MB_FLAG_CONNECTED);
|
||||
return;
|
||||
}
|
||||
int ret = mb_drv_check_node_state(drv_obj, (int *)&event_info->opt_fd, MB_RECONNECT_TIME_MS);
|
||||
int curr_fd = event_info->opt_fd;
|
||||
int ret = mb_drv_check_node_state(drv_obj, (int *)&curr_fd, MB_RECONNECT_TIME_MS);
|
||||
if ((ret != ERR_OK) && (ret != ERR_TIMEOUT)) {
|
||||
node_ptr = mb_drv_get_node(drv_obj, event_info->opt_fd);
|
||||
node_ptr = mb_drv_get_node(drv_obj, curr_fd);
|
||||
ESP_LOGW(TAG, "%p, "MB_NODE_FMT(", error handling."), ctx, (int)node_ptr->fd,
|
||||
(int)node_ptr->sock_id, node_ptr->addr_info.ip_addr_str);
|
||||
ESP_LOGE(TAG, "Node: %d, try to repair lost connection, err= %d", (int)event_info->opt_fd, ret);
|
||||
ESP_LOGE(TAG, "Node: %d, try to repair lost connection, err= %d", curr_fd, ret);
|
||||
FD_CLR(node_ptr->sock_id, &drv_obj->conn_set);
|
||||
mb_drv_lock(ctx);
|
||||
if (drv_obj->node_conn_count) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -449,8 +449,6 @@ MB_EVENT_HANDLER(mbs_on_recv_data)
|
||||
mb_drv_check_suspend_shutdown(ctx);
|
||||
return;
|
||||
}
|
||||
// send receive event to modbus object to get the new data
|
||||
drv_obj->event_cbs.mb_sync_event_cb(drv_obj->event_cbs.port_arg, MB_SYNC_EVENT_RECV_OK);
|
||||
mb_drv_lock(drv_obj);
|
||||
uint16_t msg_id = 0;
|
||||
int node_id = 0;
|
||||
@@ -465,6 +463,8 @@ MB_EVENT_HANDLER(mbs_on_recv_data)
|
||||
pnode->addr_info.ip_addr_str, (unsigned)msg_id);
|
||||
}
|
||||
mb_drv_unlock(drv_obj);
|
||||
// send receive event to modbus object to get the new data
|
||||
drv_obj->event_cbs.mb_sync_event_cb(drv_obj->event_cbs.port_arg, MB_SYNC_EVENT_RECV_OK);
|
||||
} else {
|
||||
if (transaction_item_get_state(item) != TRANSMITTED) {
|
||||
// Transaction processing is ongoing, just delete expired transactions
|
||||
@@ -488,6 +488,7 @@ MB_EVENT_HANDLER(mbs_on_send_data)
|
||||
transaction_item_handle_t item = NULL;
|
||||
esp_err_t err = ESP_ERR_INVALID_STATE;
|
||||
frame_entry_t frame_entry = {0};
|
||||
int ret = 0;
|
||||
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
|
||||
mb_node_info_t *pnode = mb_drv_get_node(drv_obj, event_info->opt_fd);
|
||||
if (pnode && !queue_is_empty(pnode->tx_queue)) {
|
||||
@@ -506,56 +507,66 @@ MB_EVENT_HANDLER(mbs_on_send_data)
|
||||
// If not, means the slave was not able to process the previous transaction on time.
|
||||
// The reason is too much active connections or incorrect response time or request rate in the master.
|
||||
if ((node_id != pnode->index) || (tid != msg_id) || (tid != pnode->tid_counter) || (MB_GET_NODE_STATE(pnode) < MB_SOCK_STATE_CONNECTED)) {
|
||||
mb_drv_lock(drv_obj);
|
||||
err = transaction_delete(port_obj->transaction, tid);
|
||||
mb_drv_unlock(drv_obj);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to remove queued TID:0x%04" PRIx16, (int)tid);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Remove the message TID:0x%04" PRIx16, (int)tid);
|
||||
}
|
||||
(void)mb_drv_set_status_flag(drv_obj, MB_FLAG_TRANSACTION_READY);
|
||||
uint64_t tick = (transaction_tick_t)transaction_item_get_tick(item);
|
||||
uint64_t time_div_us = (esp_timer_get_time() - tick);
|
||||
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", frame TID:0x%04" PRIx16 "!=0x%04" PRIx16 ", slave is busy."),
|
||||
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", frame TID:0x%04" PRIx16 "!=0x%04" PRIx16 " ,%" PRIu64 " ,%" PRIu64 " ,%" PRIx16 ", slave is busy."),
|
||||
ctx, (int)pnode->index, (int)pnode->sock_id,
|
||||
pnode->addr_info.ip_addr_str, pnode->tid_counter, tid);
|
||||
pnode->addr_info.ip_addr_str, pnode->tid_counter, tid, esp_timer_get_time(), tick, msg_id);
|
||||
ESP_LOGW(TAG, "%p, " MB_NODE_FMT(", handling time [ms]: %" PRIu64 ", exceeds slave response time in master."),
|
||||
ctx, (int)pnode->index, (int)pnode->sock_id,
|
||||
pnode->addr_info.ip_addr_str, (time_div_us / 1000));
|
||||
// Hard hack to fix the expired frames (unsafe in some cases, do not implement)
|
||||
// Hard hack to respond to next transaction with an exception
|
||||
// MB_TCP_MBAP_SET_FIELD(frame_entry.buf, MB_TCP_TID, pnode->tid_counter);
|
||||
} else {
|
||||
// Build the exception frame to inform that slave is busy
|
||||
frame_entry.buf[MB_TCP_FUNC] = (frame_entry.buf[MB_TCP_FUNC] | 0x80);
|
||||
frame_entry.buf[MB_TCP_LEN + 1] = 3; // Length: UID + FUNC + EXCEPTION
|
||||
frame_entry.buf[MB_TCP_FUNC + 1] = MB_EX_SLAVE_BUSY;
|
||||
ret = port_write_poll(pnode, frame_entry.buf, MB_TCP_FUNC + 2, MB_TCP_SEND_TIMEOUT_MS);
|
||||
mb_drv_lock(drv_obj);
|
||||
int ret = port_write_poll(pnode, frame_entry.buf, sz, MB_TCP_SEND_TIMEOUT_MS);
|
||||
if (ret < 0) {
|
||||
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", send data failure, err(errno) = %d(%u)."),
|
||||
ctx, (int)pnode->index, (int)pnode->sock_id,
|
||||
pnode->addr_info.ip_addr_str, (int)ret, (unsigned)errno);
|
||||
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, pnode->index);
|
||||
pnode->error = ret;
|
||||
if (ret >= 0) {
|
||||
err = transaction_set_state(port_obj->transaction, tid, TRANSMITTED);
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", sent packet TID: 0x%04" PRIx16 ", %p."),
|
||||
drv_obj, pnode->index, pnode->sock_id,
|
||||
pnode->addr_info.ip_addr_str, tid, frame_entry.buf);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", transaction set state fail for TID: 0x%04" PRIx16 ", %p."),
|
||||
drv_obj, pnode->index, pnode->sock_id,
|
||||
pnode->addr_info.ip_addr_str, tid, frame_entry.buf);
|
||||
}
|
||||
if (transaction_delete(port_obj->transaction, tid) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to remove queued TID:0x%04" PRIx16, tid);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Remove the message TID:0x%04" PRIx16, tid);
|
||||
}
|
||||
} else {
|
||||
pnode->error = 0;
|
||||
ESP_LOG_BUFFER_HEX_LEVEL("SENT", frame_entry.buf, ret, ESP_LOG_DEBUG);
|
||||
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, pnode->index);
|
||||
}
|
||||
(void)mb_drv_set_status_flag(drv_obj, MB_FLAG_TRANSACTION_READY);
|
||||
err = transaction_set_state(port_obj->transaction, tid, TRANSMITTED);
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", sent packet TID: 0x%04" PRIx16 ", %p."),
|
||||
drv_obj, pnode->index, pnode->sock_id,
|
||||
pnode->addr_info.ip_addr_str, tid, frame_entry.buf);
|
||||
mb_drv_unlock(drv_obj);
|
||||
} else {
|
||||
ret = port_write_poll(pnode, frame_entry.buf, frame_entry.len, MB_TCP_SEND_TIMEOUT_MS);
|
||||
mb_drv_lock(drv_obj);
|
||||
if (ret >= 0) {
|
||||
err = transaction_set_state(port_obj->transaction, tid, TRANSMITTED);
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", sent packet TID: 0x%04" PRIx16 ", %p."),
|
||||
drv_obj, pnode->index, pnode->sock_id,
|
||||
pnode->addr_info.ip_addr_str, tid, frame_entry.buf);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", transaction set state fail for TID: 0x%04" PRIx16 ", %p."),
|
||||
drv_obj, pnode->index, pnode->sock_id,
|
||||
pnode->addr_info.ip_addr_str, tid, frame_entry.buf);
|
||||
}
|
||||
if (transaction_delete_item(port_obj->transaction, item) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to remove queued TID:0x%04" PRIx16, tid);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Remove the message TID:0x%04" PRIx16, tid);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", transaction set state fail for TID: 0x%04" PRIx16 ", %p."),
|
||||
drv_obj, pnode->index, pnode->sock_id,
|
||||
pnode->addr_info.ip_addr_str, tid, frame_entry.buf);
|
||||
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, pnode->index);
|
||||
}
|
||||
if (transaction_delete_item(port_obj->transaction, item) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to remove queued TID:0x%04" PRIx16, tid);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Remove the message TID:0x%04" PRIx16, tid);
|
||||
}
|
||||
pnode->send_time = port_get_timestamp();
|
||||
pnode->send_counter = (pnode->send_counter < (USHRT_MAX - 1)) ? (pnode->send_counter + 1) : 0;
|
||||
(void)mb_drv_set_status_flag(drv_obj, MB_FLAG_TRANSACTION_READY);
|
||||
mb_drv_unlock(drv_obj);
|
||||
}
|
||||
} else {
|
||||
@@ -577,6 +588,22 @@ MB_EVENT_HANDLER(mbs_on_send_data)
|
||||
mb_drv_check_suspend_shutdown(ctx);
|
||||
}
|
||||
|
||||
static void mbs_retrigger_pending_transactions(void *ctx, mbs_tcp_port_t *port_obj)
|
||||
{
|
||||
transaction_item_handle_t pending = transaction_get_first(port_obj->transaction);
|
||||
if (pending && (transaction_item_get_state(pending) == QUEUED)) {
|
||||
int pending_node_id = 0;
|
||||
uint16_t pending_msg_id = 0;
|
||||
(void)transaction_item_get_data(pending, NULL, &pending_msg_id, &pending_node_id);
|
||||
mb_node_info_t *pending_node = mb_drv_get_node(MB_GET_DRV_PTR(ctx), pending_node_id);
|
||||
if (pending_node) {
|
||||
ESP_LOGD(TAG, "Re-trigger pending transaction TID:0x%04x for node #%d.",
|
||||
pending_msg_id, pending_node_id);
|
||||
DRIVER_SEND_EVENT(ctx, MB_EVENT_RECV_DATA, pending_node_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MB_EVENT_HANDLER(mbs_on_error)
|
||||
{
|
||||
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
|
||||
@@ -588,17 +615,34 @@ MB_EVENT_HANDLER(mbs_on_error)
|
||||
ESP_LOGD(TAG, "%s %s: fd: %d, is closed.", (char *)base, __func__, (int)event_info->opt_fd);
|
||||
return;
|
||||
}
|
||||
// Check if the node is not alive for timeout
|
||||
int ret = mb_drv_check_node_state(drv_obj, (int *)&event_info->opt_fd, MB_EVENT_SEND_RCV_TOUT_MS);
|
||||
if ((ret != ERR_OK) && (ret != ERR_TIMEOUT)) {
|
||||
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", communication fail, err= %d"),
|
||||
mb_drv_check_suspend_shutdown(ctx);
|
||||
if (event_info->opt_val == ERR_CONN) {
|
||||
ESP_LOGW(TAG, "%p, " MB_NODE_FMT(", connection closed?, err= %d."),
|
||||
port_obj, pnode->index, pnode->sock_id,
|
||||
pnode->addr_info.ip_addr_str, (int)ret);
|
||||
pnode->addr_info.ip_addr_str, (int)event_info->opt_val);
|
||||
mb_drv_lock(drv_obj);
|
||||
// delete all queued transactions for the node to be closed.
|
||||
(void)transaction_delete_by_node_id(port_obj->transaction, event_info->opt_fd);
|
||||
mb_set_linger(pnode->sock_id, 0); // send RST immediately
|
||||
mb_drv_unlock(drv_obj);
|
||||
mb_drv_close(drv_obj, event_info->opt_fd);
|
||||
// Re-trigger any pending QUEUED transactions for surviving other clients
|
||||
mbs_retrigger_pending_transactions(ctx, port_obj);
|
||||
} else {
|
||||
// An error happened, disconnect and close node after timeout.
|
||||
// The master need to reconnect again to send new transaction.
|
||||
int curr_fd = event_info->opt_fd;
|
||||
int ret = mb_drv_check_node_state(drv_obj, &curr_fd, MB_TCP_KEEP_ALIVE_TOUT_MS);
|
||||
if ((ret != ERR_OK) && (ret != ERR_TIMEOUT)) {
|
||||
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", communication fail, err=%d, drop connection."),
|
||||
port_obj, pnode->index, pnode->sock_id,
|
||||
pnode->addr_info.ip_addr_str, (int)ret);
|
||||
mb_drv_lock(drv_obj);
|
||||
(void)transaction_delete_by_node_id(port_obj->transaction, curr_fd);
|
||||
mb_drv_unlock(drv_obj);
|
||||
mb_drv_close(drv_obj, curr_fd);
|
||||
mbs_retrigger_pending_transactions(ctx, port_obj);
|
||||
}
|
||||
}
|
||||
mb_drv_check_suspend_shutdown(ctx);
|
||||
}
|
||||
@@ -646,7 +690,7 @@ MB_EVENT_HANDLER(mbs_on_timeout)
|
||||
mb_node_info_t *pnode = mb_drv_get_node(drv_obj, curr_fd);
|
||||
ESP_LOGD(TAG, "%s %s: fd: %d, count: %d", (char *)base, __func__, (int)curr_fd, drv_obj->node_conn_count);
|
||||
mb_drv_check_suspend_shutdown(ctx);
|
||||
int ret = mb_drv_check_node_state(drv_obj, &curr_fd, MB_TCP_KEEP_ALIVE_TOUT_MS);
|
||||
int ret = mb_drv_check_node_state(drv_obj, &curr_fd, CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000);
|
||||
if ((ret != ERR_OK) && (ret != ERR_TIMEOUT)) {
|
||||
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", connection lost, err=%d, drop connection."),
|
||||
port_obj, pnode->index, pnode->sock_id,
|
||||
|
||||
@@ -79,6 +79,8 @@ bool port_close_connection(mb_node_info_t *info_ptr)
|
||||
queue_flush(info_ptr->rx_queue);
|
||||
queue_flush(info_ptr->tx_queue);
|
||||
|
||||
mb_set_linger(info_ptr->sock_id, 0); // RST, avoid TIME_WAIT blocking
|
||||
|
||||
if (shutdown(info_ptr->sock_id, SHUT_RDWR) == -1) {
|
||||
ESP_LOGV(TAG, "Shutdown failed sock %d, errno=%d", info_ptr->sock_id, (int)errno);
|
||||
}
|
||||
@@ -172,7 +174,12 @@ static int port_get_buf(mb_node_info_t *info_ptr, uint8_t *pdst_buf, uint16_t le
|
||||
|
||||
// blocking read of data from socket
|
||||
ret = recv(info_ptr->sock_id, buf, bytes_left, 0);
|
||||
if (ret == 0) {
|
||||
return ERR_CONN; // FIN received, peer closed
|
||||
}
|
||||
if (ret < 0) {
|
||||
ESP_LOGD(TAG, "socket(#%d)(%s) recv return, ret=%d, errno=%d.",
|
||||
info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, ret, (int)errno);
|
||||
if (errno == EINPROGRESS || errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
// Read timeout occurred, check the timeout and return
|
||||
return 0;
|
||||
@@ -202,6 +209,12 @@ int port_read_packet(mb_node_info_t *info_ptr)
|
||||
MB_RETURN_ON_FALSE((info_ptr->sock_id > 0), -1, TAG, "try to read incorrect socket = #%d", info_ptr->sock_id);
|
||||
// Read packet header
|
||||
ret = port_get_buf(info_ptr, ptemp_buf, MB_TCP_UID, MB_READ_TICK);
|
||||
if (ret == 0) {
|
||||
ESP_LOGD(TAG, "node #%d, Socket (#%d)(%s), socket connection is closed or timeout, err=%d, ",
|
||||
info_ptr->fd, info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, ret);
|
||||
return ERR_CONN;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
info_ptr->recv_err = ret;
|
||||
return ret;
|
||||
@@ -280,6 +293,18 @@ err_t port_set_blocking(mb_node_info_t *info_ptr, bool is_blocking)
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
int mb_set_linger(int sock, int tout)
|
||||
{
|
||||
int res = -1;
|
||||
#if LWIP_SO_LINGER
|
||||
struct linger sl;
|
||||
sl.l_onoff = 1;
|
||||
sl.l_linger = tout;
|
||||
res = setsockopt(sock, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl));
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
int port_keep_alive_enable(int sock, int timeout_sec)
|
||||
{
|
||||
if ((timeout_sec > 7200) || (timeout_sec < 1)) {
|
||||
@@ -373,7 +398,7 @@ err_t port_connect(void *ctx, mb_node_info_t *info_ptr)
|
||||
}
|
||||
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
|
||||
err_t err = ERR_OK;
|
||||
char str[MDNS_NAME_BUF_LEN];
|
||||
char str[MDNS_NAME_BUF_LEN] = {0};
|
||||
char *string_ptr = NULL;
|
||||
ip_addr_t target_addr;
|
||||
struct addrinfo hint;
|
||||
@@ -474,18 +499,25 @@ int port_write_poll(mb_node_info_t *info_ptr, const uint8_t *frame, uint16_t fra
|
||||
return -1;
|
||||
}
|
||||
// Check if the socket is alive (writable and SO_ERROR == 0)
|
||||
int res = (int)port_check_alive(info_ptr, timeout);
|
||||
if ((res < 0) && (res != ERR_INPROGRESS)) {
|
||||
int ret = (int)port_check_alive(info_ptr, timeout);
|
||||
if ((ret < 0) && (ret != ERR_INPROGRESS)) {
|
||||
ESP_LOGE(TAG, MB_NODE_FMT(", is not writable, error: %d, errno %d"),
|
||||
info_ptr->index, info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, res, (int)errno);
|
||||
return res;
|
||||
info_ptr->index, info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, ret, (int)errno);
|
||||
return ret;
|
||||
}
|
||||
res = send(info_ptr->sock_id, frame, frame_len, TCP_NODELAY);
|
||||
if (res < 0) {
|
||||
ret = send(info_ptr->sock_id, frame, frame_len, TCP_NODELAY);
|
||||
if (ret < 0) {
|
||||
ESP_LOGE(TAG, MB_NODE_FMT(", send data error: %d, errno %d"),
|
||||
info_ptr->index, info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, res, (int)errno);
|
||||
info_ptr->index, info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, ret, (int)errno);
|
||||
info_ptr->error = ret;
|
||||
} else {
|
||||
ESP_LOG_BUFFER_HEX_LEVEL("SENT", frame, ret, ESP_LOG_DEBUG);
|
||||
info_ptr->error = 0;
|
||||
info_ptr->send_time = port_get_timestamp();
|
||||
info_ptr->send_counter = (info_ptr->send_counter < (USHRT_MAX - 1))
|
||||
? (info_ptr->send_counter + 1) : 0;
|
||||
}
|
||||
return res;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Scan IP address according to IPV settings
|
||||
|
||||
@@ -102,6 +102,8 @@ typedef struct frame_queue_entry_s frame_entry_t;
|
||||
typedef struct mb_node_info_s mb_node_info_t;
|
||||
typedef enum addr_type_enum mb_tcp_addr_type_t;
|
||||
|
||||
int mb_set_linger(int sock, int tout);
|
||||
|
||||
bool port_check_host_addr(const char *host_str, ip_addr_t *host_addr);
|
||||
mb_node_info_t *port_get_current_info(void *ctx);
|
||||
void port_check_shutdown(void *ctx);
|
||||
|
||||
Reference in New Issue
Block a user