Mercurial > hg > nginx
comparison src/http/ngx_http_event.c @ 86:3973260705cc
nginx-0.0.1-2003-05-12-19:52:24 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 12 May 2003 15:52:24 +0000 |
parents | fccdb921e8b8 |
children | 5f6d848dcbef |
comparison
equal
deleted
inserted
replaced
85:3549c2bf9eaf | 86:3973260705cc |
---|---|
16 #include <ngx_http_config.h> | 16 #include <ngx_http_config.h> |
17 #include <ngx_http_core_module.h> | 17 #include <ngx_http_core_module.h> |
18 #include <ngx_http_output_filter.h> | 18 #include <ngx_http_output_filter.h> |
19 | 19 |
20 | 20 |
21 static int ngx_http_init_request(ngx_event_t *ev); | 21 static void ngx_http_init_request(ngx_event_t *ev); |
22 static void ngx_http_process_request_line(ngx_event_t *rev); | |
23 static void ngx_http_process_request_headers(ngx_event_t *rev); | |
24 | |
25 | |
26 | |
27 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r); | |
28 | |
29 | |
30 | |
22 static int ngx_http_process_request(ngx_event_t *ev); | 31 static int ngx_http_process_request(ngx_event_t *ev); |
23 static int ngx_http_process_request_line(ngx_http_request_t *r); | |
24 static int ngx_http_process_request_headers(ngx_http_request_t *r); | |
25 static int ngx_http_process_request_header_line(ngx_http_request_t *r); | 32 static int ngx_http_process_request_header_line(ngx_http_request_t *r); |
26 static int ngx_http_request_handler(ngx_http_request_t *r, int error); | 33 static int ngx_http_request_handler(ngx_http_request_t *r, int error); |
27 | 34 |
28 static int ngx_http_writer(ngx_event_t *ev); | 35 static int ngx_http_writer(ngx_event_t *ev); |
29 static int ngx_http_block_read(ngx_event_t *ev); | 36 static int ngx_http_block_read(ngx_event_t *ev); |
31 static int ngx_http_set_keepalive(ngx_http_request_t *r); | 38 static int ngx_http_set_keepalive(ngx_http_request_t *r); |
32 static int ngx_http_keepalive_handler(ngx_event_t *ev); | 39 static int ngx_http_keepalive_handler(ngx_event_t *ev); |
33 static int ngx_http_set_lingering_close(ngx_http_request_t *r); | 40 static int ngx_http_set_lingering_close(ngx_http_request_t *r); |
34 static int ngx_http_lingering_close_handler(ngx_event_t *ev); | 41 static int ngx_http_lingering_close_handler(ngx_event_t *ev); |
35 | 42 |
36 static int ngx_http_close_connection(ngx_event_t *ev); | 43 static int ngx_http_close_connection(ngx_connection_t *c); |
37 static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err); | 44 static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err); |
38 static size_t ngx_http_log_error(void *data, char *buf, size_t len); | 45 static size_t ngx_http_log_error(void *data, char *buf, size_t len); |
39 | 46 |
40 | 47 |
48 /* NGX_HTTP_PARSE_ ... errors */ | |
41 | 49 |
42 static char *header_errors[] = { | 50 static char *header_errors[] = { |
43 "client %s sent invalid method", | 51 "client %s sent invalid method", |
44 "client %s sent invalid request", | 52 "client %s sent invalid request", |
45 "client %s sent too long URI", | 53 "client %s sent too long URI", |
65 | 73 |
66 { ngx_null_string, 0 } | 74 { ngx_null_string, 0 } |
67 }; | 75 }; |
68 | 76 |
69 | 77 |
70 int ngx_http_init_connection(ngx_connection_t *c) | 78 void ngx_http_init_connection(ngx_connection_t *c) |
71 { | 79 { |
80 int event; | |
72 ngx_event_t *rev; | 81 ngx_event_t *rev; |
73 ngx_http_log_ctx_t *ctx; | 82 ngx_http_log_ctx_t *lcx; |
83 | |
84 c->addr_text.data = ngx_palloc(c->pool, c->addr_text_max_len); | |
85 if (c->addr_text.data == NULL) { | |
86 ngx_http_close_connection(c); | |
87 return; | |
88 } | |
89 | |
90 c->addr_text.len = ngx_sock_ntop(c->family, c->sockaddr, | |
91 c->addr_text.data, c->addr_text_max_len); | |
92 if (c->addr_text.len == 0) { | |
93 ngx_http_close_connection(c); | |
94 return; | |
95 } | |
96 | |
97 lcx = ngx_pcalloc(c->pool, sizeof(ngx_http_log_ctx_t)); | |
98 if (lcx == NULL) { | |
99 ngx_http_close_connection(c); | |
100 return; | |
101 } | |
102 | |
103 lcx->client = c->addr_text.data; | |
104 lcx->action = "reading client request line"; | |
105 c->log->data = lcx; | |
106 c->log->handler = ngx_http_log_error; | |
74 | 107 |
75 rev = c->read; | 108 rev = c->read; |
76 rev->event_handler = ngx_http_init_request; | 109 rev->event_handler = ngx_http_init_request; |
77 | 110 |
78 rev->close_handler = ngx_http_close_connection; | |
79 c->write->close_handler = ngx_http_close_connection; | |
80 | |
81 ngx_test_null(c->addr_text.data, ngx_palloc(c->pool, c->addr_text_max_len), | |
82 NGX_ERROR); | |
83 | |
84 c->addr_text.len = ngx_sock_ntop(c->family, c->sockaddr, | |
85 c->addr_text.data, c->addr_text_max_len); | |
86 | |
87 if (c->addr_text.len == 0) { | |
88 return NGX_ERROR; | |
89 } | |
90 | |
91 ngx_test_null(ctx, ngx_pcalloc(c->pool, sizeof(ngx_http_log_ctx_t)), | |
92 NGX_ERROR); | |
93 ctx->client = c->addr_text.data; | |
94 ctx->action = "reading client request line"; | |
95 c->log->data = ctx; | |
96 c->log->handler = ngx_http_log_error; | |
97 | |
98 #if (HAVE_DEFERRED_ACCEPT) | |
99 | |
100 if (rev->ready) { | 111 if (rev->ready) { |
101 return ngx_http_init_request(rev); | 112 /* deferred accept */ |
102 } | 113 ngx_http_init_request(rev); |
103 | 114 return; |
104 #endif | 115 } |
105 | 116 |
106 ngx_add_timer(rev, c->post_accept_timeout); | 117 ngx_add_timer(rev, c->post_accept_timeout); |
107 rev->timer_set = 1; | 118 rev->timer_set = 1; |
108 | 119 |
109 #if (USE_KQUEUE) | 120 if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) { |
110 | 121 /* aio, iocp, epoll */ |
111 return ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT); | 122 ngx_http_init_request(rev); |
112 | 123 return; |
113 #else | 124 } |
114 | |
115 /* kqueue */ | |
116 | 125 |
117 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { | 126 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { |
118 return ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT); | 127 /* kqueue */ |
119 } | 128 event = NGX_CLEAR_EVENT; |
120 | 129 |
121 /* aio, iocp, epoll */ | 130 } else { |
122 | 131 /* select, poll, /dev/poll */ |
123 if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) { | 132 event = NGX_LEVEL_EVENT; |
124 return ngx_http_init_request(rev); | 133 } |
125 } | 134 |
126 | 135 if (ngx_add_event(rev, NGX_READ_EVENT, event) == NGX_ERROR) { |
127 /* select, poll, /dev/poll */ | 136 ngx_http_close_connection(c); |
128 | 137 } |
129 return ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT); | 138 |
130 | 139 return; |
131 #endif /* USE_KQUEUE */ | 140 } |
132 } | 141 |
133 | 142 |
134 | 143 static void ngx_http_init_request(ngx_event_t *rev) |
135 static int ngx_http_init_request(ngx_event_t *rev) | |
136 { | 144 { |
137 ngx_connection_t *c; | 145 ngx_connection_t *c; |
138 ngx_http_request_t *r; | 146 ngx_http_request_t *r; |
139 ngx_http_conf_ctx_t *ctx; | 147 ngx_http_conf_ctx_t *ctx; |
140 | 148 |
141 c = (ngx_connection_t *) rev->data; | 149 c = (ngx_connection_t *) rev->data; |
142 c->sent = 0; | |
143 | |
144 ngx_test_null(r, ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)), | |
145 NGX_ERROR); | |
146 | |
147 c->data = r; | |
148 r->connection = c; | |
149 r->file.fd = NGX_INVALID_FILE; | |
150 | 150 |
151 if (c->buffer == NULL) { | 151 if (c->buffer == NULL) { |
152 ngx_test_null(c->buffer, | 152 c->buffer = ngx_create_temp_hunk(c->pool, |
153 ngx_create_temp_hunk(c->pool, | 153 ngx_http_client_header_buffer_size, |
154 ngx_http_client_header_buffer_size, | 154 0, 0); |
155 0, 0), | 155 if (c->buffer == NULL) { |
156 NGX_ERROR); | 156 ngx_http_close_connection(c); |
157 } else { | 157 return; |
158 r->header_read = 1; | 158 } |
159 } | 159 } |
160 | 160 |
161 r->pipeline = c->pipeline; | 161 r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)); |
162 r->header_in = c->buffer; | 162 if (r == NULL) { |
163 | 163 ngx_http_close_connection(c); |
164 ngx_test_null(r->pool, ngx_create_pool(ngx_http_request_pool_size, c->log), | 164 return; |
165 NGX_ERROR); | 165 } |
166 | 166 |
167 ngx_test_null(r->ctx, | 167 r->pool = ngx_create_pool(ngx_http_request_pool_size, c->log); |
168 ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module), | 168 if (r->pool == NULL) { |
169 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR)); | 169 ngx_http_close_connection(c); |
170 return; | |
171 } | |
172 | |
173 r->headers_out.headers = ngx_create_table(r->pool, 10); | |
174 if (r->headers_out.headers == NULL) { | |
175 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
176 ngx_http_close_connection(c); | |
177 return; | |
178 } | |
179 | |
180 r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module); | |
181 if (r->ctx == NULL) { | |
182 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
183 ngx_http_close_connection(c); | |
184 return; | |
185 } | |
170 | 186 |
171 ctx = (ngx_http_conf_ctx_t *) c->ctx; | 187 ctx = (ngx_http_conf_ctx_t *) c->ctx; |
172 r->srv_conf = ctx->srv_conf; | 188 r->srv_conf = ctx->srv_conf; |
173 r->loc_conf = ctx->loc_conf; | 189 r->loc_conf = ctx->loc_conf; |
174 | 190 |
191 c->sent = 0; | |
192 c->data = r; | |
193 r->connection = c; | |
194 r->pipeline = c->pipeline; | |
195 r->header_in = c->buffer; | |
196 | |
197 r->file.fd = NGX_INVALID_FILE; | |
198 | |
175 r->headers_in.content_length_n = -1; | 199 r->headers_in.content_length_n = -1; |
176 r->headers_out.headers = ngx_create_table(r->pool, 10); | |
177 r->headers_out.content_length = -1; | 200 r->headers_out.content_length = -1; |
178 r->headers_out.last_modified_time = -1; | 201 r->headers_out.last_modified_time = -1; |
179 | 202 |
180 rev->event_handler = ngx_http_process_request; | 203 rev->event_handler = ngx_http_process_request_line; |
181 r->state_handler = ngx_http_process_request_line; | 204 ngx_http_process_request_line(rev); |
182 | 205 |
183 return ngx_http_process_request(rev); | 206 return; |
184 } | 207 } |
185 | 208 |
186 | 209 |
187 static int ngx_http_process_request(ngx_event_t *rev) | 210 static void ngx_http_process_request_line(ngx_event_t *rev) |
188 { | 211 { |
189 int n, rc; | 212 int rc, offset; |
190 ngx_event_t *wev; | 213 ssize_t n; |
191 ngx_connection_t *c; | 214 ngx_connection_t *c; |
192 ngx_http_request_t *r; | 215 ngx_http_request_t *r; |
193 ngx_http_log_ctx_t *lcx; | 216 ngx_http_log_ctx_t *lcx; |
194 | 217 |
195 c = (ngx_connection_t *) rev->data; | 218 c = (ngx_connection_t *) rev->data; |
196 r = (ngx_http_request_t *) c->data; | 219 r = (ngx_http_request_t *) c->data; |
197 | 220 |
198 ngx_log_debug(c->log, "http process request"); | 221 ngx_log_debug(rev->log, "http process request line"); |
199 | 222 |
200 if (rev->timedout) { | 223 if (rev->timedout) { |
201 return ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); | 224 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); |
202 } | 225 ngx_http_close_connection(c); |
203 | 226 return; |
204 do { | 227 } |
205 | 228 |
206 if (r->header_read) { | 229 n = ngx_http_read_request_header(r); |
207 r->header_read = 0; | 230 |
208 ngx_log_debug(c->log, "http preread %d" _ | 231 if (n == NGX_AGAIN || n == NGX_ERROR) { |
209 r->header_in->last - r->header_in->pos); | 232 return; |
210 | 233 } |
211 } else { | 234 |
212 n = ngx_event_recv(c, r->header_in->last, | 235 rc = ngx_parse_http_request_line(r); |
213 r->header_in->end - r->header_in->last); | |
214 | |
215 if (n == NGX_AGAIN) { | |
216 if (!r->header_timeout_set) { | |
217 | |
218 if (rev->timer_set) { | |
219 ngx_del_timer(rev); | |
220 } else { | |
221 rev->timer_set = 1; | |
222 } | |
223 | |
224 ngx_add_timer(rev, ngx_http_client_header_timeout); | |
225 r->header_timeout_set = 1; | |
226 } | |
227 | |
228 return NGX_AGAIN; | |
229 } | |
230 | |
231 if (n == NGX_ERROR) { | |
232 return ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST); | |
233 } | |
234 | |
235 ngx_log_debug(c->log, "http read %d" _ n); | |
236 | |
237 if (n == 0) { | |
238 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
239 "client closed prematurely connection"); | |
240 return ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST); | |
241 } | |
242 | |
243 r->header_in->last += n; | |
244 } | |
245 | |
246 /* the state handlers are called in the following order: | |
247 ngx_http_process_request_line(r) | |
248 ngx_http_process_request_headers(r) */ | |
249 | |
250 do { | |
251 rc = r->state_handler(r); | |
252 | |
253 } while (rc == NGX_AGAIN && r->header_in->pos < r->header_in->last); | |
254 | |
255 } while (rc == NGX_AGAIN | |
256 && (rev->ready || ngx_event_flags & NGX_HAVE_AIO_EVENT)); | |
257 | |
258 if (rc >= NGX_OK) { | |
259 | |
260 /* HTTP header done */ | |
261 | |
262 rev->event_handler = ngx_http_block_read; | |
263 | |
264 if (rc != NGX_OK) { | |
265 return ngx_http_finalize_request(r, rc); | |
266 } | |
267 | |
268 lcx = c->log->data; | |
269 lcx->action = "processing client request"; | |
270 | |
271 #if 0 | |
272 wev = c->write; | |
273 ngx_add_timer(wev, 5000); | |
274 wev->delayed = 1; | |
275 wev->timer_set = 1; | |
276 #endif | |
277 | |
278 rc = ngx_http_handler(r); | |
279 | |
280 /* a handler does its own processing */ | |
281 if (rc == NGX_DONE) { | |
282 return rc; | |
283 } | |
284 | |
285 if (rc == NGX_ERROR) { | |
286 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
287 } | |
288 | |
289 return ngx_http_finalize_request(r, rc); | |
290 | |
291 } | |
292 | |
293 /* NGX_AGAIN */ | |
294 | |
295 if (!r->header_timeout_set) { | |
296 | |
297 if (rev->timer_set) { | |
298 ngx_del_timer(rev); | |
299 } else { | |
300 rev->timer_set = 1; | |
301 } | |
302 | |
303 ngx_add_timer(rev, ngx_http_client_header_timeout); | |
304 r->header_timeout_set = 1; | |
305 } | |
306 | |
307 return rc; | |
308 } | |
309 | |
310 | |
311 static int ngx_http_process_request_line(ngx_http_request_t *r) | |
312 { | |
313 int rc, offset; | |
314 ngx_connection_t *c; | |
315 ngx_http_log_ctx_t *lcx; | |
316 | |
317 rc = ngx_read_http_request_line(r); | |
318 | |
319 c = r->connection; | |
320 | |
321 /* a request line has been parsed successfully */ | |
322 | 236 |
323 if (rc == NGX_OK) { | 237 if (rc == NGX_OK) { |
238 | |
239 /* the request line has been parsed successfully */ | |
324 | 240 |
325 if (r->http_version >= NGX_HTTP_VERSION_10 | 241 if (r->http_version >= NGX_HTTP_VERSION_10 |
326 && ngx_http_large_client_header == 0 | 242 && ngx_http_large_client_header == 0 |
327 && r->header_in->pos == r->header_in->end) | 243 && r->header_in->pos == r->header_in->end) |
328 { | 244 { |
245 /* no space for "\r\n" at the end of the header */ | |
246 | |
329 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI); | 247 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI); |
330 return NGX_HTTP_REQUEST_URI_TOO_LARGE; | 248 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE); |
249 return; | |
331 } | 250 } |
332 | 251 |
333 /* copy URI */ | 252 /* copy URI */ |
334 | 253 |
335 if (r->args_start) { | 254 if (r->args_start) { |
336 r->uri.len = r->args_start - 1 - r->uri_start; | 255 r->uri.len = r->args_start - 1 - r->uri_start; |
337 } else { | 256 } else { |
338 r->uri.len = r->uri_end - r->uri_start; | 257 r->uri.len = r->uri_end - r->uri_start; |
339 } | 258 } |
340 | 259 |
341 ngx_test_null(r->uri.data, ngx_palloc(r->pool, r->uri.len + 1), | 260 r->uri.data = ngx_palloc(r->pool, r->uri.len + 1); |
342 NGX_HTTP_INTERNAL_SERVER_ERROR); | 261 if (r->uri.data == NULL) { |
262 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
263 ngx_http_close_connection(c); | |
264 return; | |
265 } | |
343 | 266 |
344 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); | 267 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); |
345 | 268 |
346 r->request_line.len = r->request_end - r->request_start; | 269 r->request_line.len = r->request_end - r->request_start; |
347 | 270 |
348 /* if the large client headers are enabled then | 271 /* if the large client header is enabled then |
349 we need to copy a request line */ | 272 we need to copy a request line */ |
350 | 273 |
351 if (ngx_http_large_client_header) { | 274 if (ngx_http_large_client_header) { |
352 ngx_test_null(r->request_line.data, | 275 |
353 ngx_palloc(r->pool, r->request_line.len + 1), | 276 r->request_line.data = ngx_palloc(r->pool, r->request_line.len + 1); |
354 NGX_HTTP_INTERNAL_SERVER_ERROR); | 277 if (r->request_line.data == NULL) { |
278 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
279 ngx_http_close_connection(c); | |
280 return; | |
281 } | |
355 | 282 |
356 ngx_cpystrn(r->request_line.data, r->request_start, | 283 ngx_cpystrn(r->request_line.data, r->request_start, |
357 r->request_line.len + 1); | 284 r->request_line.len + 1); |
358 | 285 |
359 } else { | 286 } else { |
368 r->exten.len = r->args_start - 1 - r->uri_ext; | 295 r->exten.len = r->args_start - 1 - r->uri_ext; |
369 } else { | 296 } else { |
370 r->exten.len = r->uri_end - r->uri_ext; | 297 r->exten.len = r->uri_end - r->uri_ext; |
371 } | 298 } |
372 | 299 |
373 ngx_test_null(r->exten.data, | 300 r->exten.data = ngx_palloc(r->pool, r->exten.len + 1); |
374 ngx_palloc(r->pool, r->exten.len + 1), | 301 if (r->exten.data == NULL) { |
375 NGX_HTTP_INTERNAL_SERVER_ERROR); | 302 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
303 ngx_http_close_connection(c); | |
304 return; | |
305 } | |
376 | 306 |
377 ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1); | 307 ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1); |
378 } | 308 } |
379 | 309 |
380 /* copy URI arguments if they exist */ | 310 /* copy URI arguments if they exist */ |
381 | 311 |
382 if (r->args_start && r->uri_end > r->args_start) { | 312 if (r->args_start && r->uri_end > r->args_start) { |
383 r->args.len = r->uri_end - r->args_start; | 313 r->args.len = r->uri_end - r->args_start; |
384 | 314 |
385 ngx_test_null(r->args.data, | 315 r->args.data = ngx_palloc(r->pool, r->args.len + 1); |
386 ngx_palloc(r->pool, r->args.len + 1), | 316 if (r->args.data == NULL) { |
387 NGX_HTTP_INTERNAL_SERVER_ERROR); | 317 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
318 ngx_http_close_connection(c); | |
319 return; | |
320 } | |
388 | 321 |
389 ngx_cpystrn(r->args.data, r->args_start, r->args.len + 1); | 322 ngx_cpystrn(r->args.data, r->args_start, r->args.len + 1); |
390 } | 323 } |
391 | 324 |
392 #if 1 | 325 #if 1 /* DEBUG */ |
393 if (r->exten.data == NULL) { | 326 if (r->exten.data == NULL) { r->exten.data = ""; } |
394 r->exten.data = ""; | 327 if (r->args.data == NULL) { r->args.data = ""; } |
395 } | 328 ngx_log_debug(c->log, "HTTP: %d, %d, '%s', '%s', '%s'" _ |
396 if (r->args.data == NULL) { | |
397 r->args.data = ""; | |
398 } | |
399 ngx_log_debug(r->connection->log, "HTTP: %d, %d, '%s', '%s', '%s'" _ | |
400 r->method _ r->http_version _ | 329 r->method _ r->http_version _ |
401 r->uri.data _ r->exten.data _ r->args.data); | 330 r->uri.data _ r->exten.data _ r->args.data); |
402 if (r->exten.data[0] == '\0') { | 331 if (r->exten.data[0] == '\0') { r->exten.data = NULL; } |
403 r->exten.data = NULL; | 332 if (r->args.data[0] == '\0') { r->args.data = NULL; } |
404 } | |
405 if (r->args.data[0] == '\0') { | |
406 r->args.data = NULL; | |
407 } | |
408 #endif | 333 #endif |
409 | 334 |
410 lcx = r->connection->log->data; | 335 lcx = c->log->data; |
411 | 336 |
412 if (ngx_http_url_in_error_log) { | 337 if (ngx_http_url_in_error_log) { |
413 ngx_test_null(lcx->url, | 338 lcx->url = ngx_palloc(r->pool, r->uri_end - r->uri_start + 1); |
414 ngx_palloc(r->pool, r->uri_end - r->uri_start + 1), | 339 if (lcx->url == NULL) { |
415 NGX_HTTP_INTERNAL_SERVER_ERROR); | 340 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
341 ngx_http_close_connection(c); | |
342 return; | |
343 } | |
416 | 344 |
417 ngx_cpystrn(lcx->url, r->uri_start, r->uri_end - r->uri_start + 1); | 345 ngx_cpystrn(lcx->url, r->uri_start, r->uri_end - r->uri_start + 1); |
418 } | 346 } |
419 | 347 |
420 /* if we need to parse the headers then return NGX_AGAIN | |
421 becuase of HTTP/0.9 has no headers so return NGX_OK */ | |
422 | |
423 if (r->http_version == NGX_HTTP_VERSION_9) { | 348 if (r->http_version == NGX_HTTP_VERSION_9) { |
424 r->state_handler = NULL; | 349 /* STUB */ return; |
425 return NGX_OK; | 350 } |
426 } | 351 |
427 | 352 lcx->action = "reading client request headers"; |
428 r->headers_in.headers = ngx_create_table(r->pool, 10); | 353 r->headers_in.headers = ngx_create_table(r->pool, 10); |
429 | |
430 r->state_handler = ngx_http_process_request_headers; | |
431 lcx->action = "reading client request headers"; | |
432 | 354 |
433 if (ngx_http_large_client_header | 355 if (ngx_http_large_client_header |
434 && r->header_in->pos == r->header_in->last) | 356 && r->header_in->pos == r->header_in->last) |
435 { | 357 { |
436 r->header_in->pos = r->header_in->last = r->header_in->start; | 358 r->header_in->pos = r->header_in->last = r->header_in->start; |
437 } | 359 } |
438 | 360 |
439 return NGX_AGAIN; | |
440 | |
441 /* there was error while a request line parsing */ | |
442 | |
443 } else if (rc != NGX_AGAIN) { | 361 } else if (rc != NGX_AGAIN) { |
362 | |
363 /* there was error while a request line parsing */ | |
364 | |
444 ngx_http_header_parse_error(r, rc); | 365 ngx_http_header_parse_error(r, rc); |
445 return NGX_HTTP_BAD_REQUEST; | 366 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); |
367 return; | |
446 } | 368 } |
447 | 369 |
448 /* NGX_AGAIN: a request line parsing is still not complete */ | 370 /* NGX_AGAIN: a request line parsing is still not complete */ |
449 | 371 |
450 if (r->header_in->last == r->header_in->end) { | 372 if (r->header_in->last == r->header_in->end) { |
451 | 373 |
452 /* If it's a pipelined request and a request line is not complete | 374 /* If it's a pipelined request and a request line is not complete |
453 then we need to copy it to the start of r->header_in hunk. | 375 then we need to copy it to the start of the r->header_in hunk. |
454 We need to copy it here only if the large client headers | 376 We need to copy it here only if the large client headers |
455 are enabled otherwise a request line had been already copied | 377 are enabled otherwise a request line had been already copied |
456 to the start of r->header_in hunk in ngx_http_set_keepalive() */ | 378 to the start of the r->header_in hunk in ngx_http_set_keepalive() */ |
457 | 379 |
458 if (ngx_http_large_client_header) { | 380 if (ngx_http_large_client_header) { |
459 offset = r->request_start - r->header_in->start; | 381 offset = r->request_start - r->header_in->start; |
460 | 382 |
461 if (offset == 0) { | 383 if (offset == 0) { |
462 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI); | 384 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI); |
463 return NGX_HTTP_REQUEST_URI_TOO_LARGE; | 385 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE); |
386 return; | |
464 } | 387 } |
465 | 388 |
466 ngx_memcpy(r->header_in->start, r->request_start, | 389 ngx_memcpy(r->header_in->start, r->request_start, |
467 r->header_in->last - r->request_start); | 390 r->header_in->last - r->request_start); |
468 | 391 |
479 r->args_start -= offset; | 402 r->args_start -= offset; |
480 } | 403 } |
481 | 404 |
482 } else { | 405 } else { |
483 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI); | 406 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI); |
484 return NGX_HTTP_REQUEST_URI_TOO_LARGE; | 407 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE); |
485 } | 408 return; |
486 } | 409 } |
487 | 410 } |
488 return NGX_AGAIN; | 411 |
489 } | 412 rev->event_handler = ngx_http_process_request_headers; |
490 | 413 ngx_http_process_request_headers(rev); |
491 | 414 |
492 static int ngx_http_process_request_headers(ngx_http_request_t *r) | 415 return; |
416 } | |
417 | |
418 | |
419 static void ngx_http_process_request_headers(ngx_event_t *rev) | |
493 { | 420 { |
494 int rc, offset; | 421 int rc, offset; |
495 size_t len; | 422 size_t len; |
423 ssize_t n; | |
424 ngx_connection_t *c; | |
425 ngx_http_request_t *r; | |
496 ngx_http_log_ctx_t *ctx; | 426 ngx_http_log_ctx_t *ctx; |
497 | 427 |
428 if (rev->timedout) { | |
429 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); | |
430 ngx_http_close_connection(c); | |
431 return; | |
432 } | |
433 | |
434 n = ngx_http_read_request_header(r); | |
435 | |
436 if (n == NGX_AGAIN || n == NGX_ERROR) { | |
437 return; | |
438 } | |
439 | |
498 for ( ;; ) { | 440 for ( ;; ) { |
499 rc = ngx_read_http_header_line(r, r->header_in); | 441 rc = ngx_parse_http_header_line(r, r->header_in); |
500 | 442 |
501 /* a header line has been parsed successfully */ | 443 /* a header line has been parsed successfully */ |
502 | 444 |
503 if (rc == NGX_OK) { | 445 if (rc == NGX_OK) { |
504 if (ngx_http_process_request_header_line(r) == NGX_ERROR) { | 446 if (ngx_http_process_request_header_line(r) == NGX_ERROR) { |
790 | 732 |
791 return ngx_http_close_request(r, 0); | 733 return ngx_http_close_request(r, 0); |
792 } | 734 } |
793 | 735 |
794 | 736 |
737 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r) | |
738 { | |
739 ssize_t n; | |
740 ngx_event_t *rev; | |
741 | |
742 n = r->header_in->last - r->header_in->pos; | |
743 | |
744 if (n > 0) { | |
745 return n; | |
746 } | |
747 | |
748 n = ngx_event_recv(r->connection, r->header_in->last, | |
749 r->header_in->end - r->header_in->last); | |
750 | |
751 if (n == NGX_AGAIN) { | |
752 if (!r->header_timeout_set) { | |
753 rev = r->connection->read; | |
754 | |
755 if (rev->timer_set) { | |
756 ngx_del_timer(rev); | |
757 } else { | |
758 rev->timer_set = 1; | |
759 } | |
760 | |
761 ngx_add_timer(rev, ngx_http_client_header_timeout); | |
762 r->header_timeout_set = 1; | |
763 } | |
764 | |
765 return NGX_AGAIN; | |
766 } | |
767 | |
768 if (n == 0) { | |
769 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, | |
770 "client closed prematurely connection"); | |
771 | |
772 if (n == 0 || n == NGX_ERROR) { | |
773 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST); | |
774 ngx_http_close_connection(c); | |
775 return NGX_ERROR; | |
776 } | |
777 | |
778 r->header_in->last += n; | |
779 | |
780 return n; | |
781 } | |
782 | |
783 | |
795 static int ngx_http_block_read(ngx_event_t *ev) | 784 static int ngx_http_block_read(ngx_event_t *ev) |
796 { | 785 { |
797 ngx_log_debug(ev->log, "http read blocked"); | 786 ngx_log_debug(ev->log, "http read blocked"); |
798 | 787 |
799 /* aio does not call this handler */ | 788 /* aio does not call this handler */ |
1142 | 1131 |
1143 return NGX_OK; | 1132 return NGX_OK; |
1144 } | 1133 } |
1145 | 1134 |
1146 | 1135 |
1147 static int ngx_http_close_connection(ngx_event_t *ev) | 1136 static void ngx_http_close_connection(ngx_connection_t *c) |
1137 { | |
1138 ngx_log_debug(c->log, "close connection: %d" _ c->fd); | |
1139 | |
1140 if (c->fd == -1) { | |
1141 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed"); | |
1142 return; | |
1143 } | |
1144 | |
1145 if (c->read->timer_set) { | |
1146 ngx_del_timer(c->read); | |
1147 c->read->timer_set = 0; | |
1148 } | |
1149 | |
1150 if (c->read->active) { | |
1151 ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); | |
1152 } | |
1153 | |
1154 if (c->write->timer_set) { | |
1155 ngx_del_timer(c->write); | |
1156 c->write->timer_set = 0; | |
1157 } | |
1158 | |
1159 if (c->write->active) { | |
1160 ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT); | |
1161 } | |
1162 | |
1163 if (ngx_close_socket(c->fd) == -1) { | |
1164 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, | |
1165 ngx_close_socket_n " failed"); | |
1166 } | |
1167 | |
1168 c->fd = -1; | |
1169 | |
1170 ngx_destroy_pool(c->pool); | |
1171 | |
1172 return; | |
1173 } | |
1174 | |
1175 static int ngx_http_close_connection0(ngx_event_t *ev) | |
1148 { | 1176 { |
1149 return ngx_event_close_connection(ev); | 1177 return ngx_event_close_connection(ev); |
1150 } | 1178 } |
1151 | 1179 |
1152 | 1180 |