]> granicus.if.org Git - esp-idf/blob - components/http_server/src/httpd_txrx.c
Merge branch 'bugfix/fix_mcpwm_api_mismatch_bug' into 'master'
[esp-idf] / components / http_server / src / httpd_txrx.c
1 // Copyright 2018 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15
16 #include <errno.h>
17 #include <esp_log.h>
18 #include <esp_err.h>
19
20 #include <http_server.h>
21 #include "httpd_priv.h"
22
23 static const char *TAG = "httpd_txrx";
24
25 esp_err_t httpd_set_send_override(httpd_req_t *r, httpd_send_func_t send_func)
26 {
27     if (r == NULL || send_func == NULL) {
28         return ESP_ERR_INVALID_ARG;
29     }
30
31     if (!httpd_valid_req(r)) {
32         return ESP_ERR_HTTPD_INVALID_REQ;
33     }
34
35     struct httpd_req_aux *ra = r->aux;
36     ra->sd->send_fn = send_func;
37     return ESP_OK;
38 }
39
40 esp_err_t httpd_set_recv_override(httpd_req_t *r, httpd_recv_func_t recv_func)
41 {
42     if (r == NULL || recv_func == NULL) {
43         return ESP_ERR_INVALID_ARG;
44     }
45
46     if (!httpd_valid_req(r)) {
47         return ESP_ERR_HTTPD_INVALID_REQ;
48     }
49
50     struct httpd_req_aux *ra = r->aux;
51     ra->sd->recv_fn = recv_func;
52     return ESP_OK;
53 }
54
55 int httpd_send(httpd_req_t *r, const char *buf, size_t buf_len)
56 {
57     if (r == NULL || buf == NULL) {
58         return -1;
59     }
60
61     if (!httpd_valid_req(r)) {
62         return -1;
63     }
64
65     struct httpd_req_aux *ra = r->aux;
66     int ret = ra->sd->send_fn(ra->sd->fd, buf, buf_len, 0);
67     if (ret < 0) {
68         ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
69         return -1;
70     }
71     return ret;
72 }
73
74 static esp_err_t httpd_send_all(httpd_req_t *r, const char *buf, size_t buf_len)
75 {
76     struct httpd_req_aux *ra = r->aux;
77     int ret;
78
79     while (buf_len > 0) {
80         ret = ra->sd->send_fn(ra->sd->fd, buf, buf_len, 0);
81         if (ret < 0) {
82             ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
83             return ESP_FAIL;
84         }
85         ESP_LOGD(TAG, LOG_FMT("sent = %d"), ret);
86         buf     += ret;
87         buf_len -= ret;
88     }
89     return ESP_OK;
90 }
91
92 static size_t httpd_recv_pending(httpd_req_t *r, char *buf, size_t buf_len)
93 {
94     struct httpd_req_aux *ra = r->aux;
95     size_t offset = sizeof(ra->sd->pending_data) - ra->sd->pending_len;
96
97     /* buf_len must not be greater than remaining_len */
98     buf_len = MIN(ra->sd->pending_len, buf_len);
99     memcpy(buf, ra->sd->pending_data + offset, buf_len);
100
101     ra->sd->pending_len -= buf_len;
102     return buf_len;
103 }
104
105 int httpd_recv_with_opt(httpd_req_t *r, char *buf, size_t buf_len, bool halt_after_pending)
106 {
107     ESP_LOGD(TAG, LOG_FMT("requested length = %d"), buf_len);
108
109     size_t pending_len = 0;
110     struct httpd_req_aux *ra = r->aux;
111
112     /* First fetch pending data from local buffer */
113     if (ra->sd->pending_len > 0) {
114         ESP_LOGD(TAG, LOG_FMT("pending length = %d"), ra->sd->pending_len);
115         pending_len = httpd_recv_pending(r, buf, buf_len);
116         buf     += pending_len;
117         buf_len -= pending_len;
118
119         /* If buffer filled then no need to recv.
120          * If asked to halt after receiving pending data then
121          * return with received length */
122         if (!buf_len || halt_after_pending) {
123             return pending_len;
124         }
125     }
126
127     /* Receive data of remaining length */
128     int ret = ra->sd->recv_fn(ra->sd->fd, buf, buf_len, 0);
129     if (ret < 0) {
130         ESP_LOGD(TAG, LOG_FMT("error in recv_fn"));
131         return -1;
132     }
133
134     ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret + pending_len);
135     return ret + pending_len;
136 }
137
138 int httpd_recv(httpd_req_t *r, char *buf, size_t buf_len)
139 {
140     return httpd_recv_with_opt(r, buf, buf_len, false);
141 }
142
143 size_t httpd_unrecv(struct httpd_req *r, const char *buf, size_t buf_len)
144 {
145     struct httpd_req_aux *ra = r->aux;
146     /* Truncate if external buf_len is greater than pending_data buffer size */
147     ra->sd->pending_len = MIN(sizeof(ra->sd->pending_data), buf_len);
148
149     /* Copy data into internal pending_data buffer */
150     size_t offset = sizeof(ra->sd->pending_data) - ra->sd->pending_len;
151     memcpy(ra->sd->pending_data + offset, buf, buf_len);
152     ESP_LOGD(TAG, LOG_FMT("length = %d"), ra->sd->pending_len);
153     return ra->sd->pending_len;
154 }
155
156 /**
157  * This API appends an additional header field-value pair in the HTTP response.
158  * But the header isn't sent out until any of the send APIs is executed.
159  */
160 esp_err_t httpd_resp_set_hdr(httpd_req_t *r, const char *field, const char *value)
161 {
162     if (r == NULL || field == NULL || value == NULL) {
163         return ESP_ERR_INVALID_ARG;
164     }
165
166     if (!httpd_valid_req(r)) {
167         return ESP_ERR_HTTPD_INVALID_REQ;
168     }
169
170     struct httpd_req_aux *ra = r->aux;
171     struct httpd_data *hd = (struct httpd_data *) r->handle;
172
173     /* Number of additional headers is limited */
174     if (ra->resp_hdrs_count >= hd->config.max_resp_headers) {
175         return ESP_ERR_HTTPD_RESP_HDR;
176     }
177
178     /* Assign header field-value pair */
179     ra->resp_hdrs[ra->resp_hdrs_count].field = field;
180     ra->resp_hdrs[ra->resp_hdrs_count].value = value;
181     ra->resp_hdrs_count++;
182
183     ESP_LOGD(TAG, LOG_FMT("new header = %s: %s"), field, value);
184     return ESP_OK;
185 }
186
187 /**
188  * This API sets the status of the HTTP response to the value specified.
189  * But the status isn't sent out until any of the send APIs is executed.
190  */
191 esp_err_t httpd_resp_set_status(httpd_req_t *r, const char *status)
192 {
193     if (r == NULL || status == NULL) {
194         return ESP_ERR_INVALID_ARG;
195     }
196
197     if (!httpd_valid_req(r)) {
198         return ESP_ERR_HTTPD_INVALID_REQ;
199     }
200
201     struct httpd_req_aux *ra = r->aux;
202     ra->status = (char *)status;
203     return ESP_OK;
204 }
205
206 /**
207  * This API sets the method/type of the HTTP response to the value specified.
208  * But the method isn't sent out until any of the send APIs is executed.
209  */
210 esp_err_t httpd_resp_set_type(httpd_req_t *r, const char *type)
211 {
212     if (r == NULL || type == NULL) {
213         return ESP_ERR_INVALID_ARG;
214     }
215
216     if (!httpd_valid_req(r)) {
217         return ESP_ERR_HTTPD_INVALID_REQ;
218     }
219
220     struct httpd_req_aux *ra = r->aux;
221     ra->content_type = (char *)type;
222     return ESP_OK;
223 }
224
225 esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, size_t buf_len)
226 {
227     if (r == NULL) {
228         return ESP_ERR_INVALID_ARG;
229     }
230
231     if (!httpd_valid_req(r)) {
232         return ESP_ERR_HTTPD_INVALID_REQ;
233     }
234
235     struct httpd_req_aux *ra = r->aux;
236     const char *httpd_hdr_str = "HTTP/1.1 %s\r\nContent-Type: %s\r\nContent-Length: %d\r\n";
237     const char *colon_separator = ": ";
238     const char *cr_lf_seperator = "\r\n";
239
240     /* Request headers are no longer available */
241     ra->req_hdrs_count = 0;
242
243     /* Size of essential headers is limited by scratch buffer size */
244     if (snprintf(ra->scratch, sizeof(ra->scratch), httpd_hdr_str,
245                  ra->status, ra->content_type, buf_len) >= sizeof(ra->scratch)) {
246         return ESP_ERR_HTTPD_RESP_HDR;
247     }
248
249     /* Sending essential headers */
250     if (httpd_send_all(r, ra->scratch, strlen(ra->scratch)) != ESP_OK) {
251         return ESP_ERR_HTTPD_RESP_SEND;
252     }
253
254     /* Sending additional headers based on set_header */
255     for (unsigned i = 0; i < ra->resp_hdrs_count; i++) {
256         /* Send header field */
257         if (httpd_send_all(r, ra->resp_hdrs[i].field, strlen(ra->resp_hdrs[i].field)) != ESP_OK) {
258             return ESP_ERR_HTTPD_RESP_SEND;
259         }
260         /* Send ': ' */
261         if (httpd_send_all(r, colon_separator, strlen(colon_separator)) != ESP_OK) {
262             return ESP_ERR_HTTPD_RESP_SEND;
263         }
264         /* Send header value */
265         if (httpd_send_all(r, ra->resp_hdrs[i].value, strlen(ra->resp_hdrs[i].value)) != ESP_OK) {
266             return ESP_ERR_HTTPD_RESP_SEND;
267         }
268         /* Send CR + LF */
269         if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) {
270             return ESP_ERR_HTTPD_RESP_SEND;
271         }
272     }
273
274     /* End header section */
275     if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) {
276         return ESP_ERR_HTTPD_RESP_SEND;
277     }
278
279     /* Sending content */
280     if (buf && buf_len) {
281         if (httpd_send_all(r, buf, buf_len) != ESP_OK) {
282             return ESP_ERR_HTTPD_RESP_SEND;
283         }
284     }
285     return ESP_OK;
286 }
287
288 esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, size_t buf_len)
289 {
290     if (r == NULL) {
291         return ESP_ERR_INVALID_ARG;
292     }
293
294     if (!httpd_valid_req(r)) {
295         return ESP_ERR_HTTPD_INVALID_REQ;
296     }
297
298     struct httpd_req_aux *ra = r->aux;
299     const char *httpd_chunked_hdr_str = "HTTP/1.1 %s\r\nContent-Type: %s\r\nContent-Length: 0\r\nTransfer-Encoding: chunked\r\n";
300     const char *colon_separator = ": ";
301     const char *cr_lf_seperator = "\r\n";
302
303     /* Request headers are no longer available */
304     ra->req_hdrs_count = 0;
305
306     if (!ra->first_chunk_sent) {
307         /* Size of essential headers is limited by scratch buffer size */
308         if (snprintf(ra->scratch, sizeof(ra->scratch), httpd_chunked_hdr_str,
309                      ra->status, ra->content_type) >= sizeof(ra->scratch)) {
310             return ESP_ERR_HTTPD_RESP_HDR;
311         }
312
313         /* Sending essential headers */
314         if (httpd_send_all(r, ra->scratch, strlen(ra->scratch)) != ESP_OK) {
315             return ESP_ERR_HTTPD_RESP_SEND;
316         }
317
318         /* Sending additional headers based on set_header */
319         for (unsigned i = 0; i < ra->resp_hdrs_count; i++) {
320             /* Send header field */
321             if (httpd_send_all(r, ra->resp_hdrs[i].field, strlen(ra->resp_hdrs[i].field)) != ESP_OK) {
322                 return ESP_ERR_HTTPD_RESP_SEND;
323             }
324             /* Send ': ' */
325             if (httpd_send_all(r, colon_separator, strlen(colon_separator)) != ESP_OK) {
326                 return ESP_ERR_HTTPD_RESP_SEND;
327             }
328             /* Send header value */
329             if (httpd_send_all(r, ra->resp_hdrs[i].value, strlen(ra->resp_hdrs[i].value)) != ESP_OK) {
330                 return ESP_ERR_HTTPD_RESP_SEND;
331             }
332             /* Send CR + LF */
333             if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) {
334                 return ESP_ERR_HTTPD_RESP_SEND;
335             }
336         }
337
338         /* End header section */
339         if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) {
340             return ESP_ERR_HTTPD_RESP_SEND;
341         }
342         ra->first_chunk_sent = true;
343     }
344
345     /* Sending chunked content */
346     char len_str[10];
347     snprintf(len_str, sizeof(len_str), "%x\r\n", buf_len);
348     if (httpd_send_all(r, len_str, strlen(len_str)) != ESP_OK) {
349         return ESP_ERR_HTTPD_RESP_SEND;
350     }
351
352     if (buf) {
353         if (httpd_send_all(r, buf, buf_len) != ESP_OK) {
354             return ESP_ERR_HTTPD_RESP_SEND;
355         }
356     }
357
358     /* Indicate end of chunk */
359     if (httpd_send_all(r, "\r\n", strlen("\r\n")) != ESP_OK) {
360         return ESP_ERR_HTTPD_RESP_SEND;
361     }
362     return ESP_OK;
363 }
364
365 esp_err_t httpd_resp_send_404(httpd_req_t *r)
366 {
367     return httpd_resp_send_err(r, HTTPD_404_NOT_FOUND);
368 }
369
370 esp_err_t httpd_resp_send_err(httpd_req_t *req, httpd_err_resp_t error)
371 {
372     const char *msg;
373     const char *status;
374     switch (error) {
375     case HTTPD_501_METHOD_NOT_IMPLEMENTED:
376         status = "501 Method Not Implemented";
377         msg    = "Request method is not supported by server";
378         break;
379     case HTTPD_505_VERSION_NOT_SUPPORTED:
380         status = "505 Version Not Supported";
381         msg    = "HTTP version not supported by server";
382         break;
383     case HTTPD_400_BAD_REQUEST:
384         status = "400 Bad Request";
385         msg    = "Server unable to understand request due to invalid syntax";
386         break;
387     case HTTPD_404_NOT_FOUND:
388         status = "404 Not Found";
389         msg    = "This URI doesn't exist";
390         break;
391     case HTTPD_405_METHOD_NOT_ALLOWED:
392         status = "405 Method Not Allowed";
393         msg    = "Request method for this URI is not handled by server";
394         break;
395     case HTTPD_408_REQ_TIMEOUT:
396         status = "408 Request Timeout";
397         msg    = "Server closed this connection";
398         break;
399     case HTTPD_414_URI_TOO_LONG:
400         status = "414 URI Too Long";
401         msg    = "URI is too long for server to interpret";
402         break;
403     case HTTPD_411_LENGTH_REQUIRED:
404         status = "411 Length Required";
405         msg    = "Chunked encoding not supported by server";
406         break;
407     case HTTPD_431_REQ_HDR_FIELDS_TOO_LARGE:
408         status = "431 Request Header Fields Too Large";
409         msg    = "Header fields are too long for server to interpret";
410         break;
411     case HTTPD_XXX_UPGRADE_NOT_SUPPORTED:
412         /* If the server does not support upgrade, or is unable to upgrade
413          * it responds with a standard HTTP/1.1 response */
414         status = "200 OK";
415         msg    = "Upgrade not supported by server";
416         break;
417     case HTTPD_500_SERVER_ERROR:
418     default:
419         status = "500 Server Error";
420         msg    = "Server has encountered an unexpected error";
421     }
422     ESP_LOGW(TAG, LOG_FMT("%s - %s"), status, msg);
423
424     httpd_resp_set_status   (req, status);
425     httpd_resp_set_type     (req, HTTPD_TYPE_TEXT);
426     return httpd_resp_send  (req, msg, strlen(msg));
427 }
428
429 int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len)
430 {
431     if (r == NULL || buf == NULL) {
432         return -1;
433     }
434
435     if (!httpd_valid_req(r)) {
436         ESP_LOGW(TAG, LOG_FMT("invalid request"));
437         return -1;
438     }
439
440     struct httpd_req_aux *ra = r->aux;
441     ESP_LOGD(TAG, LOG_FMT("remaining length = %d"), ra->remaining_len);
442
443     if (buf_len > ra->remaining_len) {
444         buf_len = ra->remaining_len;
445     }
446     if (buf_len == 0) {
447         return buf_len;
448     }
449
450     int ret = httpd_recv(r, buf, buf_len);
451     if (ret < 0) {
452         ESP_LOGD(TAG, LOG_FMT("error in httpd_recv"));
453         ra->remaining_len = 0;
454         return -1;
455     }
456     ra->remaining_len -= ret;
457     ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret);
458     return ret;
459 }
460
461 int httpd_req_to_sockfd(httpd_req_t *r)
462 {
463     if (r == NULL) {
464         return -1;
465     }
466
467     if (!httpd_valid_req(r)) {
468         ESP_LOGW(TAG, LOG_FMT("invalid request"));
469         return -1;
470     }
471
472     struct httpd_req_aux *ra = r->aux;
473     return ra->sd->fd;
474 }
475
476 int httpd_default_send(int sockfd, const char *buf, size_t buf_len, int flags)
477 {
478     if (buf == NULL) {
479         return ESP_ERR_INVALID_ARG;
480     }
481
482     int ret = send(sockfd, buf, buf_len, flags);
483     if (ret < 0) {
484         ESP_LOGW(TAG, LOG_FMT("error in send = %d"), errno);
485     }
486     return ret;
487 }
488
489 int httpd_default_recv(int sockfd, char *buf, size_t buf_len, int flags)
490 {
491     if (buf == NULL) {
492         return ESP_ERR_INVALID_ARG;
493     }
494
495     int ret = recv(sockfd, buf, buf_len, flags);
496     if (ret < 0) {
497         ESP_LOGW(TAG, LOG_FMT("error in recv = %d"), errno);
498     }
499     return ret;
500 }