Skip to content

Commit

Permalink
Merge branch 'feature/add_keep_alive_for_httpserver' into 'master'
Browse files Browse the repository at this point in the history
esp_http_server: Add support to enable TCP keepalive config

Closes IDFGH-8379

See merge request espressif/esp-idf!20842
  • Loading branch information
mahavirj committed Nov 1, 2022
2 parents 1cf1b83 + e05d61d commit a6b9304
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 8 deletions.
9 changes: 8 additions & 1 deletion components/esp_http_server/include/esp_http_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ initializer that should be kept in sync
.global_transport_ctx_free_fn = NULL, \
.enable_so_linger = false, \
.linger_timeout = 0, \
.keep_alive_enable = false, \
.keep_alive_idle = 0, \
.keep_alive_interval = 0, \
.keep_alive_count = 0, \
.open_fn = NULL, \
.close_fn = NULL, \
.uri_match_fn = NULL \
Expand Down Expand Up @@ -189,7 +193,10 @@ typedef struct httpd_config {

bool enable_so_linger; /*!< bool to enable/disable linger */
int linger_timeout; /*!< linger timeout (in seconds) */

bool keep_alive_enable; /*!< Enable keep-alive timeout */
int keep_alive_idle; /*!< Keep-alive idle time. Default is 5 (second) */
int keep_alive_interval;/*!< Keep-alive interval time. Default is 5 (second) */
int keep_alive_count; /*!< Keep-alive packet retry send count. Default is 3 counts */
/**
* Custom session opening callback.
*
Expand Down
46 changes: 39 additions & 7 deletions components/esp_http_server/src/httpd_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
#include "freertos/semphr.h"
#endif

static const int DEFAULT_KEEP_ALIVE_IDLE = 5;
static const int DEFAULT_KEEP_ALIVE_INTERVAL= 5;
static const int DEFAULT_KEEP_ALIVE_COUNT= 3;

typedef struct {
fd_set *fdset;
struct httpd_data *hd;
Expand Down Expand Up @@ -46,7 +50,7 @@ static esp_err_t httpd_accept_conn(struct httpd_data *hd, int listen_fd)
socklen_t addr_from_len = sizeof(addr_from);
int new_fd = accept(listen_fd, (struct sockaddr *)&addr_from, &addr_from_len);
if (new_fd < 0) {
ESP_LOGW(TAG, LOG_FMT("error in accept (%d)"), errno);
ESP_LOGE(TAG, LOG_FMT("error in accept (%d)"), errno);
return ESP_FAIL;
}
ESP_LOGD(TAG, LOG_FMT("newfd = %d"), new_fd);
Expand All @@ -56,23 +60,51 @@ static esp_err_t httpd_accept_conn(struct httpd_data *hd, int listen_fd)
tv.tv_sec = hd->config.recv_wait_timeout;
tv.tv_usec = 0;
if (setsockopt(new_fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)) < 0) {
ESP_LOGW(TAG, LOG_FMT("error enabling SO_RCVTIMEO (%d)"), errno);
ESP_LOGE(TAG, LOG_FMT("error in setsockopt SO_RCVTIMEO (%d)"), errno);
goto exit;
}

/* Set send timeout of this fd as per config */
tv.tv_sec = hd->config.send_wait_timeout;
tv.tv_usec = 0;
if (setsockopt(new_fd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tv, sizeof(tv)) < 0) {
ESP_LOGW(TAG, LOG_FMT("error enabling SO_SNDTIMEO (%d)"), errno);
ESP_LOGE(TAG, LOG_FMT("error in setsockopt SO_SNDTIMEO (%d)"), errno);
goto exit;
}

if (hd->config.keep_alive_enable) {
int keep_alive_enable = 1;
int keep_alive_idle = hd->config.keep_alive_idle ? hd->config.keep_alive_idle : DEFAULT_KEEP_ALIVE_IDLE;
int keep_alive_interval = hd->config.keep_alive_interval ? hd->config.keep_alive_interval : DEFAULT_KEEP_ALIVE_INTERVAL;
int keep_alive_count = hd->config.keep_alive_count ? hd->config.keep_alive_count : DEFAULT_KEEP_ALIVE_COUNT;
ESP_LOGD(TAG, "Enable TCP keep alive. idle: %d, interval: %d, count: %d", keep_alive_idle, keep_alive_interval, keep_alive_count);

if (setsockopt(new_fd, SOL_SOCKET, SO_KEEPALIVE, &keep_alive_enable, sizeof(keep_alive_enable)) < 0) {
ESP_LOGE(TAG, LOG_FMT("error in setsockopt SO_KEEPALIVE (%d)"), errno);
goto exit;
}
if (setsockopt(new_fd, IPPROTO_TCP, TCP_KEEPIDLE, &keep_alive_idle, sizeof(keep_alive_idle)) < 0) {
ESP_LOGE(TAG, LOG_FMT("error in setsockopt TCP_KEEPIDLE (%d)"), errno);
goto exit;
}
if (setsockopt(new_fd, IPPROTO_TCP, TCP_KEEPINTVL, &keep_alive_interval, sizeof(keep_alive_interval)) < 0) {
ESP_LOGE(TAG, LOG_FMT("error in setsockopt TCP_KEEPINTVL (%d)"), errno);
goto exit;
}
if (setsockopt(new_fd, IPPROTO_TCP, TCP_KEEPCNT, &keep_alive_count, sizeof(keep_alive_count)) < 0) {
ESP_LOGE(TAG, LOG_FMT("error in setsockopt TCP_KEEPCNT (%d)"), errno);
goto exit;
}
}
if (ESP_OK != httpd_sess_new(hd, new_fd)) {
ESP_LOGW(TAG, LOG_FMT("session creation failed"));
close(new_fd);
return ESP_FAIL;
ESP_LOGE(TAG, LOG_FMT("session creation failed"));
goto exit;
}
ESP_LOGD(TAG, LOG_FMT("complete"));
return ESP_OK;
exit:
close(new_fd);
return ESP_FAIL;
}

struct httpd_ctrl_data {
Expand Down Expand Up @@ -321,7 +353,7 @@ static esp_err_t httpd_server_init(struct httpd_data *hd)
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) {
/* This will fail if CONFIG_LWIP_SO_REUSE is not enabled. But
* it does not affect the normal working of the HTTP Server */
ESP_LOGW(TAG, LOG_FMT("error enabling SO_REUSEADDR (%d)"), errno);
ESP_LOGW(TAG, LOG_FMT("error in setsockopt SO_REUSEADDR (%d)"), errno);
}

int ret = bind(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
Expand Down

0 comments on commit a6b9304

Please sign in to comment.