uhttpd.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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_UCODE
  34. #include <ucode/vm.h>
  35. #endif
  36. #ifdef HAVE_TLS
  37. #include <libubox/ustream-ssl.h>
  38. #endif
  39. #include "utils.h"
  40. #define UH_LIMIT_CLIENTS 64
  41. #define __enum_header(_name, _val) HDR_##_name,
  42. #define __blobmsg_header(_name, _val) [HDR_##_name] = { .name = #_val, .type = BLOBMSG_TYPE_STRING },
  43. struct client;
  44. struct alias {
  45. struct list_head list;
  46. char *alias;
  47. char *path;
  48. };
  49. struct lua_prefix {
  50. struct list_head list;
  51. const char *handler;
  52. const char *prefix;
  53. void *ctx;
  54. };
  55. #ifdef HAVE_UCODE
  56. struct ucode_prefix {
  57. struct list_head list;
  58. const char *handler;
  59. const char *prefix;
  60. uc_vm_t ctx;
  61. };
  62. #endif
  63. struct config {
  64. const char *docroot;
  65. const char *realm;
  66. const char *file;
  67. const char *error_handler;
  68. const char *cgi_prefix;
  69. const char *cgi_docroot_path;
  70. const char *cgi_path;
  71. const char *ubus_prefix;
  72. const char *ubus_socket;
  73. const char *dirlist_charset;
  74. int no_symlinks;
  75. int no_dirlists;
  76. int network_timeout;
  77. int rfc1918_filter;
  78. int tls_redirect;
  79. int tcp_keepalive;
  80. int max_script_requests;
  81. int max_connections;
  82. int http_keepalive;
  83. int script_timeout;
  84. int ubus_noauth;
  85. int ubus_cors;
  86. int cgi_prefix_len;
  87. int events_retry;
  88. struct list_head cgi_alias;
  89. struct list_head lua_prefix;
  90. #ifdef HAVE_UCODE
  91. struct list_head ucode_prefix;
  92. #endif
  93. };
  94. struct auth_realm {
  95. struct list_head list;
  96. const char *path;
  97. const char *user;
  98. const char *pass;
  99. };
  100. enum http_method {
  101. UH_HTTP_MSG_GET,
  102. UH_HTTP_MSG_POST,
  103. UH_HTTP_MSG_HEAD,
  104. UH_HTTP_MSG_OPTIONS,
  105. UH_HTTP_MSG_PUT,
  106. UH_HTTP_MSG_PATCH,
  107. UH_HTTP_MSG_DELETE,
  108. };
  109. enum http_version {
  110. UH_HTTP_VER_0_9,
  111. UH_HTTP_VER_1_0,
  112. UH_HTTP_VER_1_1,
  113. };
  114. enum http_user_agent {
  115. UH_UA_UNKNOWN,
  116. UH_UA_GECKO,
  117. UH_UA_CHROME,
  118. UH_UA_SAFARI,
  119. UH_UA_MSIE,
  120. UH_UA_KONQUEROR,
  121. UH_UA_OPERA,
  122. UH_UA_MSIE_OLD,
  123. UH_UA_MSIE_NEW,
  124. };
  125. struct http_request {
  126. enum http_method method;
  127. enum http_version version;
  128. enum http_user_agent ua;
  129. int redirect_status;
  130. int content_length;
  131. bool expect_cont;
  132. bool connection_close;
  133. bool disable_chunked;
  134. uint8_t transfer_chunked;
  135. const struct auth_realm *realm;
  136. };
  137. enum client_state {
  138. CLIENT_STATE_INIT,
  139. CLIENT_STATE_HEADER,
  140. CLIENT_STATE_DATA,
  141. CLIENT_STATE_DONE,
  142. CLIENT_STATE_CLOSE,
  143. CLIENT_STATE_CLEANUP,
  144. };
  145. struct interpreter {
  146. struct list_head list;
  147. const char *path;
  148. const char *ext;
  149. };
  150. struct path_info {
  151. const char *root;
  152. const char *phys;
  153. const char *name;
  154. const char *info;
  155. const char *query;
  156. bool redirected;
  157. struct stat stat;
  158. const struct interpreter *ip;
  159. };
  160. struct env_var {
  161. const char *name;
  162. const char *value;
  163. };
  164. struct relay {
  165. struct ustream_fd sfd;
  166. struct uloop_process proc;
  167. struct uloop_timeout timeout;
  168. struct client *cl;
  169. bool process_done;
  170. bool error;
  171. bool skip_data;
  172. int ret;
  173. int header_ofs;
  174. void (*header_cb)(struct relay *r, const char *name, const char *value);
  175. void (*header_end)(struct relay *r);
  176. void (*close)(struct relay *r, int ret);
  177. };
  178. struct dispatch_proc {
  179. struct uloop_timeout timeout;
  180. struct blob_buf hdr;
  181. struct uloop_fd wrfd;
  182. struct relay r;
  183. int status_code;
  184. char *status_msg;
  185. };
  186. struct dispatch_handler {
  187. struct list_head list;
  188. bool script;
  189. bool (*check_url)(const char *url);
  190. bool (*check_path)(struct path_info *pi, const char *url);
  191. void (*handle_request)(struct client *cl, char *url, struct path_info *pi);
  192. };
  193. #ifdef HAVE_UBUS
  194. struct dispatch_ubus {
  195. struct ubus_request req;
  196. struct uloop_timeout timeout;
  197. struct json_tokener *jstok;
  198. struct json_object *jsobj;
  199. struct json_object *jsobj_cur;
  200. char *url_path;
  201. int post_len;
  202. uint32_t obj;
  203. const char *func;
  204. struct blob_buf buf;
  205. bool req_pending;
  206. bool array;
  207. int array_idx;
  208. bool legacy; /* Got legacy request => use legacy reply */
  209. struct ubus_subscriber sub;
  210. };
  211. #endif
  212. struct dispatch {
  213. int (*data_send)(struct client *cl, const char *data, int len);
  214. void (*data_done)(struct client *cl);
  215. void (*write_cb)(struct client *cl);
  216. void (*close_fds)(struct client *cl);
  217. void (*free)(struct client *cl);
  218. void *req_data;
  219. void (*req_free)(struct client *cl);
  220. bool data_blocked;
  221. bool no_cache;
  222. union {
  223. struct {
  224. struct blob_attr **hdr;
  225. int fd;
  226. } file;
  227. struct dispatch_proc proc;
  228. #ifdef HAVE_UBUS
  229. struct dispatch_ubus ubus;
  230. #endif
  231. };
  232. };
  233. struct client {
  234. struct list_head list;
  235. int refcount;
  236. int id;
  237. struct ustream *us;
  238. struct ustream_fd sfd;
  239. #ifdef HAVE_TLS
  240. struct ustream_ssl ssl;
  241. #endif
  242. struct uloop_timeout timeout;
  243. int requests;
  244. enum client_state state;
  245. bool tls;
  246. int http_code;
  247. struct http_request request;
  248. struct uh_addr srv_addr, peer_addr;
  249. struct blob_buf hdr;
  250. struct blob_buf hdr_response;
  251. struct dispatch dispatch;
  252. };
  253. extern char uh_buf[4096];
  254. extern int n_clients;
  255. extern struct config conf;
  256. extern const char * const http_versions[];
  257. extern const char * const http_methods[];
  258. extern struct dispatch_handler cgi_dispatch;
  259. void uh_index_add(const char *filename);
  260. bool uh_accept_client(int fd, bool tls);
  261. void uh_unblock_listeners(void);
  262. void uh_setup_listeners(void);
  263. int uh_socket_bind(const char *host, const char *port, bool tls);
  264. int uh_first_tls_port(int family);
  265. bool uh_use_chunked(struct client *cl);
  266. void uh_chunk_write(struct client *cl, const void *data, int len);
  267. void uh_chunk_vprintf(struct client *cl, const char *format, va_list arg);
  268. void __printf(2, 3)
  269. uh_chunk_printf(struct client *cl, const char *format, ...);
  270. void uh_chunk_eof(struct client *cl);
  271. void uh_request_done(struct client *cl);
  272. void uh_http_header(struct client *cl, int code, const char *summary);
  273. void __printf(4, 5)
  274. uh_client_error(struct client *cl, int code, const char *summary, const char *fmt, ...);
  275. void uh_handle_request(struct client *cl);
  276. void client_poll_post_data(struct client *cl);
  277. void uh_client_read_cb(struct client *cl);
  278. void uh_client_notify_state(struct client *cl);
  279. void uh_auth_add(const char *path, const char *user, const char *pass);
  280. bool uh_auth_check(struct client *cl, const char *path, const char *auth,
  281. char **uptr, char **pptr);
  282. void uh_close_listen_fds(void);
  283. void uh_close_fds(void);
  284. void uh_interpreter_add(const char *ext, const char *path);
  285. void uh_dispatch_add(struct dispatch_handler *d);
  286. void uh_relay_open(struct client *cl, struct relay *r, int fd, int pid);
  287. void uh_relay_close(struct relay *r, int ret);
  288. void uh_relay_free(struct relay *r);
  289. void uh_relay_kill(struct client *cl, struct relay *r);
  290. struct env_var *uh_get_process_vars(struct client *cl, struct path_info *pi);
  291. bool uh_create_process(struct client *cl, struct path_info *pi, char *url,
  292. void (*cb)(struct client *cl, struct path_info *pi, char *url));
  293. int uh_plugin_init(const char *name);
  294. void uh_plugin_post_init(void);
  295. int uh_handler_add(const char *file);
  296. int uh_handler_run(struct client *cl, char **url, bool fallback);
  297. struct path_info *uh_path_lookup(struct client *cl, const char *url);
  298. static inline void uh_client_ref(struct client *cl)
  299. {
  300. cl->refcount++;
  301. }
  302. static inline void uh_client_unref(struct client *cl)
  303. {
  304. if (--cl->refcount)
  305. return;
  306. if (cl->state == CLIENT_STATE_CLEANUP)
  307. ustream_state_change(cl->us);
  308. }
  309. #endif