uhttpd.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /*
  2. * uhttpd - Tiny single-threaded httpd
  3. *
  4. * Copyright (C) 2010-2013 Jo-Philipp Wich <xm@subsignal.org>
  5. * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
  6. *
  7. * Permission to use, copy, modify, and/or distribute this software for any
  8. * purpose with or without fee is hereby granted, provided that the above
  9. * copyright notice and this permission notice appear in all copies.
  10. *
  11. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  12. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  13. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  14. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  15. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  16. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  17. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  18. */
  19. #ifndef __UHTTPD_H
  20. #define __UHTTPD_H
  21. #include <netinet/in.h>
  22. #include <limits.h>
  23. #include <dirent.h>
  24. #include <libubox/list.h>
  25. #include <libubox/uloop.h>
  26. #include <libubox/ustream.h>
  27. #include <libubox/blob.h>
  28. #include <libubox/utils.h>
  29. #ifdef HAVE_UBUS
  30. #include <libubus.h>
  31. #include <json-c/json.h>
  32. #endif
  33. #ifdef HAVE_TLS
  34. #include <libubox/ustream-ssl.h>
  35. #endif
  36. #include "utils.h"
  37. #define UH_LIMIT_CLIENTS 64
  38. #define __enum_header(_name, _val) HDR_##_name,
  39. #define __blobmsg_header(_name, _val) [HDR_##_name] = { .name = #_val, .type = BLOBMSG_TYPE_STRING },
  40. struct client;
  41. struct alias {
  42. struct list_head list;
  43. char *alias;
  44. char *path;
  45. };
  46. struct lua_prefix {
  47. struct list_head list;
  48. const char *handler;
  49. const char *prefix;
  50. void *ctx;
  51. };
  52. struct config {
  53. const char *docroot;
  54. const char *realm;
  55. const char *file;
  56. const char *error_handler;
  57. const char *cgi_prefix;
  58. const char *cgi_docroot_path;
  59. const char *cgi_path;
  60. const char *ubus_prefix;
  61. const char *ubus_socket;
  62. int no_symlinks;
  63. int no_dirlists;
  64. int network_timeout;
  65. int rfc1918_filter;
  66. int tls_redirect;
  67. int tcp_keepalive;
  68. int max_script_requests;
  69. int max_connections;
  70. int http_keepalive;
  71. int script_timeout;
  72. int ubus_noauth;
  73. int ubus_cors;
  74. int cgi_prefix_len;
  75. int events_retry;
  76. struct list_head cgi_alias;
  77. struct list_head lua_prefix;
  78. };
  79. struct auth_realm {
  80. struct list_head list;
  81. const char *path;
  82. const char *user;
  83. const char *pass;
  84. };
  85. enum http_method {
  86. UH_HTTP_MSG_GET,
  87. UH_HTTP_MSG_POST,
  88. UH_HTTP_MSG_HEAD,
  89. UH_HTTP_MSG_OPTIONS,
  90. UH_HTTP_MSG_PUT,
  91. UH_HTTP_MSG_PATCH,
  92. UH_HTTP_MSG_DELETE,
  93. };
  94. enum http_version {
  95. UH_HTTP_VER_0_9,
  96. UH_HTTP_VER_1_0,
  97. UH_HTTP_VER_1_1,
  98. };
  99. enum http_user_agent {
  100. UH_UA_UNKNOWN,
  101. UH_UA_GECKO,
  102. UH_UA_CHROME,
  103. UH_UA_SAFARI,
  104. UH_UA_MSIE,
  105. UH_UA_KONQUEROR,
  106. UH_UA_OPERA,
  107. UH_UA_MSIE_OLD,
  108. UH_UA_MSIE_NEW,
  109. };
  110. struct http_request {
  111. enum http_method method;
  112. enum http_version version;
  113. enum http_user_agent ua;
  114. int redirect_status;
  115. int content_length;
  116. bool expect_cont;
  117. bool connection_close;
  118. bool disable_chunked;
  119. uint8_t transfer_chunked;
  120. const struct auth_realm *realm;
  121. };
  122. enum client_state {
  123. CLIENT_STATE_INIT,
  124. CLIENT_STATE_HEADER,
  125. CLIENT_STATE_DATA,
  126. CLIENT_STATE_DONE,
  127. CLIENT_STATE_CLOSE,
  128. CLIENT_STATE_CLEANUP,
  129. };
  130. struct interpreter {
  131. struct list_head list;
  132. const char *path;
  133. const char *ext;
  134. };
  135. struct path_info {
  136. const char *root;
  137. const char *phys;
  138. const char *name;
  139. const char *info;
  140. const char *query;
  141. bool redirected;
  142. struct stat stat;
  143. const struct interpreter *ip;
  144. };
  145. struct env_var {
  146. const char *name;
  147. const char *value;
  148. };
  149. struct relay {
  150. struct ustream_fd sfd;
  151. struct uloop_process proc;
  152. struct uloop_timeout timeout;
  153. struct client *cl;
  154. bool process_done;
  155. bool error;
  156. bool skip_data;
  157. int ret;
  158. int header_ofs;
  159. void (*header_cb)(struct relay *r, const char *name, const char *value);
  160. void (*header_end)(struct relay *r);
  161. void (*close)(struct relay *r, int ret);
  162. };
  163. struct dispatch_proc {
  164. struct uloop_timeout timeout;
  165. struct blob_buf hdr;
  166. struct uloop_fd wrfd;
  167. struct relay r;
  168. int status_code;
  169. char *status_msg;
  170. };
  171. struct dispatch_handler {
  172. struct list_head list;
  173. bool script;
  174. bool (*check_url)(const char *url);
  175. bool (*check_path)(struct path_info *pi, const char *url);
  176. void (*handle_request)(struct client *cl, char *url, struct path_info *pi);
  177. };
  178. #ifdef HAVE_UBUS
  179. struct dispatch_ubus {
  180. struct ubus_request req;
  181. struct uloop_timeout timeout;
  182. struct json_tokener *jstok;
  183. struct json_object *jsobj;
  184. struct json_object *jsobj_cur;
  185. char *url_path;
  186. int post_len;
  187. uint32_t obj;
  188. const char *func;
  189. struct blob_buf buf;
  190. bool req_pending;
  191. bool array;
  192. int array_idx;
  193. bool legacy; /* Got legacy request => use legacy reply */
  194. struct ubus_subscriber sub;
  195. };
  196. #endif
  197. struct dispatch {
  198. int (*data_send)(struct client *cl, const char *data, int len);
  199. void (*data_done)(struct client *cl);
  200. void (*write_cb)(struct client *cl);
  201. void (*close_fds)(struct client *cl);
  202. void (*free)(struct client *cl);
  203. void *req_data;
  204. void (*req_free)(struct client *cl);
  205. bool data_blocked;
  206. bool no_cache;
  207. union {
  208. struct {
  209. struct blob_attr **hdr;
  210. int fd;
  211. } file;
  212. struct dispatch_proc proc;
  213. #ifdef HAVE_UBUS
  214. struct dispatch_ubus ubus;
  215. #endif
  216. };
  217. };
  218. struct client {
  219. struct list_head list;
  220. int refcount;
  221. int id;
  222. struct ustream *us;
  223. struct ustream_fd sfd;
  224. #ifdef HAVE_TLS
  225. struct ustream_ssl ssl;
  226. #endif
  227. struct uloop_timeout timeout;
  228. int requests;
  229. enum client_state state;
  230. bool tls;
  231. int http_code;
  232. struct http_request request;
  233. struct uh_addr srv_addr, peer_addr;
  234. struct blob_buf hdr;
  235. struct blob_buf hdr_response;
  236. struct dispatch dispatch;
  237. };
  238. extern char uh_buf[4096];
  239. extern int n_clients;
  240. extern struct config conf;
  241. extern const char * const http_versions[];
  242. extern const char * const http_methods[];
  243. extern struct dispatch_handler cgi_dispatch;
  244. void uh_index_add(const char *filename);
  245. bool uh_accept_client(int fd, bool tls);
  246. void uh_unblock_listeners(void);
  247. void uh_setup_listeners(void);
  248. int uh_socket_bind(const char *host, const char *port, bool tls);
  249. int uh_first_tls_port(int family);
  250. bool uh_use_chunked(struct client *cl);
  251. void uh_chunk_write(struct client *cl, const void *data, int len);
  252. void uh_chunk_vprintf(struct client *cl, const char *format, va_list arg);
  253. void __printf(2, 3)
  254. uh_chunk_printf(struct client *cl, const char *format, ...);
  255. void uh_chunk_eof(struct client *cl);
  256. void uh_request_done(struct client *cl);
  257. void uh_http_header(struct client *cl, int code, const char *summary);
  258. void __printf(4, 5)
  259. uh_client_error(struct client *cl, int code, const char *summary, const char *fmt, ...);
  260. void uh_handle_request(struct client *cl);
  261. void client_poll_post_data(struct client *cl);
  262. void uh_client_read_cb(struct client *cl);
  263. void uh_client_notify_state(struct client *cl);
  264. void uh_auth_add(const char *path, const char *user, const char *pass);
  265. bool uh_auth_check(struct client *cl, const char *path, const char *auth,
  266. char **uptr, char **pptr);
  267. void uh_close_listen_fds(void);
  268. void uh_close_fds(void);
  269. void uh_interpreter_add(const char *ext, const char *path);
  270. void uh_dispatch_add(struct dispatch_handler *d);
  271. void uh_relay_open(struct client *cl, struct relay *r, int fd, int pid);
  272. void uh_relay_close(struct relay *r, int ret);
  273. void uh_relay_free(struct relay *r);
  274. void uh_relay_kill(struct client *cl, struct relay *r);
  275. struct env_var *uh_get_process_vars(struct client *cl, struct path_info *pi);
  276. bool uh_create_process(struct client *cl, struct path_info *pi, char *url,
  277. void (*cb)(struct client *cl, struct path_info *pi, char *url));
  278. int uh_plugin_init(const char *name);
  279. void uh_plugin_post_init(void);
  280. int uh_handler_add(const char *file);
  281. int uh_handler_run(struct client *cl, char **url, bool fallback);
  282. struct path_info *uh_path_lookup(struct client *cl, const char *url);
  283. static inline void uh_client_ref(struct client *cl)
  284. {
  285. cl->refcount++;
  286. }
  287. static inline void uh_client_unref(struct client *cl)
  288. {
  289. if (--cl->refcount)
  290. return;
  291. if (cl->state == CLIENT_STATE_CLEANUP)
  292. ustream_state_change(cl->us);
  293. }
  294. #endif