Mercurial > hg > nginx-quic
comparison src/http/modules/ngx_http_event_proxy_handler.c @ 23:f540a63026c9
nginx-0.0.1-2002-12-06-19:32:33 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 06 Dec 2002 16:32:33 +0000 |
parents | aa3b53e74728 |
children | 77c7629a2627 |
comparison
equal
deleted
inserted
replaced
22:aa3b53e74728 | 23:f540a63026c9 |
---|---|
14 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r); | 14 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r); |
15 static int ngx_http_proxy_connect(ngx_http_request_t *r, | 15 static int ngx_http_proxy_connect(ngx_http_request_t *r, |
16 struct sockaddr_in *addr, | 16 struct sockaddr_in *addr, |
17 char *addr_text); | 17 char *addr_text); |
18 static int ngx_http_proxy_send_request(ngx_event_t *ev); | 18 static int ngx_http_proxy_send_request(ngx_event_t *ev); |
19 | |
19 static int ngx_http_proxy_read_response_header(ngx_event_t *ev); | 20 static int ngx_http_proxy_read_response_header(ngx_event_t *ev); |
21 static int ngx_http_proxy_process_status_line(ngx_http_request_t *r, | |
22 ngx_http_proxy_ctx_t *p); | |
23 | |
20 static int ngx_http_proxy_read_response_body(ngx_event_t *ev); | 24 static int ngx_http_proxy_read_response_body(ngx_event_t *ev); |
25 static int ngx_http_proxy_write_to_client(ngx_event_t *ev); | |
26 | |
27 static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx); | |
21 | 28 |
22 | 29 |
23 static char conn_close[] = "Connection: close" CRLF; | 30 static char conn_close[] = "Connection: close" CRLF; |
24 | 31 |
25 | 32 |
248 } | 255 } |
249 | 256 |
250 | 257 |
251 static int ngx_http_proxy_read_response_header(ngx_event_t *ev) | 258 static int ngx_http_proxy_read_response_header(ngx_event_t *ev) |
252 { | 259 { |
253 int n; | 260 int n, rc; |
261 ngx_hunk_t **ph; | |
254 ngx_connection_t *c; | 262 ngx_connection_t *c; |
255 ngx_http_request_t *r; | 263 ngx_http_request_t *r; |
256 ngx_http_proxy_ctx_t *p; | 264 ngx_http_proxy_ctx_t *p; |
257 | 265 |
258 if (ev->timedout) | 266 if (ev->timedout) |
262 r = (ngx_http_request_t *) c->data; | 270 r = (ngx_http_request_t *) c->data; |
263 p = (ngx_http_proxy_ctx_t *) ngx_get_module_ctx(r, ngx_http_proxy_module); | 271 p = (ngx_http_proxy_ctx_t *) ngx_get_module_ctx(r, ngx_http_proxy_module); |
264 | 272 |
265 if (p->header_in == NULL) { | 273 if (p->header_in == NULL) { |
266 ngx_test_null(p->header_in, | 274 ngx_test_null(p->header_in, |
267 ngx_palloc(r->pool, sizeof(ngx_http_proxy_header_in_t)), | 275 ngx_create_temp_hunk(r->pool, |
276 /* STUB */ 1024 /**/, 0, 0), | |
277 NGX_ERROR); | |
278 | |
279 p->header_in->type = NGX_HUNK_MEMORY; | |
280 | |
281 ngx_test_null(p->headers_in, | |
282 ngx_palloc(r->pool, sizeof(ngx_http_proxy_headers_in_t)), | |
268 NGX_ERROR); | 283 NGX_ERROR); |
269 | 284 |
270 ngx_test_null(p->hunks, | 285 ngx_test_null(p->hunks, |
271 ngx_create_array(r->pool, | 286 ngx_create_array(r->pool, |
272 /* STUB */ 10 /**/, | 287 /* STUB */ 10 /**/, |
273 sizeof(ngx_hunk_t *)), | 288 sizeof(ngx_hunk_t *)), |
274 NGX_ERROR); | 289 NGX_ERROR); |
275 | 290 |
276 p->last_hunk = 0; | 291 ngx_test_null(ph, ngx_push_array(p->hunks), NGX_ERROR); |
277 | 292 *ph = p->header_in; |
278 ngx_test_null(p->hunk, | 293 |
279 ngx_create_temp_hunk(r->pool, | 294 p->state_handler = ngx_http_proxy_process_status_line; |
280 /* STUB */ 1024 /**/, 0, 0), | 295 } |
281 NGX_ERROR); | 296 |
282 | 297 n = ngx_event_recv(c, p->header_in->last.mem, |
283 p->hunk->type = NGX_HUNK_MEMORY; | 298 p->header_in->end - p->header_in->last.mem); |
284 } | |
285 | |
286 n = ngx_event_recv(c, p->hunk->last.mem, p->hunk->end - p->hunk->last.mem); | |
287 | 299 |
288 ngx_log_debug(c->log, "READ:%d" _ n); | 300 ngx_log_debug(c->log, "READ:%d" _ n); |
289 | 301 |
290 p->hunk->last.mem += n; | 302 p->header_in->last.mem += n; |
291 | 303 |
292 *p->hunk->last.mem = '\0'; | 304 /* STUB */ |
293 ngx_log_debug(c->log, "PROXY:\n'%s'" _ p->hunk->pos.mem); | 305 *p->header_in->last.mem = '\0'; |
306 ngx_log_debug(c->log, "PROXY:\n'%s'" _ p->header_in->pos.mem); | |
307 /**/ | |
308 | |
309 if (n == 0) { | |
310 ngx_log_debug(c->log, "CLOSE proxy"); | |
311 ngx_del_event(ev, NGX_READ_EVENT); | |
312 ngx_event_close_connection(ev); | |
313 | |
314 p->hunk_n = 0; | |
315 c->write->event_handler = ngx_http_proxy_write_to_client; | |
316 return ngx_http_proxy_write_to_client(c->write); | |
317 } | |
318 | |
319 /* state_handlers are called in following order: | |
320 ngx_http_proxy_process_status_line(r, p) | |
321 ngx_http_proxy_process_reponse_header(r, p) */ | |
322 | |
323 do { | |
324 rc = (p->state_handler)(r, p); | |
325 | |
326 if (rc == NGX_ERROR) | |
327 return rc; | |
328 | |
329 /* rc == NGX_OK || rc == NGX_AGAIN */ | |
330 | |
331 } while (p->header_in->pos.mem < p->header_in->last.mem); | |
294 | 332 |
295 ev->event_handler = ngx_http_proxy_read_response_body; | 333 ev->event_handler = ngx_http_proxy_read_response_body; |
296 if (p->hunk->end - p->hunk->last.mem == 0) | 334 if (p->header_in->end - p->header_in->last.mem == 0) |
297 return ngx_http_proxy_read_response_body(ev); | 335 return ngx_http_proxy_read_response_body(ev); |
298 | 336 |
337 return NGX_WAITING; | |
338 } | |
339 | |
340 static int ngx_http_proxy_process_status_line(ngx_http_request_t *r, | |
341 ngx_http_proxy_ctx_t *p) | |
342 { | |
343 int rc; | |
344 | |
345 ngx_log_debug(r->connection->log, "STATUS: %d" _ p->status); | |
346 | |
347 rc = ngx_read_http_proxy_status_line(p); | |
348 | |
349 ngx_log_debug(r->connection->log, "STATUS: %d" _ p->status); | |
350 | |
351 if (rc == NGX_OK) { | |
352 /* STUB */ | |
353 ngx_log_debug(r->connection->log, "STATUS: %d" _ p->status); | |
354 | |
355 p->state_handler = NULL; | |
356 } | |
357 | |
358 if (p->header_in->last.mem >= p->header_in->end) { | |
359 rc = NGX_HTTP_PARSE_TOO_LONG_STATUS_LINE; | |
360 | |
361 } else if (rc == NGX_AGAIN) { | |
362 return NGX_AGAIN; | |
363 } | |
364 | |
299 /* STUB */ return NGX_ERROR; | 365 /* STUB */ return NGX_ERROR; |
300 } | 366 } |
301 | 367 |
302 static int ngx_http_proxy_read_response_body(ngx_event_t *ev) | 368 static int ngx_http_proxy_read_response_body(ngx_event_t *ev) |
303 { | 369 { |
304 int n; | 370 int n; |
305 size_t size; | 371 size_t left; |
306 ngx_hunk_t *h, **ph; | 372 ngx_hunk_t *h, **ph; |
307 ngx_connection_t *c; | 373 ngx_connection_t *c; |
308 ngx_http_request_t *r; | 374 ngx_http_request_t *r; |
309 ngx_http_proxy_ctx_t *p; | 375 ngx_http_proxy_ctx_t *p; |
310 | 376 |
313 | 379 |
314 c = (ngx_connection_t *) ev->data; | 380 c = (ngx_connection_t *) ev->data; |
315 r = (ngx_http_request_t *) c->data; | 381 r = (ngx_http_request_t *) c->data; |
316 p = (ngx_http_proxy_ctx_t *) ngx_get_module_ctx(r, ngx_http_proxy_module); | 382 p = (ngx_http_proxy_ctx_t *) ngx_get_module_ctx(r, ngx_http_proxy_module); |
317 | 383 |
318 size = 0; | 384 left = 0; |
319 | 385 |
320 if (p->hunks->nelts > 0) { | 386 if (p->hunks->nelts > 0) { |
321 h = ((ngx_hunk_t **) p->hunks->elts)[p->hunks->nelts - 1]; | 387 h = ((ngx_hunk_t **) p->hunks->elts)[p->hunks->nelts - 1]; |
322 size = h->end - h->last.mem; | 388 left = h->end - h->last.mem; |
323 } | 389 } |
324 | 390 |
325 do { | 391 do { |
326 if (size == 0) { | 392 |
393 #if (HAVE_KQUEUE) | |
394 #if !(USE_KQUEUE) | |
395 if (ngx_event_type == NGX_KQUEUE_EVENT) | |
396 #endif | |
397 /* do not allocate new block if there is EOF */ | |
398 if (ev->eof && ev->available == 0) | |
399 left = 1; | |
400 #endif | |
401 if (left == 0) { | |
327 ngx_test_null(ph, ngx_push_array(p->hunks), NGX_ERROR); | 402 ngx_test_null(ph, ngx_push_array(p->hunks), NGX_ERROR); |
328 ngx_test_null(h, | 403 ngx_test_null(h, |
329 ngx_create_temp_hunk(r->pool, | 404 ngx_create_temp_hunk(r->pool, |
330 /* STUB */ 4096 /**/, 0, 0), | 405 /* STUB */ 4096 /**/, 0, 0), |
331 NGX_ERROR); | 406 NGX_ERROR); |
336 | 411 |
337 n = ngx_event_recv(c, h->last.mem, h->end - h->last.mem); | 412 n = ngx_event_recv(c, h->last.mem, h->end - h->last.mem); |
338 | 413 |
339 ngx_log_debug(c->log, "READ:%d" _ n); | 414 ngx_log_debug(c->log, "READ:%d" _ n); |
340 | 415 |
416 if (n == NGX_AGAIN) | |
417 return NGX_WAITING; | |
418 | |
419 if (n == NGX_ERROR) | |
420 return NGX_ERROR; | |
421 | |
341 h->last.mem += n; | 422 h->last.mem += n; |
342 | 423 left = h->end - h->last.mem; |
424 | |
425 /* STUB */ | |
343 *h->last.mem = '\0'; | 426 *h->last.mem = '\0'; |
344 ngx_log_debug(c->log, "PROXY:\n'%s'" _ h->pos.mem); | 427 ngx_log_debug(c->log, "PROXY:\n'%s'" _ h->pos.mem); |
345 size = h->end - h->last.mem; | 428 /**/ |
346 | 429 |
347 /* TODO: close if KEVENT and (ev->available == 0 && ev->eof) */ | 430 } while (n > 0 && left == 0); |
348 | |
349 } while (size == 0); | |
350 | 431 |
351 if (n == 0) { | 432 if (n == 0) { |
352 return ngx_event_close_connection(ev); | 433 ngx_log_debug(c->log, "CLOSE proxy"); |
434 ngx_del_event(ev, NGX_READ_EVENT); | |
435 ngx_event_close_connection(ev); | |
436 | |
437 p->hunk_n = 0; | |
438 c->write->event_handler = ngx_http_proxy_write_to_client; | |
439 return ngx_http_proxy_write_to_client(c->write); | |
353 } | 440 } |
354 | 441 |
355 /* STUB */ return NGX_WAITING; | 442 /* STUB */ return NGX_WAITING; |
356 } | 443 } |
357 | 444 |
358 #if 0 | |
359 static int ngx_http_proxy_write_to_client(ngx_event_t *ev) | 445 static int ngx_http_proxy_write_to_client(ngx_event_t *ev) |
360 { | 446 { |
361 /* если бэкенд быстрее, то CLEAR, иначе - ONESHOT */ | 447 int rc; |
362 | 448 ngx_hunk_t *h; |
363 rc = ngx_http_output_filter(r, h); | 449 ngx_connection_t *c; |
364 } | 450 ngx_http_request_t *r; |
365 | 451 ngx_http_proxy_ctx_t *p; |
366 #endif | 452 |
453 c = (ngx_connection_t *) ev->data; | |
454 r = (ngx_http_request_t *) c->data; | |
455 p = (ngx_http_proxy_ctx_t *) ngx_get_module_ctx(r, ngx_http_proxy_module); | |
456 | |
457 do { | |
458 h = ((ngx_hunk_t **) p->hunks->elts)[p->hunk_n]; | |
459 | |
460 rc = ngx_http_output_filter(r, h); | |
461 if (rc != NGX_OK) | |
462 return rc; | |
463 | |
464 if (p->hunk_n >= p->hunks->nelts) | |
465 break; | |
466 | |
467 p->hunk_n++; | |
468 | |
469 } while (rc == NGX_OK); | |
470 | |
471 return NGX_OK; | |
472 } | |
473 | |
474 | |
475 static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx) | |
476 { | |
477 char ch; | |
478 char *p; | |
479 enum { | |
480 sw_start = 0, | |
481 sw_first_major_digit, | |
482 sw_major_digit, | |
483 sw_first_minor_digit, | |
484 sw_minor_digit, | |
485 sw_status, | |
486 sw_space_after_status, | |
487 sw_status_text, | |
488 sw_almost_done, | |
489 sw_done | |
490 } state; | |
491 | |
492 state = ctx->state; | |
493 p = ctx->header_in->pos.mem; | |
494 | |
495 while (p < ctx->header_in->last.mem && state < sw_done) { | |
496 ch = *p++; | |
497 | |
498 fprintf(stderr, "state: %d, pos: %x, end: %x, char: '%c', status: %d\n", | |
499 state, p, ctx->header_in->last.mem, ch, ctx->status); | |
500 | |
501 switch (state) { | |
502 | |
503 /* "HTTP/" */ | |
504 case sw_start: | |
505 if (p + 3 >= ctx->header_in->last.mem) | |
506 return NGX_AGAIN; | |
507 | |
508 if (ch != 'H' || *p != 'T' || *(p + 1) != 'T' || *(p + 2) != 'P' | |
509 || *(p + 3) != '/') | |
510 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
511 | |
512 p += 4; | |
513 state = sw_first_major_digit; | |
514 break; | |
515 | |
516 /* first digit of major HTTP version */ | |
517 case sw_first_major_digit: | |
518 if (ch < '1' || ch > '9') | |
519 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
520 | |
521 state = sw_major_digit; | |
522 break; | |
523 | |
524 /* major HTTP version or dot */ | |
525 case sw_major_digit: | |
526 if (ch == '.') { | |
527 state = sw_first_minor_digit; | |
528 break; | |
529 } | |
530 | |
531 if (ch < '0' || ch > '9') | |
532 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
533 | |
534 break; | |
535 | |
536 /* first digit of minor HTTP version */ | |
537 case sw_first_minor_digit: | |
538 if (ch < '0' || ch > '9') | |
539 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
540 | |
541 state = sw_minor_digit; | |
542 break; | |
543 | |
544 /* minor HTTP version or end of request line */ | |
545 case sw_minor_digit: | |
546 if (ch == ' ') { | |
547 state = sw_status; | |
548 break; | |
549 } | |
550 | |
551 if (ch < '0' || ch > '9') | |
552 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
553 | |
554 break; | |
555 | |
556 /* HTTP status code */ | |
557 case sw_status: | |
558 if (ch < '0' || ch > '9') | |
559 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
560 | |
561 ctx->status = ctx->status * 10 + ch - '0'; | |
562 | |
563 if (++ctx->status_count == 3) | |
564 state = sw_space_after_status; | |
565 | |
566 break; | |
567 | |
568 /* space or end of line */ | |
569 case sw_space_after_status: | |
570 switch (ch) { | |
571 case ' ': | |
572 ctx->status_text = p - 1; | |
573 state = sw_status_text; | |
574 break; | |
575 case CR: | |
576 state = sw_almost_done; | |
577 break; | |
578 case LF: | |
579 state = sw_done; | |
580 break; | |
581 default: | |
582 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
583 } | |
584 break; | |
585 | |
586 /* any text until end of line */ | |
587 case sw_status_text: | |
588 switch (ch) { | |
589 case CR: | |
590 state = sw_almost_done; | |
591 break; | |
592 case LF: | |
593 state = sw_done; | |
594 break; | |
595 } | |
596 break; | |
597 | |
598 /* end of request line */ | |
599 case sw_almost_done: | |
600 ctx->request_end = p - 2; | |
601 switch (ch) { | |
602 case LF: | |
603 state = sw_done; | |
604 break; | |
605 default: | |
606 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
607 } | |
608 break; | |
609 } | |
610 } | |
611 | |
612 ctx->header_in->pos.mem = p; | |
613 | |
614 if (state == sw_done) { | |
615 if (ctx->request_end == NULL) | |
616 ctx->request_end = p - 1; | |
617 ctx->state = sw_start; | |
618 return NGX_OK; | |
619 } else { | |
620 ctx->state = state; | |
621 return NGX_AGAIN; | |
622 } | |
623 } |