Merge branch 'feature/httpd_sock_err' into 'master'
HTTP Server : Return HTTPD_SOCK_ERR_ based on errno set during send / recv See merge request idf/esp-idf!3445
This commit is contained in:
commit
ca74afd5ca
9 changed files with 198 additions and 48 deletions
|
@ -348,19 +348,40 @@ 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
|
* - 0 : Buffer length parameter is zero / connection closed by peer
|
||||||
|
* - 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);
|
||||||
|
|
||||||
|
@ -461,8 +482,10 @@ 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
|
* - 0 : Buffer length parameter is zero / connection closed by peer
|
||||||
* - -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);
|
||||||
|
|
||||||
|
@ -664,6 +687,7 @@ esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, size_t buf_len)
|
||||||
#define HTTPD_207 "207 Multi-Status" /*!< HTTP Response 207 */
|
#define HTTPD_207 "207 Multi-Status" /*!< HTTP Response 207 */
|
||||||
#define HTTPD_400 "400 Bad Request" /*!< HTTP Response 400 */
|
#define HTTPD_400 "400 Bad Request" /*!< HTTP Response 400 */
|
||||||
#define HTTPD_404 "404 Not Found" /*!< HTTP Response 404 */
|
#define HTTPD_404 "404 Not Found" /*!< HTTP Response 404 */
|
||||||
|
#define HTTPD_408 "408 Request Timeout" /*!< HTTP Response 408 */
|
||||||
#define HTTPD_500 "500 Internal Server Error" /*!< HTTP Response 500 */
|
#define HTTPD_500 "500 Internal Server Error" /*!< HTTP Response 500 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -768,6 +792,52 @@ esp_err_t httpd_resp_set_hdr(httpd_req_t *r, const char *field, const char *valu
|
||||||
*/
|
*/
|
||||||
esp_err_t httpd_resp_send_404(httpd_req_t *r);
|
esp_err_t httpd_resp_send_404(httpd_req_t *r);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper function for HTTP 408
|
||||||
|
*
|
||||||
|
* Send HTTP 408 message. If you wish to send additional data in the body of the
|
||||||
|
* response, please use the lower-level functions directly.
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
* - This API is supposed to be called only from the context of
|
||||||
|
* a URI handler where httpd_req_t* request pointer is valid.
|
||||||
|
* - Once this API is called, all request headers are purged, so
|
||||||
|
* request headers need be copied into separate buffers if
|
||||||
|
* they are required later.
|
||||||
|
*
|
||||||
|
* @param[in] r The request being responded to
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK : On successfully sending the response packet
|
||||||
|
* - ESP_ERR_INVALID_ARG : Null arguments
|
||||||
|
* - ESP_ERR_HTTPD_RESP_SEND : Error in raw send
|
||||||
|
* - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer
|
||||||
|
*/
|
||||||
|
esp_err_t httpd_resp_send_408(httpd_req_t *r);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper function for HTTP 500
|
||||||
|
*
|
||||||
|
* Send HTTP 500 message. If you wish to send additional data in the body of the
|
||||||
|
* response, please use the lower-level functions directly.
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
* - This API is supposed to be called only from the context of
|
||||||
|
* a URI handler where httpd_req_t* request pointer is valid.
|
||||||
|
* - Once this API is called, all request headers are purged, so
|
||||||
|
* request headers need be copied into separate buffers if
|
||||||
|
* they are required later.
|
||||||
|
*
|
||||||
|
* @param[in] r The request being responded to
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK : On successfully sending the response packet
|
||||||
|
* - ESP_ERR_INVALID_ARG : Null arguments
|
||||||
|
* - ESP_ERR_HTTPD_RESP_SEND : Error in raw send
|
||||||
|
* - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer
|
||||||
|
*/
|
||||||
|
esp_err_t httpd_resp_send_500(httpd_req_t *r);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Raw HTTP send
|
* @brief Raw HTTP send
|
||||||
*
|
*
|
||||||
|
@ -796,7 +866,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);
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ static esp_err_t verify_url (http_parser *parser)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep URI with terminating null character. Note URI string pointed
|
/* Keep URI with terminating null character. Note URI string pointed
|
||||||
* by 'at' is not NULL terminated, therfore use length provided by
|
* by 'at' is not NULL terminated, therefore use length provided by
|
||||||
* parser while copying the URI to buffer */
|
* parser while copying the URI to buffer */
|
||||||
strlcpy((char *)r->uri, at, (length + 1));
|
strlcpy((char *)r->uri, at, (length + 1));
|
||||||
ESP_LOGD(TAG, LOG_FMT("received URI = %s"), r->uri);
|
ESP_LOGD(TAG, LOG_FMT("received URI = %s"), r->uri);
|
||||||
|
@ -291,7 +291,7 @@ static esp_err_t cb_headers_complete(http_parser *parser)
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In absence of body/chunked enoding, http_parser sets content_len to -1 */
|
/* In absence of body/chunked encoding, http_parser sets content_len to -1 */
|
||||||
r->content_len = ((int)parser->content_length != -1 ?
|
r->content_len = ((int)parser->content_length != -1 ?
|
||||||
parser->content_length : 0);
|
parser->content_length : 0);
|
||||||
|
|
||||||
|
@ -391,14 +391,14 @@ static int read_block(httpd_req_t *req, size_t offset, size_t length)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive data into buffer. If data is pending (from unrecv) then return
|
/* Receive data into buffer. If data is pending (from unrecv) then return
|
||||||
* immediatly after receiving pending data, as pending data may just complete
|
* immediately after receiving pending data, as pending data may just complete
|
||||||
* this request packet. */
|
* this request packet. */
|
||||||
int nbytes = httpd_recv_with_opt(req, raux->scratch + offset, buf_len, true);
|
int nbytes = httpd_recv_with_opt(req, raux->scratch + offset, buf_len, true);
|
||||||
if (nbytes < 0) {
|
if (nbytes < 0) {
|
||||||
ESP_LOGD(TAG, LOG_FMT("error in httpd_recv"));
|
ESP_LOGD(TAG, LOG_FMT("error in httpd_recv"));
|
||||||
/* Connection error. Notify Timeout in all cases.
|
if (nbytes == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||||
* Need some way to check errno for ETIMEDOUT. */
|
|
||||||
httpd_resp_send_err(req, HTTPD_408_REQ_TIMEOUT);
|
httpd_resp_send_err(req, HTTPD_408_REQ_TIMEOUT);
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
} else if (nbytes == 0) {
|
} else if (nbytes == 0) {
|
||||||
ESP_LOGD(TAG, LOG_FMT("connection closed"));
|
ESP_LOGD(TAG, LOG_FMT("connection closed"));
|
||||||
|
@ -500,7 +500,7 @@ static esp_err_t httpd_parse_req(struct httpd_data *hd)
|
||||||
http_parser parser;
|
http_parser parser;
|
||||||
parser_data_t parser_data;
|
parser_data_t parser_data;
|
||||||
|
|
||||||
/* Initilaize parser */
|
/* Initialize parser */
|
||||||
parse_init(r, &parser, &parser_data);
|
parse_init(r, &parser, &parser_data);
|
||||||
|
|
||||||
/* Set offset to start of scratch buffer */
|
/* Set offset to start of scratch buffer */
|
||||||
|
|
|
@ -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,16 @@ 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;
|
if ((ret == HTTPD_SOCK_ERR_TIMEOUT) && (pending_len != 0)) {
|
||||||
|
/* If recv() timeout occurred, but pending data is
|
||||||
|
* present, return length of pending data.
|
||||||
|
* This behavior is similar to that of socket recv()
|
||||||
|
* function, which, in case has only partially read the
|
||||||
|
* requested length, due to timeout, returns with read
|
||||||
|
* length, rather than error */
|
||||||
|
return pending_len;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret + pending_len);
|
ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret + pending_len);
|
||||||
|
@ -367,6 +376,16 @@ esp_err_t httpd_resp_send_404(httpd_req_t *r)
|
||||||
return httpd_resp_send_err(r, HTTPD_404_NOT_FOUND);
|
return httpd_resp_send_err(r, HTTPD_404_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t httpd_resp_send_408(httpd_req_t *r)
|
||||||
|
{
|
||||||
|
return httpd_resp_send_err(r, HTTPD_408_REQ_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t httpd_resp_send_500(httpd_req_t *r)
|
||||||
|
{
|
||||||
|
return httpd_resp_send_err(r, HTTPD_500_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t httpd_resp_send_err(httpd_req_t *req, httpd_err_resp_t error)
|
esp_err_t httpd_resp_send_err(httpd_req_t *req, httpd_err_resp_t error)
|
||||||
{
|
{
|
||||||
const char *msg;
|
const char *msg;
|
||||||
|
@ -429,12 +448,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 +469,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 +491,44 @@ 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 sockfd)
|
||||||
|
{
|
||||||
|
int errval;
|
||||||
|
int sock_err;
|
||||||
|
size_t sock_err_len = sizeof(sock_err);
|
||||||
|
|
||||||
|
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &sock_err, &sock_err_len) < 0) {
|
||||||
|
ESP_LOGE(TAG, LOG_FMT("error calling getsockopt : %d"), errno);
|
||||||
|
return HTTPD_SOCK_ERR_FAIL;
|
||||||
|
}
|
||||||
|
ESP_LOGW(TAG, LOG_FMT("error in %s : %d"), ctx, sock_err);
|
||||||
|
|
||||||
|
switch(sock_err) {
|
||||||
|
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", sockfd);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -489,12 +536,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", sockfd);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,7 +216,6 @@ esp_err_t httpd_uri(struct httpd_data *hd)
|
||||||
if (uri->handler(req) != ESP_OK) {
|
if (uri->handler(req) != ESP_OK) {
|
||||||
/* Handler returns error, this socket should be closed */
|
/* Handler returns error, this socket should be closed */
|
||||||
ESP_LOGW(TAG, LOG_FMT("uri handler execution failed"));
|
ESP_LOGW(TAG, LOG_FMT("uri handler execution failed"));
|
||||||
httpd_resp_send_err(req, HTTPD_408_REQ_TIMEOUT);
|
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
|
|
|
@ -29,15 +29,26 @@ Application Example
|
||||||
/* Our URI handler function to be called during POST /uri request */
|
/* Our URI handler function to be called during POST /uri request */
|
||||||
esp_err_t post_handler(httpd_req_t *req)
|
esp_err_t post_handler(httpd_req_t *req)
|
||||||
{
|
{
|
||||||
/* Read request content */
|
/* Destination buffer for content of HTTP POST request.
|
||||||
|
* httpd_req_recv() accepts char* only, but content could
|
||||||
|
* as well be any binary data (needs type casting).
|
||||||
|
* In case of string data, null termination will be absent, and
|
||||||
|
* content length would give length of string */
|
||||||
char[100] content;
|
char[100] content;
|
||||||
|
|
||||||
/* Truncate if content length larger than the buffer */
|
/* Truncate if content length larger than the buffer */
|
||||||
size_t recv_size = MIN(req->content_len, sizeof(content));
|
size_t recv_size = MIN(req->content_len, sizeof(content));
|
||||||
|
|
||||||
int ret = httpd_req_recv(req, content, recv_size);
|
int ret = httpd_req_recv(req, content, recv_size);
|
||||||
if (ret < 0) {
|
if (ret <= 0) { /* 0 return value indicates connection closed */
|
||||||
/* In case of recv error, returning ESP_FAIL will
|
/* Check if timeout occurred */
|
||||||
|
if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||||
|
/* In case of timeout one can choose to retry calling
|
||||||
|
* httpd_req_recv(), but to keep it simple, here we
|
||||||
|
* respond with an HTTP 408 (Request Timeout) error */
|
||||||
|
httpd_resp_send_408(req);
|
||||||
|
}
|
||||||
|
/* In case of error, returning ESP_FAIL will
|
||||||
* ensure that the underlying socket is closed */
|
* ensure that the underlying socket is closed */
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,13 +50,17 @@ esp_err_t echo_post_handler(httpd_req_t *req)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
|
httpd_resp_send_500(req);
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (off < req->content_len) {
|
while (off < req->content_len) {
|
||||||
/* Read data received in the request */
|
/* Read data received in the request */
|
||||||
ret = httpd_req_recv(req, buf + off, req->content_len - off);
|
ret = httpd_req_recv(req, buf + off, req->content_len - off);
|
||||||
if (ret < 0) {
|
if (ret <= 0) {
|
||||||
|
if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||||
|
httpd_resp_send_408(req);
|
||||||
|
}
|
||||||
free (buf);
|
free (buf);
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +109,10 @@ esp_err_t adder_post_handler(httpd_req_t *req)
|
||||||
|
|
||||||
/* Read data received in the request */
|
/* Read data received in the request */
|
||||||
ret = httpd_req_recv(req, buf, sizeof(buf));
|
ret = httpd_req_recv(req, buf, sizeof(buf));
|
||||||
if (ret < 0) {
|
if (ret <= 0) {
|
||||||
|
if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||||
|
httpd_resp_send_408(req);
|
||||||
|
}
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +144,10 @@ esp_err_t leftover_data_post_handler(httpd_req_t *req)
|
||||||
|
|
||||||
/* Read data received in the request */
|
/* Read data received in the request */
|
||||||
ret = httpd_req_recv(req, buf, sizeof(buf) - 1);
|
ret = httpd_req_recv(req, buf, sizeof(buf) - 1);
|
||||||
if (ret < 0) {
|
if (ret <= 0) {
|
||||||
|
if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||||
|
httpd_resp_send_408(req);
|
||||||
|
}
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -350,7 +350,7 @@ def get_hello(dut, port):
|
||||||
|
|
||||||
def put_hello(dut, port):
|
def put_hello(dut, port):
|
||||||
# PUT /hello returns 405'
|
# PUT /hello returns 405'
|
||||||
Utility.console_log("[test] PUT /hello returns 405' =>", end=' ')
|
Utility.console_log("[test] PUT /hello returns 405 =>", end=' ')
|
||||||
conn = http.client.HTTPConnection(dut, int(port), timeout=15)
|
conn = http.client.HTTPConnection(dut, int(port), timeout=15)
|
||||||
conn.request("PUT", "/hello", "Hello")
|
conn.request("PUT", "/hello", "Hello")
|
||||||
resp = conn.getresponse()
|
resp = conn.getresponse()
|
||||||
|
@ -363,7 +363,7 @@ def put_hello(dut, port):
|
||||||
|
|
||||||
def post_hello(dut, port):
|
def post_hello(dut, port):
|
||||||
# POST /hello returns 405'
|
# POST /hello returns 405'
|
||||||
Utility.console_log("[test] POST /hello returns 404' =>", end=' ')
|
Utility.console_log("[test] POST /hello returns 404 =>", end=' ')
|
||||||
conn = http.client.HTTPConnection(dut, int(port), timeout=15)
|
conn = http.client.HTTPConnection(dut, int(port), timeout=15)
|
||||||
conn.request("POST", "/hello", "Hello")
|
conn.request("POST", "/hello", "Hello")
|
||||||
resp = conn.getresponse()
|
resp = conn.getresponse()
|
||||||
|
@ -376,7 +376,7 @@ def post_hello(dut, port):
|
||||||
|
|
||||||
def post_echo(dut, port):
|
def post_echo(dut, port):
|
||||||
# POST /echo echoes data'
|
# POST /echo echoes data'
|
||||||
Utility.console_log("[test] POST /echo echoes data' =>", end=' ')
|
Utility.console_log("[test] POST /echo echoes data =>", end=' ')
|
||||||
conn = http.client.HTTPConnection(dut, int(port), timeout=15)
|
conn = http.client.HTTPConnection(dut, int(port), timeout=15)
|
||||||
conn.request("POST", "/echo", "Hello")
|
conn.request("POST", "/echo", "Hello")
|
||||||
resp = conn.getresponse()
|
resp = conn.getresponse()
|
||||||
|
@ -392,7 +392,7 @@ def post_echo(dut, port):
|
||||||
|
|
||||||
def put_echo(dut, port):
|
def put_echo(dut, port):
|
||||||
# PUT /echo echoes data'
|
# PUT /echo echoes data'
|
||||||
Utility.console_log("[test] PUT /echo echoes data' =>", end=' ')
|
Utility.console_log("[test] PUT /echo echoes data =>", end=' ')
|
||||||
conn = http.client.HTTPConnection(dut, int(port), timeout=15)
|
conn = http.client.HTTPConnection(dut, int(port), timeout=15)
|
||||||
conn.request("PUT", "/echo", "Hello")
|
conn.request("PUT", "/echo", "Hello")
|
||||||
resp = conn.getresponse()
|
resp = conn.getresponse()
|
||||||
|
@ -408,7 +408,7 @@ def put_echo(dut, port):
|
||||||
|
|
||||||
def get_echo(dut, port):
|
def get_echo(dut, port):
|
||||||
# GET /echo returns 404'
|
# GET /echo returns 404'
|
||||||
Utility.console_log("[test] GET /echo returns 405' =>", end=' ')
|
Utility.console_log("[test] GET /echo returns 405 =>", end=' ')
|
||||||
conn = http.client.HTTPConnection(dut, int(port), timeout=15)
|
conn = http.client.HTTPConnection(dut, int(port), timeout=15)
|
||||||
conn.request("GET", "/echo")
|
conn.request("GET", "/echo")
|
||||||
resp = conn.getresponse()
|
resp = conn.getresponse()
|
||||||
|
@ -595,7 +595,7 @@ def packet_size_limit_test(dut, port, test_size):
|
||||||
s.request("POST", url=path, body=random_data)
|
s.request("POST", url=path, body=random_data)
|
||||||
resp = s.getresponse()
|
resp = s.getresponse()
|
||||||
if not test_val("Error", "200", str(resp.status)):
|
if not test_val("Error", "200", str(resp.status)):
|
||||||
if test_val("Error", "408", str(resp.status)):
|
if test_val("Error", "500", str(resp.status)):
|
||||||
Utility.console_log("Data too large to be allocated")
|
Utility.console_log("Data too large to be allocated")
|
||||||
test_size = test_size//10
|
test_size = test_size//10
|
||||||
else:
|
else:
|
||||||
|
@ -619,14 +619,12 @@ def packet_size_limit_test(dut, port, test_size):
|
||||||
def code_500_server_error_test(dut, port):
|
def code_500_server_error_test(dut, port):
|
||||||
Utility.console_log("[test] 500 Server Error test =>", end=' ')
|
Utility.console_log("[test] 500 Server Error test =>", end=' ')
|
||||||
s = Session(dut, port)
|
s = Session(dut, port)
|
||||||
s.client.sendall(b"abcdefgh\0")
|
# Sending a very large content length will cause malloc to fail
|
||||||
|
content_len = 2**31
|
||||||
|
s.client.sendall(("POST /echo HTTP/1.1\r\nHost: " + dut + "\r\nContent-Length: " + str(content_len) + "\r\n\r\nABCD").encode())
|
||||||
s.read_resp_hdrs()
|
s.read_resp_hdrs()
|
||||||
resp = s.read_resp_data()
|
resp = s.read_resp_data()
|
||||||
# Presently server sends back 400 Bad Request
|
if not test_val("Server Error", "500", s.status):
|
||||||
#if not test_val("Server Error", "500", s.status):
|
|
||||||
#s.close()
|
|
||||||
#return False
|
|
||||||
if not test_val("Server Error", "400", s.status):
|
|
||||||
s.close()
|
s.close()
|
||||||
return False
|
return False
|
||||||
s.close()
|
s.close()
|
||||||
|
|
|
@ -48,7 +48,10 @@ esp_err_t adder_post_handler(httpd_req_t *req)
|
||||||
|
|
||||||
/* Read data received in the request */
|
/* Read data received in the request */
|
||||||
ret = httpd_req_recv(req, buf, sizeof(buf));
|
ret = httpd_req_recv(req, buf, sizeof(buf));
|
||||||
if (ret < 0) {
|
if (ret <= 0) {
|
||||||
|
if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||||
|
httpd_resp_send_408(req);
|
||||||
|
}
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +114,10 @@ esp_err_t adder_put_handler(httpd_req_t *req)
|
||||||
|
|
||||||
/* Read data received in the request */
|
/* Read data received in the request */
|
||||||
ret = httpd_req_recv(req, buf, sizeof(buf));
|
ret = httpd_req_recv(req, buf, sizeof(buf));
|
||||||
if (ret < 0) {
|
if (ret <= 0) {
|
||||||
|
if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||||
|
httpd_resp_send_408(req);
|
||||||
|
}
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,11 @@ esp_err_t echo_post_handler(httpd_req_t *req)
|
||||||
while (remaining > 0) {
|
while (remaining > 0) {
|
||||||
/* Read the data for the request */
|
/* Read the data for the request */
|
||||||
if ((ret = httpd_req_recv(req, buf,
|
if ((ret = httpd_req_recv(req, buf,
|
||||||
MIN(remaining, sizeof(buf)))) < 0) {
|
MIN(remaining, sizeof(buf)))) <= 0) {
|
||||||
|
if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||||
|
/* Retry receiving if timeout occurred */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +160,10 @@ esp_err_t ctrl_put_handler(httpd_req_t *req)
|
||||||
char buf;
|
char buf;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if ((ret = httpd_req_recv(req, &buf, 1)) < 0) {
|
if ((ret = httpd_req_recv(req, &buf, 1)) <= 0) {
|
||||||
|
if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||||
|
httpd_resp_send_408(req);
|
||||||
|
}
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue