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 }