esp_http_server improvements to allow adding transport layer encryption

Changes:
- renamed `httpd_free_sess_ctx_fn_t` to `httpd_free_ctx_fn_t`
- added a `httpd_handle_t` argument to `httpd_send_func_t` and `httpd_recv_func_t`
- internal function `httpd_sess_get()` is no longer static, as it's used in other
  files besides httpd_sess.c

Bug fixes:
- removed a trailing semicolon from `HTTPD_DEFAULT_CONFIG()`
- fixed issue with failed `select()`, now it automatically closes invalid sockets
  instead of shutting down the entire server

New features:
- `httpd_resp_send()` and `httpd_resp_send_chunk()` now accept -1 as length to use
  `strlen()` internally
- added `httpd_sess_set_ctx()` to accompany `httpd_sess_get_ctx()`
- added a "transport context" to the session structure (next to user context)
- added `httpd_sess_{get,set}_transport_ctx()` to work with this transport context
- added "global user context" and "global transport context" stored in the server
  config (and then the handle); supports a user-provided free_fn
- added a "pending func" to e.g. check for data in the transport layer receive
  buffer
- added functions `httpd_set_sess_{send,recv,pending}_override()` that target
  a session by ID (i.e. not using a request object)
- added `httpd_set_pending_override()`
- added a "open_fn" and "close_fn" - functions called when creating and closing
  a session. These may be used to set up transport layer encryption or some other
  session-wide feature
This commit is contained in:
Ondřej Hruška
2018-10-31 22:59:57 +01:00
committed by bot
parent 26bcb7f2cf
commit a10fc02dd9
5 changed files with 441 additions and 37 deletions

View File

@@ -62,8 +62,8 @@ static esp_err_t httpd_accept_conn(struct httpd_data *hd, int listen_fd)
tv.tv_usec = 0;
setsockopt(new_fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof(tv));
if (httpd_sess_new(hd, new_fd)) {
ESP_LOGW(TAG, LOG_FMT("no slots left for launching new session"));
if (ESP_OK != httpd_sess_new(hd, new_fd)) {
ESP_LOGW(TAG, LOG_FMT("session creation failed"));
close(new_fd);
return ESP_FAIL;
}
@@ -102,6 +102,16 @@ esp_err_t httpd_queue_work(httpd_handle_t handle, httpd_work_fn_t work, void *ar
return ESP_OK;
}
void *httpd_get_global_user_ctx(httpd_handle_t handle)
{
return ((struct httpd_data *)handle)->config.global_user_ctx;
}
void *httpd_get_global_transport_ctx(httpd_handle_t handle)
{
return ((struct httpd_data *)handle)->config.global_transport_ctx;
}
static void httpd_close_all_sessions(struct httpd_data *hd)
{
int fd = -1;
@@ -159,11 +169,8 @@ static esp_err_t httpd_server(struct httpd_data *hd)
int active_cnt = select(maxfd + 1, &read_set, NULL, NULL, NULL);
if (active_cnt < 0) {
ESP_LOGE(TAG, LOG_FMT("error in select (%d)"), errno);
/* Assert, as it's not possible to recover from this point onwards,
* and there is no way to notify the main thread that server handle
* has become invalid */
assert(false);
return ESP_FAIL;
httpd_sess_delete_invalid(hd);
return ESP_OK;
}
/* Case0: Do we have a control message? */
@@ -367,7 +374,27 @@ esp_err_t httpd_stop(httpd_handle_t handle)
ESP_LOGD(TAG, LOG_FMT("sent control msg to stop server"));
while (hd->hd_td.status != THREAD_STOPPED) {
httpd_os_thread_sleep(1000);
httpd_os_thread_sleep(100);
}
/* Release global user context, if not NULL */
if (hd->config.global_user_ctx) {
if (hd->config.global_user_ctx_free_fn) {
hd->config.global_user_ctx_free_fn(hd->config.global_user_ctx);
} else {
free(hd->config.global_user_ctx);
}
hd->config.global_user_ctx = NULL;
}
/* Release global transport context, if not NULL */
if (hd->config.global_transport_ctx) {
if (hd->config.global_transport_ctx_free_fn) {
hd->config.global_transport_ctx_free_fn(hd->config.global_transport_ctx);
} else {
free(hd->config.global_transport_ctx);
}
hd->config.global_transport_ctx = NULL;
}
ESP_LOGD(TAG, LOG_FMT("server stopped"));