]> granicus.if.org Git - esp-idf/commitdiff
HTTP Server : Return HTTPD_SOCK_ERR_ based on errno set during send / recv
authorAnurag Kar <anurag.kar@espressif.com>
Mon, 8 Oct 2018 11:15:45 +0000 (16:45 +0530)
committerAnurag Kar <anurag.kar@espressif.com>
Wed, 17 Oct 2018 12:06:50 +0000 (17:36 +0530)
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.

components/http_server/include/http_server.h
components/http_server/src/httpd_txrx.c

index cdbd039ca863e3c56625aa3b1704be8fa6a7840a..fa65dd32fb5750099499efa09a72ef5ba85efeba 100644 (file)
@@ -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
+ *
+ * @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
  *  - 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);
 
 /**
  * @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
  *  - 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);
 
@@ -462,7 +482,9 @@ int httpd_req_to_sockfd(httpd_req_t *r);
  * @return
  *  - Bytes    : Number of bytes read into the buffer successfully
  *  - 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);
 
@@ -796,7 +818,9 @@ esp_err_t httpd_resp_send_404(httpd_req_t *r);
  *
  * @return
  *  - 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);
 
index 5cf95b351d82d498223f81e617c8700f6cadee82..d45d960d46e052386e68111db57bb6a29d6bff8a 100644 (file)
@@ -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)
 {
     if (r == NULL || buf == NULL) {
-        return -1;
+        return HTTPD_SOCK_ERR_INVALID;
     }
 
     if (!httpd_valid_req(r)) {
-        return -1;
+        return HTTPD_SOCK_ERR_INVALID;
     }
 
     struct httpd_req_aux *ra = r->aux;
     int ret = ra->sd->send_fn(ra->sd->fd, buf, buf_len, 0);
     if (ret < 0) {
         ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
-        return -1;
+        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);
     if (ret < 0) {
         ESP_LOGD(TAG, LOG_FMT("error in recv_fn"));
-        return -1;
+        return ret;
     }
 
     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)
 {
     if (r == NULL || buf == NULL) {
-        return -1;
+        return HTTPD_SOCK_ERR_INVALID;
     }
 
     if (!httpd_valid_req(r)) {
         ESP_LOGW(TAG, LOG_FMT("invalid request"));
-        return -1;
+        return HTTPD_SOCK_ERR_INVALID;
     }
 
     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);
     if (ret < 0) {
         ESP_LOGD(TAG, LOG_FMT("error in httpd_recv"));
-        ra->remaining_len = 0;
-        return -1;
+        return ret;
     }
     ra->remaining_len -= 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;
 }
 
+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)
 {
     if (buf == NULL) {
-        return ESP_ERR_INVALID_ARG;
+        return HTTPD_SOCK_ERR_INVALID;
     }
 
     int ret = send(sockfd, buf, buf_len, flags);
     if (ret < 0) {
-        ESP_LOGW(TAG, LOG_FMT("error in send = %d"), errno);
+        return httpd_sock_err("send");
     }
     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)
 {
     if (buf == NULL) {
-        return ESP_ERR_INVALID_ARG;
+        return HTTPD_SOCK_ERR_INVALID;
     }
 
     int ret = recv(sockfd, buf, buf_len, flags);
     if (ret < 0) {
-        ESP_LOGW(TAG, LOG_FMT("error in recv = %d"), errno);
+        return httpd_sock_err("recv");
     }
     return ret;
 }