esp_httpd_priv.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  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. #ifndef _HTTPD_PRIV_H_
  15. #define _HTTPD_PRIV_H_
  16. #include <stdbool.h>
  17. #include <sys/socket.h>
  18. #include <sys/param.h>
  19. #include <netinet/in.h>
  20. #include <esp_log.h>
  21. #include <esp_err.h>
  22. #include <esp_http_server.h>
  23. #include "osal.h"
  24. #ifdef __cplusplus
  25. extern "C" {
  26. #endif
  27. /* Size of request data block/chunk (not to be confused with chunked encoded data)
  28. * that is received and parsed in one turn of the parsing process. This should not
  29. * exceed the scratch buffer size and should at least be 8 bytes */
  30. #define PARSER_BLOCK_SIZE 128
  31. /* Calculate the maximum size needed for the scratch buffer */
  32. #define HTTPD_SCRATCH_BUF MAX(HTTPD_MAX_REQ_HDR_LEN, HTTPD_MAX_URI_LEN)
  33. /* Formats a log string to prepend context function name */
  34. #define LOG_FMT(x) "%s: " x, __func__
  35. /**
  36. * @brief Thread related data for internal use
  37. */
  38. struct thread_data {
  39. othread_t handle; /*!< Handle to thread/task */
  40. enum {
  41. THREAD_IDLE = 0,
  42. THREAD_RUNNING,
  43. THREAD_STOPPING,
  44. THREAD_STOPPED,
  45. } status; /*!< State of the thread */
  46. };
  47. /**
  48. * @brief A database of all the open sockets in the system.
  49. */
  50. struct sock_db {
  51. int fd; /*!< The file descriptor for this socket */
  52. void *ctx; /*!< A custom context for this socket */
  53. bool ignore_sess_ctx_changes; /*!< Flag indicating if session context changes should be ignored */
  54. void *transport_ctx; /*!< A custom 'transport' context for this socket, to be used by send/recv/pending */
  55. httpd_handle_t handle; /*!< Server handle */
  56. httpd_free_ctx_fn_t free_ctx; /*!< Function for freeing the context */
  57. httpd_free_ctx_fn_t free_transport_ctx; /*!< Function for freeing the 'transport' context */
  58. httpd_send_func_t send_fn; /*!< Send function for this socket */
  59. httpd_recv_func_t recv_fn; /*!< Receive function for this socket */
  60. httpd_pending_func_t pending_fn; /*!< Pending function for this socket */
  61. uint64_t lru_counter; /*!< LRU Counter indicating when the socket was last used */
  62. char pending_data[PARSER_BLOCK_SIZE]; /*!< Buffer for pending data to be received */
  63. size_t pending_len; /*!< Length of pending data to be received */
  64. };
  65. /**
  66. * @brief Auxiliary data structure for use during reception and processing
  67. * of requests and temporarily keeping responses
  68. */
  69. struct httpd_req_aux {
  70. struct sock_db *sd; /*!< Pointer to socket database */
  71. char scratch[HTTPD_SCRATCH_BUF + 1]; /*!< Temporary buffer for our operations (1 byte extra for null termination) */
  72. size_t remaining_len; /*!< Amount of data remaining to be fetched */
  73. char *status; /*!< HTTP response's status code */
  74. char *content_type; /*!< HTTP response's content type */
  75. bool first_chunk_sent; /*!< Used to indicate if first chunk sent */
  76. unsigned req_hdrs_count; /*!< Count of total headers in request packet */
  77. unsigned resp_hdrs_count; /*!< Count of additional headers in response packet */
  78. struct resp_hdr {
  79. const char *field;
  80. const char *value;
  81. } *resp_hdrs; /*!< Additional headers in response packet */
  82. struct http_parser_url url_parse_res; /*!< URL parsing result, used for retrieving URL elements */
  83. };
  84. /**
  85. * @brief Server data for each instance. This is exposed publicly as
  86. * httpd_handle_t but internal structure/members are kept private.
  87. */
  88. struct httpd_data {
  89. httpd_config_t config; /*!< HTTPD server configuration */
  90. int listen_fd; /*!< Server listener FD */
  91. int ctrl_fd; /*!< Ctrl message receiver FD */
  92. int msg_fd; /*!< Ctrl message sender FD */
  93. struct thread_data hd_td; /*!< Information for the HTTPD thread */
  94. struct sock_db *hd_sd; /*!< The socket database */
  95. httpd_uri_t **hd_calls; /*!< Registered URI handlers */
  96. struct httpd_req hd_req; /*!< The current HTTPD request */
  97. struct httpd_req_aux hd_req_aux; /*!< Additional data about the HTTPD request kept unexposed */
  98. /* Array of registered error handler functions */
  99. httpd_err_handler_func_t *err_handler_fns;
  100. };
  101. /******************* Group : Session Management ********************/
  102. /** @name Session Management
  103. * Functions related to HTTP session management
  104. * @{
  105. */
  106. /**
  107. * @brief Retrieve a session by its descriptor
  108. *
  109. * @param[in] hd Server instance data
  110. * @param[in] sockfd Socket FD
  111. * @return pointer into the socket DB, or NULL if not found
  112. */
  113. struct sock_db *httpd_sess_get(struct httpd_data *hd, int sockfd);
  114. /**
  115. * @brief Delete sessions whose FDs have became invalid.
  116. * This is a recovery strategy e.g. after select() fails.
  117. *
  118. * @param[in] hd Server instance data
  119. */
  120. void httpd_sess_delete_invalid(struct httpd_data *hd);
  121. /**
  122. * @brief Initializes an http session by resetting the sockets database.
  123. *
  124. * @param[in] hd Server instance data
  125. */
  126. void httpd_sess_init(struct httpd_data *hd);
  127. /**
  128. * @brief Starts a new session for client requesting connection and adds
  129. * it's descriptor to the socket database.
  130. *
  131. * @param[in] hd Server instance data
  132. * @param[in] newfd Descriptor of the new client to be added to the session.
  133. *
  134. * @return
  135. * - ESP_OK : on successfully queuing the work
  136. * - ESP_FAIL : in case of control socket error while sending
  137. */
  138. esp_err_t httpd_sess_new(struct httpd_data *hd, int newfd);
  139. /**
  140. * @brief Processes incoming HTTP requests
  141. *
  142. * @param[in] hd Server instance data
  143. * @param[in] clifd Descriptor of the client from which data is to be received
  144. *
  145. * @return
  146. * - ESP_OK : on successfully receiving, parsing and responding to a request
  147. * - ESP_FAIL : in case of failure in any of the stages of processing
  148. */
  149. esp_err_t httpd_sess_process(struct httpd_data *hd, int clifd);
  150. /**
  151. * @brief Remove client descriptor from the session / socket database
  152. * and close the connection for this client.
  153. *
  154. * @note The returned descriptor should be used by httpd_sess_iterate()
  155. * to continue the iteration correctly. This ensures that the
  156. * iteration is not restarted abruptly which may cause reading from
  157. * a socket which has been already processed and thus blocking
  158. * the server loop until data appears on that socket.
  159. *
  160. * @param[in] hd Server instance data
  161. * @param[in] clifd Descriptor of the client to be removed from the session.
  162. *
  163. * @return
  164. * - +VE : Client descriptor preceding the one being deleted
  165. * - -1 : No descriptor preceding the one being deleted
  166. */
  167. int httpd_sess_delete(struct httpd_data *hd, int clifd);
  168. /**
  169. * @brief Free session context
  170. *
  171. * @param[in] ctx Pointer to session context
  172. * @param[in] free_fn Free function to call on session context
  173. */
  174. void httpd_sess_free_ctx(void *ctx, httpd_free_ctx_fn_t free_fn);
  175. /**
  176. * @brief Add descriptors present in the socket database to an fdset and
  177. * update the value of maxfd which are needed by the select function
  178. * for looking through all available sockets for incoming data.
  179. *
  180. * @param[in] hd Server instance data
  181. * @param[out] fdset File descriptor set to be updated.
  182. * @param[out] maxfd Maximum value among all file descriptors.
  183. */
  184. void httpd_sess_set_descriptors(struct httpd_data *hd, fd_set *fdset, int *maxfd);
  185. /**
  186. * @brief Iterates through the list of client fds in the session /socket database.
  187. * Passing the value of a client fd returns the fd for the next client
  188. * in the database. In order to iterate from the beginning pass -1 as fd.
  189. *
  190. * @param[in] hd Server instance data
  191. * @param[in] fd Last accessed client descriptor.
  192. * -1 to reset iterator to start of database.
  193. *
  194. * @return
  195. * - +VE : Client descriptor next in the database
  196. * - -1 : End of iteration
  197. */
  198. int httpd_sess_iterate(struct httpd_data *hd, int fd);
  199. /**
  200. * @brief Checks if session can accept another connection from new client.
  201. * If sockets database is full then this returns false.
  202. *
  203. * @param[in] hd Server instance data
  204. *
  205. * @return True if session can accept new clients
  206. */
  207. bool httpd_is_sess_available(struct httpd_data *hd);
  208. /**
  209. * @brief Checks if session has any pending data/packets
  210. * for processing
  211. *
  212. * This is needed as httpd_unrecv may un-receive next
  213. * packet in the stream. If only partial packet was
  214. * received then select() would mark the fd for processing
  215. * as remaining part of the packet would still be in socket
  216. * recv queue. But if a complete packet got unreceived
  217. * then it would not be processed until further data is
  218. * received on the socket. This is when this function
  219. * comes in use, as it checks the socket's pending data
  220. * buffer.
  221. *
  222. * @param[in] hd Server instance data
  223. * @param[in] fd Client descriptor
  224. *
  225. * @return True if there is any pending data
  226. */
  227. bool httpd_sess_pending(struct httpd_data *hd, int fd);
  228. /**
  229. * @brief Removes the least recently used client from the session
  230. *
  231. * This may be useful if new clients are requesting for connection but
  232. * max number of connections is reached, in which case the client which
  233. * is inactive for the longest will be removed from the session.
  234. *
  235. * @param[in] hd Server instance data
  236. *
  237. * @return
  238. * - ESP_OK : if session closure initiated successfully
  239. * - ESP_FAIL : if failed
  240. */
  241. esp_err_t httpd_sess_close_lru(struct httpd_data *hd);
  242. /** End of Group : Session Management
  243. * @}
  244. */
  245. /****************** Group : URI Handling ********************/
  246. /** @name URI Handling
  247. * Methods for accessing URI handlers
  248. * @{
  249. */
  250. /**
  251. * @brief For an HTTP request, searches through all the registered URI handlers
  252. * and invokes the appropriate one if found
  253. *
  254. * @param[in] hd Server instance data for which handler needs to be invoked
  255. *
  256. * @return
  257. * - ESP_OK : if handler found and executed successfully
  258. * - ESP_FAIL : otherwise
  259. */
  260. esp_err_t httpd_uri(struct httpd_data *hd);
  261. /**
  262. * @brief Unregister all URI handlers
  263. *
  264. * @param[in] hd Server instance data
  265. */
  266. void httpd_unregister_all_uri_handlers(struct httpd_data *hd);
  267. /**
  268. * @brief Validates the request to prevent users from calling APIs, that are to
  269. * be called only inside a URI handler, outside the handler context
  270. *
  271. * @param[in] req Pointer to HTTP request that needs to be validated
  272. *
  273. * @return
  274. * - true : if valid request
  275. * - false : otherwise
  276. */
  277. bool httpd_validate_req_ptr(httpd_req_t *r);
  278. /* httpd_validate_req_ptr() adds some overhead to frequently used APIs,
  279. * and is useful mostly for debugging, so it's preferable to disable
  280. * the check by default and enable it only if necessary */
  281. #ifdef CONFIG_HTTPD_VALIDATE_REQ
  282. #define httpd_valid_req(r) httpd_validate_req_ptr(r)
  283. #else
  284. #define httpd_valid_req(r) true
  285. #endif
  286. /** End of Group : URI Handling
  287. * @}
  288. */
  289. /****************** Group : Processing ********************/
  290. /** @name Processing
  291. * Methods for processing HTTP requests
  292. * @{
  293. */
  294. /**
  295. * @brief Initiates the processing of HTTP request
  296. *
  297. * Receives incoming TCP packet on a socket, then parses the packet as
  298. * HTTP request and fills httpd_req_t data structure with the extracted
  299. * URI, headers are ready to be fetched from scratch buffer and calling
  300. * http_recv() after this reads the body of the request.
  301. *
  302. * @param[in] hd Server instance data
  303. * @param[in] sd Pointer to socket which is needed for receiving TCP packets.
  304. *
  305. * @return
  306. * - ESP_OK : if request packet is valid
  307. * - ESP_FAIL : otherwise
  308. */
  309. esp_err_t httpd_req_new(struct httpd_data *hd, struct sock_db *sd);
  310. /**
  311. * @brief For an HTTP request, resets the resources allocated for it and
  312. * purges any data left to be received
  313. *
  314. * @param[in] hd Server instance data
  315. *
  316. * @return
  317. * - ESP_OK : if request packet deleted and resources cleaned.
  318. * - ESP_FAIL : otherwise.
  319. */
  320. esp_err_t httpd_req_delete(struct httpd_data *hd);
  321. /**
  322. * @brief For handling HTTP errors by invoking registered
  323. * error handler function
  324. *
  325. * @param[in] req Pointer to the HTTP request for which error occurred
  326. * @param[in] error Error type
  327. *
  328. * @return
  329. * - ESP_OK : error handled successful
  330. * - ESP_FAIL : failure indicates that the underlying socket needs to be closed
  331. */
  332. esp_err_t httpd_req_handle_err(httpd_req_t *req, httpd_err_code_t error);
  333. /** End of Group : Parsing
  334. * @}
  335. */
  336. /****************** Group : Send/Receive ********************/
  337. /** @name Send and Receive
  338. * Methods for transmitting and receiving HTTP requests and responses
  339. * @{
  340. */
  341. /**
  342. * @brief For sending out data in response to an HTTP request.
  343. *
  344. * @param[in] req Pointer to the HTTP request for which the response needs to be sent
  345. * @param[in] buf Pointer to the buffer from where the body of the response is taken
  346. * @param[in] buf_len Length of the buffer
  347. *
  348. * @return
  349. * - Length of data : if successful
  350. * - ESP_FAIL : if failed
  351. */
  352. int httpd_send(httpd_req_t *req, const char *buf, size_t buf_len);
  353. /**
  354. * @brief For receiving HTTP request data
  355. *
  356. * @note The exposed API httpd_recv() is simply this function with last parameter
  357. * set as false. This function is used internally during reception and
  358. * processing of a new request. The option to halt after receiving pending
  359. * data prevents the server from requesting more data than is needed for
  360. * completing a packet in case when all the remaining part of the packet is
  361. * in the pending buffer.
  362. *
  363. * @param[in] req Pointer to new HTTP request which only has the socket descriptor
  364. * @param[out] buf Pointer to the buffer which will be filled with the received data
  365. * @param[in] buf_len Length of the buffer
  366. * @param[in] halt_after_pending When set true, halts immediately after receiving from
  367. * pending buffer
  368. *
  369. * @return
  370. * - Length of data : if successful
  371. * - ESP_FAIL : if failed
  372. */
  373. int httpd_recv_with_opt(httpd_req_t *r, char *buf, size_t buf_len, bool halt_after_pending);
  374. /**
  375. * @brief For un-receiving HTTP request data
  376. *
  377. * This function copies data into internal buffer pending_data so that
  378. * when httpd_recv is called, it first fetches this pending data and
  379. * then only starts receiving from the socket
  380. *
  381. * @note If data is too large for the internal buffer then only
  382. * part of the data is unreceived, reflected in the returned
  383. * length. Make sure that such truncation is checked for and
  384. * handled properly.
  385. *
  386. * @param[in] req Pointer to new HTTP request which only has the socket descriptor
  387. * @param[in] buf Pointer to the buffer from where data needs to be un-received
  388. * @param[in] buf_len Length of the buffer
  389. *
  390. * @return Length of data copied into pending buffer
  391. */
  392. size_t httpd_unrecv(struct httpd_req *r, const char *buf, size_t buf_len);
  393. /**
  394. * @brief This is the low level default send function of the HTTPD. This should
  395. * NEVER be called directly. The semantics of this is exactly similar to
  396. * send() of the BSD socket API.
  397. *
  398. * @param[in] hd Server instance data
  399. * @param[in] sockfd Socket descriptor for sending data
  400. * @param[in] buf Pointer to the buffer from where the body of the response is taken
  401. * @param[in] buf_len Length of the buffer
  402. * @param[in] flags Flags for mode selection
  403. *
  404. * @return
  405. * - Length of data : if successful
  406. * - -1 : if failed (appropriate errno is set)
  407. */
  408. int httpd_default_send(httpd_handle_t hd, int sockfd, const char *buf, size_t buf_len, int flags);
  409. /**
  410. * @brief This is the low level default recv function of the HTTPD. This should
  411. * NEVER be called directly. The semantics of this is exactly similar to
  412. * recv() of the BSD socket API.
  413. *
  414. * @param[in] hd Server instance data
  415. * @param[in] sockfd Socket descriptor for sending data
  416. * @param[out] buf Pointer to the buffer which will be filled with the received data
  417. * @param[in] buf_len Length of the buffer
  418. * @param[in] flags Flags for mode selection
  419. *
  420. * @return
  421. * - Length of data : if successful
  422. * - -1 : if failed (appropriate errno is set)
  423. */
  424. int httpd_default_recv(httpd_handle_t hd, int sockfd, char *buf, size_t buf_len, int flags);
  425. /** End of Group : Send and Receive
  426. * @}
  427. */
  428. #ifdef __cplusplus
  429. }
  430. #endif
  431. #endif /* ! _HTTPD_PRIV_H_ */