uhttpd.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  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. struct list_head cgi_alias;
  76. struct list_head lua_prefix;
  77. };
  78. struct auth_realm {
  79. struct list_head list;
  80. const char *path;
  81. const char *user;
  82. const char *pass;
  83. };
  84. enum http_method {
  85. UH_HTTP_MSG_GET,
  86. UH_HTTP_MSG_POST,
  87. UH_HTTP_MSG_HEAD,
  88. UH_HTTP_MSG_OPTIONS,
  89. UH_HTTP_MSG_PUT,
  90. UH_HTTP_MSG_PATCH,
  91. UH_HTTP_MSG_DELETE,
  92. };
  93. enum http_version {
  94. UH_HTTP_VER_0_9,
  95. UH_HTTP_VER_1_0,
  96. UH_HTTP_VER_1_1,
  97. };
  98. enum http_user_agent {
  99. UH_UA_UNKNOWN,
  100. UH_UA_GECKO,
  101. UH_UA_CHROME,
  102. UH_UA_SAFARI,
  103. UH_UA_MSIE,
  104. UH_UA_KONQUEROR,
  105. UH_UA_OPERA,
  106. UH_UA_MSIE_OLD,
  107. UH_UA_MSIE_NEW,
  108. };
  109. struct http_request {
  110. enum http_method method;
  111. enum http_version version;
  112. enum http_user_agent ua;
  113. int redirect_status;
  114. int content_length;
  115. bool expect_cont;
  116. bool connection_close;
  117. bool disable_chunked;
  118. uint8_t transfer_chunked;
  119. const struct auth_realm *realm;
  120. };
  121. enum client_state {
  122. CLIENT_STATE_INIT,
  123. CLIENT_STATE_HEADER,
  124. CLIENT_STATE_DATA,
  125. CLIENT_STATE_DONE,
  126. CLIENT_STATE_CLOSE,
  127. CLIENT_STATE_CLEANUP,
  128. };
  129. struct interpreter {
  130. struct list_head list;
  131. const char *path;
  132. const char *ext;
  133. };
  134. struct path_info {
  135. const char *root;
  136. const char *phys;
  137. const char *name;
  138. const char *info;
  139. const char *query;
  140. bool redirected;
  141. struct stat stat;
  142. const struct interpreter *ip;
  143. };
  144. struct env_var {
  145. const char *name;
  146. const char *value;
  147. };
  148. struct relay {
  149. struct ustream_fd sfd;
  150. struct uloop_process proc;
  151. struct uloop_timeout timeout;
  152. struct client *cl;
  153. bool process_done;
  154. bool error;
  155. bool skip_data;
  156. int ret;
  157. int header_ofs;
  158. void (*header_cb)(struct relay *r, const char *name, const char *value);
  159. void (*header_end)(struct relay *r);
  160. void (*close)(struct relay *r, int ret);
  161. };
  162. struct dispatch_proc {
  163. struct uloop_timeout timeout;
  164. struct blob_buf hdr;
  165. struct uloop_fd wrfd;
  166. struct relay r;
  167. int status_code;
  168. char *status_msg;
  169. };
  170. struct dispatch_handler {
  171. struct list_head list;
  172. bool script;
  173. bool (*check_url)(const char *url);
  174. bool (*check_path)(struct path_info *pi, const char *url);
  175. void (*handle_request)(struct client *cl, char *url, struct path_info *pi);
  176. };
  177. #ifdef HAVE_UBUS
  178. struct dispatch_ubus {
  179. struct ubus_request req;
  180. struct uloop_timeout timeout;
  181. struct json_tokener *jstok;
  182. struct json_object *jsobj;
  183. struct json_object *jsobj_cur;
  184. int post_len;
  185. uint32_t obj;
  186. const char *func;
  187. struct blob_buf buf;
  188. bool req_pending;
  189. bool array;
  190. int array_idx;
  191. };
  192. #endif
  193. struct dispatch {
  194. int (*data_send)(struct client *cl, const char *data, int len);
  195. void (*data_done)(struct client *cl);
  196. void (*write_cb)(struct client *cl);
  197. void (*close_fds)(struct client *cl);
  198. void (*free)(struct client *cl);
  199. void *req_data;
  200. void (*req_free)(struct client *cl);
  201. bool data_blocked;
  202. bool no_cache;
  203. union {
  204. struct {
  205. struct blob_attr **hdr;
  206. int fd;
  207. } file;
  208. struct dispatch_proc proc;
  209. #ifdef HAVE_UBUS
  210. struct dispatch_ubus ubus;
  211. #endif
  212. };
  213. };
  214. struct client {
  215. struct list_head list;
  216. int refcount;
  217. int id;
  218. struct ustream *us;
  219. struct ustream_fd sfd;
  220. #ifdef HAVE_TLS
  221. struct ustream_ssl ssl;
  222. #endif
  223. struct uloop_timeout timeout;
  224. int requests;
  225. enum client_state state;
  226. bool tls;
  227. int http_code;
  228. struct http_request request;
  229. struct uh_addr srv_addr, peer_addr;
  230. struct blob_buf hdr;
  231. struct blob_buf hdr_response;
  232. struct dispatch dispatch;
  233. };
  234. extern char uh_buf[4096];
  235. extern int n_clients;
  236. extern struct config conf;
  237. extern const char * const http_versions[];
  238. extern const char * const http_methods[];
  239. extern struct dispatch_handler cgi_dispatch;
  240. void uh_index_add(const char *filename);
  241. bool uh_accept_client(int fd, bool tls);
  242. void uh_unblock_listeners(void);
  243. void uh_setup_listeners(void);
  244. int uh_socket_bind(const char *host, const char *port, bool tls);
  245. int uh_first_tls_port(int family);
  246. bool uh_use_chunked(struct client *cl);
  247. void uh_chunk_write(struct client *cl, const void *data, int len);
  248. void uh_chunk_vprintf(struct client *cl, const char *format, va_list arg);
  249. void __printf(2, 3)
  250. uh_chunk_printf(struct client *cl, const char *format, ...);
  251. void uh_chunk_eof(struct client *cl);
  252. void uh_request_done(struct client *cl);
  253. void uh_http_header(struct client *cl, int code, const char *summary);
  254. void __printf(4, 5)
  255. uh_client_error(struct client *cl, int code, const char *summary, const char *fmt, ...);
  256. void uh_handle_request(struct client *cl);
  257. void client_poll_post_data(struct client *cl);
  258. void uh_client_read_cb(struct client *cl);
  259. void uh_client_notify_state(struct client *cl);
  260. void uh_auth_add(const char *path, const char *user, const char *pass);
  261. bool uh_auth_check(struct client *cl, const char *path, const char *auth,
  262. char **uptr, char **pptr);
  263. void uh_close_listen_fds(void);
  264. void uh_close_fds(void);
  265. void uh_interpreter_add(const char *ext, const char *path);
  266. void uh_dispatch_add(struct dispatch_handler *d);
  267. void uh_relay_open(struct client *cl, struct relay *r, int fd, int pid);
  268. void uh_relay_close(struct relay *r, int ret);
  269. void uh_relay_free(struct relay *r);
  270. void uh_relay_kill(struct client *cl, struct relay *r);
  271. struct env_var *uh_get_process_vars(struct client *cl, struct path_info *pi);
  272. bool uh_create_process(struct client *cl, struct path_info *pi, char *url,
  273. void (*cb)(struct client *cl, struct path_info *pi, char *url));
  274. int uh_plugin_init(const char *name);
  275. void uh_plugin_post_init(void);
  276. int uh_handler_add(const char *file);
  277. int uh_handler_run(struct client *cl, char **url, bool fallback);
  278. struct path_info *uh_path_lookup(struct client *cl, const char *url);
  279. static inline void uh_client_ref(struct client *cl)
  280. {
  281. cl->refcount++;
  282. }
  283. static inline void uh_client_unref(struct client *cl)
  284. {
  285. if (--cl->refcount)
  286. return;
  287. if (cl->state == CLIENT_STATE_CLEANUP)
  288. ustream_state_change(cl->us);
  289. }
  290. #endif