httpp-benchmark

httpp-benchmark.git
git clone git://git.lenczewski.org/httpp-benchmark.git
Log | Files | Refs | README | LICENSE

mblhttp.h (2989B)


      1 #ifndef MBLHTTP_H
      2 #define MBLHTTP_H
      3 
      4 #include <ctype.h>
      5 #include <stddef.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 #include <strings.h>
      9 
     10 struct mbl_http_str {
     11 	char *ptr;
     12 	int len;
     13 };
     14 
     15 struct mbl_http_buf {
     16 	void *ptr;
     17 	int len;
     18 };
     19 
     20 struct mbl_http_header {
     21 	struct mbl_http_str key, val;
     22 };
     23 
     24 struct mbl_http_msg {
     25 	struct mbl_http_str request_line;
     26 
     27 	struct mbl_http_header *hdrs;
     28 	size_t hdrs_len, hdrs_cap;
     29 
     30 	struct mbl_http_buf body;
     31 };
     32 
     33 /* please ignore the stray `static inline` functions, this really probably
     34  * be split out into its own .c source file, but this is faster and much
     35  * less faff :)
     36  */
     37 
     38 static inline int
     39 parse_request_line(char **ptr, char *end, struct mbl_http_str *out)
     40 {
     41 	char *start = *ptr;
     42 	while (start < end) {
     43 		if (*start++ == '\r' && *start++ == '\n') {
     44 			out->ptr = *ptr;
     45 			out->len = (start - *ptr) - 2;
     46 
     47 			*ptr = start;
     48 
     49 			return 0;
     50 		}
     51 	}
     52 
     53 	*ptr = start;
     54 
     55 	return -1;
     56 }
     57 
     58 static inline int
     59 parse_request_header(char *ptr, char *end, struct mbl_http_header *out)
     60 {
     61 	char *delim = memchr(ptr, ':', end - ptr);
     62 	if (!delim) /* malformed http header */
     63 		return -1;
     64 
     65 	out->key.ptr = ptr;
     66 	out->key.len = delim - ptr;
     67 
     68 	out->val.ptr = ++delim;
     69 	out->val.len = end - delim;
     70 
     71 	/* ltrim key */
     72 	while (isspace(*out->key.ptr) && out->key.len) {
     73 		out->key.ptr++;
     74 		out->key.len--;
     75 	}
     76 
     77 	/* ltrim val */
     78 	while (isspace(*out->val.ptr) && out->val.len) {
     79 		out->val.ptr++;
     80 		out->val.len--;
     81 	}
     82 
     83 	return 0;
     84 }
     85 
     86 static inline int
     87 parse_request_headers(char **ptr, char *end,
     88 		      struct mbl_http_header *hdrs, size_t cap, size_t *len)
     89 {
     90 	char *start = *ptr;
     91 
     92 	char term[2] = { '\r', '\n' };
     93 
     94 	*len = 0;
     95 
     96 	while (start < end) {
     97 		char *hdr_begin = start;
     98 		char *hdr_end = memmem(start, end - start, term, sizeof term);
     99 
    100 		if (!hdr_end) /* no \r\n found, malformed http request */
    101 			return -1;
    102 
    103 		if (hdr_begin == hdr_end) { /* final \r\n */
    104 			start = hdr_end + sizeof term;
    105 			break;
    106 		}
    107 
    108 		/* have header, parse it */
    109 		if (*len < cap) {
    110 			struct mbl_http_header *hdr = hdrs + (*len)++;
    111 			if (parse_request_header(hdr_begin, hdr_end, hdr) < 0)
    112 				return -2;
    113 		}
    114 
    115 		start = hdr_end + sizeof term;
    116 	}
    117 
    118 	*ptr = start;
    119 
    120 	return 0;
    121 }
    122 
    123 static inline int
    124 mbl_http_msg_parse(struct mbl_http_msg *msg, char *buf, size_t len,
    125 		   struct mbl_http_header hdrs[], size_t hdrs_cap)
    126 {
    127 	msg->hdrs = hdrs;
    128 	msg->hdrs_cap = hdrs_cap;
    129 
    130 	char *ptr = buf, *end = buf + len;
    131 	if (parse_request_line(&ptr, end, &msg->request_line) < 0)
    132 		return -1;
    133 
    134 	if (parse_request_headers(&ptr, end, msg->hdrs, msg->hdrs_cap, &msg->hdrs_len) < 0)
    135 		return -2;
    136 
    137 	msg->body.ptr = ptr;
    138 	msg->body.len = end - ptr;
    139 
    140 	return 0;
    141 }
    142 
    143 static inline struct mbl_http_header *
    144 mbl_http_msg_find_header(struct mbl_http_msg *msg, char const *key, int len)
    145 {
    146 	for (size_t i = 0; i < msg->hdrs_len; i++) {
    147 		struct mbl_http_header *hdr = msg->hdrs + i;
    148 
    149 		if (hdr->key.len != len)
    150 			continue;
    151 
    152 		if (strncasecmp(hdr->key.ptr, key, len) == 0)
    153 			return hdr;
    154 	}
    155 
    156 	return NULL;
    157 }
    158 
    159 #endif /* MBLHTTP_H */