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);