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

@@ -22,6 +22,30 @@
static const char *TAG = "httpd_txrx";
esp_err_t httpd_set_sess_send_override(httpd_handle_t hd, int sockfd, httpd_send_func_t send_func)
{
struct sock_db *sess = httpd_sess_get(hd, sockfd);
if (!sess) return ESP_ERR_INVALID_ARG;
sess->send_fn = send_func;
return ESP_OK;
}
esp_err_t httpd_set_sess_recv_override(httpd_handle_t hd, int sockfd, httpd_recv_func_t recv_func)
{
struct sock_db *sess = httpd_sess_get(hd, sockfd);
if (!sess) return ESP_ERR_INVALID_ARG;
sess->recv_fn = recv_func;
return ESP_OK;
}
esp_err_t httpd_set_sess_pending_override(httpd_handle_t hd, int sockfd, httpd_pending_func_t pending_func)
{
struct sock_db *sess = httpd_sess_get(hd, sockfd);
if (!sess) return ESP_ERR_INVALID_ARG;
sess->pending_fn = pending_func;
return ESP_OK;
}
esp_err_t httpd_set_send_override(httpd_req_t *r, httpd_send_func_t send_func)
{
if (r == NULL || send_func == NULL) {
@@ -52,6 +76,21 @@ esp_err_t httpd_set_recv_override(httpd_req_t *r, httpd_recv_func_t recv_func)
return ESP_OK;
}
esp_err_t httpd_set_pending_override(httpd_req_t *r, httpd_pending_func_t pending_func)
{
if (r == NULL || pending_func == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (!httpd_valid_req(r)) {
return ESP_ERR_HTTPD_INVALID_REQ;
}
struct httpd_req_aux *ra = r->aux;
ra->sd->pending_fn = pending_func;
return ESP_OK;
}
int httpd_send(httpd_req_t *r, const char *buf, size_t buf_len)
{
if (r == NULL || buf == NULL) {
@@ -63,7 +102,7 @@ int httpd_send(httpd_req_t *r, const char *buf, size_t buf_len)
}
struct httpd_req_aux *ra = r->aux;
int ret = ra->sd->send_fn(ra->sd->fd, buf, buf_len, 0);
int ret = ra->sd->send_fn(ra->sd->handle, ra->sd->fd, buf, buf_len, 0);
if (ret < 0) {
ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
return ret;
@@ -77,7 +116,7 @@ static esp_err_t httpd_send_all(httpd_req_t *r, const char *buf, size_t buf_len)
int ret;
while (buf_len > 0) {
ret = ra->sd->send_fn(ra->sd->fd, buf, buf_len, 0);
ret = ra->sd->send_fn(ra->sd->handle, ra->sd->fd, buf, buf_len, 0);
if (ret < 0) {
ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
return ESP_FAIL;
@@ -125,7 +164,7 @@ int httpd_recv_with_opt(httpd_req_t *r, char *buf, size_t buf_len, bool halt_aft
}
/* Receive data of remaining length */
int ret = ra->sd->recv_fn(ra->sd->fd, buf, buf_len, 0);
int ret = ra->sd->recv_fn(ra->sd->handle, ra->sd->fd, buf, buf_len, 0);
if (ret < 0) {
ESP_LOGD(TAG, LOG_FMT("error in recv_fn"));
if ((ret == HTTPD_SOCK_ERR_TIMEOUT) && (pending_len != 0)) {
@@ -231,7 +270,7 @@ esp_err_t httpd_resp_set_type(httpd_req_t *r, const char *type)
return ESP_OK;
}
esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, size_t buf_len)
esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, ssize_t buf_len)
{
if (r == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -246,6 +285,8 @@ esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, size_t buf_len)
const char *colon_separator = ": ";
const char *cr_lf_seperator = "\r\n";
if (buf_len == -1) buf_len = strlen(buf);
/* Request headers are no longer available */
ra->req_hdrs_count = 0;
@@ -294,7 +335,7 @@ esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, size_t buf_len)
return ESP_OK;
}
esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, size_t buf_len)
esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, ssize_t buf_len)
{
if (r == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -304,6 +345,8 @@ esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, size_t buf_len)
return ESP_ERR_HTTPD_INVALID_REQ;
}
if (buf_len == -1) buf_len = strlen(buf);
struct httpd_req_aux *ra = r->aux;
const char *httpd_chunked_hdr_str = "HTTP/1.1 %s\r\nContent-Type: %s\r\nTransfer-Encoding: chunked\r\n";
const char *colon_separator = ": ";
@@ -359,7 +402,7 @@ esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, size_t buf_len)
}
if (buf) {
if (httpd_send_all(r, buf, buf_len) != ESP_OK) {
if (httpd_send_all(r, buf, (size_t) buf_len) != ESP_OK) {
return ESP_ERR_HTTPD_RESP_SEND;
}
}
@@ -520,8 +563,9 @@ static int httpd_sock_err(const char *ctx, int sockfd)
return errval;
}
int httpd_default_send(int sockfd, const char *buf, size_t buf_len, int flags)
int httpd_default_send(httpd_handle_t hd, int sockfd, const char *buf, size_t buf_len, int flags)
{
(void)hd;
if (buf == NULL) {
return HTTPD_SOCK_ERR_INVALID;
}
@@ -533,8 +577,9 @@ int httpd_default_send(int sockfd, const char *buf, size_t buf_len, int flags)
return ret;
}
int httpd_default_recv(int sockfd, char *buf, size_t buf_len, int flags)
int httpd_default_recv(httpd_handle_t hd, int sockfd, char *buf, size_t buf_len, int flags)
{
(void)hd;
if (buf == NULL) {
return HTTPD_SOCK_ERR_INVALID;
}