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