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