Line data Source code
1 : /*
2 : * lwan - web server
3 : * Copyright (c) 2012 L. A. F. Pereira <l@tia.mat.br>
4 : *
5 : * This program is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU General Public License
7 : * as published by the Free Software Foundation; either version 2
8 : * of the License, or any later version.
9 : *
10 : * This program is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : * GNU General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU General Public License
16 : * along with this program; if not, write to the Free Software
17 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 : */
19 :
20 : #pragma once
21 :
22 : #include <stdlib.h>
23 : #include <limits.h>
24 :
25 : #include "lwan.h"
26 :
27 : struct lwan_request_parser_helper {
28 : struct lwan_value *buffer; /* The whole request buffer */
29 : char *next_request; /* For pipelined requests */
30 :
31 : char **header_start; /* Headers: n: start, n+1: end */
32 : size_t n_header_start; /* len(header_start) */
33 :
34 : struct lwan_value accept_encoding; /* Accept-Encoding: */
35 :
36 : struct lwan_value query_string; /* Stuff after ? and before # */
37 :
38 : struct lwan_value body_data; /* Request body for POST and PUT */
39 : struct lwan_value content_type; /* Content-Type: for POST and PUT */
40 : struct lwan_value content_length; /* Content-Length: */
41 :
42 : struct lwan_value connection; /* Connection: */
43 :
44 : struct lwan_value host; /* Host: */
45 :
46 : struct lwan_key_value_array cookies, query_params, post_params;
47 :
48 : struct { /* If-Modified-Since: */
49 : struct lwan_value raw;
50 : time_t parsed;
51 : } if_modified_since;
52 :
53 : struct { /* Range: */
54 : struct lwan_value raw;
55 : off_t from, to;
56 : } range;
57 :
58 : uint64_t request_id; /* Request ID for debugging purposes */
59 :
60 : time_t error_when_time; /* Time to abort request read */
61 : int error_when_n_packets; /* Max. number of packets */
62 : int urls_rewritten; /* Times URLs have been rewritten */
63 : };
64 :
65 : #define DEFAULT_BUFFER_SIZE 4096
66 : #define DEFAULT_HEADERS_SIZE 2048
67 :
68 : #define N_HEADER_START 64
69 :
70 : #define LWAN_CONCAT(a_, b_) a_ ## b_
71 : #define LWAN_TMP_ID_DETAIL(n_) LWAN_CONCAT(lwan_tmp_id, n_)
72 : #define LWAN_TMP_ID LWAN_TMP_ID_DETAIL(__COUNTER__)
73 :
74 : #define LWAN_MIN_MAX_DETAIL(a_, b_, name_a_, name_b_, op_) \
75 : ({ \
76 : const __typeof__((a_) + 0) name_a_ = (a_); \
77 : const __typeof__((b_) + 0) name_b_ = (b_); \
78 : name_a_ op_ name_b_ ? name_b_ : name_a_; \
79 : })
80 :
81 : #define LWAN_MIN(a_, b_) LWAN_MIN_MAX_DETAIL(a_, b_, LWAN_TMP_ID, LWAN_TMP_ID, >)
82 :
83 : #define LWAN_MAX(a_, b_) LWAN_MIN_MAX_DETAIL(a_, b_, LWAN_TMP_ID, LWAN_TMP_ID, <)
84 :
85 : void lwan_set_thread_name(const char *name);
86 :
87 : void lwan_response_init(struct lwan *l);
88 : void lwan_response_shutdown(struct lwan *l);
89 :
90 : int lwan_create_listen_socket(const struct lwan *l,
91 : bool print_listening_msg,
92 : bool is_https);
93 :
94 : void lwan_thread_init(struct lwan *l);
95 : void lwan_thread_shutdown(struct lwan *l);
96 :
97 : void lwan_status_init(struct lwan *l);
98 : void lwan_status_shutdown(struct lwan *l);
99 :
100 : void lwan_job_thread_init(void);
101 : void lwan_job_thread_main_loop(void);
102 : void lwan_job_thread_shutdown(void);
103 : void lwan_job_add(bool (*cb)(void *data), void *data);
104 : void lwan_job_del(bool (*cb)(void *data), void *data);
105 :
106 : void lwan_tables_init(void);
107 : void lwan_tables_shutdown(void);
108 :
109 : void lwan_readahead_init(void);
110 : void lwan_readahead_shutdown(void);
111 : void lwan_readahead_queue(int fd, off_t off, size_t size);
112 : void lwan_madvise_queue(void *addr, size_t size);
113 :
114 : char *lwan_strbuf_extend_unsafe(struct lwan_strbuf *s, size_t by);
115 :
116 : void lwan_process_request(struct lwan *l, struct lwan_request *request);
117 : size_t lwan_prepare_response_header_full(struct lwan_request *request,
118 : enum lwan_http_status status, char headers[],
119 : size_t headers_buf_size, const struct lwan_key_value *additional_headers);
120 :
121 : void lwan_response(struct lwan_request *request, enum lwan_http_status status);
122 : void lwan_default_response(struct lwan_request *request,
123 : enum lwan_http_status status);
124 : void lwan_fill_default_response(struct lwan_strbuf *buffer,
125 : enum lwan_http_status status);
126 :
127 :
128 : const char *lwan_get_config_path(char *path_buf, size_t path_buf_len);
129 :
130 : uint8_t lwan_char_isspace(char ch) __attribute__((pure));
131 : uint8_t lwan_char_isxdigit(char ch) __attribute__((pure));
132 : uint8_t lwan_char_isdigit(char ch) __attribute__((pure));
133 :
134 : static ALWAYS_INLINE __attribute__((pure)) size_t lwan_nextpow2(size_t number)
135 : {
136 : #if defined(LWAN_HAVE_BUILTIN_CLZLL)
137 : static const int size_bits = (int)sizeof(number) * CHAR_BIT;
138 :
139 : if (sizeof(size_t) == sizeof(unsigned int)) {
140 : return (size_t)1 << (size_bits - __builtin_clz((unsigned int)number));
141 : } else if (sizeof(size_t) == sizeof(unsigned long)) {
142 3009 : return (size_t)1 << (size_bits - __builtin_clzl((unsigned long)number));
143 : } else if (sizeof(size_t) == sizeof(unsigned long long)) {
144 : return (size_t)1 << (size_bits - __builtin_clzll((unsigned long long)number));
145 : } else {
146 : (void)size_bits;
147 : }
148 : #endif
149 :
150 : number--;
151 : number |= number >> 1;
152 : number |= number >> 2;
153 : number |= number >> 4;
154 : number |= number >> 8;
155 : number |= number >> 16;
156 : #if __SIZE_WIDTH__ == 64
157 : number |= number >> 32;
158 : #endif
159 :
160 : return number + 1;
161 : }
162 :
163 : #if defined(LWAN_HAVE_MBEDTLS)
164 : #include <mbedtls/ctr_drbg.h>
165 : #include <mbedtls/entropy.h>
166 : #include <mbedtls/ssl.h>
167 :
168 : struct lwan_tls_context {
169 : mbedtls_ssl_config config;
170 : mbedtls_x509_crt server_cert;
171 : mbedtls_pk_context server_key;
172 :
173 : mbedtls_entropy_context entropy;
174 :
175 : mbedtls_ctr_drbg_context ctr_drbg;
176 : };
177 : #endif
178 :
179 : #ifdef LWAN_HAVE_LUA
180 : #include <lua.h>
181 :
182 : lua_State *lwan_lua_create_state(const char *script_file, const char *script);
183 : void lwan_lua_state_push_request(lua_State *L, struct lwan_request *request);
184 : const char *lwan_lua_state_last_error(lua_State *L);
185 : #endif
186 :
187 : /* This macro is used as an attempt to convince the compiler that it should
188 : * never elide an expression -- for instance, when writing fuzz-test or
189 : * micro-benchmarks. */
190 : #define LWAN_NO_DISCARD(...) \
191 : do { \
192 : __typeof__(__VA_ARGS__) no_discard_ = __VA_ARGS__; \
193 : __asm__ __volatile__("" ::"g"(no_discard_) : "memory"); \
194 : } while (0)
195 :
196 0 : static inline void lwan_always_bzero(void *ptr, size_t len)
197 : {
198 0 : LWAN_NO_DISCARD(memset(ptr, 0, len));
199 0 : }
200 :
201 : #ifdef __APPLE__
202 : #define SECTION_START(name_) __start_##name_[] __asm("section$start$__DATA$" #name_)
203 : #define SECTION_END(name_) __stop_##name_[] __asm("section$end$__DATA$" #name_)
204 : #else
205 : #define SECTION_START(name_) __start_##name_[]
206 : #define SECTION_END(name_) __stop_##name_[]
207 : #endif
208 :
209 : #define SECTION_START_SYMBOL(section_name_, iter_) \
210 : ({ \
211 : extern const typeof(*iter_) SECTION_START(section_name_); \
212 : __start_##section_name_; \
213 : })
214 :
215 : #define SECTION_STOP_SYMBOL(section_name_, iter_) \
216 : ({ \
217 : extern const typeof(*iter_) SECTION_END(section_name_); \
218 : __stop_##section_name_; \
219 : })
220 :
221 : #define LWAN_SECTION_FOREACH(section_name_, iter_) \
222 : for (iter_ = SECTION_START_SYMBOL(section_name_, iter_); \
223 : iter_ < SECTION_STOP_SYMBOL(section_name_, iter_); (iter_)++)
224 :
225 : extern clockid_t monotonic_clock_id;
226 :
227 : static inline void *
228 13834 : lwan_aligned_alloc(size_t n, size_t alignment)
229 : {
230 : void *ret;
231 :
232 13834 : assert((alignment & (alignment - 1)) == 0);
233 13834 : assert((alignment % (sizeof(void *))) == 0);
234 :
235 13834 : n = (n + alignment - 1) & ~(alignment - 1);
236 13834 : if (UNLIKELY(posix_memalign(&ret, alignment, n)))
237 0 : return NULL;
238 :
239 13834 : return ret;
240 : }
241 :
242 : static ALWAYS_INLINE int lwan_calculate_n_packets(size_t total)
243 : {
244 : /* 740 = 1480 (a common MTU) / 2, so that Lwan'll optimistically error out
245 : * after ~2x number of expected packets to fully read the request body.*/
246 334 : return LWAN_MAX(5, (int)(total / 740));
247 : }
248 :
249 : long int lwan_getentropy(void *buffer, size_t buffer_len, int flags);
250 : uint64_t lwan_random_uint64();
251 :
252 : const char *lwan_http_status_as_string(enum lwan_http_status status)
253 : __attribute__((const)) __attribute__((warn_unused_result));
254 : const char *lwan_http_status_as_string_with_code(enum lwan_http_status status)
255 : __attribute__((const)) __attribute__((warn_unused_result));
256 : const char *lwan_http_status_as_descriptive_string(enum lwan_http_status status)
257 : __attribute__((const)) __attribute__((warn_unused_result));
258 :
259 : int lwan_connection_get_fd(const struct lwan *lwan,
260 : const struct lwan_connection *conn)
261 : __attribute__((pure)) __attribute__((warn_unused_result));
262 :
263 : int lwan_format_rfc_time(const time_t in, char out LWAN_ARRAY_PARAM(30));
264 : int lwan_parse_rfc_time(const char in LWAN_ARRAY_PARAM(30), time_t *out);
265 :
266 : void lwan_straitjacket_enforce_from_config(struct config *c);
267 :
268 : uint64_t lwan_request_get_id(struct lwan_request *request);
269 :
270 : ssize_t lwan_find_headers(char **header_start, struct lwan_value *buffer,
271 : char **next_request);
272 : const char *lwan_request_get_header_from_helper(struct lwan_request_parser_helper *helper,
273 : const char *header);
274 :
275 : sa_family_t lwan_socket_parse_address(char *listener, char **node, char **port);
276 :
277 : void lwan_request_foreach_header_for_cgi(struct lwan_request *request,
278 : void (*cb)(const char *header_name,
279 : size_t header_len,
280 : const char *value,
281 : size_t value_len,
282 : void *user_data),
283 : void *user_data);
|