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