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 <esp_http_server.h> 21 #include "esp_httpd_priv.h" 22 23 static const char *TAG = "httpd_txrx"; 24 25 esp_err_t httpd_sess_set_send_override(httpd_handle_t hd, int sockfd, httpd_send_func_t send_func) 26 { 27 struct sock_db *sess = httpd_sess_get(hd, sockfd); 28 if (!sess) { 29 return ESP_ERR_INVALID_ARG; 30 } 31 sess->send_fn = send_func; 32 return ESP_OK; 33 } 34 35 esp_err_t httpd_sess_set_recv_override(httpd_handle_t hd, int sockfd, httpd_recv_func_t recv_func) 36 { 37 struct sock_db *sess = httpd_sess_get(hd, sockfd); 38 if (!sess) { 39 return ESP_ERR_INVALID_ARG; 40 } 41 sess->recv_fn = recv_func; 42 return ESP_OK; 43 } 44 45 esp_err_t httpd_sess_set_pending_override(httpd_handle_t hd, int sockfd, httpd_pending_func_t pending_func) 46 { 47 struct sock_db *sess = httpd_sess_get(hd, sockfd); 48 if (!sess) { 49 return ESP_ERR_INVALID_ARG; 50 } 51 sess->pending_fn = pending_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 HTTPD_SOCK_ERR_INVALID; 59 } 60 61 if (!httpd_valid_req(r)) { 62 return HTTPD_SOCK_ERR_INVALID; 63 } 64 65 struct httpd_req_aux *ra = r->aux; 66 int ret = ra->sd->send_fn(ra->sd->handle, ra->sd->fd, buf, buf_len, 0); 67 if (ret < 0) { 68 ESP_LOGD(TAG, LOG_FMT("error in send_fn")); 69 return ret; 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->handle, 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->handle, ra->sd->fd, buf, buf_len, 0); 129 if (ret < 0) { 130 ESP_LOGD(TAG, LOG_FMT("error in recv_fn")); 131 if ((ret == HTTPD_SOCK_ERR_TIMEOUT) && (pending_len != 0)) { 132 /* If recv() timeout occurred, but pending data is 133 * present, return length of pending data. 134 * This behavior is similar to that of socket recv() 135 * function, which, in case has only partially read the 136 * requested length, due to timeout, returns with read 137 * length, rather than error */ 138 return pending_len; 139 } 140 return ret; 141 } 142 143 ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret + pending_len); 144 return ret + pending_len; 145 } 146 147 int httpd_recv(httpd_req_t *r, char *buf, size_t buf_len) 148 { 149 return httpd_recv_with_opt(r, buf, buf_len, false); 150 } 151 152 size_t httpd_unrecv(struct httpd_req *r, const char *buf, size_t buf_len) 153 { 154 struct httpd_req_aux *ra = r->aux; 155 /* Truncate if external buf_len is greater than pending_data buffer size */ 156 ra->sd->pending_len = MIN(sizeof(ra->sd->pending_data), buf_len); 157 158 /* Copy data into internal pending_data buffer with the exact offset 159 * such that it is right aligned inside the buffer */ 160 size_t offset = sizeof(ra->sd->pending_data) - ra->sd->pending_len; 161 memcpy(ra->sd->pending_data + offset, buf, ra->sd->pending_len); 162 ESP_LOGD(TAG, LOG_FMT("length = %d"), ra->sd->pending_len); 163 return ra->sd->pending_len; 164 } 165 166 /** 167 * This API appends an additional header field-value pair in the HTTP response. 168 * But the header isn't sent out until any of the send APIs is executed. 169 */ 170 esp_err_t httpd_resp_set_hdr(httpd_req_t *r, const char *field, const char *value) 171 { 172 if (r == NULL || field == NULL || value == NULL) { 173 return ESP_ERR_INVALID_ARG; 174 } 175 176 if (!httpd_valid_req(r)) { 177 return ESP_ERR_HTTPD_INVALID_REQ; 178 } 179 180 struct httpd_req_aux *ra = r->aux; 181 struct httpd_data *hd = (struct httpd_data *) r->handle; 182 183 /* Number of additional headers is limited */ 184 if (ra->resp_hdrs_count >= hd->config.max_resp_headers) { 185 return ESP_ERR_HTTPD_RESP_HDR; 186 } 187 188 /* Assign header field-value pair */ 189 ra->resp_hdrs[ra->resp_hdrs_count].field = field; 190 ra->resp_hdrs[ra->resp_hdrs_count].value = value; 191 ra->resp_hdrs_count++; 192 193 ESP_LOGD(TAG, LOG_FMT("new header = %s: %s"), field, value); 194 return ESP_OK; 195 } 196 197 /** 198 * This API sets the status of the HTTP response to the value specified. 199 * But the status isn't sent out until any of the send APIs is executed. 200 */ 201 esp_err_t httpd_resp_set_status(httpd_req_t *r, const char *status) 202 { 203 if (r == NULL || status == NULL) { 204 return ESP_ERR_INVALID_ARG; 205 } 206 207 if (!httpd_valid_req(r)) { 208 return ESP_ERR_HTTPD_INVALID_REQ; 209 } 210 211 struct httpd_req_aux *ra = r->aux; 212 ra->status = (char *)status; 213 return ESP_OK; 214 } 215 216 /** 217 * This API sets the method/type of the HTTP response to the value specified. 218 * But the method isn't sent out until any of the send APIs is executed. 219 */ 220 esp_err_t httpd_resp_set_type(httpd_req_t *r, const char *type) 221 { 222 if (r == NULL || type == NULL) { 223 return ESP_ERR_INVALID_ARG; 224 } 225 226 if (!httpd_valid_req(r)) { 227 return ESP_ERR_HTTPD_INVALID_REQ; 228 } 229 230 struct httpd_req_aux *ra = r->aux; 231 ra->content_type = (char *)type; 232 return ESP_OK; 233 } 234 235 esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, ssize_t buf_len) 236 { 237 if (r == NULL) { 238 return ESP_ERR_INVALID_ARG; 239 } 240 241 if (!httpd_valid_req(r)) { 242 return ESP_ERR_HTTPD_INVALID_REQ; 243 } 244 245 struct httpd_req_aux *ra = r->aux; 246 const char *httpd_hdr_str = "HTTP/1.1 %s\r\nContent-Type: %s\r\nContent-Length: %d\r\n"; 247 const char *colon_separator = ": "; 248 const char *cr_lf_seperator = "\r\n"; 249 250 if (buf_len == HTTPD_RESP_USE_STRLEN) { 251 buf_len = strlen(buf); 252 } 253 254 /* Request headers are no longer available */ 255 ra->req_hdrs_count = 0; 256 257 /* Size of essential headers is limited by scratch buffer size */ 258 if (snprintf(ra->scratch, sizeof(ra->scratch), httpd_hdr_str, 259 ra->status, ra->content_type, buf_len) >= sizeof(ra->scratch)) { 260 return ESP_ERR_HTTPD_RESP_HDR; 261 } 262 263 /* Sending essential headers */ 264 if (httpd_send_all(r, ra->scratch, strlen(ra->scratch)) != ESP_OK) { 265 return ESP_ERR_HTTPD_RESP_SEND; 266 } 267 268 /* Sending additional headers based on set_header */ 269 for (unsigned i = 0; i < ra->resp_hdrs_count; i++) { 270 /* Send header field */ 271 if (httpd_send_all(r, ra->resp_hdrs[i].field, strlen(ra->resp_hdrs[i].field)) != ESP_OK) { 272 return ESP_ERR_HTTPD_RESP_SEND; 273 } 274 /* Send ': ' */ 275 if (httpd_send_all(r, colon_separator, strlen(colon_separator)) != ESP_OK) { 276 return ESP_ERR_HTTPD_RESP_SEND; 277 } 278 /* Send header value */ 279 if (httpd_send_all(r, ra->resp_hdrs[i].value, strlen(ra->resp_hdrs[i].value)) != ESP_OK) { 280 return ESP_ERR_HTTPD_RESP_SEND; 281 } 282 /* Send CR + LF */ 283 if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) { 284 return ESP_ERR_HTTPD_RESP_SEND; 285 } 286 } 287 288 /* End header section */ 289 if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) { 290 return ESP_ERR_HTTPD_RESP_SEND; 291 } 292 293 /* Sending content */ 294 if (buf && buf_len) { 295 if (httpd_send_all(r, buf, buf_len) != ESP_OK) { 296 return ESP_ERR_HTTPD_RESP_SEND; 297 } 298 } 299 return ESP_OK; 300 } 301 302 esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, ssize_t buf_len) 303 { 304 if (r == NULL) { 305 return ESP_ERR_INVALID_ARG; 306 } 307 308 if (!httpd_valid_req(r)) { 309 return ESP_ERR_HTTPD_INVALID_REQ; 310 } 311 312 if (buf_len == HTTPD_RESP_USE_STRLEN) { 313 buf_len = strlen(buf); 314 } 315 316 struct httpd_req_aux *ra = r->aux; 317 const char *httpd_chunked_hdr_str = "HTTP/1.1 %s\r\nContent-Type: %s\r\nTransfer-Encoding: chunked\r\n"; 318 const char *colon_separator = ": "; 319 const char *cr_lf_seperator = "\r\n"; 320 321 /* Request headers are no longer available */ 322 ra->req_hdrs_count = 0; 323 324 if (!ra->first_chunk_sent) { 325 /* Size of essential headers is limited by scratch buffer size */ 326 if (snprintf(ra->scratch, sizeof(ra->scratch), httpd_chunked_hdr_str, 327 ra->status, ra->content_type) >= sizeof(ra->scratch)) { 328 return ESP_ERR_HTTPD_RESP_HDR; 329 } 330 331 /* Sending essential headers */ 332 if (httpd_send_all(r, ra->scratch, strlen(ra->scratch)) != ESP_OK) { 333 return ESP_ERR_HTTPD_RESP_SEND; 334 } 335 336 /* Sending additional headers based on set_header */ 337 for (unsigned i = 0; i < ra->resp_hdrs_count; i++) { 338 /* Send header field */ 339 if (httpd_send_all(r, ra->resp_hdrs[i].field, strlen(ra->resp_hdrs[i].field)) != ESP_OK) { 340 return ESP_ERR_HTTPD_RESP_SEND; 341 } 342 /* Send ': ' */ 343 if (httpd_send_all(r, colon_separator, strlen(colon_separator)) != ESP_OK) { 344 return ESP_ERR_HTTPD_RESP_SEND; 345 } 346 /* Send header value */ 347 if (httpd_send_all(r, ra->resp_hdrs[i].value, strlen(ra->resp_hdrs[i].value)) != ESP_OK) { 348 return ESP_ERR_HTTPD_RESP_SEND; 349 } 350 /* Send CR + LF */ 351 if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) { 352 return ESP_ERR_HTTPD_RESP_SEND; 353 } 354 } 355 356 /* End header section */ 357 if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) { 358 return ESP_ERR_HTTPD_RESP_SEND; 359 } 360 ra->first_chunk_sent = true; 361 } 362 363 /* Sending chunked content */ 364 char len_str[10]; 365 snprintf(len_str, sizeof(len_str), "%x\r\n", buf_len); 366 if (httpd_send_all(r, len_str, strlen(len_str)) != ESP_OK) { 367 return ESP_ERR_HTTPD_RESP_SEND; 368 } 369 370 if (buf) { 371 if (httpd_send_all(r, buf, (size_t) buf_len) != ESP_OK) { 372 return ESP_ERR_HTTPD_RESP_SEND; 373 } 374 } 375 376 /* Indicate end of chunk */ 377 if (httpd_send_all(r, "\r\n", strlen("\r\n")) != ESP_OK) { 378 return ESP_ERR_HTTPD_RESP_SEND; 379 } 380 return ESP_OK; 381 } 382 383 esp_err_t httpd_resp_send_err(httpd_req_t *req, httpd_err_code_t error, const char *usr_msg) 384 { 385 esp_err_t ret; 386 const char *msg; 387 const char *status; 388 389 switch (error) { 390 case HTTPD_501_METHOD_NOT_IMPLEMENTED: 391 status = "501 Method Not Implemented"; 392 msg = "Request method is not supported by server"; 393 break; 394 case HTTPD_505_VERSION_NOT_SUPPORTED: 395 status = "505 Version Not Supported"; 396 msg = "HTTP version not supported by server"; 397 break; 398 case HTTPD_400_BAD_REQUEST: 399 status = "400 Bad Request"; 400 msg = "Server unable to understand request due to invalid syntax"; 401 break; 402 case HTTPD_404_NOT_FOUND: 403 status = "404 Not Found"; 404 msg = "This URI does not exist"; 405 break; 406 case HTTPD_405_METHOD_NOT_ALLOWED: 407 status = "405 Method Not Allowed"; 408 msg = "Request method for this URI is not handled by server"; 409 break; 410 case HTTPD_408_REQ_TIMEOUT: 411 status = "408 Request Timeout"; 412 msg = "Server closed this connection"; 413 break; 414 case HTTPD_414_URI_TOO_LONG: 415 status = "414 URI Too Long"; 416 msg = "URI is too long for server to interpret"; 417 break; 418 case HTTPD_411_LENGTH_REQUIRED: 419 status = "411 Length Required"; 420 msg = "Chunked encoding not supported by server"; 421 break; 422 case HTTPD_431_REQ_HDR_FIELDS_TOO_LARGE: 423 status = "431 Request Header Fields Too Large"; 424 msg = "Header fields are too long for server to interpret"; 425 break; 426 case HTTPD_500_INTERNAL_SERVER_ERROR: 427 default: 428 status = "500 Internal Server Error"; 429 msg = "Server has encountered an unexpected error"; 430 } 431 432 /* If user has provided custom message, override default message */ 433 msg = usr_msg ? usr_msg : msg; 434 ESP_LOGW(TAG, LOG_FMT("%s - %s"), status, msg); 435 436 /* Set error code in HTTP response */ 437 httpd_resp_set_status(req, status); 438 httpd_resp_set_type(req, HTTPD_TYPE_TEXT); 439 440 #ifdef CONFIG_HTTPD_ERR_RESP_NO_DELAY 441 /* Use TCP_NODELAY option to force socket to send data in buffer 442 * This ensures that the error message is sent before the socket 443 * is closed */ 444 struct httpd_req_aux *ra = req->aux; 445 int nodelay = 1; 446 if (setsockopt(ra->sd->fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)) < 0) { 447 /* If failed to turn on TCP_NODELAY, throw warning and continue */ 448 ESP_LOGW(TAG, LOG_FMT("error calling setsockopt : %d"), errno); 449 nodelay = 0; 450 } 451 #endif 452 453 /* Send HTTP error message */ 454 ret = httpd_resp_send(req, msg, HTTPD_RESP_USE_STRLEN); 455 456 #ifdef CONFIG_HTTPD_ERR_RESP_NO_DELAY 457 /* If TCP_NODELAY was set successfully above, time to disable it */ 458 if (nodelay == 1) { 459 nodelay = 0; 460 if (setsockopt(ra->sd->fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)) < 0) { 461 /* If failed to turn off TCP_NODELAY, throw error and 462 * return failure to signal for socket closure */ 463 ESP_LOGE(TAG, LOG_FMT("error calling setsockopt : %d"), errno); 464 return ESP_ERR_INVALID_STATE; 465 } 466 } 467 #endif 468 469 return ret; 470 } 471 472 esp_err_t httpd_register_err_handler(httpd_handle_t handle, 473 httpd_err_code_t error, 474 httpd_err_handler_func_t err_handler_fn) 475 { 476 if (handle == NULL || error >= HTTPD_ERR_CODE_MAX) { 477 return ESP_ERR_INVALID_ARG; 478 } 479 480 struct httpd_data *hd = (struct httpd_data *) handle; 481 hd->err_handler_fns[error] = err_handler_fn; 482 return ESP_OK; 483 } 484 485 esp_err_t httpd_req_handle_err(httpd_req_t *req, httpd_err_code_t error) 486 { 487 struct httpd_data *hd = (struct httpd_data *) req->handle; 488 esp_err_t ret; 489 490 /* Invoke custom error handler if configured */ 491 if (hd->err_handler_fns[error]) { 492 ret = hd->err_handler_fns[error](req, error); 493 494 /* If error code is 500, force return failure 495 * irrespective of the handler's return value */ 496 ret = (error == HTTPD_500_INTERNAL_SERVER_ERROR ? ESP_FAIL : ret); 497 } else { 498 /* If no handler is registered for this error default 499 * behavior is to send the HTTP error response and 500 * return failure for closure of underlying socket */ 501 httpd_resp_send_err(req, error, NULL); 502 ret = ESP_FAIL; 503 } 504 return ret; 505 } 506 507 int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len) 508 { 509 if (r == NULL || buf == NULL) { 510 return HTTPD_SOCK_ERR_INVALID; 511 } 512 513 if (!httpd_valid_req(r)) { 514 ESP_LOGW(TAG, LOG_FMT("invalid request")); 515 return HTTPD_SOCK_ERR_INVALID; 516 } 517 518 struct httpd_req_aux *ra = r->aux; 519 ESP_LOGD(TAG, LOG_FMT("remaining length = %d"), ra->remaining_len); 520 521 if (buf_len > ra->remaining_len) { 522 buf_len = ra->remaining_len; 523 } 524 if (buf_len == 0) { 525 return buf_len; 526 } 527 528 int ret = httpd_recv(r, buf, buf_len); 529 if (ret < 0) { 530 ESP_LOGD(TAG, LOG_FMT("error in httpd_recv")); 531 return ret; 532 } 533 ra->remaining_len -= ret; 534 ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret); 535 return ret; 536 } 537 538 int httpd_req_to_sockfd(httpd_req_t *r) 539 { 540 if (r == NULL) { 541 return -1; 542 } 543 544 if (!httpd_valid_req(r)) { 545 ESP_LOGW(TAG, LOG_FMT("invalid request")); 546 return -1; 547 } 548 549 struct httpd_req_aux *ra = r->aux; 550 return ra->sd->fd; 551 } 552 553 static int httpd_sock_err(const char *ctx, int sockfd) 554 { 555 int errval; 556 ESP_LOGW(TAG, LOG_FMT("error in %s : %d"), ctx, errno); 557 558 switch(errno) { 559 case EAGAIN: 560 case EINTR: 561 errval = HTTPD_SOCK_ERR_TIMEOUT; 562 break; 563 case EINVAL: 564 case EBADF: 565 case EFAULT: 566 case ENOTSOCK: 567 errval = HTTPD_SOCK_ERR_INVALID; 568 break; 569 default: 570 errval = HTTPD_SOCK_ERR_FAIL; 571 } 572 return errval; 573 } 574 575 int httpd_default_send(httpd_handle_t hd, int sockfd, const char *buf, size_t buf_len, int flags) 576 { 577 (void)hd; 578 if (buf == NULL) { 579 return HTTPD_SOCK_ERR_INVALID; 580 } 581 582 int ret = send(sockfd, buf, buf_len, flags); 583 if (ret < 0) { 584 return httpd_sock_err("send", sockfd); 585 } 586 return ret; 587 } 588 589 int httpd_default_recv(httpd_handle_t hd, int sockfd, char *buf, size_t buf_len, int flags) 590 { 591 (void)hd; 592 if (buf == NULL) { 593 return HTTPD_SOCK_ERR_INVALID; 594 } 595 596 int ret = recv(sockfd, buf, buf_len, flags); 597 if (ret < 0) { 598 return httpd_sock_err("recv", sockfd); 599 } 600 return ret; 601 } 602 603 int httpd_socket_send(httpd_handle_t hd, int sockfd, const char *buf, size_t buf_len, int flags) 604 { 605 struct sock_db *sess = httpd_sess_get(hd, sockfd); 606 if (!sess) { 607 return ESP_ERR_INVALID_ARG; 608 } 609 if (!sess->send_fn) { 610 return ESP_ERR_INVALID_STATE; 611 } 612 return sess->send_fn(hd, sockfd, buf, buf_len, flags); 613 } 614 615 int httpd_socket_recv(httpd_handle_t hd, int sockfd, char *buf, size_t buf_len, int flags) 616 { 617 struct sock_db *sess = httpd_sess_get(hd, sockfd); 618 if (!sess) { 619 return ESP_ERR_INVALID_ARG; 620 } 621 if (!sess->recv_fn) { 622 return ESP_ERR_INVALID_STATE; 623 } 624 return sess->recv_fn(hd, sockfd, buf, buf_len, flags); 625 }