Mercurial > hg > nginx-quic
comparison src/http/modules/proxy/ngx_http_event_proxy_handler.c @ 79:eacfdd1c31b9
nginx-0.0.1-2003-04-22-19:02:58 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 22 Apr 2003 15:02:58 +0000 |
parents | 57c2e18d3572 |
children | 939bc7cd9a90 |
comparison
equal
deleted
inserted
replaced
78:9f81437e0ad3 | 79:eacfdd1c31b9 |
---|---|
330 c = NULL; | 330 c = NULL; |
331 | 331 |
332 if (c) { | 332 if (c) { |
333 p->cached_connection = 1; | 333 p->cached_connection = 1; |
334 p->connection = c; | 334 p->connection = c; |
335 c->write->event_handler = ngx_http_proxy_process_upstream_event; | 335 c->write->event_handler = c->read->event_handler = |
336 ngx_http_proxy_process_upstream_event; | |
336 rc = ngx_http_proxy_send_request(p); | 337 rc = ngx_http_proxy_send_request(p); |
337 | 338 |
338 } else { | 339 } else { |
339 p->cached_connection = 0; | 340 p->cached_connection = 0; |
340 p->connection = NULL; | 341 p->connection = NULL; |
368 return ngx_http_proxy_finalize_request(p, | 369 return ngx_http_proxy_finalize_request(p, |
369 NGX_HTTP_INTERNAL_SERVER_ERROR); | 370 NGX_HTTP_INTERNAL_SERVER_ERROR); |
370 return NGX_DONE; | 371 return NGX_DONE; |
371 } | 372 } |
372 | 373 |
373 if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT | 374 if (p->tries /* STUB !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ |
374 || (rc == NGX_OK | 375 |
375 && p->status == NGX_HTTP_INTERNAL_SERVER_ERROR | 376 && (rc == NGX_HTTP_BAD_GATEWAY |
376 && p->lcf->retry_500_error)) | 377 || rc == NGX_HTTP_GATEWAY_TIME_OUT |
378 || (rc == NGX_OK | |
379 && p->status == NGX_HTTP_INTERNAL_SERVER_ERROR | |
380 && p->lcf->retry_500_error))) | |
377 { | 381 { |
378 if (ev) { | 382 if (ev) { |
379 ngx_event_close_connection(ev); | 383 ngx_event_close_connection(ev); |
380 ev = NULL; | 384 ev = NULL; |
381 } | 385 } |
400 | 404 |
401 if (p->tries == 0) { | 405 if (p->tries == 0) { |
402 ngx_http_proxy_finalize_request(p, p->last_error); | 406 ngx_http_proxy_finalize_request(p, p->last_error); |
403 return NGX_ERROR; | 407 return NGX_ERROR; |
404 } | 408 } |
409 | |
410 /* reinitialize the proxy context for the next upstream */ | |
405 | 411 |
406 p->headers_in.server->key.len = 0; | 412 p->headers_in.server->key.len = 0; |
407 p->headers_in.connection->key.len = 0; | 413 p->headers_in.connection->key.len = 0; |
408 p->headers_in.content_type->key.len = 0; | 414 p->headers_in.content_type->key.len = 0; |
409 p->headers_in.content_length->key.len = 0; | 415 p->headers_in.content_length->key.len = 0; |
439 | 445 |
440 if (p->upstreams->number > 1) { | 446 if (p->upstreams->number > 1) { |
441 if (p->tries == p->upstreams->number) { | 447 if (p->tries == p->upstreams->number) { |
442 | 448 |
443 /* Here is the race condition | 449 /* Here is the race condition |
444 when the upstreams are shared between threads or processes | 450 when the upstreams are shared between |
445 but it should not be serious */ | 451 the threads or the processes but it should not be serious */ |
446 | 452 |
447 p->cur_upstream = p->upstreams->current++; | 453 p->cur_upstream = p->upstreams->current++; |
448 | 454 |
449 if (p->upstreams->current >= p->upstreams->number) { | 455 if (p->upstreams->current >= p->upstreams->number) { |
450 p->upstreams->current = 0; | 456 p->upstreams->current = 0; |
463 if (p->upstreams->max_fails > 0) { | 469 if (p->upstreams->max_fails > 0) { |
464 | 470 |
465 for ( ;; ) { | 471 for ( ;; ) { |
466 u = &p->upstreams->u[p->cur_upstream]; | 472 u = &p->upstreams->u[p->cur_upstream]; |
467 | 473 |
474 | |
468 /* Here is the race condition | 475 /* Here is the race condition |
469 when the upstreams are shared between threads or processes | 476 when the upstreams are shared between |
470 but it should not be serious */ | 477 the threads or the processes but it should not be serious */ |
471 | 478 |
472 if (u->fails > p->upstreams->max_fails | 479 if (u->fails > p->upstreams->max_fails |
473 || u->accessed < p->upstreams->fail_timeout) | 480 || u->accessed < p->upstreams->fail_timeout) |
474 { | 481 { |
475 break; | 482 break; |
500 s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0); | 507 s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0); |
501 | 508 |
502 if (s == -1) { | 509 if (s == -1) { |
503 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, | 510 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, |
504 ngx_socket_n " failed"); | 511 ngx_socket_n " failed"); |
505 return NGX_ERROR; | 512 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
506 } | 513 } |
507 | 514 |
508 if (p->lcf->rcvbuf) { | 515 if (p->lcf->rcvbuf) { |
509 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, | 516 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, |
510 (const void *) &p->lcf->rcvbuf, sizeof(int)) == -1) { | 517 (const void *) &p->lcf->rcvbuf, sizeof(int)) == -1) { |
514 if (ngx_close_socket(s) == -1) { | 521 if (ngx_close_socket(s) == -1) { |
515 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, | 522 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, |
516 ngx_close_socket_n " failed"); | 523 ngx_close_socket_n " failed"); |
517 } | 524 } |
518 | 525 |
519 return NGX_ERROR; | 526 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
520 } | 527 } |
521 } | 528 } |
522 | 529 |
523 if (ngx_nonblocking(s) == -1) { | 530 if (ngx_nonblocking(s) == -1) { |
524 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, | 531 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, |
527 if (ngx_close_socket(s) == -1) { | 534 if (ngx_close_socket(s) == -1) { |
528 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, | 535 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, |
529 ngx_close_socket_n " failed"); | 536 ngx_close_socket_n " failed"); |
530 } | 537 } |
531 | 538 |
532 return NGX_ERROR; | 539 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
533 } | 540 } |
534 | 541 |
535 c = &ngx_connections[s]; | 542 c = &ngx_connections[s]; |
536 rev = &ngx_read_events[s]; | 543 rev = &ngx_read_events[s]; |
537 wev = &ngx_write_events[s]; | 544 wev = &ngx_write_events[s]; |
547 rev->first = wev->first = 1; | 554 rev->first = wev->first = 1; |
548 rev->log = wev->log = c->log = p->log; | 555 rev->log = wev->log = c->log = p->log; |
549 c->fd = s; | 556 c->fd = s; |
550 wev->close_handler = rev->close_handler = ngx_event_close_connection; | 557 wev->close_handler = rev->close_handler = ngx_event_close_connection; |
551 | 558 |
552 #if !(USE_KQUEUE) | |
553 | |
554 #if (HAVE_EDGE_EVENT) /* epoll */ | |
555 | |
556 if (ngx_event_flags & NGX_HAVE_EDGE_EVENT) { | 559 if (ngx_event_flags & NGX_HAVE_EDGE_EVENT) { |
557 if (ngx_edge_add_event(wev) != NGX_OK) { | 560 if (ngx_edge_add_event(wev) != NGX_OK) { |
558 return NGX_ERROR; | 561 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
559 } | 562 } |
560 } | 563 } |
561 | |
562 #endif | |
563 | |
564 #endif | |
565 | 564 |
566 ngx_test_null(c->pool, ngx_create_pool(p->lcf->conn_pool_size, p->log), | 565 ngx_test_null(c->pool, ngx_create_pool(p->lcf->conn_pool_size, p->log), |
567 NGX_ERROR); | 566 NGX_HTTP_INTERNAL_SERVER_ERROR); |
568 | 567 |
569 ngx_test_null(p->sockaddr, | 568 ngx_test_null(p->sockaddr, |
570 ngx_pcalloc(c->pool, sizeof(struct sockaddr_in)), | 569 ngx_pcalloc(c->pool, sizeof(struct sockaddr_in)), |
571 NGX_ERROR); | 570 NGX_HTTP_INTERNAL_SERVER_ERROR); |
572 | 571 |
573 addr = (struct sockaddr_in *) p->sockaddr; | 572 addr = (struct sockaddr_in *) p->sockaddr; |
574 | 573 |
575 addr->sin_family = AF_INET; | 574 addr->sin_family = AF_INET; |
576 addr->sin_addr.s_addr = p->upstreams->u[p->cur_upstream].addr; | 575 addr->sin_addr.s_addr = p->upstreams->u[p->cur_upstream].addr; |
586 if (ngx_close_socket(s) == -1) { | 585 if (ngx_close_socket(s) == -1) { |
587 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, | 586 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, |
588 ngx_close_socket_n " failed"); | 587 ngx_close_socket_n " failed"); |
589 } | 588 } |
590 | 589 |
591 ngx_destroy_pool(c->pool); | |
592 | |
593 return NGX_HTTP_BAD_GATEWAY; | 590 return NGX_HTTP_BAD_GATEWAY; |
594 } | 591 } |
595 } | 592 } |
596 | 593 |
597 c->data = p->request; | 594 c->data = p->request; |
598 p->connection = c; | 595 p->connection = c; |
599 | 596 |
600 ngx_test_null(c->pool, ngx_create_pool(p->lcf->conn_pool_size, p->log), | 597 if ((ngx_event_flags & NGX_HAVE_EDGE_EVENT) == 0) { /* not epoll */ |
601 NGX_ERROR); | 598 |
602 | 599 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { /* kqueue */ |
603 #if (USE_KQUEUE) | |
604 | |
605 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT) != NGX_OK) { | |
606 return NGX_ERROR; | |
607 } | |
608 | |
609 #else | |
610 | |
611 if ((ngx_event_flags & NGX_HAVE_EDGE_EVENT) == 0) { /* not epoll */ | |
612 | |
613 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { /* kqueue */ | |
614 event = NGX_CLEAR_EVENT; | 600 event = NGX_CLEAR_EVENT; |
615 | 601 |
616 } else { /* select, poll, /dev/poll */ | 602 } else { /* select, poll, /dev/poll */ |
617 event = NGX_LEVEL_EVENT; | 603 event = NGX_LEVEL_EVENT; |
618 } | 604 } |
619 | 605 |
620 /* TODO: aio, iocp */ | 606 /* TODO: aio, iocp */ |
621 | 607 |
622 if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) { | 608 if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) { |
623 return NGX_ERROR; | 609 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
624 } | 610 } |
625 } | 611 } |
626 | |
627 #endif /* USE_KQUEUE */ | |
628 | 612 |
629 wev->event_handler = rev->event_handler = | 613 wev->event_handler = rev->event_handler = |
630 ngx_http_proxy_process_upstream_event; | 614 ngx_http_proxy_process_upstream_event; |
631 | 615 |
632 p->state_write_upstream_handler = ngx_http_proxy_send_request; | 616 p->state_write_upstream_handler = ngx_http_proxy_send_request; |
643 /* The connection is in a progress */ | 627 /* The connection is in a progress */ |
644 | 628 |
645 wev->timer_set = 1; | 629 wev->timer_set = 1; |
646 ngx_add_timer(wev, p->lcf->connect_timeout); | 630 ngx_add_timer(wev, p->lcf->connect_timeout); |
647 | 631 |
648 #if (USE_KQUEUE) | |
649 | |
650 if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) != NGX_OK) { | |
651 return NGX_ERROR; | |
652 } | |
653 | |
654 #else | |
655 | |
656 /* TODO: aio, iocp */ | 632 /* TODO: aio, iocp */ |
657 | 633 |
658 if (ngx_event_flags & NGX_HAVE_EDGE_EVENT) { | 634 if (ngx_event_flags & NGX_HAVE_EDGE_EVENT) { |
659 return NGX_DONE; | 635 return NGX_DONE; |
660 } | 636 } |
661 | 637 |
662 if (ngx_add_event(wev, NGX_WRITE_EVENT, event) != NGX_OK) { | 638 if (ngx_add_event(wev, NGX_WRITE_EVENT, event) != NGX_OK) { |
663 return NGX_ERROR; | 639 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
664 } | 640 } |
665 | |
666 #endif /* USE_KQUEUE */ | |
667 | 641 |
668 return NGX_DONE; | 642 return NGX_DONE; |
669 } | 643 } |
670 | 644 |
671 | 645 |
1121 { | 1095 { |
1122 return ngx_event_proxy_write_to_downstream(p->event_proxy); | 1096 return ngx_event_proxy_write_to_downstream(p->event_proxy); |
1123 } | 1097 } |
1124 | 1098 |
1125 | 1099 |
1126 #if 0 | |
1127 static int ngx_http_proxy_read_upstream_body(ngx_event_t *rev) | |
1128 { | |
1129 int rc, n, size, eof; | |
1130 ngx_hunk_t *h; | |
1131 ngx_chain_t *chain, *ce, *tce; | |
1132 ngx_event_t *wev; | |
1133 ngx_connection_t *c; | |
1134 ngx_http_request_t *r; | |
1135 ngx_http_proxy_ctx_t *p; | |
1136 | |
1137 c = (ngx_connection_t *) rev->data; | |
1138 r = (ngx_http_request_t *) c->data; | |
1139 p = (ngx_http_proxy_ctx_t *) | |
1140 ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); | |
1141 | |
1142 eof = 0; | |
1143 | |
1144 for ( ;; ) { | |
1145 | |
1146 #if (USE_KQUEUE) | |
1147 | |
1148 if (ev->eof && ev->available == 0) { | |
1149 eof = 1; | |
1150 break; | |
1151 } | |
1152 | |
1153 #elif (HAVE_KQUEUE0) | |
1154 | |
1155 if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT | |
1156 && ev->eof && ev->available == 0) | |
1157 { | |
1158 eof = 1; | |
1159 break; | |
1160 } | |
1161 | |
1162 #endif | |
1163 | |
1164 /* use the free hunks if they exist */ | |
1165 | |
1166 if (p->free_hunks) { | |
1167 chain = p->free_hunks; | |
1168 p->free_hunks = NULL; | |
1169 | |
1170 /* allocate a new hunk if it's still allowed */ | |
1171 | |
1172 } else if (p->allocated < p->lcf->max_block_size) { | |
1173 ngx_test_null(h, | |
1174 ngx_create_temp_hunk(r->pool, p->block_size, 50, 50), | |
1175 NGX_ERROR); | |
1176 | |
1177 p->allocated += p->block_size; | |
1178 | |
1179 ngx_test_null(tce, ngx_create_chain_entry(r->pool), NGX_ERROR); | |
1180 tce->hunk = h; | |
1181 tce->next = NULL; | |
1182 chain = tce; | |
1183 | |
1184 /* use the shadow hunks if they exist */ | |
1185 | |
1186 } else if (p->shadow_hunks) { | |
1187 chain = p->shadow_hunks; | |
1188 p->shadow_hunks = NULL; | |
1189 | |
1190 /* write all the incoming hunks or the first hunk only | |
1191 to a temporary file and convert them to the shadow hunks */ | |
1192 | |
1193 } else { | |
1194 if (r->cachable) { | |
1195 rc = ngx_http_proxy_write_chain_to_temp_file(p); | |
1196 if (rc != NGX_OK) { | |
1197 return rc; | |
1198 } | |
1199 | |
1200 } else { | |
1201 tce = p->in_hunks->next; | |
1202 p->in_hunks->next = NULL; | |
1203 | |
1204 rc = ngx_http_proxy_write_chain_to_temp_file(p); | |
1205 if (rc != NGX_OK) { | |
1206 p->in_hunks = tce; | |
1207 return rc; | |
1208 } | |
1209 | |
1210 p->in_hunks = tce; | |
1211 } | |
1212 } | |
1213 | |
1214 n = ngx_recv_chain(c, chain); | |
1215 | |
1216 if (n == NGX_ERROR) { | |
1217 return NGX_ERROR; | |
1218 } | |
1219 | |
1220 if (n == NGX_AGAIN) { | |
1221 return NGX_AGAIN; | |
1222 } | |
1223 | |
1224 if (n == 0) { | |
1225 eof = 1; | |
1226 break; | |
1227 } | |
1228 | |
1229 for (ce = chain; ce && n > 0; ce = ce->next) { | |
1230 ngx_test_null(tce, ngx_create_chain_entry(r->pool), NGX_ERROR); | |
1231 tce->hunk = ce->hunk; | |
1232 tce->next = NULL; | |
1233 | |
1234 if (p->last_in_hunk) { | |
1235 p->last_in_hunk->next = tce; | |
1236 p->last_in_hunk = tce; | |
1237 | |
1238 } else { | |
1239 p->last_in_hunk = tce; | |
1240 } | |
1241 | |
1242 size = ce->hunk->end - ce->hunk->last; | |
1243 | |
1244 if (n >= size) { | |
1245 n -= size; | |
1246 ce->hunk->last = ce->hunk->end; | |
1247 if (ce->hunk->shadow) { | |
1248 ce->hunk->shadow->type &= ~(NGX_HUNK_TEMP | |
1249 |NGX_HUNK_IN_MEMORY | |
1250 |NGX_HUNK_RECYCLED); | |
1251 ce->hunk->shadow->shadow = NULL; | |
1252 | |
1253 } | |
1254 | |
1255 continue; | |
1256 } | |
1257 | |
1258 ce->hunk->last += n; | |
1259 if (ce->hunk->shadow) { | |
1260 ce->hunk->shadow->type &= ~(NGX_HUNK_TEMP | |
1261 |NGX_HUNK_IN_MEMORY | |
1262 |NGX_HUNK_RECYCLED); | |
1263 ce->hunk->shadow->shadow = NULL; | |
1264 } | |
1265 | |
1266 break; | |
1267 } | |
1268 | |
1269 if (ce) { | |
1270 ce->next = p->free_hunks; | |
1271 p->free_hunks = ce; | |
1272 break; | |
1273 } | |
1274 } | |
1275 | |
1276 wev = p->request->connection->write; | |
1277 | |
1278 if (r->cachable) { | |
1279 if (p->in_hunks) { | |
1280 rc = ngx_http_proxy_write_chain_to_temp_file(p); | |
1281 if (rc != NGX_OK) { | |
1282 return rc; | |
1283 } | |
1284 } | |
1285 | |
1286 if (p->out_hunks && wev->ready) { | |
1287 return ngx_http_proxy_write_upstream_body(wev); | |
1288 } | |
1289 | |
1290 } else { | |
1291 if ((p->out_hunks || p->in_hunks) && wev->ready) { | |
1292 return ngx_http_proxy_write_upstream_body(wev); | |
1293 } | |
1294 } | |
1295 | |
1296 return NGX_OK; | |
1297 } | |
1298 | |
1299 | |
1300 static int ngx_http_proxy_write_chain_to_temp_file(ngx_http_proxy_ctx_t *p) | |
1301 { | |
1302 int i, rc; | |
1303 ngx_hunk_t *h; | |
1304 ngx_chain_t *ce, *tce; | |
1305 | |
1306 if (p->temp_file->fd == NGX_INVALID_FILE) { | |
1307 rc = ngx_create_temp_file(p->temp_file, p->lcf->temp_path, | |
1308 p->request->pool, | |
1309 0, 2, | |
1310 p->request->cachable); | |
1311 | |
1312 if (rc != NGX_OK) { | |
1313 return rc; | |
1314 } | |
1315 | |
1316 if (p->lcf->temp_file_warn) { | |
1317 ngx_log_error(NGX_LOG_WARN, p->log, 0, | |
1318 "an upstream response is buffered " | |
1319 "to a temporary file"); | |
1320 } | |
1321 } | |
1322 | |
1323 if (ngx_write_chain_to_file(p->temp_file, p->in_hunks, | |
1324 p->temp_offset, p->request->pool) == NGX_ERROR) { | |
1325 return NGX_ERROR; | |
1326 } | |
1327 | |
1328 for (ce = p->in_hunks; ce; ce = ce->next) { | |
1329 ngx_test_null(h, ngx_pcalloc(p->request->pool, sizeof(ngx_hunk_t)), | |
1330 NGX_ERROR); | |
1331 | |
1332 h->type = NGX_HUNK_FILE | |
1333 |NGX_HUNK_TEMP|NGX_HUNK_IN_MEMORY|NGX_HUNK_RECYCLED; | |
1334 | |
1335 ce->hunk->shadow = h; | |
1336 h->shadow = ce->hunk; | |
1337 | |
1338 h->file_pos = p->temp_offset; | |
1339 p->temp_offset += ce->hunk->last - ce->hunk->pos; | |
1340 h->file_last = p->temp_offset; | |
1341 | |
1342 h->file->fd = p->temp_file->fd; | |
1343 h->file->log = p->log; | |
1344 | |
1345 h->pos = ce->hunk->pos; | |
1346 h->last = ce->hunk->last; | |
1347 h->start = ce->hunk->start; | |
1348 h->end = ce->hunk->end; | |
1349 h->pre_start = ce->hunk->pre_start; | |
1350 h->post_end = ce->hunk->post_end; | |
1351 | |
1352 ngx_test_null(tce, ngx_create_chain_entry(p->request->pool), NGX_ERROR); | |
1353 tce->hunk = h; | |
1354 tce->next = NULL; | |
1355 | |
1356 if (p->last_out_hunk) { | |
1357 p->last_out_hunk->next = tce; | |
1358 p->last_out_hunk = tce; | |
1359 | |
1360 } else { | |
1361 p->last_out_hunk = tce; | |
1362 } | |
1363 } | |
1364 | |
1365 return NGX_OK; | |
1366 } | |
1367 | |
1368 static int ngx_http_proxy_write_upstream_body(ngx_event_t *wev) | |
1369 { | |
1370 int rc; | |
1371 ngx_hunk_t *h, *sh; | |
1372 ngx_chain_t *ce; | |
1373 ngx_connection_t *c; | |
1374 ngx_http_request_t *r; | |
1375 ngx_http_proxy_ctx_t *p; | |
1376 | |
1377 c = (ngx_connection_t *) wev->data; | |
1378 r = (ngx_http_request_t *) c->data; | |
1379 p = (ngx_http_proxy_ctx_t *) | |
1380 ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); | |
1381 | |
1382 while (p->out_hunks) { | |
1383 h = p->out_hunks->hunk; | |
1384 rc = ngx_http_output_filter(r, h); | |
1385 | |
1386 if (rc == NGX_ERROR) { | |
1387 return NGX_ERROR; | |
1388 } | |
1389 | |
1390 if (rc == NGX_AGAIN || h->pos < h->last) { | |
1391 return NGX_AGAIN; | |
1392 } | |
1393 | |
1394 p->out_hunks = p->out_hunks->next; | |
1395 | |
1396 /* if the complete hunk has a shadow hunk | |
1397 then add a shadow hunk to p->free_hunks chain */ | |
1398 | |
1399 sh = h->shadow; | |
1400 | |
1401 if (sh) { | |
1402 sh->pos = sh->last = sh->start; | |
1403 ngx_test_null(ce, ngx_create_chain_entry(r->pool), NGX_ERROR); | |
1404 ce->hunk = sh; | |
1405 ce->next = p->free_hunks; | |
1406 p->free_hunks = ce; | |
1407 } | |
1408 } | |
1409 | |
1410 return NGX_OK; | |
1411 } | |
1412 | |
1413 | |
1414 #endif | |
1415 | |
1416 | |
1417 | |
1418 | |
1419 static int ngx_http_proxy_read_response_body(ngx_event_t *ev) | |
1420 { | |
1421 int n; | |
1422 char *buf; | |
1423 size_t left, size; | |
1424 ngx_hunk_t *h, **ph; | |
1425 ngx_connection_t *c; | |
1426 ngx_http_request_t *r; | |
1427 ngx_http_proxy_ctx_t *p; | |
1428 | |
1429 if (ev->timedout) { | |
1430 return NGX_ERROR; | |
1431 } | |
1432 | |
1433 c = (ngx_connection_t *) ev->data; | |
1434 r = (ngx_http_request_t *) c->data; | |
1435 p = (ngx_http_proxy_ctx_t *) | |
1436 ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); | |
1437 | |
1438 if (p->hunks.nelts > 0) { | |
1439 h = ((ngx_hunk_t **) p->hunks.elts)[p->hunks.nelts - 1]; | |
1440 left = h->end - h->last; | |
1441 | |
1442 } else { | |
1443 h = NULL; | |
1444 left = 0; | |
1445 } | |
1446 | |
1447 do { | |
1448 | |
1449 #if (USE_KQUEUE) | |
1450 | |
1451 /* do not allocate new block if there is EOF */ | |
1452 if (ev->eof && ev->available == 0) { | |
1453 left = 1; | |
1454 } | |
1455 | |
1456 #elif (HAVE_KQUEUE) | |
1457 | |
1458 if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT) { | |
1459 /* do not allocate new block if there is EOF */ | |
1460 if (ev->eof && ev->available == 0) { | |
1461 left = 1; | |
1462 } | |
1463 } | |
1464 | |
1465 #endif | |
1466 | |
1467 if (left == 0) { | |
1468 ngx_test_null(ph, ngx_push_array(&p->hunks), NGX_ERROR); | |
1469 ngx_test_null(h, | |
1470 ngx_create_temp_hunk(r->pool, | |
1471 /* STUB */ 4096 /**/, 0, 0), | |
1472 NGX_ERROR); | |
1473 | |
1474 h->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY; | |
1475 *ph = h; | |
1476 } | |
1477 | |
1478 if (h != NULL) { | |
1479 buf = h->last; | |
1480 size = h->end - h->last; | |
1481 | |
1482 } else { | |
1483 buf = (char *) &buf; | |
1484 size = 0; | |
1485 } | |
1486 | |
1487 n = ngx_event_recv(c, buf, size); | |
1488 | |
1489 ngx_log_debug(c->log, "READ:%d" _ n); | |
1490 | |
1491 if (n == NGX_AGAIN) { | |
1492 return NGX_DONE; | |
1493 } | |
1494 | |
1495 if (n == NGX_ERROR) { | |
1496 return NGX_ERROR; | |
1497 } | |
1498 | |
1499 h->last += n; | |
1500 left = h->end - h->last; | |
1501 | |
1502 /* STUB */ | |
1503 *h->last = '\0'; | |
1504 ngx_log_debug(c->log, "PROXY:\n'%s'" _ h->pos); | |
1505 /**/ | |
1506 | |
1507 } while (n > 0 && left == 0); | |
1508 | |
1509 if (n == 0) { | |
1510 ngx_log_debug(c->log, "CLOSE proxy"); | |
1511 #if 0 | |
1512 ngx_del_event(ev, NGX_READ_EVENT, NGX_CLOSE_EVENT); | |
1513 #endif | |
1514 ngx_event_close_connection(ev); | |
1515 | |
1516 p->hunk_n = 0; | |
1517 c->write->event_handler = ngx_http_proxy_write_to_client; | |
1518 return ngx_http_proxy_write_to_client(c->write); | |
1519 } | |
1520 | |
1521 /* STUB */ return NGX_DONE; | |
1522 } | |
1523 | |
1524 | |
1525 static int ngx_http_proxy_write_to_client(ngx_event_t *ev) | |
1526 { | |
1527 int rc; | |
1528 ngx_hunk_t *h; | |
1529 ngx_connection_t *c; | |
1530 ngx_http_request_t *r; | |
1531 ngx_http_proxy_ctx_t *p; | |
1532 | |
1533 c = (ngx_connection_t *) ev->data; | |
1534 r = (ngx_http_request_t *) c->data; | |
1535 p = (ngx_http_proxy_ctx_t *) | |
1536 ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); | |
1537 | |
1538 do { | |
1539 h = ((ngx_hunk_t **) p->hunks.elts)[p->hunk_n]; | |
1540 | |
1541 rc = ngx_http_output_filter(r, h); | |
1542 if (rc != NGX_OK) { | |
1543 return rc; | |
1544 } | |
1545 | |
1546 if (p->hunk_n >= p->hunks.nelts) { | |
1547 break; | |
1548 } | |
1549 | |
1550 p->hunk_n++; | |
1551 | |
1552 } while (rc == NGX_OK); | |
1553 | |
1554 return NGX_OK; | |
1555 } | |
1556 | 1100 |
1557 | 1101 |
1558 static int ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int error) | 1102 static int ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int error) |
1559 { | 1103 { |
1560 return ngx_http_finalize_request(p->request, error); | 1104 return ngx_http_finalize_request(p->request, error); |