forked from espressif/esp-idf
HTTP Server : Return HTTPD_SOCK_ERR_ based on errno set during send / recv
This feature allows `httpd_req_recv()` and `httpd_send()` functions to return specific `HTTPD_SOCK_ERR_` codes in case of socket errors. This is useful in case of errors like `EAGAIN`, `EINTR`, etc. when the user may want to retry `httpd_req_recv()` / `httpd_send()` function call.
This commit is contained in:
@@ -348,19 +348,39 @@ esp_err_t httpd_unregister_uri(httpd_handle_t handle, const char* uri);
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define HTTPD_SOCK_ERR_FAIL -1
|
||||||
|
#define HTTPD_SOCK_ERR_INVALID -2
|
||||||
|
#define HTTPD_SOCK_ERR_TIMEOUT -3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Prototype for HTTPDs low-level send function
|
* @brief Prototype for HTTPDs low-level send function
|
||||||
|
*
|
||||||
|
* @note User specified send function must handle errors internally,
|
||||||
|
* depending upon the set value of errno, and return specific
|
||||||
|
* HTTPD_SOCK_ERR_ codes, which will eventually be conveyed as
|
||||||
|
* return value of httpd_send() function
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* - Bytes : The number of bytes sent successfully
|
* - Bytes : The number of bytes sent successfully
|
||||||
* - -VE : In case of error
|
* - HTTPD_SOCK_ERR_INVALID : Invalid arguments
|
||||||
|
* - HTTPD_SOCK_ERR_TIMEOUT : Timeout/interrupted while calling socket send()
|
||||||
|
* - HTTPD_SOCK_ERR_FAIL : Unrecoverable error while calling socket send()
|
||||||
*/
|
*/
|
||||||
typedef int (*httpd_send_func_t)(int sockfd, const char *buf, size_t buf_len, int flags);
|
typedef int (*httpd_send_func_t)(int sockfd, const char *buf, size_t buf_len, int flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Prototype for HTTPDs low-level recv function
|
* @brief Prototype for HTTPDs low-level recv function
|
||||||
|
*
|
||||||
|
* @note User specified recv function must handle errors internally,
|
||||||
|
* depending upon the set value of errno, and return specific
|
||||||
|
* HTTPD_SOCK_ERR_ codes, which will eventually be conveyed as
|
||||||
|
* return value of httpd_req_recv() function
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* - Bytes : The number of bytes received successfully
|
* - Bytes : The number of bytes received successfully
|
||||||
* - -VE : In case of error
|
* - HTTPD_SOCK_ERR_INVALID : Invalid arguments
|
||||||
|
* - HTTPD_SOCK_ERR_TIMEOUT : Timeout/interrupted while calling socket recv()
|
||||||
|
* - HTTPD_SOCK_ERR_FAIL : Unrecoverable error while calling socket recv()
|
||||||
*/
|
*/
|
||||||
typedef int (*httpd_recv_func_t)(int sockfd, char *buf, size_t buf_len, int flags);
|
typedef int (*httpd_recv_func_t)(int sockfd, char *buf, size_t buf_len, int flags);
|
||||||
|
|
||||||
@@ -462,7 +482,9 @@ int httpd_req_to_sockfd(httpd_req_t *r);
|
|||||||
* @return
|
* @return
|
||||||
* - Bytes : Number of bytes read into the buffer successfully
|
* - Bytes : Number of bytes read into the buffer successfully
|
||||||
* - Zero : When no more data is left for read
|
* - Zero : When no more data is left for read
|
||||||
* - -1 : On raw recv error / Null arguments / Request pointer is invalid
|
* - HTTPD_SOCK_ERR_INVALID : Invalid arguments
|
||||||
|
* - HTTPD_SOCK_ERR_TIMEOUT : Timeout/interrupted while calling socket recv()
|
||||||
|
* - HTTPD_SOCK_ERR_FAIL : Unrecoverable error while calling socket recv()
|
||||||
*/
|
*/
|
||||||
int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len);
|
int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len);
|
||||||
|
|
||||||
@@ -796,7 +818,9 @@ esp_err_t httpd_resp_send_404(httpd_req_t *r);
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - Bytes : Number of bytes that were sent successfully
|
* - Bytes : Number of bytes that were sent successfully
|
||||||
* - -1 : Error in raw send / Invalid request / Null arguments
|
* - HTTPD_SOCK_ERR_INVALID : Invalid arguments
|
||||||
|
* - HTTPD_SOCK_ERR_TIMEOUT : Timeout/interrupted while calling socket send()
|
||||||
|
* - HTTPD_SOCK_ERR_FAIL : Unrecoverable error while calling socket send()
|
||||||
*/
|
*/
|
||||||
int httpd_send(httpd_req_t *r, const char *buf, size_t buf_len);
|
int httpd_send(httpd_req_t *r, const char *buf, size_t buf_len);
|
||||||
|
|
||||||
|
@@ -55,18 +55,18 @@ esp_err_t httpd_set_recv_override(httpd_req_t *r, httpd_recv_func_t recv_func)
|
|||||||
int httpd_send(httpd_req_t *r, const char *buf, size_t buf_len)
|
int httpd_send(httpd_req_t *r, const char *buf, size_t buf_len)
|
||||||
{
|
{
|
||||||
if (r == NULL || buf == NULL) {
|
if (r == NULL || buf == NULL) {
|
||||||
return -1;
|
return HTTPD_SOCK_ERR_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!httpd_valid_req(r)) {
|
if (!httpd_valid_req(r)) {
|
||||||
return -1;
|
return HTTPD_SOCK_ERR_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct httpd_req_aux *ra = r->aux;
|
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->fd, buf, buf_len, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
|
ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -128,7 +128,7 @@ int httpd_recv_with_opt(httpd_req_t *r, char *buf, size_t buf_len, bool halt_aft
|
|||||||
int ret = ra->sd->recv_fn(ra->sd->fd, buf, buf_len, 0);
|
int ret = ra->sd->recv_fn(ra->sd->fd, buf, buf_len, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ESP_LOGD(TAG, LOG_FMT("error in recv_fn"));
|
ESP_LOGD(TAG, LOG_FMT("error in recv_fn"));
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret + pending_len);
|
ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret + pending_len);
|
||||||
@@ -429,12 +429,12 @@ esp_err_t httpd_resp_send_err(httpd_req_t *req, httpd_err_resp_t error)
|
|||||||
int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len)
|
int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len)
|
||||||
{
|
{
|
||||||
if (r == NULL || buf == NULL) {
|
if (r == NULL || buf == NULL) {
|
||||||
return -1;
|
return HTTPD_SOCK_ERR_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!httpd_valid_req(r)) {
|
if (!httpd_valid_req(r)) {
|
||||||
ESP_LOGW(TAG, LOG_FMT("invalid request"));
|
ESP_LOGW(TAG, LOG_FMT("invalid request"));
|
||||||
return -1;
|
return HTTPD_SOCK_ERR_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct httpd_req_aux *ra = r->aux;
|
struct httpd_req_aux *ra = r->aux;
|
||||||
@@ -450,8 +450,7 @@ int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len)
|
|||||||
int ret = httpd_recv(r, buf, buf_len);
|
int ret = httpd_recv(r, buf, buf_len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ESP_LOGD(TAG, LOG_FMT("error in httpd_recv"));
|
ESP_LOGD(TAG, LOG_FMT("error in httpd_recv"));
|
||||||
ra->remaining_len = 0;
|
return ret;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
ra->remaining_len -= ret;
|
ra->remaining_len -= ret;
|
||||||
ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret);
|
ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret);
|
||||||
@@ -473,15 +472,38 @@ int httpd_req_to_sockfd(httpd_req_t *r)
|
|||||||
return ra->sd->fd;
|
return ra->sd->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int httpd_sock_err(const char *ctx)
|
||||||
|
{
|
||||||
|
int errval;
|
||||||
|
|
||||||
|
ESP_LOGW(TAG, LOG_FMT("errno in %s : %d"), ctx, errno);
|
||||||
|
|
||||||
|
switch(errno) {
|
||||||
|
case EAGAIN:
|
||||||
|
case EINTR:
|
||||||
|
errval = HTTPD_SOCK_ERR_TIMEOUT;
|
||||||
|
break;
|
||||||
|
case EINVAL:
|
||||||
|
case EBADF:
|
||||||
|
case EFAULT:
|
||||||
|
case ENOTSOCK:
|
||||||
|
errval = HTTPD_SOCK_ERR_INVALID;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errval = HTTPD_SOCK_ERR_FAIL;
|
||||||
|
}
|
||||||
|
return errval;
|
||||||
|
}
|
||||||
|
|
||||||
int httpd_default_send(int sockfd, const char *buf, size_t buf_len, int flags)
|
int httpd_default_send(int sockfd, const char *buf, size_t buf_len, int flags)
|
||||||
{
|
{
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return HTTPD_SOCK_ERR_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = send(sockfd, buf, buf_len, flags);
|
int ret = send(sockfd, buf, buf_len, flags);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ESP_LOGW(TAG, LOG_FMT("error in send = %d"), errno);
|
return httpd_sock_err("send");
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -489,12 +511,12 @@ int httpd_default_send(int sockfd, const char *buf, size_t buf_len, int flags)
|
|||||||
int httpd_default_recv(int sockfd, char *buf, size_t buf_len, int flags)
|
int httpd_default_recv(int sockfd, char *buf, size_t buf_len, int flags)
|
||||||
{
|
{
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return HTTPD_SOCK_ERR_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = recv(sockfd, buf, buf_len, flags);
|
int ret = recv(sockfd, buf, buf_len, flags);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ESP_LOGW(TAG, LOG_FMT("error in recv = %d"), errno);
|
return httpd_sock_err("recv");
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user