Libevhtp  0.3.7
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
evhtp.c
Go to the documentation of this file.
1 #define _GNU_SOURCE
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include <errno.h>
6 #include <signal.h>
7 #include <strings.h>
8 #include <inttypes.h>
9 #ifndef WIN32
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <netinet/tcp.h>
13 #include <arpa/inet.h>
14 #else
15 #define WINVER 0x0501
16 #include <winsock2.h>
17 #include <ws2tcpip.h>
18 #endif
19 #ifndef NO_SYS_UN
20 #include <sys/un.h>
21 #endif
22 
23 #include <sys/tree.h>
24 
25 #include "evhtp.h"
26 
27 static int _evhtp_request_parser_start(htparser * p);
28 static int _evhtp_request_parser_path(htparser * p, const char * data, size_t len);
29 static int _evhtp_request_parser_args(htparser * p, const char * data, size_t len);
30 static int _evhtp_request_parser_header_key(htparser * p, const char * data, size_t len);
31 static int _evhtp_request_parser_header_val(htparser * p, const char * data, size_t len);
32 static int _evhtp_request_parser_hostname(htparser * p, const char * data, size_t len);
33 static int _evhtp_request_parser_headers(htparser * p);
34 static int _evhtp_request_parser_body(htparser * p, const char * data, size_t len);
35 static int _evhtp_request_parser_fini(htparser * p);
36 static int _evhtp_request_parser_chunk_new(htparser * p);
37 static int _evhtp_request_parser_chunk_fini(htparser * p);
38 static int _evhtp_request_parser_chunks_fini(htparser * p);
39 static int _evhtp_request_parser_headers_start(htparser * p);
40 
41 static void _evhtp_connection_readcb(evbev_t * bev, void * arg);
42 
43 static evhtp_connection_t * _evhtp_connection_new(evhtp_t * htp, evutil_socket_t sock, evhtp_type type);
44 
45 static evhtp_uri_t * _evhtp_uri_new(void);
46 static void _evhtp_uri_free(evhtp_uri_t * uri);
47 
48 static evhtp_path_t * _evhtp_path_new(const char * data, size_t len);
49 static void _evhtp_path_free(evhtp_path_t * path);
50 
51 #define HOOK_AVAIL(var, hook_name) (var->hooks && var->hooks->hook_name)
52 #define HOOK_FUNC(var, hook_name) (var->hooks->hook_name)
53 #define HOOK_ARGS(var, hook_name) var->hooks->hook_name ## _arg
54 
55 #define HOOK_REQUEST_RUN(request, hook_name, ...) do { \
56  if (HOOK_AVAIL(request, hook_name)) { \
57  return HOOK_FUNC(request, hook_name) (request, __VA_ARGS__, \
58  HOOK_ARGS(request, hook_name)); \
59  } \
60  \
61  if (HOOK_AVAIL(evhtp_request_get_connection(request), hook_name)) { \
62  return HOOK_FUNC(request->conn, hook_name) (request, __VA_ARGS__, \
63  HOOK_ARGS(request->conn, hook_name)); \
64  } \
65 } while (0)
66 
67 #define HOOK_REQUEST_RUN_NARGS(request, hook_name) do { \
68  if (HOOK_AVAIL(request, hook_name)) { \
69  return HOOK_FUNC(request, hook_name) (request, \
70  HOOK_ARGS(request, hook_name)); \
71  } \
72  \
73  if (HOOK_AVAIL(request->conn, hook_name)) { \
74  return HOOK_FUNC(request->conn, hook_name) (request, \
75  HOOK_ARGS(request->conn, hook_name)); \
76  } \
77 } while (0);
78 
79 #ifndef EVHTP_DISABLE_EVTHR
80 #define _evhtp_lock(h) do { \
81  if (h->lock) { \
82  pthread_mutex_lock(h->lock); \
83  } \
84 } while (0)
85 
86 #define _evhtp_unlock(h) do { \
87  if (h->lock) { \
88  pthread_mutex_unlock(h->lock); \
89  } \
90 } while (0)
91 #else
92 #define _evhtp_lock(h) do {} while (0)
93 #define _evhtp_unlock(h) do {} while (0)
94 #endif
95 
96 #ifndef TAILQ_FOREACH_SAFE
97 #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
98  for ((var) = TAILQ_FIRST((head)); \
99  (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
100  (var) = (tvar))
101 #endif
102 
103 static int scode_tree_initialized = 0;
104 
108 struct status_code {
110  const char * str;
111 
112  RB_ENTRY(status_code) entry;
113 };
114 
115 
116 static int
117 status_code_cmp(void * _a, void * _b) {
118  struct status_code * a = _a;
119  struct status_code * b = _b;
120 
121  return b->code - a->code;
122 }
123 
124 RB_HEAD(status_code_tree, status_code) status_code_head = RB_INITIALIZER(&status_code_head);
125 RB_GENERATE(status_code_tree, status_code, entry, status_code_cmp)
126 
127 #define scode_add(scode, cstr) do { \
128  struct status_code * c = malloc(sizeof(struct status_code)); \
129  \
130  c->code = scode; \
131  c->str = cstr; \
132  \
133  RB_INSERT(status_code_tree, &status_code_head, c); \
134 } while (0)
135 
136 static void
137 status_code_init(void) {
139  /* Already initialized. */
140  return;
141  }
142 
143  /* 100 codes */
144  scode_add(EVHTP_RES_CONTINUE, "Continue");
145  scode_add(EVHTP_RES_SWITCH_PROTO, "Switching Protocols");
146  scode_add(EVHTP_RES_PROCESSING, "Processing");
147  scode_add(EVHTP_RES_URI_TOOLONG, "URI Too Long");
148 
149  /* 200 codes */
150  scode_add(EVHTP_RES_200, "OK");
151  scode_add(EVHTP_RES_CREATED, "Created");
152  scode_add(EVHTP_RES_ACCEPTED, "Accepted");
153  scode_add(EVHTP_RES_NAUTHINFO, "No Auth Info");
154  scode_add(EVHTP_RES_NOCONTENT, "No Content");
155  scode_add(EVHTP_RES_RSTCONTENT, "Reset Content");
156  scode_add(EVHTP_RES_PARTIAL, "Partial Content");
157  scode_add(EVHTP_RES_MSTATUS, "Multi-Status");
158  scode_add(EVHTP_RES_IMUSED, "IM Used");
159 
160  /* 300 codes */
161  scode_add(EVHTP_RES_300, "Redirect");
162  scode_add(EVHTP_RES_MOVEDPERM, "Moved Permanently");
163  scode_add(EVHTP_RES_FOUND, "Found");
164  scode_add(EVHTP_RES_SEEOTHER, "See Other");
165  scode_add(EVHTP_RES_NOTMOD, "Not Modified");
166  scode_add(EVHTP_RES_USEPROXY, "Use Proxy");
167  scode_add(EVHTP_RES_SWITCHPROXY, "Switch Proxy");
168  scode_add(EVHTP_RES_TMPREDIR, "Temporary Redirect");
169 
170  /* 400 codes */
171  scode_add(EVHTP_RES_400, "Bad Request");
172  scode_add(EVHTP_RES_UNAUTH, "Unauthorized");
173  scode_add(EVHTP_RES_PAYREQ, "Payment Required");
174  scode_add(EVHTP_RES_FORBIDDEN, "Forbidden");
175  scode_add(EVHTP_RES_NOTFOUND, "Not Found");
176  scode_add(EVHTP_RES_METHNALLOWED, "Not Allowed");
177  scode_add(EVHTP_RES_NACCEPTABLE, "Not Acceptable");
178  scode_add(EVHTP_RES_PROXYAUTHREQ, "Proxy Authentication Required");
179  scode_add(EVHTP_RES_TIMEOUT, "Request Timeout");
180  scode_add(EVHTP_RES_CONFLICT, "Conflict");
181  scode_add(EVHTP_RES_GONE, "Gone");
182  scode_add(EVHTP_RES_LENREQ, "Length Required");
183  scode_add(EVHTP_RES_PRECONDFAIL, "Precondition Failed");
184  scode_add(EVHTP_RES_ENTOOLARGE, "Entity Too Large");
185  scode_add(EVHTP_RES_URITOOLARGE, "Request-URI Too Long");
186  scode_add(EVHTP_RES_UNSUPPORTED, "Unsupported Media Type");
187  scode_add(EVHTP_RES_RANGENOTSC, "Requested Range Not Satisfiable");
188  scode_add(EVHTP_RES_EXPECTFAIL, "Expectation Failed");
189  scode_add(EVHTP_RES_IAMATEAPOT, "I'm a teapot");
190 
191  /* 500 codes */
192  scode_add(EVHTP_RES_SERVERR, "Internal Server Error");
193  scode_add(EVHTP_RES_NOTIMPL, "Not Implemented");
194  scode_add(EVHTP_RES_BADGATEWAY, "Bad Gateway");
195  scode_add(EVHTP_RES_SERVUNAVAIL, "Service Unavailable");
196  scode_add(EVHTP_RES_GWTIMEOUT, "Gateway Timeout");
197  scode_add(EVHTP_RES_VERNSUPPORT, "HTTP Version Not Supported");
198  scode_add(EVHTP_RES_BWEXEED, "Bandwidth Limit Exceeded");
199 
201 } /* status_code_init */
202 
203 const char *
205  struct status_code c;
206  struct status_code * found;
207 
208  c.code = code;
209 
210  if (!(found = RB_FIND(status_code_tree, &status_code_head, &c))) {
211  return "DERP";
212  }
213 
214  return found->str;
215 }
216 
220 static htparse_hooks request_psets = {
221  .on_msg_begin = _evhtp_request_parser_start,
222  .method = NULL,
223  .scheme = NULL,
224  .host = NULL,
225  .port = NULL,
228  .uri = NULL,
229  .on_hdrs_begin = _evhtp_request_parser_headers_start,
232  .hostname = _evhtp_request_parser_hostname,
233  .on_hdrs_complete = _evhtp_request_parser_headers,
234  .on_new_chunk = _evhtp_request_parser_chunk_new,
235  .on_chunk_complete = _evhtp_request_parser_chunk_fini,
236  .on_chunks_complete = _evhtp_request_parser_chunks_fini,
238  .on_msg_complete = _evhtp_request_parser_fini
239 };
240 
241 #ifndef EVHTP_DISABLE_SSL
242 static int session_id_context = 1;
243 #ifndef EVHTP_DISABLE_EVTHR
244 static int ssl_num_locks;
246 static int ssl_locks_initialized = 0;
247 #endif
248 #endif
249 
250 /*
251  * COMPAT FUNCTIONS
252  */
253 
254 #ifdef NO_STRNLEN
255 static size_t
256 strnlen(const char * s, size_t maxlen) {
257  const char * e;
258  size_t n;
259 
260  for (e = s, n = 0; *e && n < maxlen; e++, n++) {
261  ;
262  }
263 
264  return n;
265 }
266 
267 #endif
268 
269 #ifdef NO_STRNDUP
270 static char *
271 strndup(const char * s, size_t n) {
272  size_t len = strnlen(s, n);
273  char * ret;
274 
275  if (len < n) {
276  return strdup(s);
277  }
278 
279  ret = malloc(n + 1);
280  ret[n] = '\0';
281 
282  strncpy(ret, s, n);
283  return ret;
284 }
285 
286 #endif
287 
288 /*
289  * PRIVATE FUNCTIONS
290  */
291 
299 static inline unsigned int
300 _evhtp_quick_hash(const char * str) {
301  unsigned int h = 0;
302 
303  for (; *str; str++) {
304  h = 31 * h + *str;
305  }
306 
307  return h;
308 }
309 
318 static inline int
319 _evhtp_is_http_10(const char major, const char minor) {
320  if (major >= 1 && minor <= 0) {
321  return 1;
322  }
323 
324  return 0;
325 }
326 
335 static inline int
336 _evhtp_is_http_11(const char major, const char minor) {
337  if (major >= 1 && minor >= 1) {
338  return 1;
339  }
340 
341  return 0;
342 }
343 
353 static inline evhtp_proto
354 _evhtp_protocol(const char major, const char minor) {
355  if (_evhtp_is_http_10(major, minor)) {
356  return EVHTP_PROTO_10;
357  }
358 
359  if (_evhtp_is_http_11(major, minor)) {
360  return EVHTP_PROTO_11;
361  }
362 
363  return EVHTP_PROTO_INVALID;
364 }
365 
374 static inline evhtp_res
376  HOOK_REQUEST_RUN(request, on_path, path);
377 
378  return EVHTP_RES_OK;
379 }
380 
391 static inline evhtp_res
393  HOOK_REQUEST_RUN(request, on_header, header);
394 
395  return EVHTP_RES_OK;
396 }
397 
407 static inline evhtp_res
409  HOOK_REQUEST_RUN(request, on_headers, headers);
410 
411  return EVHTP_RES_OK;
412 }
413 
424 static inline evhtp_res
426  HOOK_REQUEST_RUN(request, on_read, buf);
427 
428  return EVHTP_RES_OK;
429 }
430 
439 static inline evhtp_res
441  HOOK_REQUEST_RUN_NARGS(request, on_request_fini);
442 
443  return EVHTP_RES_OK;
444 }
445 
446 static inline evhtp_res
447 _evhtp_chunk_new_hook(evhtp_request_t * request, uint64_t len) {
448  HOOK_REQUEST_RUN(request, on_new_chunk, len);
449 
450  return EVHTP_RES_OK;
451 }
452 
453 static inline evhtp_res
455  HOOK_REQUEST_RUN_NARGS(request, on_chunk_fini);
456 
457  return EVHTP_RES_OK;
458 }
459 
460 static inline evhtp_res
462  HOOK_REQUEST_RUN_NARGS(request, on_chunks_fini);
463 
464  return EVHTP_RES_OK;
465 }
466 
467 static inline evhtp_res
469  HOOK_REQUEST_RUN_NARGS(request, on_headers_start);
470 
471  return EVHTP_RES_OK;
472 }
473 
482 static inline evhtp_res
484  if (connection->hooks && connection->hooks->on_connection_fini) {
485  return (connection->hooks->on_connection_fini)(connection,
486  connection->hooks->on_connection_fini_arg);
487  }
488 
489  return EVHTP_RES_OK;
490 }
491 
492 static inline evhtp_res
493 _evhtp_hostname_hook(evhtp_request_t * r, const char * hostname) {
494  HOOK_REQUEST_RUN(r, on_hostname, hostname);
495 
496  return EVHTP_RES_OK;
497 }
498 
499 static inline evhtp_res
501  if (connection->hooks && connection->hooks->on_write) {
502  return (connection->hooks->on_write)(connection,
503  connection->hooks->on_write_arg);
504  }
505 
506  return EVHTP_RES_OK;
507 }
508 
519 static int
520 _evhtp_glob_match(const char * pattern, const char * string) {
521  size_t pat_len;
522  size_t str_len;
523 
524  if (!pattern || !string) {
525  return 0;
526  }
527 
528  pat_len = strlen(pattern);
529  str_len = strlen(string);
530 
531  while (pat_len) {
532  if (pattern[0] == '*') {
533  while (pattern[1] == '*') {
534  pattern++;
535  pat_len--;
536  }
537 
538  if (pat_len == 1) {
539  return 1;
540  }
541 
542  while (str_len) {
543  if (_evhtp_glob_match(pattern + 1, string)) {
544  return 1;
545  }
546 
547  string++;
548  str_len--;
549  }
550 
551  return 0;
552  } else {
553  if (pattern[0] != string[0]) {
554  return 0;
555  }
556 
557  string++;
558  str_len--;
559  }
560 
561  pattern++;
562  pat_len--;
563 
564  if (str_len == 0) {
565  while (*pattern == '*') {
566  pattern++;
567  pat_len--;
568  }
569  break;
570  }
571  }
572 
573  if (pat_len == 0 && str_len == 0) {
574  return 1;
575  }
576 
577  return 0;
578 } /* _evhtp_glob_match */
579 
580 static evhtp_callback_t *
582  const char * path,
583  unsigned int * start_offset,
584  unsigned int * end_offset) {
585 #ifndef EVHTP_DISABLE_REGEX
586  regmatch_t pmatch[28];
587 #endif
588  evhtp_callback_t * callback;
589 
590  if (cbs == NULL) {
591  return NULL;
592  }
593 
594  TAILQ_FOREACH(callback, cbs, next) {
595  switch (callback->type) {
597  if (strcmp(callback->val.path, path) == 0) {
598  *start_offset = 0;
599  *end_offset = (unsigned int)strlen(path);
600  return callback;
601  }
602  break;
603 #ifndef EVHTP_DISABLE_REGEX
605  if (regexec(callback->val.regex, path, callback->val.regex->re_nsub + 1, pmatch, 0) == 0) {
606  *start_offset = pmatch[callback->val.regex->re_nsub].rm_so;
607  *end_offset = pmatch[callback->val.regex->re_nsub].rm_eo;
608 
609  return callback;
610  }
611 
612  break;
613 #endif
615  if (_evhtp_glob_match(callback->val.glob, path) == 1) {
616  *start_offset = 0;
617  *end_offset = (unsigned int)strlen(path);
618  return callback;
619  }
620  default:
621  break;
622  } /* switch */
623  }
624 
625  return NULL;
626 } /* _evhtp_callback_find */
627 
635 static evhtp_request_t *
637  evhtp_request_t * req;
638 
639  if (!(req = calloc(sizeof(evhtp_request_t), 1))) {
640  return NULL;
641  }
642 
643  req->conn = c;
644  req->htp = c ? c->htp : NULL;
645  req->status = EVHTP_RES_OK;
646  req->buffer_in = evbuffer_new();
647  req->buffer_out = evbuffer_new();
648  req->headers_in = malloc(sizeof(evhtp_headers_t));
649  req->headers_out = malloc(sizeof(evhtp_headers_t));
650 
651  TAILQ_INIT(req->headers_in);
652  TAILQ_INIT(req->headers_out);
653 
654  return req;
655 }
656 
662 static void
664  if (request == NULL) {
665  return;
666  }
667 
668  _evhtp_request_fini_hook(request);
669  _evhtp_uri_free(request->uri);
670 
671  evhtp_headers_free(request->headers_in);
673 
674 
675  if (request->buffer_in) {
676  evbuffer_free(request->buffer_in);
677  }
678 
679  if (request->buffer_out) {
680  evbuffer_free(request->buffer_out);
681  }
682 
683  free(request->hooks);
684  free(request);
685 }
686 
692 static evhtp_uri_t *
694  evhtp_uri_t * uri;
695 
696  if (!(uri = calloc(sizeof(evhtp_uri_t), 1))) {
697  return NULL;
698  }
699 
700  return uri;
701 }
702 
708 static void
710  if (uri == NULL) {
711  return;
712  }
713 
714  evhtp_query_free(uri->query);
715  _evhtp_path_free(uri->path);
716 
717  free(uri->fragment);
718  free(uri->query_raw);
719  free(uri);
720 }
721 
737 static evhtp_path_t *
738 _evhtp_path_new(const char * data, size_t len) {
739  evhtp_path_t * req_path;
740  const char * data_end = (const char *)(data + len);
741  char * path = NULL;
742  char * file = NULL;
743 
744  if (!(req_path = calloc(sizeof(evhtp_path_t), 1))) {
745  return NULL;
746  }
747 
748  if (len == 0) {
749  /*
750  * odd situation here, no preceding "/", so just assume the path is "/"
751  */
752  path = strdup("/");
753  } else if (*data != '/') {
754  /* request like GET stupid HTTP/1.0, treat stupid as the file, and
755  * assume the path is "/"
756  */
757  path = strdup("/");
758  file = strndup(data, len);
759  } else {
760  if (data[len - 1] != '/') {
761  /*
762  * the last character in data is assumed to be a file, not the end of path
763  * loop through the input data backwards until we find a "/"
764  */
765  size_t i;
766 
767  for (i = (len - 1); i != 0; i--) {
768  if (data[i] == '/') {
769  /*
770  * we have found a "/" representing the start of the file,
771  * and the end of the path
772  */
773  size_t path_len;
774  size_t file_len;
775 
776  path_len = (size_t)(&data[i] - data) + 1;
777  file_len = (size_t)(data_end - &data[i + 1]);
778 
779  /* check for overflow */
780  if ((const char *)(data + path_len) > data_end) {
781  fprintf(stderr, "PATH Corrupted.. (path_len > len)\n");
782  free(req_path);
783  return NULL;
784  }
785 
786  /* check for overflow */
787  if ((const char *)(&data[i + 1] + file_len) > data_end) {
788  fprintf(stderr, "FILE Corrupted.. (file_len > len)\n");
789  free(req_path);
790  return NULL;
791  }
792 
793  path = strndup(data, path_len);
794  file = strndup(&data[i + 1], file_len);
795 
796  break;
797  }
798  }
799 
800  if (i == 0 && data[i] == '/' && !file && !path) {
801  /* drops here if the request is something like GET /foo */
802  path = strdup("/");
803 
804  if (len > 1) {
805  file = strndup((const char *)(data + 1), len);
806  }
807  }
808  } else {
809  /* the last character is a "/", thus the request is just a path */
810  path = strndup(data, len);
811  }
812  }
813 
814  if (len != 0) {
815  req_path->full = strndup(data, len);
816  }
817 
818  req_path->path = path;
819  req_path->file = file;
820 
821  return req_path;
822 } /* _evhtp_path_new */
823 
824 static void
826  if (path == NULL) {
827  return;
828  }
829 
830  free(path->full);
831 
832  free(path->path);
833  free(path->file);
834  free(path->match_start);
835  free(path->match_end);
836 
837  free(path);
838 }
839 
840 static int
842  evhtp_connection_t * c = htparser_get_userdata(p);
843 
844  if (c->type == evhtp_type_client) {
845  return 0;
846  }
847 
848  if (c->paused == 1) {
849  return -1;
850  }
851 
852  if (c->request) {
853  if (c->request->finished == 1) {
855  } else {
856  return -1;
857  }
858  }
859 
860  if (!(c->request = _evhtp_request_new(c))) {
861  return -1;
862  }
863 
864  return 0;
865 }
866 
867 static int
868 _evhtp_request_parser_args(htparser * p, const char * data, size_t len) {
869  evhtp_connection_t * c = htparser_get_userdata(p);
870  evhtp_uri_t * uri = c->request->uri;
871 
872  if (c->type == evhtp_type_client) {
873  /* as a client, technically we should never get here, but just in case
874  * we return a 0 to the parser to continue.
875  */
876  return 0;
877  }
878 
879  if (!(uri->query = evhtp_parse_query(data, len))) {
881  return -1;
882  }
883 
884  uri->query_raw = calloc(len + 1, 1);
885  memcpy(uri->query_raw, data, len);
886 
887  return 0;
888 }
889 
890 static int
892  evhtp_connection_t * c = htparser_get_userdata(p);
893 
895  return -1;
896  }
897 
898  return 0;
899 }
900 
901 static int
902 _evhtp_request_parser_header_key(htparser * p, const char * data, size_t len) {
903  evhtp_connection_t * c = htparser_get_userdata(p);
904  char * key_s; /* = strndup(data, len); */
905  evhtp_header_t * hdr;
906 
907  key_s = malloc(len + 1);
908  key_s[len] = '\0';
909  memcpy(key_s, data, len);
910 
911  if ((hdr = evhtp_header_key_add(c->request->headers_in, key_s, 0)) == NULL) {
913  return -1;
914  }
915 
916  hdr->k_heaped = 1;
917  return 0;
918 }
919 
920 static int
921 _evhtp_request_parser_header_val(htparser * p, const char * data, size_t len) {
922  evhtp_connection_t * c = htparser_get_userdata(p);
923  char * val_s;
924  evhtp_header_t * header;
925 
926  val_s = malloc(len + 1);
927  val_s[len] = '\0';
928  memcpy(val_s, data, len);
929 
930  if ((header = evhtp_header_val_add(c->request->headers_in, val_s, 0)) == NULL) {
931  free(val_s);
933  return -1;
934  }
935 
936  header->v_heaped = 1;
937 
938  if ((c->request->status = _evhtp_header_hook(c->request, header)) != EVHTP_RES_OK) {
939  return -1;
940  }
941 
942  return 0;
943 }
944 
945 static inline evhtp_t *
946 _evhtp_request_find_vhost(evhtp_t * evhtp, const char * name) {
947  evhtp_t * evhtp_vhost;
948  evhtp_alias_t * evhtp_alias;
949 
950  TAILQ_FOREACH(evhtp_vhost, &evhtp->vhosts, next_vhost) {
951  if (evhtp_vhost->server_name == NULL) {
952  continue;
953  }
954 
955  if (_evhtp_glob_match(evhtp_vhost->server_name, name) == 1) {
956  return evhtp_vhost;
957  }
958 
959  TAILQ_FOREACH(evhtp_alias, &evhtp_vhost->aliases, next) {
960  if (evhtp_alias->alias == NULL) {
961  continue;
962  }
963 
964  if (_evhtp_glob_match(evhtp_alias->alias, name) == 1) {
965  return evhtp_vhost;
966  }
967  }
968  }
969 
970  return NULL;
971 }
972 
973 static inline int
975  evhtp_t * evhtp;
976  evhtp_connection_t * conn;
977  evhtp_uri_t * uri;
978  evhtp_path_t * path;
979  evhtp_hooks_t * hooks;
980  evhtp_callback_t * callback;
982  void * cbarg;
983 
984  if (request == NULL) {
985  return -1;
986  }
987 
988  if ((evhtp = request->htp) == NULL) {
989  return -1;
990  }
991 
992  if ((conn = request->conn) == NULL) {
993  return -1;
994  }
995 
996  if ((uri = request->uri) == NULL) {
997  return -1;
998  }
999 
1000  if ((path = uri->path) == NULL) {
1001  return -1;
1002  }
1003 
1004  hooks = NULL;
1005  callback = NULL;
1006  cb = NULL;
1007  cbarg = NULL;
1008 
1009  if ((callback = _evhtp_callback_find(evhtp->callbacks, path->full,
1010  &path->matched_soff, &path->matched_eoff))) {
1011  /* matched a callback using both path and file (/a/b/c/d) */
1012  cb = callback->cb;
1013  cbarg = callback->cbarg;
1014  hooks = callback->hooks;
1015  } else if ((callback = _evhtp_callback_find(evhtp->callbacks, path->path,
1016  &path->matched_soff, &path->matched_eoff))) {
1017  /* matched a callback using *just* the path (/a/b/c/) */
1018  cb = callback->cb;
1019  cbarg = callback->cbarg;
1020  hooks = callback->hooks;
1021  } else {
1022  /* no callbacks found for either case, use defaults */
1023  cb = evhtp->defaults.cb;
1024  cbarg = evhtp->defaults.cbarg;
1025 
1026  path->matched_soff = 0;
1027  path->matched_eoff = (unsigned int)strlen(path->full);
1028  }
1029 
1030  if (path->match_start == NULL) {
1031  path->match_start = calloc(strlen(path->full) + 1, 1);
1032  }
1033 
1034  if (path->match_end == NULL) {
1035  path->match_end = calloc(strlen(path->full) + 1, 1);
1036  }
1037 
1038  if (path->matched_eoff - path->matched_soff) {
1039  memcpy(path->match_start, (void *)(path->full + path->matched_soff),
1040  path->matched_eoff - path->matched_soff);
1041  } else {
1042  memcpy(path->match_start, (void *)(path->full + path->matched_soff),
1043  strlen((const char *)(path->full + path->matched_soff)));
1044  }
1045 
1046  memcpy(path->match_end,
1047  (void *)(path->full + path->matched_eoff),
1048  strlen(path->full) - path->matched_eoff);
1049 
1050  if (hooks != NULL) {
1051  if (request->hooks == NULL) {
1052  request->hooks = malloc(sizeof(evhtp_hooks_t));
1053  }
1054 
1055  memcpy(request->hooks, hooks, sizeof(evhtp_hooks_t));
1056  }
1057 
1058  request->cb = cb;
1059  request->cbarg = cbarg;
1060 
1061  return 0;
1062 } /* _evhtp_request_set_callbacks */
1063 
1064 static int
1065 _evhtp_request_parser_hostname(htparser * p, const char * data, size_t len) {
1066  evhtp_connection_t * c = htparser_get_userdata(p);
1067  evhtp_t * evhtp;
1068  evhtp_t * evhtp_vhost;
1069 
1070 #ifndef EVHTP_DISABLE_SSL
1071  if (c->vhost_via_sni == 1 && c->ssl != NULL) {
1072  /* use the SNI set hostname instead of the header hostname */
1073  const char * host;
1074 
1075  host = SSL_get_servername(c->ssl, TLSEXT_NAMETYPE_host_name);
1076 
1077  if ((c->request->status = _evhtp_hostname_hook(c->request, host)) != EVHTP_RES_OK) {
1078  return -1;
1079  }
1080 
1081  return 0;
1082  }
1083 #endif
1084 
1085  evhtp = c->htp;
1086 
1087  /* since this is called after _evhtp_request_parser_path(), which already
1088  * setup callbacks for the URI, we must now attempt to find callbacks which
1089  * are specific to this host.
1090  */
1091  _evhtp_lock(evhtp);
1092  {
1093  if ((evhtp_vhost = _evhtp_request_find_vhost(evhtp, data))) {
1094  _evhtp_lock(evhtp_vhost);
1095  {
1096  /* if we found a match for the host, we must set the htp
1097  * variables for both the connection and the request.
1098  */
1099  c->htp = evhtp_vhost;
1100  c->request->htp = evhtp_vhost;
1101 
1103  }
1104  _evhtp_unlock(evhtp_vhost);
1105  }
1106  }
1107  _evhtp_unlock(evhtp);
1108 
1109  if ((c->request->status = _evhtp_hostname_hook(c->request, data)) != EVHTP_RES_OK) {
1110  return -1;
1111  }
1112 
1113  return 0;
1114 } /* _evhtp_request_parser_hostname */
1115 
1116 static int
1117 _evhtp_request_parser_path(htparser * p, const char * data, size_t len) {
1118  evhtp_connection_t * c = htparser_get_userdata(p);
1119  evhtp_uri_t * uri;
1120  evhtp_path_t * path;
1121 
1122  if (!(uri = _evhtp_uri_new())) {
1124  return -1;
1125  }
1126 
1127  if (!(path = _evhtp_path_new(data, len))) {
1128  _evhtp_uri_free(uri);
1130  return -1;
1131  }
1132 
1133  uri->path = path;
1134  uri->scheme = htparser_get_scheme(p);
1135 
1136  c->request->method = htparser_get_method(p);
1137  c->request->uri = uri;
1138 
1139  _evhtp_lock(c->htp);
1140  {
1142  }
1143  _evhtp_unlock(c->htp);
1144 
1145  if ((c->request->status = _evhtp_path_hook(c->request, path)) != EVHTP_RES_OK) {
1146  return -1;
1147  }
1148 
1149  return 0;
1150 } /* _evhtp_request_parser_path */
1151 
1152 static int
1154  evhtp_connection_t * c = htparser_get_userdata(p);
1155 
1156  /* XXX proto should be set with htparsers on_hdrs_begin hook */
1157  c->request->keepalive = htparser_should_keep_alive(p);
1158  c->request->proto = _evhtp_protocol(htparser_get_major(p), htparser_get_minor(p));
1160 
1161  if (c->request->status != EVHTP_RES_OK) {
1162  return -1;
1163  }
1164 
1165  if (c->type == evhtp_type_server && c->htp->disable_100_cont == 0) {
1166  /* only send a 100 continue response if it hasn't been disabled via
1167  * evhtp_disable_100_continue.
1168  */
1169  if (!evhtp_header_find(c->request->headers_in, "Expect")) {
1170  return 0;
1171  }
1172 
1173  evbuffer_add_printf(bufferevent_get_output(c->bev),
1174  "HTTP/%d.%d 100 Continue\r\n\r\n",
1175  htparser_get_major(p),
1176  htparser_get_minor(p));
1177  }
1178 
1179  return 0;
1180 }
1181 
1182 static int
1183 _evhtp_request_parser_body(htparser * p, const char * data, size_t len) {
1184  evhtp_connection_t * c = htparser_get_userdata(p);
1185  evbuf_t * buf;
1186  int res = 0;
1187 
1188  if (c->max_body_size > 0 && c->body_bytes_read + len >= c->max_body_size) {
1189  c->error = 1;
1191 
1192  return -1;
1193  }
1194 
1195  buf = evbuffer_new();
1196  evbuffer_add(buf, data, len);
1197 
1198  if ((c->request->status = _evhtp_body_hook(c->request, buf)) != EVHTP_RES_OK) {
1199  res = -1;
1200  }
1201 
1202  if (evbuffer_get_length(buf)) {
1203  evbuffer_add_buffer(c->request->buffer_in, buf);
1204  }
1205 
1206  evbuffer_free(buf);
1207 
1208  c->body_bytes_read += len;
1209 
1210  return res;
1211 }
1212 
1213 static int
1215  evhtp_connection_t * c = htparser_get_userdata(p);
1216 
1218  htparser_get_content_length(p))) != EVHTP_RES_OK) {
1219  return -1;
1220  }
1221 
1222  return 0;
1223 }
1224 
1225 static int
1227  evhtp_connection_t * c = htparser_get_userdata(p);
1228 
1230  return -1;
1231  }
1232 
1233  return 0;
1234 }
1235 
1236 static int
1238  evhtp_connection_t * c = htparser_get_userdata(p);
1239 
1241  return -1;
1242  }
1243 
1244  return 0;
1245 }
1246 
1257 static int
1259  const char * content_type;
1260 
1261  if (req == NULL) {
1262  return 0;
1263  }
1264 
1265  if (req->uri == NULL || req->uri->query != NULL) {
1266  return 0;
1267  }
1268 
1269  if (evhtp_request_content_len(req) == 0) {
1270  return 0;
1271  }
1272 
1273  if (evhtp_request_content_len(req) !=
1274  evbuffer_get_length(req->buffer_in)) {
1275  return 0;
1276  }
1277 
1278  content_type = evhtp_kv_find(req->headers_in, "content-type");
1279 
1280  if (content_type == NULL) {
1281  return 0;
1282  }
1283 
1284  if (strncasecmp(content_type, "application/x-www-form-urlencoded", 33)) {
1285  return 0;
1286  }
1287 
1288  return 1;
1289 }
1290 
1291 static int
1293  evhtp_connection_t * c = htparser_get_userdata(p);
1294 
1295  /* check to see if we should use the body of the request as the query
1296  * arguments.
1297  */
1298  if (_evhtp_should_parse_query_body(c->request) == 1) {
1299  const char * body;
1300  size_t body_len;
1301  evhtp_uri_t * uri;
1302  evbuf_t * buf_in;
1303 
1304  uri = c->request->uri;
1305  buf_in = c->request->buffer_in;
1306 
1307  body_len = evbuffer_get_length(buf_in);
1308  body = (const char *)evbuffer_pullup(buf_in, body_len);
1309 
1310  uri->query_raw = calloc(body_len + 1, 1);
1311  memcpy(uri->query_raw, body, body_len);
1312 
1313  uri->query = evhtp_parse_query(body, body_len);
1314  }
1315 
1316 
1317  /*
1318  * XXX c->request should never be NULL, but we have found some path of
1319  * execution where this actually happens. We will check for now, but the bug
1320  * path needs to be tracked down.
1321  *
1322  */
1323  if (c->request && c->request->cb) {
1324  (c->request->cb)(c->request, c->request->cbarg);
1325  }
1326 
1327  return 0;
1328 }
1329 
1330 static int
1331 _evhtp_create_headers(evhtp_header_t * header, void * arg) {
1332  evbuf_t * buf = arg;
1333 
1334  evbuffer_add(buf, header->key, header->klen);
1335  evbuffer_add(buf, ": ", 2);
1336  evbuffer_add(buf, header->val, header->vlen);
1337  evbuffer_add(buf, "\r\n", 2);
1338  return 0;
1339 }
1340 
1341 static evbuf_t *
1343  evbuf_t * buf = evbuffer_new();
1344  const char * content_type = evhtp_header_find(request->headers_out, "Content-Type");
1345 
1346  if (htparser_get_multipart(request->conn->parser) == 1) {
1347  goto check_proto;
1348  }
1349 
1350  if (evbuffer_get_length(request->buffer_out) && request->chunked == 0) {
1351  /* add extra headers (like content-length/type) if not already present */
1352 
1353  if (!evhtp_header_find(request->headers_out, "Content-Length")) {
1354  char lstr[128];
1355  int sres;
1356 #ifndef WIN32
1357  sres = snprintf(lstr, sizeof(lstr), "%zu",
1358 #else
1359  sres = snprintf(lstr, sizeof(lstr), "%u",
1360 #endif
1361  evbuffer_get_length(request->buffer_out));
1362 
1363  if (sres >= sizeof(lstr) || sres < 0) {
1364  /* overflow condition, this should never happen, but if it does,
1365  * well lets just shut the connection down */
1366  request->keepalive = 0;
1367  goto check_proto;
1368  }
1369 
1371  evhtp_header_new("Content-Length", lstr, 0, 1));
1372  }
1373 
1374  if (!content_type) {
1376  evhtp_header_new("Content-Type", "text/plain", 0, 0));
1377  }
1378  } else {
1379  if (!evhtp_header_find(request->headers_out, "Content-Length")) {
1380  const char * chunked = evhtp_header_find(request->headers_out,
1381  "transfer-encoding");
1382 
1383  if (!chunked || !strstr(chunked, "chunked")) {
1385  evhtp_header_new("Content-Length", "0", 0, 0));
1386  }
1387  }
1388  }
1389 
1390 check_proto:
1391  /* add the proper keep-alive type headers based on http version */
1392  switch (request->proto) {
1393  case EVHTP_PROTO_11:
1394  if (request->keepalive == 0) {
1395  /* protocol is HTTP/1.1 but client wanted to close */
1397  evhtp_header_new("Connection", "close", 0, 0));
1398  }
1399  break;
1400  case EVHTP_PROTO_10:
1401  if (request->keepalive == 1) {
1402  /* protocol is HTTP/1.0 and clients wants to keep established */
1404  evhtp_header_new("Connection", "keep-alive", 0, 0));
1405  }
1406  break;
1407  default:
1408  /* this sometimes happens when a response is made but paused before
1409  * the method has been parsed */
1410  htparser_set_major(request->conn->parser, 1);
1411  htparser_set_minor(request->conn->parser, 0);
1412  break;
1413  } /* switch */
1414 
1415  /* add the status line */
1416  evbuffer_add_printf(buf, "HTTP/%d.%d %d %s\r\n",
1417  htparser_get_major(request->conn->parser),
1418  htparser_get_minor(request->conn->parser),
1419  code, status_code_to_str(code));
1420 
1422  evbuffer_add(buf, "\r\n", 2);
1423 
1424  if (evbuffer_get_length(request->buffer_out)) {
1425  evbuffer_add_buffer(buf, request->buffer_out);
1426  }
1427 
1428  return buf;
1429 } /* _evhtp_create_reply */
1430 
1431 static void
1432 _evhtp_connection_resumecb(int fd, short events, void * arg) {
1433  evhtp_connection_t * c = arg;
1434 
1435  c->paused = 0;
1436 
1437  bufferevent_enable(c->bev, EV_READ);
1438 
1439  if (c->request) {
1440  c->request->status = EVHTP_RES_OK;
1441  }
1442 
1443  if (c->free_connection == 1) {
1445  return;
1446  }
1447 
1449 }
1450 
1451 static void
1452 _evhtp_connection_readcb(evbev_t * bev, void * arg) {
1453  evhtp_connection_t * c = arg;
1454  void * buf;
1455  size_t nread;
1456  size_t avail;
1457 
1458  avail = evbuffer_get_length(bufferevent_get_input(bev));
1459 
1460  if (c->request) {
1461  c->request->status = EVHTP_RES_OK;
1462  }
1463 
1464  if (c->paused == 1) {
1465  return;
1466  }
1467 
1468  buf = evbuffer_pullup(bufferevent_get_input(bev), avail);
1469 
1470  bufferevent_disable(bev, EV_WRITE);
1471  {
1472  nread = htparser_run(c->parser, &request_psets, (const char *) buf, avail);
1473  }
1474  bufferevent_enable(bev, EV_WRITE);
1475 
1476  if (c->owner != 1) {
1477  /*
1478  * someone has taken the ownership of this connection, we still need to
1479  * drain the input buffer that had been read up to this point.
1480  */
1481  evbuffer_drain(bufferevent_get_input(bev), nread);
1483  return;
1484  }
1485 
1486  if (c->request) {
1487  switch (c->request->status) {
1489  if (c->request->hooks && c->request->hooks->on_error) {
1490  (*c->request->hooks->on_error)(c->request, -1, c->request->hooks->on_error_arg);
1491  }
1493  return;
1494  default:
1495  break;
1496  }
1497  }
1498 
1499  evbuffer_drain(bufferevent_get_input(bev), nread);
1500 
1501  if (c->request && c->request->status == EVHTP_RES_PAUSE) {
1503  } else if (avail != nread) {
1505  }
1506 } /* _evhtp_connection_readcb */
1507 
1508 static void
1510  evhtp_connection_t * c = arg;
1511 
1512  if (c->request == NULL) {
1513  return;
1514  }
1515 
1517 
1518  if (c->paused == 1) {
1519  return;
1520  }
1521 
1522  if (c->request->finished == 0 || evbuffer_get_length(bufferevent_get_output(bev))) {
1523  return;
1524  }
1525 
1526  /*
1527  * if there is a set maximum number of keepalive requests configured, check
1528  * to make sure we are not over it. If we have gone over the max we set the
1529  * keepalive bit to 0, thus closing the connection.
1530  */
1531  if (c->htp->max_keepalive_requests) {
1532  if (++c->num_requests >= c->htp->max_keepalive_requests) {
1533  c->request->keepalive = 0;
1534  }
1535  }
1536 
1537  if (c->request->keepalive) {
1539 
1540  c->request = NULL;
1541  c->body_bytes_read = 0;
1542 
1543  if (c->htp->parent && c->vhost_via_sni == 0) {
1544  /* this request was servied by a virtual host evhtp_t structure
1545  * which was *NOT* found via SSL SNI lookup. In this case we want to
1546  * reset our connections evhtp_t structure back to the original so
1547  * that subsequent requests can have a different Host: header.
1548  */
1549  evhtp_t * orig_htp = c->htp->parent;
1550 
1551  c->htp = orig_htp;
1552  }
1553 
1554  htparser_init(c->parser, htp_type_request);
1555 
1556 
1557  htparser_set_userdata(c->parser, c);
1558  return;
1559  } else {
1561  return;
1562  }
1563 
1564  return;
1565 } /* _evhtp_connection_writecb */
1566 
1567 static void
1568 _evhtp_connection_eventcb(evbev_t * bev, short events, void * arg) {
1569  evhtp_connection_t * c = arg;
1570 
1571  if ((events & BEV_EVENT_CONNECTED)) {
1572  if (c->type == evhtp_type_client) {
1573  bufferevent_setcb(bev,
1577  }
1578 
1579  return;
1580  }
1581 
1582  if (c->ssl && !(events & BEV_EVENT_EOF)) {
1583  /* XXX need to do better error handling for SSL specific errors */
1584  c->error = 1;
1585 
1586  if (c->request) {
1587  c->request->error = 1;
1588  }
1589  }
1590 
1591  if (events == (BEV_EVENT_EOF | BEV_EVENT_READING)) {
1592  if (errno == EAGAIN) {
1593  /* libevent will sometimes recv again when it's not actually ready,
1594  * this results in a 0 return value, and errno will be set to EAGAIN
1595  * (try again). This does not mean there is a hard socket error, but
1596  * simply needs to be read again.
1597  *
1598  * but libevent will disable the read side of the bufferevent
1599  * anyway, so we must re-enable it.
1600  */
1601  bufferevent_enable(bev, EV_READ);
1602  errno = 0;
1603  return;
1604  }
1605  }
1606 
1607  c->error = 1;
1608 
1609  if (c->request && c->request->hooks && c->request->hooks->on_error) {
1610  (*c->request->hooks->on_error)(c->request, events,
1611  c->request->hooks->on_error_arg);
1612  }
1613 
1614 
1615  if (c->paused == 1) {
1616  c->free_connection = 1;
1617  } else {
1619  }
1620 } /* _evhtp_connection_eventcb */
1621 
1622 static int
1624  void * args;
1625  evhtp_res res;
1626 
1627  if (htp->defaults.pre_accept == NULL) {
1628  return 0;
1629  }
1630 
1631  args = htp->defaults.pre_accept_cbarg;
1632  res = htp->defaults.pre_accept(conn, args);
1633 
1634  if (res != EVHTP_RES_OK) {
1635  return -1;
1636  }
1637 
1638  return 0;
1639 }
1640 
1641 static int
1642 _evhtp_connection_accept(evbase_t * evbase, evhtp_connection_t * connection) {
1643  struct timeval * c_recv_timeo;
1644  struct timeval * c_send_timeo;
1645 
1646  if (_evhtp_run_pre_accept(connection->htp, connection) < 0) {
1647  evutil_closesocket(connection->sock);
1648  return -1;
1649  }
1650 
1651 #ifndef EVHTP_DISABLE_SSL
1652  if (connection->htp->ssl_ctx != NULL) {
1653  connection->ssl = SSL_new(connection->htp->ssl_ctx);
1654  connection->bev = bufferevent_openssl_socket_new(evbase,
1655  connection->sock,
1656  connection->ssl,
1657  BUFFEREVENT_SSL_ACCEPTING,
1658  connection->htp->bev_flags);
1659  SSL_set_app_data(connection->ssl, connection);
1660  goto end;
1661  }
1662 #endif
1663 
1664  connection->bev = bufferevent_socket_new(evbase,
1665  connection->sock,
1666  connection->htp->bev_flags);
1667 #ifndef EVHTP_DISABLE_SSL
1668 end:
1669 #endif
1670 
1671  if (connection->recv_timeo.tv_sec || connection->recv_timeo.tv_usec) {
1672  c_recv_timeo = &connection->recv_timeo;
1673  } else if (connection->htp->recv_timeo.tv_sec ||
1674  connection->htp->recv_timeo.tv_usec) {
1675  c_recv_timeo = &connection->htp->recv_timeo;
1676  } else {
1677  c_recv_timeo = NULL;
1678  }
1679 
1680  if (connection->send_timeo.tv_sec || connection->send_timeo.tv_usec) {
1681  c_send_timeo = &connection->send_timeo;
1682  } else if (connection->htp->send_timeo.tv_sec ||
1683  connection->htp->send_timeo.tv_usec) {
1684  c_send_timeo = &connection->htp->send_timeo;
1685  } else {
1686  c_send_timeo = NULL;
1687  }
1688 
1689  evhtp_connection_set_timeouts(connection, c_recv_timeo, c_send_timeo);
1690 
1691  connection->resume_ev = event_new(evbase, -1, EV_READ | EV_PERSIST,
1692  _evhtp_connection_resumecb, connection);
1693  event_add(connection->resume_ev, NULL);
1694 
1695  bufferevent_enable(connection->bev, EV_READ);
1696  bufferevent_setcb(connection->bev,
1699  _evhtp_connection_eventcb, connection);
1700 
1701  return 0;
1702 } /* _evhtp_connection_accept */
1703 
1704 static void
1707 }
1708 
1709 static evhtp_connection_t *
1710 _evhtp_connection_new(evhtp_t * htp, evutil_socket_t sock, evhtp_type type) {
1711  evhtp_connection_t * connection;
1712  htp_type ptype;
1713 
1714  switch (type) {
1715  case evhtp_type_client:
1716  ptype = htp_type_response;
1717  break;
1718  case evhtp_type_server:
1719  ptype = htp_type_request;
1720  break;
1721  default:
1722  return NULL;
1723  }
1724 
1725  if (!(connection = calloc(sizeof(evhtp_connection_t), 1))) {
1726  return NULL;
1727  }
1728 
1729  connection->error = 0;
1730  connection->owner = 1;
1731  connection->paused = 0;
1732  connection->sock = sock;
1733  connection->htp = htp;
1734  connection->type = type;
1735  connection->parser = htparser_new();
1736 
1737  htparser_init(connection->parser, ptype);
1738  htparser_set_userdata(connection->parser, connection);
1739 
1740  TAILQ_INIT(&connection->pending);
1741 
1742  return connection;
1743 }
1744 
1745 #ifdef LIBEVENT_HAS_SHUTDOWN
1746 #ifndef EVHTP_DISABLE_SSL
1747 static void
1748 _evhtp_shutdown_eventcb(evbev_t * bev, short events, void * arg) {
1749 }
1750 
1751 #endif
1752 #endif
1753 
1754 static int
1756  void * args;
1757  evhtp_res res;
1758 
1759  if (htp->defaults.post_accept == NULL) {
1760  return 0;
1761  }
1762 
1763  args = htp->defaults.post_accept_cbarg;
1764  res = htp->defaults.post_accept(connection, args);
1765 
1766  if (res != EVHTP_RES_OK) {
1767  return -1;
1768  }
1769 
1770  return 0;
1771 }
1772 
1773 #ifndef EVHTP_DISABLE_EVTHR
1774 static void
1775 _evhtp_run_in_thread(evthr_t * thr, void * arg, void * shared) {
1776  evhtp_t * htp = shared;
1777  evhtp_connection_t * connection = arg;
1778 
1779  connection->evbase = evthr_get_base(thr);
1780  connection->thread = thr;
1781 
1782  evthr_inc_backlog(connection->thread);
1783 
1784  if (_evhtp_connection_accept(connection->evbase, connection) < 0) {
1785  evhtp_connection_free(connection);
1786  return;
1787  }
1788 
1789  if (_evhtp_run_post_accept(htp, connection) < 0) {
1790  evhtp_connection_free(connection);
1791  return;
1792  }
1793 }
1794 
1795 #endif
1796 
1797 static void
1798 _evhtp_accept_cb(evserv_t * serv, int fd, struct sockaddr * s, int sl, void * arg) {
1799  evhtp_t * htp = arg;
1800  evhtp_connection_t * connection;
1801 
1802  if (!(connection = _evhtp_connection_new(htp, fd, evhtp_type_server))) {
1803  return;
1804  }
1805 
1806  connection->saddr = malloc(sl);
1807  memcpy(connection->saddr, s, sl);
1808 
1809 #ifndef EVHTP_DISABLE_EVTHR
1810  if (htp->thr_pool != NULL) {
1811  if (evthr_pool_defer(htp->thr_pool, _evhtp_run_in_thread, connection) != EVTHR_RES_OK) {
1812  evutil_closesocket(connection->sock);
1813  evhtp_connection_free(connection);
1814  return;
1815  }
1816  return;
1817  }
1818 #endif
1819  connection->evbase = htp->evbase;
1820 
1821  if (_evhtp_connection_accept(htp->evbase, connection) < 0) {
1822  evhtp_connection_free(connection);
1823  return;
1824  }
1825 
1826  if (_evhtp_run_post_accept(htp, connection) < 0) {
1827  evhtp_connection_free(connection);
1828  return;
1829  }
1830 }
1831 
1832 #ifndef EVHTP_DISABLE_SSL
1833 #ifndef EVHTP_DISABLE_EVTHR
1834 static unsigned long
1836 #ifndef WIN32
1837  return (unsigned long)pthread_self();
1838 #else
1839  return (unsigned long)(pthread_self().p);
1840 #endif
1841 }
1842 
1843 static void
1844 _evhtp_ssl_thread_lock(int mode, int type, const char * file, int line) {
1845  if (type < ssl_num_locks) {
1846  if (mode & CRYPTO_LOCK) {
1847  pthread_mutex_lock(&(ssl_locks[type]));
1848  } else {
1849  pthread_mutex_unlock(&(ssl_locks[type]));
1850  }
1851  }
1852 }
1853 
1854 #endif
1855 static void
1857  evhtp_t * htp;
1858  evhtp_ssl_cfg_t * cfg;
1859  unsigned char * sid;
1860  unsigned int slen;
1861 
1862  htp = (evhtp_t *)SSL_CTX_get_app_data(ctx);
1863  cfg = htp->ssl_cfg;
1864 
1865  sid = sess->session_id;
1866  slen = sess->session_id_length;
1867 
1868  if (cfg->scache_del) {
1869  (cfg->scache_del)(htp, sid, slen);
1870  }
1871 }
1872 
1873 static int
1875  evhtp_connection_t * connection;
1876  evhtp_ssl_cfg_t * cfg;
1877  unsigned char * sid;
1878  int slen;
1879 
1880  connection = (evhtp_connection_t *)SSL_get_app_data(ssl);
1881  cfg = connection->htp->ssl_cfg;
1882 
1883  sid = sess->session_id;
1884  slen = sess->session_id_length;
1885 
1886  SSL_set_timeout(sess, cfg->scache_timeout);
1887 
1888  if (cfg->scache_add) {
1889  return (cfg->scache_add)(connection, sid, slen, sess);
1890  }
1891 
1892  return 0;
1893 }
1894 
1895 static evhtp_ssl_sess_t *
1896 _evhtp_ssl_get_scache_ent(evhtp_ssl_t * ssl, unsigned char * sid, int sid_len, int * copy) {
1897  evhtp_connection_t * connection;
1898  evhtp_ssl_cfg_t * cfg;
1899  evhtp_ssl_sess_t * sess;
1900 
1901  connection = (evhtp_connection_t * )SSL_get_app_data(ssl);
1902  cfg = connection->htp->ssl_cfg;
1903  sess = NULL;
1904 
1905  if (cfg->scache_get) {
1906  sess = (cfg->scache_get)(connection, sid, sid_len);
1907  }
1908 
1909  *copy = 0;
1910 
1911  return sess;
1912 }
1913 
1914 static int
1915 _evhtp_ssl_servername(evhtp_ssl_t * ssl, int * unused, void * arg) {
1916  const char * sname;
1917  evhtp_connection_t * connection;
1918  evhtp_t * evhtp;
1919  evhtp_t * evhtp_vhost;
1920 
1921  if (!(sname = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
1922  return SSL_TLSEXT_ERR_NOACK;
1923  }
1924 
1925  if (!(connection = SSL_get_app_data(ssl))) {
1926  return SSL_TLSEXT_ERR_NOACK;
1927  }
1928 
1929  if (!(evhtp = connection->htp)) {
1930  return SSL_TLSEXT_ERR_NOACK;
1931  }
1932 
1933  if ((evhtp_vhost = _evhtp_request_find_vhost(evhtp, sname))) {
1934  connection->htp = evhtp_vhost;
1935  connection->vhost_via_sni = 1;
1936 
1937  SSL_set_SSL_CTX(ssl, evhtp_vhost->ssl_ctx);
1938  SSL_set_options(ssl, SSL_CTX_get_options(ssl->ctx));
1939 
1940  if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) ||
1941  (SSL_num_renegotiations(ssl) == 0)) {
1942  SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ssl->ctx),
1943  SSL_CTX_get_verify_callback(ssl->ctx));
1944  }
1945 
1946  return SSL_TLSEXT_ERR_OK;
1947  }
1948 
1949  return SSL_TLSEXT_ERR_NOACK;
1950 } /* _evhtp_ssl_servername */
1951 
1952 #endif
1953 
1954 /*
1955  * PUBLIC FUNCTIONS
1956  */
1957 
1958 htp_method
1960  return htparser_get_method(r->conn->parser);
1961 }
1962 
1968 void
1970  if ((bufferevent_get_enabled(c->bev) & EV_READ)) {
1971  c->paused = 1;
1972  bufferevent_disable(c->bev, EV_READ);
1973  }
1974 }
1975 
1981 void
1983  if (!(bufferevent_get_enabled(c->bev) & EV_READ)) {
1984  /* bufferevent_enable(c->bev, EV_READ); */
1985  c->paused = 0;
1986  event_active(c->resume_ev, EV_WRITE, 1);
1987  }
1988 }
1989 
1997 void
1999  request->status = EVHTP_RES_PAUSE;
2000  evhtp_connection_pause(request->conn);
2001 }
2002 
2010 void
2012  evhtp_connection_resume(request->conn);
2013 }
2014 
2016 evhtp_header_key_add(evhtp_headers_t * headers, const char * key, char kalloc) {
2017  evhtp_header_t * header;
2018 
2019  if (!(header = evhtp_header_new(key, NULL, kalloc, 0))) {
2020  return NULL;
2021  }
2022 
2023  evhtp_headers_add_header(headers, header);
2024 
2025  return header;
2026 }
2027 
2029 evhtp_header_val_add(evhtp_headers_t * headers, const char * val, char valloc) {
2030  evhtp_header_t * header;
2031 
2032  if (!headers || !val) {
2033  return NULL;
2034  }
2035 
2036  if (!(header = TAILQ_LAST(headers, evhtp_headers_s))) {
2037  return NULL;
2038  }
2039 
2040  if (header->val != NULL) {
2041  return NULL;
2042  }
2043 
2044  header->vlen = strlen(val);
2045 
2046  if (valloc == 1) {
2047  header->val = malloc(header->vlen + 1);
2048  header->val[header->vlen] = '\0';
2049  memcpy(header->val, val, header->vlen);
2050  } else {
2051  header->val = (char *)val;
2052  }
2053 
2054  header->v_heaped = valloc;
2055 
2056  return header;
2057 }
2058 
2059 evhtp_kvs_t *
2061  evhtp_kvs_t * kvs = malloc(sizeof(evhtp_kvs_t));
2062 
2063  TAILQ_INIT(kvs);
2064  return kvs;
2065 }
2066 
2067 evhtp_kv_t *
2068 evhtp_kv_new(const char * key, const char * val, char kalloc, char valloc) {
2069  evhtp_kv_t * kv;
2070 
2071  if (!(kv = malloc(sizeof(evhtp_kv_t)))) {
2072  return NULL;
2073  }
2074 
2075  kv->k_heaped = kalloc;
2076  kv->v_heaped = valloc;
2077  kv->klen = 0;
2078  kv->vlen = 0;
2079  kv->key = NULL;
2080  kv->val = NULL;
2081 
2082  if (key != NULL) {
2083  kv->klen = strlen(key);
2084 
2085  if (kalloc == 1) {
2086  char * s = malloc(kv->klen + 1);
2087 
2088  s[kv->klen] = '\0';
2089  memcpy(s, key, kv->klen);
2090  kv->key = s;
2091  } else {
2092  kv->key = (char *)key;
2093  }
2094  }
2095 
2096  if (val != NULL) {
2097  kv->vlen = strlen(val);
2098 
2099  if (valloc == 1) {
2100  char * s = malloc(kv->vlen + 1);
2101 
2102  s[kv->vlen] = '\0';
2103  memcpy(s, val, kv->vlen);
2104  kv->val = s;
2105  } else {
2106  kv->val = (char *)val;
2107  }
2108  }
2109 
2110  return kv;
2111 } /* evhtp_kv_new */
2112 
2113 void
2115  if (kv == NULL) {
2116  return;
2117  }
2118 
2119  if (kv->k_heaped) {
2120  free(kv->key);
2121  }
2122 
2123  if (kv->v_heaped) {
2124  free(kv->val);
2125  }
2126 
2127  free(kv);
2128 }
2129 
2130 void
2132  if (kvs == NULL || kv == NULL) {
2133  return;
2134  }
2135 
2136  TAILQ_REMOVE(kvs, kv, next);
2137 
2138  evhtp_kv_free(kv);
2139 }
2140 
2141 void
2143  evhtp_kv_t * kv;
2144  evhtp_kv_t * save;
2145 
2146  if (kvs == NULL) {
2147  return;
2148  }
2149 
2150  for (kv = TAILQ_FIRST(kvs); kv != NULL; kv = save) {
2151  save = TAILQ_NEXT(kv, next);
2152 
2153  TAILQ_REMOVE(kvs, kv, next);
2154 
2155  evhtp_kv_free(kv);
2156  }
2157 
2158  free(kvs);
2159 }
2160 
2161 int
2163  evhtp_kv_t * kv;
2164 
2165  if (kvs == NULL || cb == NULL) {
2166  return -1;
2167  }
2168 
2169  TAILQ_FOREACH(kv, kvs, next) {
2170  int res;
2171 
2172  if ((res = cb(kv, arg))) {
2173  return res;
2174  }
2175  }
2176 
2177  return 0;
2178 }
2179 
2180 const char *
2181 evhtp_kv_find(evhtp_kvs_t * kvs, const char * key) {
2182  evhtp_kv_t * kv;
2183 
2184  if (kvs == NULL || key == NULL) {
2185  return NULL;
2186  }
2187 
2188  TAILQ_FOREACH(kv, kvs, next) {
2189  if (strcasecmp(kv->key, key) == 0) {
2190  return kv->val;
2191  }
2192  }
2193 
2194  return NULL;
2195 }
2196 
2197 evhtp_kv_t *
2198 evhtp_kvs_find_kv(evhtp_kvs_t * kvs, const char * key) {
2199  evhtp_kv_t * kv;
2200 
2201  if (kvs == NULL || key == NULL) {
2202  return NULL;
2203  }
2204 
2205  TAILQ_FOREACH(kv, kvs, next) {
2206  if (strcasecmp(kv->key, key) == 0) {
2207  return kv;
2208  }
2209  }
2210 
2211  return NULL;
2212 }
2213 
2214 void
2216  if (kvs == NULL || kv == NULL) {
2217  return;
2218  }
2219 
2220  TAILQ_INSERT_TAIL(kvs, kv, next);
2221 }
2222 
2223 void
2225  if (dst == NULL || src == NULL) {
2226  return;
2227  }
2228 
2229  evhtp_kv_t * kv;
2230 
2231  TAILQ_FOREACH(kv, src, next) {
2232  evhtp_kvs_add_kv(dst, evhtp_kv_new(kv->key, kv->val, kv->k_heaped, kv->v_heaped));
2233  }
2234 }
2235 
2236 typedef enum {
2248 
2249 static inline int
2250 evhtp_is_hex_query_char(unsigned char ch) {
2251  switch (ch) {
2252  case 'a': case 'A':
2253  case 'b': case 'B':
2254  case 'c': case 'C':
2255  case 'd': case 'D':
2256  case 'e': case 'E':
2257  case 'f': case 'F':
2258  case '0':
2259  case '1':
2260  case '2':
2261  case '3':
2262  case '4':
2263  case '5':
2264  case '6':
2265  case '7':
2266  case '8':
2267  case '9':
2268  return 1;
2269  default:
2270  return 0;
2271  } /* switch */
2272 }
2273 
2278 };
2279 
2280 int
2281 evhtp_unescape_string(unsigned char ** out, unsigned char * str, size_t str_len) {
2282  unsigned char * optr;
2283  unsigned char * sptr;
2284  unsigned char d;
2285  unsigned char ch;
2286  unsigned char c;
2287  size_t i;
2288  enum unscape_state state;
2289 
2290  if (out == NULL || *out == NULL) {
2291  return -1;
2292  }
2293 
2294  state = unscape_state_start;
2295  optr = *out;
2296  sptr = str;
2297  d = 0;
2298 
2299  for (i = 0; i < str_len; i++) {
2300  ch = *sptr++;
2301 
2302  switch (state) {
2303  case unscape_state_start:
2304  if (ch == '%') {
2305  state = unscape_state_hex1;
2306  break;
2307  }
2308 
2309  *optr++ = ch;
2310 
2311  break;
2312  case unscape_state_hex1:
2313  if (ch >= '0' && ch <= '9') {
2314  d = (unsigned char)(ch - '0');
2315  state = unscape_state_hex2;
2316  break;
2317  }
2318 
2319  c = (unsigned char)(ch | 0x20);
2320 
2321  if (c >= 'a' && c <= 'f') {
2322  d = (unsigned char)(c - 'a' + 10);
2323  state = unscape_state_hex2;
2324  break;
2325  }
2326 
2327  state = unscape_state_start;
2328  *optr++ = ch;
2329  break;
2330  case unscape_state_hex2:
2331  state = unscape_state_start;
2332 
2333  if (ch >= '0' && ch <= '9') {
2334  ch = (unsigned char)((d << 4) + ch - '0');
2335 
2336  *optr++ = ch;
2337  break;
2338  }
2339 
2340  c = (unsigned char)(ch | 0x20);
2341 
2342  if (c >= 'a' && c <= 'f') {
2343  ch = (unsigned char)((d << 4) + c - 'a' + 10);
2344  *optr++ = ch;
2345  break;
2346  }
2347 
2348  break;
2349  } /* switch */
2350  }
2351 
2352  return 0;
2353 } /* evhtp_unescape_string */
2354 
2355 evhtp_query_t *
2356 evhtp_parse_query(const char * query, size_t len) {
2357  evhtp_query_t * query_args;
2359  char * key_buf = NULL;
2360  char * val_buf = NULL;
2361  int key_idx;
2362  int val_idx;
2363  unsigned char ch;
2364  size_t i;
2365 
2366  query_args = evhtp_query_new();
2367 
2368  if (!(key_buf = malloc(len + 1))) {
2369  return NULL;
2370  }
2371 
2372  if (!(val_buf = malloc(len + 1))) {
2373  free(key_buf);
2374  return NULL;
2375  }
2376 
2377  key_idx = 0;
2378  val_idx = 0;
2379 
2380  for (i = 0; i < len; i++) {
2381  ch = query[i];
2382 
2383  if (key_idx >= len || val_idx >= len) {
2384  goto error;
2385  }
2386 
2387  switch (state) {
2388  case s_query_start:
2389  memset(key_buf, 0, len);
2390  memset(val_buf, 0, len);
2391 
2392  key_idx = 0;
2393  val_idx = 0;
2394 
2395  switch (ch) {
2396  case '?':
2397  state = s_query_key;
2398  break;
2399  case '/':
2400  state = s_query_question_mark;
2401  break;
2402  default:
2403  state = s_query_key;
2404  goto query_key;
2405  }
2406 
2407  break;
2408  case s_query_question_mark:
2409  switch (ch) {
2410  case '?':
2411  state = s_query_key;
2412  break;
2413  case '/':
2414  state = s_query_question_mark;
2415  break;
2416  default:
2417  goto error;
2418  }
2419  break;
2420 query_key:
2421  case s_query_key:
2422  switch (ch) {
2423  case '=':
2424  state = s_query_val;
2425  break;
2426  case '%':
2427  key_buf[key_idx++] = ch;
2428  key_buf[key_idx] = '\0';
2429  state = s_query_key_hex_1;
2430  break;
2431  default:
2432  key_buf[key_idx++] = ch;
2433  key_buf[key_idx] = '\0';
2434  break;
2435  }
2436  break;
2437  case s_query_key_hex_1:
2438  if (!evhtp_is_hex_query_char(ch)) {
2439  /* not hex, so we treat as a normal key */
2440  if ((key_idx + 2) >= len) {
2441  /* we need to insert \%<ch>, but not enough space */
2442  goto error;
2443  }
2444 
2445  key_buf[key_idx - 1] = '%';
2446  key_buf[key_idx++] = ch;
2447  key_buf[key_idx] = '\0';
2448  state = s_query_key;
2449  break;
2450  }
2451 
2452  key_buf[key_idx++] = ch;
2453  key_buf[key_idx] = '\0';
2454 
2455  state = s_query_key_hex_2;
2456  break;
2457  case s_query_key_hex_2:
2458  if (!evhtp_is_hex_query_char(ch)) {
2459  goto error;
2460  }
2461 
2462  key_buf[key_idx++] = ch;
2463  key_buf[key_idx] = '\0';
2464 
2465  state = s_query_key;
2466  break;
2467  case s_query_val:
2468  switch (ch) {
2469  case ';':
2470  case '&':
2471  evhtp_kvs_add_kv(query_args, evhtp_kv_new(key_buf, val_buf, 1, 1));
2472 
2473  memset(key_buf, 0, len);
2474  memset(val_buf, 0, len);
2475 
2476  key_idx = 0;
2477  val_idx = 0;
2478 
2479  state = s_query_key;
2480 
2481  break;
2482  case '%':
2483  val_buf[val_idx++] = ch;
2484  val_buf[val_idx] = '\0';
2485 
2486  state = s_query_val_hex_1;
2487  break;
2488  default:
2489  val_buf[val_idx++] = ch;
2490  val_buf[val_idx] = '\0';
2491 
2492  break;
2493  } /* switch */
2494  break;
2495  case s_query_val_hex_1:
2496  if (!evhtp_is_hex_query_char(ch)) {
2497  /* not really a hex val */
2498  if ((val_idx + 2) >= len) {
2499  /* we need to insert \%<ch>, but not enough space */
2500  goto error;
2501  }
2502 
2503 
2504  val_buf[val_idx - 1] = '%';
2505  val_buf[val_idx++] = ch;
2506  val_buf[val_idx] = '\0';
2507 
2508  state = s_query_val;
2509  break;
2510  }
2511 
2512  val_buf[val_idx++] = ch;
2513  val_buf[val_idx] = '\0';
2514 
2515  state = s_query_val_hex_2;
2516  break;
2517  case s_query_val_hex_2:
2518  if (!evhtp_is_hex_query_char(ch)) {
2519  goto error;
2520  }
2521 
2522  val_buf[val_idx++] = ch;
2523  val_buf[val_idx] = '\0';
2524 
2525  state = s_query_val;
2526  break;
2527  default:
2528  /* bad state */
2529  goto error;
2530  } /* switch */
2531  }
2532 
2533  if (key_idx && val_idx) {
2534  evhtp_kvs_add_kv(query_args, evhtp_kv_new(key_buf, val_buf, 1, 1));
2535  }
2536 
2537  free(key_buf);
2538  free(val_buf);
2539 
2540  return query_args;
2541 error:
2542  free(key_buf);
2543  free(val_buf);
2544 
2545  return NULL;
2546 } /* evhtp_parse_query */
2547 
2548 void
2550  evhtp_connection_t * c;
2551  evbuf_t * reply_buf;
2552 
2553  c = evhtp_request_get_connection(request);
2554 
2555  if (!(reply_buf = _evhtp_create_reply(request, code))) {
2557  return;
2558  }
2559 
2560  bufferevent_write_buffer(c->bev, reply_buf);
2561  evbuffer_free(reply_buf);
2562 }
2563 
2564 void
2566  evhtp_connection_t * c;
2567 
2568  c = request->conn;
2569 
2570  bufferevent_write_buffer(c->bev, buf);
2571 }
2572 
2573 void
2575  request->finished = 1;
2576 
2578  evhtp_request_get_connection(request));
2579 }
2580 
2581 void
2583  evhtp_connection_t * c;
2584  evbuf_t * reply_buf;
2585 
2586  c = evhtp_request_get_connection(request);
2587  request->finished = 1;
2588 
2589  if (!(reply_buf = _evhtp_create_reply(request, code))) {
2590  evhtp_connection_free(request->conn);
2591  return;
2592  }
2593 
2594  bufferevent_write_buffer(evhtp_connection_get_bev(c), reply_buf);
2595  evbuffer_free(reply_buf);
2596 }
2597 
2598 int
2599 evhtp_response_needs_body(const evhtp_res code, const htp_method method) {
2600  return code != EVHTP_RES_NOCONTENT &&
2601  code != EVHTP_RES_NOTMOD &&
2602  (code < 100 || code >= 200) &&
2603  method != htp_method_HEAD;
2604 }
2605 
2606 void
2608  evhtp_header_t * content_len;
2609 
2610  if (evhtp_response_needs_body(code, request->method)) {
2611  content_len = evhtp_headers_find_header(request->headers_out, "Content-Length");
2612 
2613  switch (request->proto) {
2614  case EVHTP_PROTO_11:
2615 
2616  /*
2617  * prefer HTTP/1.1 chunked encoding to closing the connection;
2618  * note RFC 2616 section 4.4 forbids it with Content-Length:
2619  * and it's not necessary then anyway.
2620  */
2621 
2622  evhtp_kv_rm_and_free(request->headers_out, content_len);
2623  request->chunked = 1;
2624  break;
2625  case EVHTP_PROTO_10:
2626  /*
2627  * HTTP/1.0 can be chunked as long as the Content-Length header
2628  * is set to 0
2629  */
2630  evhtp_kv_rm_and_free(request->headers_out, content_len);
2631 
2633  evhtp_header_new("Content-Length", "0", 0, 0));
2634 
2635  request->chunked = 1;
2636  break;
2637  default:
2638  request->chunked = 0;
2639  break;
2640  } /* switch */
2641  } else {
2642  request->chunked = 0;
2643  }
2644 
2645  if (request->chunked == 1) {
2647  evhtp_header_new("Transfer-Encoding", "chunked", 0, 0));
2648 
2649  /*
2650  * if data already exists on the output buffer, we automagically convert
2651  * it to the first chunk.
2652  */
2653  if (evbuffer_get_length(request->buffer_out) > 0) {
2654  char lstr[128];
2655  int sres;
2656 
2657  sres = snprintf(lstr, sizeof(lstr), "%x\r\n",
2658  (unsigned)evbuffer_get_length(request->buffer_out));
2659 
2660  if (sres >= sizeof(lstr) || sres < 0) {
2661  /* overflow condition, shouldn't ever get here, but lets
2662  * terminate the connection asap */
2663  goto end;
2664  }
2665 
2666  evbuffer_prepend(request->buffer_out, lstr, strlen(lstr));
2667  evbuffer_add(request->buffer_out, "\r\n", 2);
2668  }
2669  }
2670 
2671 end:
2672  evhtp_send_reply_start(request, code);
2673 } /* evhtp_send_reply_chunk_start */
2674 
2675 void
2677  evbuf_t * output;
2678 
2679  output = bufferevent_get_output(request->conn->bev);
2680 
2681  if (evbuffer_get_length(buf) == 0) {
2682  return;
2683  }
2684  if (request->chunked) {
2685  evbuffer_add_printf(output, "%x\r\n",
2686  (unsigned)evbuffer_get_length(buf));
2687  }
2688  evhtp_send_reply_body(request, buf);
2689  if (request->chunked) {
2690  evbuffer_add(output, "\r\n", 2);
2691  }
2692  bufferevent_flush(request->conn->bev, EV_WRITE, BEV_FLUSH);
2693 }
2694 
2695 void
2697  if (request->chunked) {
2698  evbuffer_add(bufferevent_get_output(evhtp_request_get_bev(request)),
2699  "0\r\n\r\n", 5);
2700  }
2701 
2702  evhtp_send_reply_end(request);
2703 }
2704 
2705 void
2707  evconnlistener_free(htp->server);
2708  htp->server = NULL;
2709 }
2710 
2711 int
2712 evhtp_bind_sockaddr(evhtp_t * htp, struct sockaddr * sa, size_t sin_len, int backlog) {
2713 #ifndef WIN32
2714  signal(SIGPIPE, SIG_IGN);
2715 #endif
2716 
2717  htp->server = evconnlistener_new_bind(htp->evbase, _evhtp_accept_cb, (void *)htp,
2718  LEV_OPT_THREADSAFE | LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
2719  backlog, sa, sin_len);
2720  if (!htp->server) {
2721  return -1;
2722  }
2723 
2724 #ifdef USE_DEFER_ACCEPT
2725  {
2726  evutil_socket_t sock;
2727  int one = 1;
2728 
2729  sock = evconnlistener_get_fd(htp->server);
2730 
2731  setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &one, (ev_socklen_t)sizeof(one));
2732  setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &one, (ev_socklen_t)sizeof(one));
2733  }
2734 #endif
2735 
2736 #ifndef EVHTP_DISABLE_SSL
2737  if (htp->ssl_ctx != NULL) {
2738  /* if ssl is enabled and we have virtual hosts, set our servername
2739  * callback. We do this here because we want to make sure that this gets
2740  * set after all potential virtualhosts have been set, not just after
2741  * ssl_init.
2742  */
2743  if (TAILQ_FIRST(&htp->vhosts) != NULL) {
2744  SSL_CTX_set_tlsext_servername_callback(htp->ssl_ctx,
2746  }
2747  }
2748 #endif
2749 
2750  return 0;
2751 }
2752 
2753 int
2754 evhtp_bind_socket(evhtp_t * htp, const char * baddr, uint16_t port, int backlog) {
2755  struct sockaddr_in sin;
2756  struct sockaddr_in6 sin6;
2757 
2758 #ifndef NO_SYS_UN
2759  struct sockaddr_un sun;
2760 #endif
2761  struct sockaddr * sa;
2762  size_t sin_len;
2763 
2764  memset(&sin, 0, sizeof(sin));
2765 
2766  if (!strncmp(baddr, "ipv6:", 5)) {
2767  memset(&sin6, 0, sizeof(sin6));
2768 
2769  baddr += 5;
2770  sin_len = sizeof(struct sockaddr_in6);
2771  sin6.sin6_port = htons(port);
2772  sin6.sin6_family = AF_INET6;
2773 
2774  evutil_inet_pton(AF_INET6, baddr, &sin6.sin6_addr);
2775  sa = (struct sockaddr *)&sin6;
2776  } else if (!strncmp(baddr, "unix:", 5)) {
2777 #ifndef NO_SYS_UN
2778  baddr += 5;
2779 
2780  if (strlen(baddr) >= sizeof(sun.sun_path)) {
2781  return -1;
2782  }
2783 
2784  memset(&sun, 0, sizeof(sun));
2785 
2786  sin_len = sizeof(struct sockaddr_un);
2787  sun.sun_family = AF_UNIX;
2788 
2789  strncpy(sun.sun_path, baddr, strlen(baddr));
2790 
2791  sa = (struct sockaddr *)&sun;
2792 #else
2793  fprintf(stderr, "System does not support AF_UNIX sockets\n");
2794  return -1;
2795 #endif
2796  } else {
2797  if (!strncmp(baddr, "ipv4:", 5)) {
2798  baddr += 5;
2799  }
2800 
2801  sin_len = sizeof(struct sockaddr_in);
2802 
2803  sin.sin_family = AF_INET;
2804  sin.sin_port = htons(port);
2805  sin.sin_addr.s_addr = inet_addr(baddr);
2806 
2807  sa = (struct sockaddr *)&sin;
2808  }
2809 
2810  return evhtp_bind_sockaddr(htp, sa, sin_len, backlog);
2811 } /* evhtp_bind_socket */
2812 
2813 void
2815  evhtp_callback_t * callback;
2816  evhtp_callback_t * tmp;
2817 
2818  if (callbacks == NULL) {
2819  return;
2820  }
2821 
2822  TAILQ_FOREACH_SAFE(callback, callbacks, next, tmp) {
2823  TAILQ_REMOVE(callbacks, callback, next);
2824 
2825  evhtp_callback_free(callback);
2826  }
2827 
2828  free(callbacks);
2829 }
2830 
2832 evhtp_callback_new(const char * path, evhtp_callback_type type, evhtp_callback_cb cb, void * arg) {
2833  evhtp_callback_t * hcb;
2834 
2835  if (!(hcb = calloc(sizeof(evhtp_callback_t), 1))) {
2836  return NULL;
2837  }
2838 
2839  hcb->type = type;
2840  hcb->cb = cb;
2841  hcb->cbarg = arg;
2842 
2843  switch (type) {
2845  hcb->hash = _evhtp_quick_hash(path);
2846  hcb->val.path = strdup(path);
2847  break;
2848 #ifndef EVHTP_DISABLE_REGEX
2850  hcb->val.regex = malloc(sizeof(regex_t));
2851 
2852  if (regcomp(hcb->val.regex, (char *)path, REG_EXTENDED) != 0) {
2853  free(hcb->val.regex);
2854  free(hcb);
2855  return NULL;
2856  }
2857  break;
2858 #endif
2860  hcb->val.glob = strdup(path);
2861  break;
2862  default:
2863  free(hcb);
2864  return NULL;
2865  } /* switch */
2866 
2867  return hcb;
2868 }
2869 
2870 void
2872  if (callback == NULL) {
2873  return;
2874  }
2875 
2876  switch (callback->type) {
2878  free(callback->val.path);
2879  break;
2881  free(callback->val.glob);
2882  break;
2883 #ifndef EVHTP_DISABLE_REGEX
2885  regfree(callback->val.regex);
2886  free(callback->val.regex);
2887  break;
2888 #endif
2889  }
2890 
2891  if (callback->hooks) {
2892  free(callback->hooks);
2893  }
2894 
2895  free(callback);
2896 
2897  return;
2898 }
2899 
2900 int
2902  TAILQ_INSERT_TAIL(cbs, cb, next);
2903 
2904  return 0;
2905 }
2906 
2907 int
2908 evhtp_set_hook(evhtp_hooks_t ** hooks, evhtp_hook_type type, evhtp_hook cb, void * arg) {
2909  if (*hooks == NULL) {
2910  if (!(*hooks = calloc(sizeof(evhtp_hooks_t), 1))) {
2911  return -1;
2912  }
2913  }
2914 
2915  switch (type) {
2917  (*hooks)->on_headers_start = (evhtp_hook_headers_start_cb)cb;
2918  (*hooks)->on_headers_start_arg = arg;
2919  break;
2920  case evhtp_hook_on_header:
2921  (*hooks)->on_header = (evhtp_hook_header_cb)cb;
2922  (*hooks)->on_header_arg = arg;
2923  break;
2924  case evhtp_hook_on_headers:
2925  (*hooks)->on_headers = (evhtp_hook_headers_cb)cb;
2926  (*hooks)->on_headers_arg = arg;
2927  break;
2928  case evhtp_hook_on_path:
2929  (*hooks)->on_path = (evhtp_hook_path_cb)cb;
2930  (*hooks)->on_path_arg = arg;
2931  break;
2932  case evhtp_hook_on_read:
2933  (*hooks)->on_read = (evhtp_hook_read_cb)cb;
2934  (*hooks)->on_read_arg = arg;
2935  break;
2937  (*hooks)->on_request_fini = (evhtp_hook_request_fini_cb)cb;
2938  (*hooks)->on_request_fini_arg = arg;
2939  break;
2941  (*hooks)->on_connection_fini = (evhtp_hook_connection_fini_cb)cb;
2942  (*hooks)->on_connection_fini_arg = arg;
2943  break;
2944  case evhtp_hook_on_error:
2945  (*hooks)->on_error = (evhtp_hook_err_cb)cb;
2946  (*hooks)->on_error_arg = arg;
2947  break;
2949  (*hooks)->on_new_chunk = (evhtp_hook_chunk_new_cb)cb;
2950  (*hooks)->on_new_chunk_arg = arg;
2951  break;
2953  (*hooks)->on_chunk_fini = (evhtp_hook_chunk_fini_cb)cb;
2954  (*hooks)->on_chunk_fini_arg = arg;
2955  break;
2957  (*hooks)->on_chunks_fini = (evhtp_hook_chunks_fini_cb)cb;
2958  (*hooks)->on_chunks_fini_arg = arg;
2959  break;
2961  (*hooks)->on_hostname = (evhtp_hook_hostname_cb)cb;
2962  (*hooks)->on_hostname_arg = arg;
2963  break;
2964  case evhtp_hook_on_write:
2965  (*hooks)->on_write = (evhtp_hook_write_cb)cb;
2966  (*hooks)->on_write_arg = arg;
2967  break;
2968  default:
2969  return -1;
2970  } /* switch */
2971 
2972  return 0;
2973 } /* evhtp_set_hook */
2974 
2975 int
2977  return evhtp_set_hook(hooks, type, NULL, NULL);
2978 }
2979 
2980 int
2982  int res = 0;
2983 
2985  res -= 1;
2986  }
2987 
2988  if (evhtp_unset_hook(hooks, evhtp_hook_on_header)) {
2989  res -= 1;
2990  }
2991 
2993  res -= 1;
2994  }
2995 
2996  if (evhtp_unset_hook(hooks, evhtp_hook_on_path)) {
2997  res -= 1;
2998  }
2999 
3000  if (evhtp_unset_hook(hooks, evhtp_hook_on_read)) {
3001  res -= 1;
3002  }
3003 
3005  res -= 1;
3006  }
3007 
3009  res -= 1;
3010  }
3011 
3012  if (evhtp_unset_hook(hooks, evhtp_hook_on_error)) {
3013  res -= 1;
3014  }
3015 
3017  res -= 1;
3018  }
3019 
3021  res -= 1;
3022  }
3023 
3025  res -= 1;
3026  }
3027 
3029  res -= 1;
3030  }
3031 
3032  if (evhtp_unset_hook(hooks, evhtp_hook_on_write)) {
3033  return -1;
3034  }
3035 
3036  return res;
3037 } /* evhtp_unset_all_hooks */
3038 
3040 evhtp_set_cb(evhtp_t * htp, const char * path, evhtp_callback_cb cb, void * arg) {
3041  evhtp_callback_t * hcb;
3042 
3043  _evhtp_lock(htp);
3044 
3045  if (htp->callbacks == NULL) {
3046  if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), 1))) {
3047  _evhtp_unlock(htp);
3048  return NULL;
3049  }
3050 
3051  TAILQ_INIT(htp->callbacks);
3052  }
3053 
3054  if (!(hcb = evhtp_callback_new(path, evhtp_callback_type_hash, cb, arg))) {
3055  _evhtp_unlock(htp);
3056  return NULL;
3057  }
3058 
3059  if (evhtp_callbacks_add_callback(htp->callbacks, hcb)) {
3060  evhtp_callback_free(hcb);
3061  _evhtp_unlock(htp);
3062  return NULL;
3063  }
3064 
3065  _evhtp_unlock(htp);
3066  return hcb;
3067 }
3068 
3069 #ifndef EVHTP_DISABLE_EVTHR
3070 static void
3071 _evhtp_thread_init(evthr_t * thr, void * arg) {
3072  evhtp_t * htp = (evhtp_t *)arg;
3073 
3074  if (htp->thread_init_cb) {
3075  htp->thread_init_cb(htp, thr, htp->thread_init_cbarg);
3076  }
3077 }
3078 
3079 int
3080 evhtp_use_threads(evhtp_t * htp, evhtp_thread_init_cb init_cb, int nthreads, void * arg) {
3081  htp->thread_init_cb = init_cb;
3082  htp->thread_init_cbarg = arg;
3083 
3084 #ifndef EVHTP_DISABLE_SSL
3086 #endif
3087 
3088  if (!(htp->thr_pool = evthr_pool_new(nthreads, _evhtp_thread_init, htp))) {
3089  return -1;
3090  }
3091 
3092  evthr_pool_start(htp->thr_pool);
3093  return 0;
3094 }
3095 
3096 #endif
3097 
3098 #ifndef EVHTP_DISABLE_EVTHR
3099 int
3101  if (htp == NULL) {
3102  return -1;
3103  }
3104 
3105  if (!(htp->lock = malloc(sizeof(pthread_mutex_t)))) {
3106  return -1;
3107  }
3108 
3109  return pthread_mutex_init(htp->lock, NULL);
3110 }
3111 
3112 #endif
3113 
3114 #ifndef EVHTP_DISABLE_REGEX
3116 evhtp_set_regex_cb(evhtp_t * htp, const char * pattern, evhtp_callback_cb cb, void * arg) {
3117  evhtp_callback_t * hcb;
3118 
3119  _evhtp_lock(htp);
3120 
3121  if (htp->callbacks == NULL) {
3122  if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), 1))) {
3123  _evhtp_unlock(htp);
3124  return NULL;
3125  }
3126 
3127  TAILQ_INIT(htp->callbacks);
3128  }
3129 
3130  if (!(hcb = evhtp_callback_new(pattern, evhtp_callback_type_regex, cb, arg))) {
3131  _evhtp_unlock(htp);
3132  return NULL;
3133  }
3134 
3135  if (evhtp_callbacks_add_callback(htp->callbacks, hcb)) {
3136  evhtp_callback_free(hcb);
3137  _evhtp_unlock(htp);
3138  return NULL;
3139  }
3140 
3141  _evhtp_unlock(htp);
3142  return hcb;
3143 }
3144 
3145 #endif
3146 
3148 evhtp_set_glob_cb(evhtp_t * htp, const char * pattern, evhtp_callback_cb cb, void * arg) {
3149  evhtp_callback_t * hcb;
3150 
3151  _evhtp_lock(htp);
3152 
3153  if (htp->callbacks == NULL) {
3154  if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), 1))) {
3155  _evhtp_unlock(htp);
3156  return NULL;
3157  }
3158 
3159  TAILQ_INIT(htp->callbacks);
3160  }
3161 
3162  if (!(hcb = evhtp_callback_new(pattern, evhtp_callback_type_glob, cb, arg))) {
3163  _evhtp_unlock(htp);
3164  return NULL;
3165  }
3166 
3167  if (evhtp_callbacks_add_callback(htp->callbacks, hcb)) {
3168  evhtp_callback_free(hcb);
3169  _evhtp_unlock(htp);
3170  return NULL;
3171  }
3172 
3173  _evhtp_unlock(htp);
3174  return hcb;
3175 }
3176 
3177 void
3179  htp->defaults.cb = cb;
3180  htp->defaults.cbarg = arg;
3181 }
3182 
3183 void
3185  htp->defaults.pre_accept = cb;
3186  htp->defaults.pre_accept_cbarg = arg;
3187 }
3188 
3189 void
3191  htp->defaults.post_accept = cb;
3192  htp->defaults.post_accept_cbarg = arg;
3193 }
3194 
3195 #ifndef EVHTP_DISABLE_SSL
3196 #ifndef EVHTP_DISABLE_EVTHR
3197 int
3199  int i;
3200 
3201  if (ssl_locks_initialized == 1) {
3202  return 0;
3203  }
3204 
3206 
3207  ssl_num_locks = CRYPTO_num_locks();
3208  ssl_locks = malloc(ssl_num_locks * sizeof(evhtp_mutex_t));
3209 
3210  for (i = 0; i < ssl_num_locks; i++) {
3211  pthread_mutex_init(&(ssl_locks[i]), NULL);
3212  }
3213 
3214  CRYPTO_set_id_callback(_evhtp_ssl_get_thread_id);
3215  CRYPTO_set_locking_callback(_evhtp_ssl_thread_lock);
3216 
3217  return 0;
3218 }
3219 
3220 #endif
3221 
3222 int
3224  long cache_mode;
3225  evhtp_ssl_scache_init init_cb = NULL;
3226  evhtp_ssl_scache_add add_cb = NULL;
3227  evhtp_ssl_scache_get get_cb = NULL;
3228  evhtp_ssl_scache_del del_cb = NULL;
3229 
3230  if (cfg == NULL || htp == NULL || cfg->pemfile == NULL) {
3231  return -1;
3232  }
3233 
3234  SSL_library_init();
3235  SSL_load_error_strings();
3236  RAND_poll();
3237 
3238 #if OPENSSL_VERSION_NUMBER < 0x10000000L
3239  STACK_OF(SSL_COMP) * comp_methods = SSL_COMP_get_compression_methods();
3240  sk_SSL_COMP_zero(comp_methods);
3241 #endif
3242 
3243  htp->ssl_cfg = cfg;
3244  htp->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
3245 
3246 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
3247  SSL_CTX_set_options(htp->ssl_ctx, SSL_MODE_RELEASE_BUFFERS | SSL_OP_NO_COMPRESSION);
3248  /* SSL_CTX_set_options(htp->ssl_ctx, SSL_MODE_AUTO_RETRY); */
3249  SSL_CTX_set_timeout(htp->ssl_ctx, cfg->ssl_ctx_timeout);
3250 #endif
3251 
3252  SSL_CTX_set_options(htp->ssl_ctx, cfg->ssl_opts);
3253 
3254 #ifndef OPENSSL_NO_ECDH
3255  if (cfg->named_curve != NULL) {
3256  EC_KEY * ecdh = NULL;
3257  int nid = 0;
3258 
3259  nid = OBJ_sn2nid(cfg->named_curve);
3260  if (nid == 0) {
3261  fprintf(stderr, "ECDH initialization failed: unknown curve %s\n", cfg->named_curve);
3262  }
3263  ecdh = EC_KEY_new_by_curve_name(nid);
3264  if (ecdh == NULL) {
3265  fprintf(stderr, "ECDH initialization failed for curve %s\n", cfg->named_curve);
3266  }
3267  SSL_CTX_set_tmp_ecdh(htp->ssl_ctx, ecdh);
3268  EC_KEY_free(ecdh);
3269  }
3270 #endif /* OPENSSL_NO_ECDH */
3271 #ifndef OPENSSL_NO_DH
3272  if (cfg->dhparams != NULL) {
3273  FILE *fh;
3274  DH *dh;
3275 
3276  fh = fopen(cfg->dhparams, "r");
3277  if (fh != NULL) {
3278  dh = PEM_read_DHparams(fh, NULL, NULL, NULL);
3279  if (dh != NULL) {
3280  SSL_CTX_set_tmp_dh(htp->ssl_ctx, dh);
3281  DH_free(dh);
3282  } else {
3283  fprintf(stderr, "DH initialization failed: unable to parse file %s\n", cfg->dhparams);
3284  }
3285  fclose(fh);
3286  } else {
3287  fprintf(stderr, "DH initialization failed: unable to open file %s\n", cfg->dhparams);
3288  }
3289  }
3290 #endif /* OPENSSL_NO_DH */
3291 
3292  if (cfg->ciphers != NULL) {
3293  SSL_CTX_set_cipher_list(htp->ssl_ctx, cfg->ciphers);
3294  }
3295 
3296  SSL_CTX_load_verify_locations(htp->ssl_ctx, cfg->cafile, cfg->capath);
3297  X509_STORE_set_flags(SSL_CTX_get_cert_store(htp->ssl_ctx), cfg->store_flags);
3298  SSL_CTX_set_verify(htp->ssl_ctx, cfg->verify_peer, cfg->x509_verify_cb);
3299 
3300  if (cfg->x509_chk_issued_cb != NULL) {
3301  htp->ssl_ctx->cert_store->check_issued = cfg->x509_chk_issued_cb;
3302  }
3303 
3304  if (cfg->verify_depth) {
3305  SSL_CTX_set_verify_depth(htp->ssl_ctx, cfg->verify_depth);
3306  }
3307 
3308  switch (cfg->scache_type) {
3310  cache_mode = SSL_SESS_CACHE_OFF;
3311  break;
3313  cache_mode = SSL_SESS_CACHE_SERVER |
3314  SSL_SESS_CACHE_NO_INTERNAL |
3315  SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
3316 
3317  init_cb = cfg->scache_init;
3318  add_cb = cfg->scache_add;
3319  get_cb = cfg->scache_get;
3320  del_cb = cfg->scache_del;
3321  break;
3323  cache_mode = SSL_SESS_CACHE_SERVER |
3324  SSL_SESS_CACHE_NO_INTERNAL |
3325  SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
3326 
3327 #if 0
3328  init_cb = _evhtp_ssl_builtin_init;
3329  add_cb = _evhtp_ssl_builtin_add;
3330  get_cb = _evhtp_ssl_builtin_get;
3331  del_cb = _evhtp_ssl_builtin_del;
3332 #endif
3333  break;
3335  default:
3336  cache_mode = SSL_SESS_CACHE_SERVER;
3337  break;
3338  } /* switch */
3339 
3340  SSL_CTX_use_certificate_file(htp->ssl_ctx, cfg->pemfile, SSL_FILETYPE_PEM);
3341  SSL_CTX_use_PrivateKey_file(htp->ssl_ctx,
3342  cfg->privfile ? cfg->privfile : cfg->pemfile, SSL_FILETYPE_PEM);
3343 
3344  SSL_CTX_set_session_id_context(htp->ssl_ctx,
3345  (void *)&session_id_context,
3346  sizeof(session_id_context));
3347 
3348  SSL_CTX_set_app_data(htp->ssl_ctx, htp);
3349  SSL_CTX_set_session_cache_mode(htp->ssl_ctx, cache_mode);
3350 
3351  if (cache_mode != SSL_SESS_CACHE_OFF) {
3352  SSL_CTX_sess_set_cache_size(htp->ssl_ctx,
3353  cfg->scache_size ? cfg->scache_size : 1024);
3354 
3357  SSL_CTX_sess_set_new_cb(htp->ssl_ctx, _evhtp_ssl_add_scache_ent);
3358  SSL_CTX_sess_set_get_cb(htp->ssl_ctx, _evhtp_ssl_get_scache_ent);
3359  SSL_CTX_sess_set_remove_cb(htp->ssl_ctx, _evhtp_ssl_delete_scache_ent);
3360 
3361  if (cfg->scache_init) {
3362  cfg->args = (cfg->scache_init)(htp);
3363  }
3364  }
3365  }
3366 
3367  return 0;
3368 } /* evhtp_use_ssl */
3369 
3370 #endif
3371 
3372 evbev_t *
3374  return connection->bev;
3375 }
3376 
3377 evbev_t *
3379  evbev_t * bev = evhtp_connection_get_bev(connection);
3380 
3381  if (connection->hooks) {
3382  evhtp_unset_all_hooks(&connection->hooks);
3383  }
3384 
3385  if (connection->request && connection->request->hooks) {
3386  evhtp_unset_all_hooks(&connection->request->hooks);
3387  }
3388 
3389  evhtp_connection_set_bev(connection, NULL);
3390 
3391  connection->owner = 0;
3392 
3393  bufferevent_disable(bev, EV_READ);
3394  bufferevent_setcb(bev, NULL, NULL, NULL, NULL);
3395 
3396  return bev;
3397 }
3398 
3399 evbev_t *
3401  return evhtp_connection_get_bev(request->conn);
3402 }
3403 
3404 evbev_t *
3407 }
3408 
3409 void
3411  conn->bev = bev;
3412 }
3413 
3414 void
3416  evhtp_connection_set_bev(request->conn, bev);
3417 }
3418 
3421  return request->conn;
3422 }
3423 
3424 void
3426  const struct timeval * rtimeo,
3427  const struct timeval * wtimeo) {
3428  if (!c) {
3429  return;
3430  }
3431 
3432  bufferevent_set_timeouts(c->bev, rtimeo, wtimeo);
3433 }
3434 
3435 void
3437  if (len == 0) {
3438  c->max_body_size = c->htp->max_body_size;
3439  } else {
3440  c->max_body_size = len;
3441  }
3442 }
3443 
3444 void
3447 }
3448 
3449 void
3451  if (connection == NULL) {
3452  return;
3453  }
3454 
3455  _evhtp_request_free(connection->request);
3456  _evhtp_connection_fini_hook(connection);
3457 
3458  free(connection->parser);
3459  free(connection->hooks);
3460  free(connection->saddr);
3461 
3462  if (connection->resume_ev) {
3463  event_free(connection->resume_ev);
3464  }
3465 
3466  if (connection->bev) {
3467 #ifdef LIBEVENT_HAS_SHUTDOWN
3468  bufferevent_shutdown(connection->bev, _evhtp_shutdown_eventcb);
3469 #else
3470 #ifndef EVHTP_DISABLE_SSL
3471  if (connection->ssl != NULL) {
3472  SSL_set_shutdown(connection->ssl, SSL_RECEIVED_SHUTDOWN);
3473  SSL_shutdown(connection->ssl);
3474  }
3475 #endif
3476  bufferevent_free(connection->bev);
3477 #endif
3478  }
3479 
3480 #ifndef EVHTP_DISABLE_EVTHR
3481  if (connection->thread && connection->type == evhtp_type_server) {
3482  evthr_dec_backlog(connection->thread);
3483  }
3484 #endif
3485 
3486  if (connection->ratelimit_cfg != NULL) {
3487  ev_token_bucket_cfg_free(connection->ratelimit_cfg);
3488  }
3489 
3490  free(connection);
3491 } /* evhtp_connection_free */
3492 
3493 void
3495  _evhtp_request_free(request);
3496 }
3497 
3498 void
3499 evhtp_set_timeouts(evhtp_t * htp, const struct timeval * r_timeo, const struct timeval * w_timeo) {
3500  if (r_timeo != NULL) {
3501  htp->recv_timeo = *r_timeo;
3502  }
3503 
3504  if (w_timeo != NULL) {
3505  htp->send_timeo = *w_timeo;
3506  }
3507 }
3508 
3509 void
3511  htp->max_keepalive_requests = num;
3512 }
3513 
3520 void
3521 evhtp_set_bev_flags(evhtp_t * htp, int flags) {
3522  htp->bev_flags = flags;
3523 }
3524 
3525 void
3526 evhtp_set_max_body_size(evhtp_t * htp, uint64_t len) {
3527  htp->max_body_size = len;
3528 }
3529 
3530 void
3532  htp->disable_100_cont = 1;
3533 }
3534 
3535 int
3536 evhtp_add_alias(evhtp_t * evhtp, const char * name) {
3537  evhtp_alias_t * alias;
3538 
3539  if (evhtp == NULL || name == NULL) {
3540  return -1;
3541  }
3542 
3543  if (!(alias = calloc(sizeof(evhtp_alias_t), 1))) {
3544  return -1;
3545  }
3546 
3547  alias->alias = strdup(name);
3548 
3549  TAILQ_INSERT_TAIL(&evhtp->aliases, alias, next);
3550 
3551  return 0;
3552 }
3553 
3570 int
3571 evhtp_add_vhost(evhtp_t * evhtp, const char * name, evhtp_t * vhost) {
3572  if (evhtp == NULL || name == NULL || vhost == NULL) {
3573  return -1;
3574  }
3575 
3576  if (TAILQ_FIRST(&vhost->vhosts) != NULL) {
3577  /* vhosts cannot have secondary vhosts defined */
3578  return -1;
3579  }
3580 
3581  if (!(vhost->server_name = strdup(name))) {
3582  return -1;
3583  }
3584 
3585  /* set the parent of this vhost so when the request has been completely
3586  * serviced, the vhost can be reset to the original evhtp structure.
3587  *
3588  * This allows for a keep-alive connection to make multiple requests with
3589  * different Host: values.
3590  */
3591  vhost->parent = evhtp;
3592 
3593  /* inherit various flags from the parent evhtp structure */
3594  vhost->bev_flags = evhtp->bev_flags;
3595  vhost->max_body_size = evhtp->max_body_size;
3597  vhost->recv_timeo = evhtp->recv_timeo;
3598  vhost->send_timeo = evhtp->send_timeo;
3599 
3600  TAILQ_INSERT_TAIL(&evhtp->vhosts, vhost, next_vhost);
3601 
3602  return 0;
3603 }
3604 
3605 evhtp_t *
3606 evhtp_new(evbase_t * evbase, void * arg) {
3607  evhtp_t * htp;
3608 
3609  if (evbase == NULL) {
3610  return NULL;
3611  }
3612 
3613  if (!(htp = calloc(sizeof(evhtp_t), 1))) {
3614  return NULL;
3615  }
3616 
3617  status_code_init();
3618 
3619  htp->arg = arg;
3620  htp->evbase = evbase;
3621  htp->bev_flags = BEV_OPT_CLOSE_ON_FREE;
3622 
3623  TAILQ_INIT(&htp->vhosts);
3624  TAILQ_INIT(&htp->aliases);
3625 
3626  evhtp_set_gencb(htp, _evhtp_default_request_cb, (void *)htp);
3627 
3628  return htp;
3629 }
3630 
3631 void
3633  evhtp_alias_t * evhtp_alias, * tmp;
3634 
3635  if (evhtp == NULL) {
3636  return;
3637  }
3638 
3639 #ifndef EVHTP_DISABLE_EVTHR
3640  if (evhtp->thr_pool) {
3641  evthr_pool_stop(evhtp->thr_pool);
3642  evthr_pool_free(evhtp->thr_pool);
3643  }
3644 #endif
3645 
3646  if (evhtp->server_name) {
3647  free(evhtp->server_name);
3648  }
3649 
3650  if (evhtp->callbacks) {
3652  }
3653 
3654  TAILQ_FOREACH_SAFE(evhtp_alias, &evhtp->aliases, next, tmp) {
3655  if (evhtp_alias->alias != NULL) {
3656  free(evhtp_alias->alias);
3657  }
3658  TAILQ_REMOVE(&evhtp->aliases, evhtp_alias, next);
3659  free(evhtp_alias);
3660  }
3661 
3662 #ifndef EVHTP_DISABLE_SSL
3663  if (evhtp->ssl_ctx) {
3664  SSL_CTX_free(evhtp->ssl_ctx);
3665  }
3666 #endif
3667 
3668  free(evhtp);
3669 }
3670 
3671 int
3673  size_t read_rate, size_t read_burst,
3674  size_t write_rate, size_t write_burst,
3675  const struct timeval * tick) {
3676  struct ev_token_bucket_cfg * tcfg;
3677 
3678  if (conn == NULL || conn->bev == NULL) {
3679  return -1;
3680  }
3681 
3682  tcfg = ev_token_bucket_cfg_new(read_rate, read_burst,
3683  write_rate, write_burst, tick);
3684 
3685  if (tcfg == NULL) {
3686  return -1;
3687  }
3688 
3689  conn->ratelimit_cfg = tcfg;
3690 
3691  return bufferevent_set_rate_limit(conn->bev, tcfg);
3692 }
3693 
3694 /*****************************************************************
3695 * client request functions *
3696 *****************************************************************/
3697 
3699 evhtp_connection_new(evbase_t * evbase, const char * addr, uint16_t port) {
3700  evhtp_connection_t * conn;
3701  struct sockaddr_in sin;
3702 
3703  if (evbase == NULL) {
3704  return NULL;
3705  }
3706 
3707  if (!(conn = _evhtp_connection_new(NULL, -1, evhtp_type_client))) {
3708  return NULL;
3709  }
3710 
3711  sin.sin_family = AF_INET;
3712  sin.sin_addr.s_addr = inet_addr(addr);
3713  sin.sin_port = htons(port);
3714 
3715  conn->evbase = evbase;
3716  conn->bev = bufferevent_socket_new(evbase, -1, BEV_OPT_CLOSE_ON_FREE);
3717 
3718  bufferevent_enable(conn->bev, EV_READ);
3719 
3720  bufferevent_setcb(conn->bev, NULL, NULL,
3722 
3723  bufferevent_socket_connect(conn->bev,
3724  (struct sockaddr *)&sin, sizeof(sin));
3725 
3726  return conn;
3727 }
3728 
3731  evhtp_request_t * r;
3732 
3733  if (!(r = _evhtp_request_new(NULL))) {
3734  return NULL;
3735  }
3736 
3737  r->cb = cb;
3738  r->cbarg = arg;
3739  r->proto = EVHTP_PROTO_11;
3740 
3741  return r;
3742 }
3743 
3744 int
3746  htp_method meth, const char * uri) {
3747  evbuf_t * obuf;
3748  char * proto;
3749 
3750  obuf = bufferevent_get_output(c->bev);
3751  r->conn = c;
3752  c->request = r;
3753 
3754  switch (r->proto) {
3755  case EVHTP_PROTO_10:
3756  proto = "1.0";
3757  break;
3758  case EVHTP_PROTO_11:
3759  default:
3760  proto = "1.1";
3761  break;
3762  }
3763 
3764  evbuffer_add_printf(obuf, "%s %s HTTP/%s\r\n",
3765  htparser_get_methodstr_m(meth), uri, proto);
3766 
3768  evbuffer_add_reference(obuf, "\r\n", 2, NULL, NULL);
3769 
3770  return 0;
3771 }
3772 
3773 unsigned int
3775  return htparser_get_status(r->conn->parser);
3776 }
3777 
char * key
Definition: evhtp.h:334
evhtp_callbacks_t * callbacks
Definition: evhtp.h:285
#define EVHTP_RES_SWITCHPROXY
Definition: evhtp.h:209
int evhtp_callbacks_add_callback(evhtp_callbacks_t *cbs, evhtp_callback_t *cb)
Adds a evhtp_callback_t to the evhtp_callbacks_t list.
Definition: evhtp.c:2901
#define EVHTP_RES_300
Definition: evhtp.h:202
uint16_t evhtp_res
Definition: evhtp.h:75
#define EVHTP_RES_SERVUNAVAIL
Definition: evhtp.h:237
int evhtp_bind_socket(evhtp_t *htp, const char *baddr, uint16_t port, int backlog)
bind to a socket, optionally with specific protocol support formatting. The addr can be defined as on...
Definition: evhtp.c:2754
static evhtp_res _evhtp_header_hook(evhtp_request_t *request, evhtp_header_t *header)
runs the user-defined on_header hook for a request
Definition: evhtp.c:392
void(* evhtp_ssl_scache_del)(evhtp_t *htp, unsigned char *sid, int sid_len)
Definition: evhtp.h:168
evhtp_res(* evhtp_hook_header_cb)(evhtp_request_t *req, evhtp_header_t *hdr, void *arg)
Definition: evhtp.h:148
static int _evhtp_glob_match(const char *pattern, const char *string)
glob/wildcard type pattern matching.
Definition: evhtp.c:520
evhtp_ssl_scache_init scache_init
Definition: evhtp.h:496
#define _evhtp_lock(h)
Definition: evhtp.c:80
static htparse_hooks request_psets
callback definitions for request processing from libhtparse
Definition: evhtp.c:220
int evhtp_use_threads(evhtp_t *htp, evhtp_thread_init_cb init_cb, int nthreads, void *arg)
Definition: evhtp.c:3080
evhtp_proto proto
Definition: evhtp.h:404
static unsigned int _evhtp_quick_hash(const char *str)
a weak hash function
Definition: evhtp.c:300
int finished
Definition: evhtp.h:408
evhtp_ssl_sess_t *(* evhtp_ssl_scache_get)(evhtp_connection_t *connection, unsigned char *sid, int sid_len)
Definition: evhtp.h:169
long store_flags
Definition: evhtp.h:492
#define evhtp_query_free
Definition: evhtp.h:935
#define EVHTP_RES_METHNALLOWED
Definition: evhtp.h:218
void evhtp_set_max_keepalive_requests(evhtp_t *htp, uint64_t num)
sets a maximum number of requests that a single connection can make.
Definition: evhtp.c:3510
evhtp_ssl_scache_del scache_del
Definition: evhtp.h:499
void * on_connection_fini_arg
Definition: evhtp.h:469
int evhtp_add_vhost(evhtp_t *evhtp, const char *name, evhtp_t *vhost)
add a virtual host.
Definition: evhtp.c:3571
int(* evhtp_ssl_scache_add)(evhtp_connection_t *connection, unsigned char *sid, int sid_len, evhtp_ssl_sess_t *sess)
Definition: evhtp.h:167
#define EVHTP_RES_ENTOOLARGE
Definition: evhtp.h:226
evhtp_ssl_chk_issued_cb x509_chk_issued_cb
Definition: evhtp.h:491
evbase_t * evbase
Definition: evhtp.h:422
evhtp_header_t * evhtp_header_val_add(evhtp_headers_t *headers, const char *val, char valloc)
finds the last header in the headers tailq and adds the value
Definition: evhtp.c:2029
const char * status_code_to_str(evhtp_res code)
Definition: evhtp.c:204
#define EVHTP_RES_SWITCH_PROTO
Definition: evhtp.h:188
struct evbuffer evbuf_t
Definition: evhtp.h:46
void evhtp_send_reply_chunk_end(evhtp_request_t *request)
call when all chunks have been sent and you wish to send the last bits. This will add the last 0CRLFC...
Definition: evhtp.c:2696
void evhtp_disable_100_continue(evhtp_t *htp)
when a client sends an Expect: 100-continue, if this is function is called, evhtp will not send a HTT...
Definition: evhtp.c:3531
evbev_t * evhtp_connection_take_ownership(evhtp_connection_t *connection)
let a user take ownership of the underlying bufferevent and free all other underlying resources...
Definition: evhtp.c:3378
static evhtp_res _evhtp_connection_write_hook(evhtp_connection_t *connection)
Definition: evhtp.c:500
#define EVHTP_RES_IAMATEAPOT
Definition: evhtp.h:231
#define EVHTP_RES_BADGATEWAY
Definition: evhtp.h:236
#define EVHTP_RES_TMPREDIR
Definition: evhtp.h:210
static int _evhtp_request_parser_hostname(htparser *p, const char *data, size_t len)
Definition: evhtp.c:1065
#define EVHTP_RES_PRECONDFAIL
Definition: evhtp.h:225
static evhtp_connection_t * _evhtp_connection_new(evhtp_t *htp, evutil_socket_t sock, evhtp_type type)
Definition: evhtp.c:1710
char * alias
Definition: evhtp.h:252
int evhtp_unset_hook(evhtp_hooks_t **hooks, evhtp_hook_type type)
remove a specific hook from being called.
Definition: evhtp.c:2976
void evhtp_send_reply_chunk(evhtp_request_t *request, evbuf_t *buf)
send a chunk reply.
Definition: evhtp.c:2676
unsigned char * query_raw
Definition: evhtp.h:357
evhtp_ssl_t * ssl
Definition: evhtp.h:425
char * privfile
Definition: evhtp.h:480
evhtp_thread_init_cb thread_init_cb
Definition: evhtp.h:282
int evhtp_use_callback_locks(evhtp_t *htp)
creates a lock around callbacks and hooks, allowing for threaded applications to add/remove/modify ho...
Definition: evhtp.c:3100
evhtp_ssl_verify_cb x509_verify_cb
Definition: evhtp.h:490
#define EVHTP_RES_SERVERR
Definition: evhtp.h:234
char * glob
Definition: evhtp.h:319
evbase_t * evbase
Definition: evhtp.h:262
#define evhtp_query_new
Definition: evhtp.h:934
void * cbarg
Definition: evhtp.h:246
void evhtp_send_reply_end(evhtp_request_t *request)
Definition: evhtp.c:2574
evhtp_hook_write_cb on_write
Definition: evhtp.h:461
char * path
Definition: evhtp.h:318
evhtp_ssl_cfg_t * ssl_cfg
Definition: evhtp.h:273
evhtp_callback_t * evhtp_set_regex_cb(evhtp_t *htp, const char *pattern, evhtp_callback_cb cb, void *arg)
sets a callback to be executed based on a regex pattern
Definition: evhtp.c:3116
unsigned char * fragment
Definition: evhtp.h:356
htp_method evhtp_request_get_method(evhtp_request_t *r)
returns the htp_method enum version of the request method.
Definition: evhtp.c:1959
static int _evhtp_request_parser_chunk_new(htparser *p)
Definition: evhtp.c:1214
static int evhtp_is_hex_query_char(unsigned char ch)
Definition: evhtp.c:2250
evhtp_defaults_t defaults
Definition: evhtp.h:286
evbuf_t * buffer_out
Definition: evhtp.h:401
regex_t * regex
Definition: evhtp.h:321
void * thread_init_cbarg
Definition: evhtp.h:283
static int _evhtp_is_http_11(const char major, const char minor)
helper function to determine if http version is HTTP/1.1
Definition: evhtp.c:336
void(* evhtp_callback_cb)(evhtp_request_t *req, void *arg)
Definition: evhtp.h:140
char k_heaped
Definition: evhtp.h:340
uint8_t error
Definition: evhtp.h:433
uint64_t max_body_size
Definition: evhtp.h:267
static int _evhtp_request_parser_path(htparser *p, const char *data, size_t len)
Definition: evhtp.c:1117
main structure containing all configuration information
Definition: evhtp.h:260
evhtp_res(* evhtp_hook)()
Definition: evhtp.h:144
void evhtp_send_reply(evhtp_request_t *request, evhtp_res code)
Definition: evhtp.c:2582
void evhtp_set_timeouts(evhtp_t *htp, const struct timeval *r_timeo, const struct timeval *w_timeo)
set a read/write timeout on all things evhtp_t. When the timeout expires your error hook will be call...
Definition: evhtp.c:3499
SSL evhtp_ssl_t
Definition: evhtp.h:34
evhtp_callback_cb cb
Definition: evhtp.h:411
#define HOOK_REQUEST_RUN(request, hook_name,...)
Definition: evhtp.c:55
static int _evhtp_request_set_callbacks(evhtp_request_t *request)
Definition: evhtp.c:974
void evhtp_request_pause(evhtp_request_t *request)
Wrapper around evhtp_connection_pause.
Definition: evhtp.c:1998
uint64_t num_requests
Definition: evhtp.h:439
int evhtp_ssl_init(evhtp_t *htp, evhtp_ssl_cfg_t *cfg)
Definition: evhtp.c:3223
void * args
Definition: evhtp.h:500
#define evhtp_headers_t
Definition: evhtp.h:84
evhtp_request_t * request
Definition: evhtp.h:436
void * on_error_arg
Definition: evhtp.h:470
evhtp_res(* evhtp_hook_chunks_fini_cb)(evhtp_request_t *r, void *arg)
Definition: evhtp.h:156
evhtp_connection_t * evhtp_request_get_connection(evhtp_request_t *request)
returns the underlying evhtp_connection_t structure from a request
Definition: evhtp.c:3420
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: evhtp.c:97
static int _evhtp_run_pre_accept(evhtp_t *htp, evhtp_connection_t *conn)
Definition: evhtp.c:1623
#define EVHTP_RES_UNSUPPORTED
Definition: evhtp.h:228
void evhtp_connection_set_bev(evhtp_connection_t *conn, evbev_t *bev)
Sets the connections underlying bufferevent.
Definition: evhtp.c:3410
void(* evhtp_hook_err_cb)(evhtp_request_t *req, evhtp_error_flags errtype, void *arg)
Definition: evhtp.h:141
struct evhtp_callbacks_s evhtp_callbacks_t
Definition: evhtp.h:62
static evhtp_uri_t * _evhtp_uri_new(void)
create an overlay URI structure
Definition: evhtp.c:693
#define EVHTP_RES_GWTIMEOUT
Definition: evhtp.h:238
#define EVHTP_RES_SEEOTHER
Definition: evhtp.h:206
static evhtp_t * _evhtp_request_find_vhost(evhtp_t *evhtp, const char *name)
Definition: evhtp.c:946
static evhtp_res _evhtp_hostname_hook(evhtp_request_t *r, const char *hostname)
Definition: evhtp.c:493
static int _evhtp_ssl_add_scache_ent(evhtp_ssl_t *ssl, evhtp_ssl_sess_t *sess)
Definition: evhtp.c:1874
uint64_t body_bytes_read
Definition: evhtp.h:438
char * path
Definition: evhtp.h:379
int evhtp_connection_set_rate_limit(evhtp_connection_t *conn, size_t read_rate, size_t read_burst, size_t write_rate, size_t write_burst, const struct timeval *tick)
Definition: evhtp.c:3672
int evhtp_kvs_for_each(evhtp_kvs_t *kvs, evhtp_kvs_iterator cb, void *arg)
Definition: evhtp.c:2162
SSL_SESSION evhtp_ssl_sess_t
Definition: evhtp.h:33
evhtp_headers_t * headers_in
Definition: evhtp.h:402
#define EVHTP_RES_EXPECTFAIL
Definition: evhtp.h:230
evhtp_callback_cb cb
Definition: evhtp.h:312
void evhtp_request_free(evhtp_request_t *request)
Definition: evhtp.c:3494
#define EVHTP_RES_ERROR
Definition: evhtp.h:179
evhtp_ssl_scache_type scache_type
Definition: evhtp.h:493
#define EVHTP_RES_CREATED
Definition: evhtp.h:193
SSL_CTX evhtp_ssl_ctx_t
Definition: evhtp.h:35
void evhtp_kv_free(evhtp_kv_t *kv)
Definition: evhtp.c:2114
char free_connection
Definition: evhtp.h:442
struct ev_token_bucket_cfg * ratelimit_cfg
Definition: evhtp.h:443
#define EVHTP_RES_FATAL
Definition: evhtp.h:181
#define EVHTP_RES_MOVEDPERM
Definition: evhtp.h:204
unsigned int evhtp_request_status(evhtp_request_t *r)
Definition: evhtp.c:3774
evhtp_res(* evhtp_hook_headers_start_cb)(evhtp_request_t *r, void *arg)
Definition: evhtp.h:157
#define EVHTP_RES_MSTATUS
Definition: evhtp.h:199
evutil_socket_t sock
Definition: evhtp.h:432
evhtp_connection_t * evhtp_connection_new(evbase_t *evbase, const char *addr, uint16_t port)
allocate a new connection
Definition: evhtp.c:3699
struct evhtp_kvs_s evhtp_kvs_t
Definition: evhtp.h:66
static evhtp_res _evhtp_chunk_fini_hook(evhtp_request_t *request)
Definition: evhtp.c:454
long scache_timeout
Definition: evhtp.h:494
static int _evhtp_request_parser_chunk_fini(htparser *p)
Definition: evhtp.c:1226
#define EVHTP_RES_NOTMOD
Definition: evhtp.h:207
#define EVHTP_RES_NAUTHINFO
Definition: evhtp.h:195
void evhtp_unbind_socket(evhtp_t *htp)
stops the listening socket.
Definition: evhtp.c:2706
static evhtp_mutex_t * ssl_locks
Definition: evhtp.c:245
evhtp_t * parent
Definition: evhtp.h:261
evhtp_headers_t * headers_out
Definition: evhtp.h:403
#define EVHTP_RES_DATA_TOO_LONG
Definition: evhtp.h:183
void * pre_accept_cbarg
Definition: evhtp.h:247
#define evhtp_headers_s
Definition: evhtp.h:80
static int _evhtp_create_headers(evhtp_header_t *header, void *arg)
Definition: evhtp.c:1331
evhtp_res(* evhtp_hook_chunk_new_cb)(evhtp_request_t *r, uint64_t len, void *arg)
Definition: evhtp.h:154
long ssl_ctx_timeout
Definition: evhtp.h:487
int evhtp_bind_sockaddr(evhtp_t *htp, struct sockaddr *sa, size_t sin_len, int backlog)
bind to an already allocated sockaddr.
Definition: evhtp.c:2712
a generic key/value structure
Definition: evhtp.h:333
a structure containing all information for a http request.
Definition: evhtp.h:395
#define EVHTP_RES_LENREQ
Definition: evhtp.h:224
evhtp_callback_cb cb
Definition: evhtp.h:243
htp_scheme scheme
Definition: evhtp.h:359
const char * str
Definition: evhtp.c:110
int evhtp_unescape_string(unsigned char **out, unsigned char *str, size_t str_len)
Unescapes strings like '%7B1,%202,%203%7D' would become '{1, 2, 3}'.
Definition: evhtp.c:2281
struct timeval send_timeo
Definition: evhtp.h:289
void evhtp_callback_free(evhtp_callback_t *callback)
Definition: evhtp.c:2871
void(* evhtp_thread_init_cb)(evhtp_t *htp, evthr_t *thr, void *arg)
Definition: evhtp.h:139
int verify_depth
Definition: evhtp.h:489
static int session_id_context
Definition: evhtp.c:242
evhtp_res(* evhtp_hook_headers_cb)(evhtp_request_t *req, evhtp_headers_t *hdr, void *arg)
Definition: evhtp.h:149
uint64_t max_body_size
Definition: evhtp.h:437
struct sockaddr * saddr
Definition: evhtp.h:429
evhtp_request_t * evhtp_request_new(evhtp_callback_cb cb, void *arg)
allocate a new request
Definition: evhtp.c:3730
#define scode_add(scode, cstr)
#define evhtp_headers_find_header
Definition: evhtp.h:925
void evhtp_request_resume(evhtp_request_t *request)
Wrapper around evhtp_connection_resume.
Definition: evhtp.c:2011
void evhtp_set_gencb(evhtp_t *htp, evhtp_callback_cb cb, void *arg)
sets a callback which is called if no other callbacks are matched
Definition: evhtp.c:3178
void evhtp_callbacks_free(evhtp_callbacks_t *callbacks)
Definition: evhtp.c:2814
#define EVHTP_RES_NOCONTENT
Definition: evhtp.h:196
unscape_state
Definition: evhtp.c:2274
evhtp_hook_type
types associated with where a developer can hook into during the request processing cycle...
Definition: evhtp.h:98
htparser * parser
Definition: evhtp.h:427
union evhtp_callback_s::@0 val
evhtp_pre_accept_cb pre_accept
Definition: evhtp.h:244
#define EVHTP_RES_PROXYAUTHREQ
Definition: evhtp.h:220
void evhtp_set_max_body_size(evhtp_t *htp, uint64_t len)
set a max body size to accept for an incoming request, this will default to unlimited.
Definition: evhtp.c:3526
static evhtp_ssl_sess_t * _evhtp_ssl_get_scache_ent(evhtp_ssl_t *ssl, unsigned char *sid, int sid_len, int *copy)
Definition: evhtp.c:1896
void evhtp_set_pre_accept_cb(evhtp_t *htp, evhtp_pre_accept_cb cb, void *arg)
Definition: evhtp.c:3184
structure containing a single callback and configuration
Definition: evhtp.h:310
evhtp_res(* evhtp_hook_read_cb)(evhtp_request_t *req, evbuf_t *buf, void *arg)
Definition: evhtp.h:151
evhtp_proto
Definition: evhtp.h:122
void * cbarg
Definition: evhtp.h:314
void evhtp_connection_set_timeouts(evhtp_connection_t *c, const struct timeval *rtimeo, const struct timeval *wtimeo)
sets a connection-specific read/write timeout which overrides the global read/write settings...
Definition: evhtp.c:3425
char * cafile
Definition: evhtp.h:481
int(* evhtp_kvs_iterator)(evhtp_kv_t *kv, void *arg)
Definition: evhtp.h:161
long scache_size
Definition: evhtp.h:495
#define EVHTP_RES_RANGENOTSC
Definition: evhtp.h:229
evhtp_type type
Definition: evhtp.h:440
void evhtp_free(evhtp_t *evhtp)
Definition: evhtp.c:3632
size_t vlen
Definition: evhtp.h:338
void evhtp_send_reply_start(evhtp_request_t *request, evhtp_res code)
Definition: evhtp.c:2549
evhtp_post_accept_cb post_accept
Definition: evhtp.h:245
#define EVHTP_RES_UNAUTH
Definition: evhtp.h:214
evthr_t * thread
Definition: evhtp.h:424
static void _evhtp_thread_init(evthr_t *thr, void *arg)
Definition: evhtp.c:3071
evhtp_query_t * query
Definition: evhtp.h:358
static int _evhtp_request_parser_headers(htparser *p)
Definition: evhtp.c:1153
static int _evhtp_request_parser_header_key(htparser *p, const char *data, size_t len)
Definition: evhtp.c:902
query_parser_state
Definition: evhtp.c:2236
evhtp_ssl_ctx_t * ssl_ctx
Definition: evhtp.h:272
void evhtp_connection_resume(evhtp_connection_t *c)
resumes a connection (enables reading) and activates resume event.
Definition: evhtp.c:1982
static void _evhtp_run_in_thread(evthr_t *thr, void *arg, void *shared)
Definition: evhtp.c:1775
uint8_t owner
Definition: evhtp.h:434
int evhtp_set_hook(evhtp_hooks_t **hooks, evhtp_hook_type type, evhtp_hook cb, void *arg)
sets a callback hook for either a connection or a path/regex .
Definition: evhtp.c:2908
evhtp_path_t * path
Definition: evhtp.h:355
static int _evhtp_run_post_accept(evhtp_t *htp, evhtp_connection_t *connection)
Definition: evhtp.c:1755
static int _evhtp_request_parser_start(htparser *p)
Definition: evhtp.c:841
#define EVHTP_RES_CONFLICT
Definition: evhtp.h:222
static void _evhtp_connection_eventcb(evbev_t *bev, short events, void *arg)
Definition: evhtp.c:1568
char * full
Definition: evhtp.h:378
evhtp_callback_type
Definition: evhtp.h:114
#define EVHTP_RES_FOUND
Definition: evhtp.h:205
static int _evhtp_connection_accept(evbase_t *evbase, evhtp_connection_t *connection)
Definition: evhtp.c:1642
static void _evhtp_connection_resumecb(int fd, short events, void *arg)
Definition: evhtp.c:1432
evhtp_type
Definition: evhtp.h:128
static evhtp_path_t * _evhtp_path_new(const char *data, size_t len)
parses the path and file from an input buffer
Definition: evhtp.c:738
#define EVHTP_RES_URITOOLARGE
Definition: evhtp.h:227
char * dhparams
Definition: evhtp.h:485
a generic container representing an entire URI strucutre
Definition: evhtp.h:353
evhtp_ssl_scache_get scache_get
Definition: evhtp.h:498
struct evconnlistener evserv_t
Definition: evhtp.h:48
static unsigned long _evhtp_ssl_get_thread_id(void)
Definition: evhtp.c:1835
static int _evhtp_should_parse_query_body(evhtp_request_t *req)
determines if the request body contains the query arguments. if the query is NULL and the contenet le...
Definition: evhtp.c:1258
evhtp_res(* evhtp_hook_chunk_fini_cb)(evhtp_request_t *r, void *arg)
Definition: evhtp.h:155
void evhtp_set_bev_flags(evhtp_t *htp, int flags)
set bufferevent flags, defaults to BEV_OPT_CLOSE_ON_FREE
Definition: evhtp.c:3521
#define EVHTP_RES_TIMEOUT
Definition: evhtp.h:221
uint8_t vhost_via_sni
Definition: evhtp.h:435
static int ssl_locks_initialized
Definition: evhtp.c:246
event_t * resume_ev
Definition: evhtp.h:428
evbev_t * evhtp_request_get_bev(evhtp_request_t *request)
returns the underlying requests bufferevent
Definition: evhtp.c:3400
#define EVHTP_RES_IMUSED
Definition: evhtp.h:200
#define EVHTP_RES_PROCESSING
Definition: evhtp.h:189
static evhtp_res _evhtp_chunks_fini_hook(evhtp_request_t *request)
Definition: evhtp.c:461
evbev_t * evhtp_connection_get_bev(evhtp_connection_t *connection)
returns the underlying connections bufferevent
Definition: evhtp.c:3373
void evhtp_headers_add_header(evhtp_headers_t *headers, evhtp_header_t *header)
adds an evhtp_header_t to the end of the evhtp_headers_t tailq
static int scode_tree_initialized
Definition: evhtp.c:103
static int _evhtp_is_http_10(const char major, const char minor)
helper function to determine if http version is HTTP/1.0
Definition: evhtp.c:319
void * post_accept_cbarg
Definition: evhtp.h:248
static evhtp_request_t * _evhtp_request_new(evhtp_connection_t *c)
Creates a new evhtp_request_t.
Definition: evhtp.c:636
static void _evhtp_request_free(evhtp_request_t *request)
frees all data in an evhtp_request_t along with calling finished hooks
Definition: evhtp.c:663
static evbuf_t * _evhtp_create_reply(evhtp_request_t *request, evhtp_res code)
Definition: evhtp.c:1342
evhtp_callback_t * evhtp_set_cb(evhtp_t *htp, const char *path, evhtp_callback_cb cb, void *arg)
sets a callback to be executed on a specific path
Definition: evhtp.c:3040
void evhtp_send_reply_body(evhtp_request_t *request, evbuf_t *buf)
Definition: evhtp.c:2565
pthread_mutex_t * lock
Definition: evhtp.h:281
static int _evhtp_request_parser_args(htparser *p, const char *data, size_t len)
Definition: evhtp.c:868
void evhtp_kvs_free(evhtp_kvs_t *kvs)
Definition: evhtp.c:2142
evhtp_res(* evhtp_hook_write_cb)(evhtp_connection_t *conn, void *arg)
Definition: evhtp.h:159
pthread_mutex_t evhtp_mutex_t
Definition: evhtp.h:57
#define EVHTP_RES_FORBIDDEN
Definition: evhtp.h:216
evhtp_res(* evhtp_hook_request_fini_cb)(evhtp_request_t *req, void *arg)
Definition: evhtp.h:152
evbev_t * evhtp_request_take_ownership(evhtp_request_t *request)
Definition: evhtp.c:3405
evhtp_connection_t * conn
Definition: evhtp.h:397
void evhtp_kvs_add_kv(evhtp_kvs_t *kvs, evhtp_kv_t *kv)
appends a key/val structure to a evhtp_kvs_t tailq
Definition: evhtp.c:2215
static evhtp_res _evhtp_path_hook(evhtp_request_t *request, evhtp_path_t *path)
runs the user-defined on_path hook for a request
Definition: evhtp.c:375
static int _evhtp_ssl_servername(evhtp_ssl_t *ssl, int *unused, void *arg)
Definition: evhtp.c:1915
evhtp_res(* evhtp_hook_hostname_cb)(evhtp_request_t *r, const char *hostname, void *arg)
Definition: evhtp.h:158
static evhtp_res _evhtp_connection_fini_hook(evhtp_connection_t *connection)
runs the user-definedhook called just prior to a connection being closed
Definition: evhtp.c:483
const char * evhtp_header_find(evhtp_headers_t *headers, const char *key)
finds the value of a key in a evhtp_headers_t structure
#define EVHTP_RES_GONE
Definition: evhtp.h:223
int bev_flags
Definition: evhtp.h:266
int evhtp_add_alias(evhtp_t *evhtp, const char *name)
Add an alias hostname for a virtual-host specific evhtp_t. This avoids having multiple evhtp_t virtua...
Definition: evhtp.c:3536
#define EVHTP_RES_RSTCONTENT
Definition: evhtp.h:197
void * arg
Definition: evhtp.h:265
struct bufferevent evbev_t
Definition: evhtp.h:49
void evhtp_set_post_accept_cb(evhtp_t *htp, evhtp_post_accept_cb cb, void *arg)
Definition: evhtp.c:3190
#define evhtp_query_t
Definition: evhtp.h:85
evhtp_hook_connection_fini_cb on_connection_fini
Definition: evhtp.h:455
#define EVHTP_RES_PARTIAL
Definition: evhtp.h:198
char * capath
Definition: evhtp.h:482
void evhtp_request_set_max_body_size(evhtp_request_t *req, uint64_t len)
just calls evhtp_connection_set_max_body_size for the request.
Definition: evhtp.c:3445
static evhtp_res _evhtp_headers_start_hook(evhtp_request_t *request)
Definition: evhtp.c:468
struct timeval send_timeo
Definition: evhtp.h:431
evhtp_res(* evhtp_pre_accept_cb)(evhtp_connection_t *conn, void *arg)
Definition: evhtp.h:146
static evhtp_res _evhtp_chunk_new_hook(evhtp_request_t *request, uint64_t len)
Definition: evhtp.c:447
RB_HEAD(status_code_tree, status_code)
Definition: evhtp.c:124
void evhtp_send_reply_chunk_start(evhtp_request_t *request, evhtp_res code)
start a chunked response. If data already exists on the output buffer, this will be converted to the ...
Definition: evhtp.c:2607
An RBTREE entry for the status code -> str matcher.
Definition: evhtp.c:108
unsigned int hash
Definition: evhtp.h:313
struct timeval recv_timeo
Definition: evhtp.h:430
static evhtp_callback_t * _evhtp_callback_find(evhtp_callbacks_t *cbs, const char *path, unsigned int *start_offset, unsigned int *end_offset)
Definition: evhtp.c:581
void evhtp_connection_set_max_body_size(evhtp_connection_t *c, uint64_t len)
set a max body size for a specific connection, this will default to the size set by evhtp_set_max_bod...
Definition: evhtp.c:3436
evhtp_hooks_t * hooks
Definition: evhtp.h:426
#define evhtp_header_t
Definition: evhtp.h:83
#define HOOK_REQUEST_RUN_NARGS(request, hook_name)
Definition: evhtp.c:67
evhtp_res code
Definition: evhtp.c:109
static void _evhtp_connection_writecb(evbev_t *bev, void *arg)
Definition: evhtp.c:1509
static evhtp_res _evhtp_headers_hook(evhtp_request_t *request, evhtp_headers_t *headers)
runs the user-defined on_Headers hook for a request after all headers have been parsed.
Definition: evhtp.c:408
static void _evhtp_path_free(evhtp_path_t *path)
Definition: evhtp.c:825
unsigned int matched_soff
Definition: evhtp.h:383
unsigned int matched_eoff
Definition: evhtp.h:386
evhtp_callback_t * evhtp_callback_new(const char *path, evhtp_callback_type type, evhtp_callback_cb cb, void *arg)
creates a new evhtp_callback_t structure.
Definition: evhtp.c:2832
char * file
Definition: evhtp.h:380
#define EVHTP_RES_NOTFOUND
Definition: evhtp.h:217
static void _evhtp_ssl_thread_lock(int mode, int type, const char *file, int line)
Definition: evhtp.c:1844
evhtp_hook_err_cb on_error
Definition: evhtp.h:456
evhtp_callback_type type
Definition: evhtp.h:311
char * named_curve
Definition: evhtp.h:484
static int status_code_cmp(void *_a, void *_b)
Definition: evhtp.c:117
char * match_end
Definition: evhtp.h:382
int evhtp_ssl_use_threads(void)
Definition: evhtp.c:3198
evhtp_uri_t * uri
Definition: evhtp.h:399
static int ssl_num_locks
Definition: evhtp.c:244
char * server_name
Definition: evhtp.h:264
#define evhtp_headers_for_each
Definition: evhtp.h:926
void evhtp_connection_pause(evhtp_connection_t *c)
pauses a connection (disables reading)
Definition: evhtp.c:1969
#define EVHTP_RES_PAYREQ
Definition: evhtp.h:215
evthr_pool_t * thr_pool
Definition: evhtp.h:277
void evhtp_kv_rm_and_free(evhtp_kvs_t *kvs, evhtp_kv_t *kv)
Definition: evhtp.c:2131
char * val
Definition: evhtp.h:335
static void _evhtp_connection_readcb(evbev_t *bev, void *arg)
Definition: evhtp.c:1452
static evhtp_res _evhtp_body_hook(evhtp_request_t *request, evbuf_t *buf)
runs the user-defined on_body hook for requests containing a body. the data is stored in the request-...
Definition: evhtp.c:425
#define EVHTP_RES_NOTIMPL
Definition: evhtp.h:235
evhtp_res(* evhtp_hook_connection_fini_cb)(evhtp_connection_t *connection, void *arg)
Definition: evhtp.h:153
evserv_t * server
Definition: evhtp.h:263
static void _evhtp_default_request_cb(evhtp_request_t *request, void *arg)
Definition: evhtp.c:1705
void evhtp_request_set_bev(evhtp_request_t *request, evbev_t *bev)
sets the underlying bufferevent for a evhtp_request
Definition: evhtp.c:3415
void evhtp_connection_free(evhtp_connection_t *connection)
free's all connection related resources, this will also call your request fini hook and request fini ...
Definition: evhtp.c:3450
evhtp_t * htp
Definition: evhtp.h:421
evhtp_kv_t * evhtp_kvs_find_kv(evhtp_kvs_t *kvs, const char *key)
Definition: evhtp.c:2198
int evhtp_unset_all_hooks(evhtp_hooks_t **hooks)
removes all hooks.
Definition: evhtp.c:2981
#define evhtp_headers_free
Definition: evhtp.h:930
#define EVHTP_RES_BWEXEED
Definition: evhtp.h:240
const char * evhtp_kv_find(evhtp_kvs_t *kvs, const char *key)
Definition: evhtp.c:2181
uint64_t max_keepalive_requests
Definition: evhtp.h:268
evhtp_res(* evhtp_post_accept_cb)(evhtp_connection_t *conn, void *arg)
Definition: evhtp.h:147
evhtp_callback_t * evhtp_set_glob_cb(evhtp_t *htp, const char *pattern, evhtp_callback_cb cb, void *arg)
sets a callback to to be executed on simple glob/wildcard patterns this is useful if the app does not...
Definition: evhtp.c:3148
#define EVHTP_RES_NACCEPTABLE
Definition: evhtp.h:219
static void _evhtp_uri_free(evhtp_uri_t *uri)
frees an overlay URI structure
Definition: evhtp.c:709
#define EVHTP_RES_200
Definition: evhtp.h:192
static void _evhtp_ssl_delete_scache_ent(evhtp_ssl_ctx_t *ctx, evhtp_ssl_sess_t *sess)
Definition: evhtp.c:1856
int evhtp_make_request(evhtp_connection_t *c, evhtp_request_t *r, htp_method meth, const char *uri)
make a client request
Definition: evhtp.c:3745
evbev_t * bev
Definition: evhtp.h:423
evhtp_hooks_t * hooks
Definition: evhtp.h:315
size_t klen
Definition: evhtp.h:337
void *(* evhtp_ssl_scache_init)(evhtp_t *)
Definition: evhtp.h:170
int evhtp_response_needs_body(const evhtp_res code, const htp_method method)
Determine if a response should have a body. Follows the rules in RFC 2616 section 4...
Definition: evhtp.c:2599
htp_method method
Definition: evhtp.h:405
evhtp_query_t * evhtp_parse_query(const char *query, size_t len)
Parses the query portion of the uri into a set of key/values.
Definition: evhtp.c:2356
static int _evhtp_request_parser_headers_start(htparser *p)
Definition: evhtp.c:891
char * pemfile
Definition: evhtp.h:479
#define EVHTP_RES_VERNSUPPORT
Definition: evhtp.h:239
evhtp_header_t * evhtp_header_key_add(evhtp_headers_t *headers, const char *key, char kalloc)
creates a new evhtp_header_t, sets only the key, and adds to the evhtp_headers TAILQ ...
Definition: evhtp.c:2016
#define EVHTP_RES_CONTINUE
Definition: evhtp.h:187
static void _evhtp_accept_cb(evserv_t *serv, int fd, struct sockaddr *s, int sl, void *arg)
Definition: evhtp.c:1798
static int _evhtp_request_parser_chunks_fini(htparser *p)
Definition: evhtp.c:1237
evhtp_kv_t * evhtp_kv_new(const char *key, const char *val, char kalloc, char valloc)
Allocates a new key/value structure.
Definition: evhtp.c:2068
evbuf_t * buffer_in
Definition: evhtp.h:400
evhtp_header_t * evhtp_header_new(const char *key, const char *val, char kalloc, char valloc)
creates a new evhtp_header_t key/val structure
evhtp_hooks_t * hooks
Definition: evhtp.h:398
static int _evhtp_request_parser_fini(htparser *p)
Definition: evhtp.c:1292
void * cbarg
Definition: evhtp.h:412
#define EVHTP_RES_400
Definition: evhtp.h:212
#define EVHTP_RES_OK
Definition: evhtp.h:184
static evhtp_res _evhtp_request_fini_hook(evhtp_request_t *request)
runs the user-defined hook called just prior to a request been free()'d
Definition: evhtp.c:440
static int _evhtp_request_parser_body(htparser *p, const char *data, size_t len)
Definition: evhtp.c:1183
evhtp_ssl_scache_add scache_add
Definition: evhtp.h:497
char * ciphers
Definition: evhtp.h:483
struct timeval recv_timeo
Definition: evhtp.h:288
void * on_write_arg
Definition: evhtp.h:475
int keepalive
Definition: evhtp.h:407
static evhtp_proto _evhtp_protocol(const char major, const char minor)
returns the HTTP protocol version
Definition: evhtp.c:354
evhtp_kvs_t * evhtp_kvs_new(void)
Definition: evhtp.c:2060
#define _evhtp_unlock(h)
Definition: evhtp.c:86
#define EVHTP_RES_ACCEPTED
Definition: evhtp.h:194
evhtp_t * htp
Definition: evhtp.h:396
static int _evhtp_request_parser_header_val(htparser *p, const char *data, size_t len)
Definition: evhtp.c:921
structure which represents a URI path and or file
Definition: evhtp.h:377
char * match_start
Definition: evhtp.h:381
#define EVHTP_RES_PAUSE
Definition: evhtp.h:180
int disable_100_cont
Definition: evhtp.h:269
char v_heaped
Definition: evhtp.h:341
int verify_peer
Definition: evhtp.h:488
void evhtp_kvs_add_kvs(evhtp_kvs_t *dst, evhtp_kvs_t *src)
appends all key/val structures from src tailq onto dst tailq
Definition: evhtp.c:2224
evhtp_t * evhtp_new(evbase_t *evbase, void *arg)
creates a new evhtp_t instance
Definition: evhtp.c:3606
evhtp_res status
Definition: evhtp.h:406
evhtp_res(* evhtp_hook_path_cb)(evhtp_request_t *req, evhtp_path_t *path, void *arg)
Definition: evhtp.h:150
long ssl_opts
Definition: evhtp.h:486
#define evhtp_request_content_len(r)
Definition: evhtp.h:418
#define EVHTP_RES_USEPROXY
Definition: evhtp.h:208
#define EVHTP_RES_URI_TOOLONG
Definition: evhtp.h:190