Lines 143-148
static int proxy_connect_canon(request_rec *r, cha
Link Here
|
143 |
return OK; |
143 |
return OK; |
144 |
} |
144 |
} |
145 |
|
145 |
|
|
|
146 |
struct proxy_connect_conn |
147 |
{ |
148 |
conn_rec *c; |
149 |
const char *name; |
150 |
apr_bucket_brigade *bb; |
151 |
ap_filter_t *core_filter; |
152 |
ap_out_filter_func core_output; |
153 |
apr_interval_time_t timeout; |
154 |
struct proxy_connect_conn *other; |
155 |
unsigned int readable:1, |
156 |
drain:1; |
157 |
apr_pollfd_t pfd; |
158 |
}; |
159 |
|
160 |
static void add_pollset(apr_pollset_t *pollset, |
161 |
struct proxy_connect_conn *conn, |
162 |
apr_int16_t events) |
163 |
{ |
164 |
apr_status_t rv; |
165 |
|
166 |
if ((conn->pfd.reqevents & events) != 0) { |
167 |
return; |
168 |
} |
169 |
|
170 |
if (conn->pfd.reqevents) { |
171 |
rv = apr_pollset_remove(pollset, &conn->pfd); |
172 |
if (rv != APR_SUCCESS) { |
173 |
AP_DEBUG_ASSERT(1); |
174 |
} |
175 |
} |
176 |
|
177 |
conn->pfd.reqevents |= events; |
178 |
rv = apr_pollset_add(pollset, &conn->pfd); |
179 |
if (rv != APR_SUCCESS) { |
180 |
AP_DEBUG_ASSERT(1); |
181 |
} |
182 |
} |
183 |
|
184 |
static void del_pollset(apr_pollset_t *pollset, |
185 |
struct proxy_connect_conn *conn, |
186 |
apr_int16_t events) |
187 |
{ |
188 |
apr_status_t rv; |
189 |
|
190 |
if ((conn->pfd.reqevents & events) == 0) { |
191 |
return; |
192 |
} |
193 |
|
194 |
rv = apr_pollset_remove(pollset, &conn->pfd); |
195 |
if (rv != APR_SUCCESS) { |
196 |
AP_DEBUG_ASSERT(1); |
197 |
} |
198 |
|
199 |
conn->pfd.reqevents &= ~events; |
200 |
if (conn->pfd.reqevents) { |
201 |
rv = apr_pollset_add(pollset, &conn->pfd); |
202 |
if (rv != APR_SUCCESS) { |
203 |
AP_DEBUG_ASSERT(1); |
204 |
} |
205 |
} |
206 |
} |
207 |
|
146 |
/* CONNECT handler */ |
208 |
/* CONNECT handler */ |
147 |
static int proxy_connect_handler(request_rec *r, proxy_worker *worker, |
209 |
static int proxy_connect_handler(request_rec *r, proxy_worker *worker, |
148 |
proxy_server_conf *conf, |
210 |
proxy_server_conf *conf, |
Lines 153-176
static int proxy_connect_handler(request_rec *r, p
Link Here
|
153 |
ap_get_module_config(r->server->module_config, &proxy_connect_module); |
215 |
ap_get_module_config(r->server->module_config, &proxy_connect_module); |
154 |
|
216 |
|
155 |
apr_pool_t *p = r->pool; |
217 |
apr_pool_t *p = r->pool; |
156 |
apr_socket_t *sock; |
|
|
157 |
conn_rec *c = r->connection; |
218 |
conn_rec *c = r->connection; |
158 |
conn_rec *backconn; |
|
|
159 |
int done = 0; |
160 |
|
161 |
apr_bucket_brigade *bb_front; |
162 |
apr_bucket_brigade *bb_back; |
163 |
apr_status_t rv; |
219 |
apr_status_t rv; |
164 |
apr_size_t nbytes; |
220 |
apr_size_t nbytes; |
165 |
char buffer[HUGE_STRING_LEN]; |
221 |
char buffer[HUGE_STRING_LEN]; |
166 |
apr_socket_t *client_socket = ap_get_conn_socket(c); |
222 |
int failed = 0, rc; |
167 |
int failed, rc; |
|
|
168 |
apr_pollset_t *pollset; |
223 |
apr_pollset_t *pollset; |
169 |
apr_pollfd_t pollfd; |
|
|
170 |
const apr_pollfd_t *signalled; |
224 |
const apr_pollfd_t *signalled; |
171 |
apr_int32_t pollcnt, pi; |
225 |
apr_int32_t pollcnt, pi; |
172 |
apr_int16_t pollevent; |
|
|
173 |
apr_sockaddr_t *nexthop; |
226 |
apr_sockaddr_t *nexthop; |
|
|
227 |
apr_interval_time_t timeout; |
228 |
struct proxy_connect_conn conns[2], *client, *backend; |
229 |
#if AP_MODULE_MAGIC_AT_LEAST(20120211, 69) |
230 |
apr_size_t read_buf_size = ap_get_read_buf_size(r); |
231 |
#else |
232 |
apr_size_t read_buf_size = CONN_BLKSZ; |
233 |
#endif |
174 |
|
234 |
|
175 |
apr_uri_t uri; |
235 |
apr_uri_t uri; |
176 |
const char *connectname; |
236 |
const char *connectname; |
Lines 237-243
static int proxy_connect_handler(request_rec *r, p
Link Here
|
237 |
* |
297 |
* |
238 |
* We have determined who to connect to. Now make the connection. |
298 |
* We have determined who to connect to. Now make the connection. |
239 |
*/ |
299 |
*/ |
|
|
300 |
memset(conns, 0, sizeof conns); |
240 |
|
301 |
|
|
|
302 |
client = &conns[0]; |
303 |
client->pfd.p = p; |
304 |
client->pfd.desc_type = APR_POLL_SOCKET; |
305 |
client->pfd.desc.s = ap_get_conn_socket(c); |
306 |
client->pfd.reqevents = APR_POLLIN | APR_POLLHUP; |
307 |
client->pfd.client_data = client; |
308 |
client->name = "client"; |
309 |
client->readable = 1; |
310 |
client->c = c; |
311 |
|
312 |
backend = &conns[1]; |
313 |
backend->pfd.p = p; |
314 |
backend->pfd.desc_type = APR_POLL_SOCKET; |
315 |
backend->pfd.reqevents = APR_POLLIN | APR_POLLHUP; |
316 |
backend->pfd.client_data = backend; |
317 |
backend->name = "backend"; |
318 |
backend->readable = 1; |
319 |
|
320 |
client->other = backend; |
321 |
backend->other = client; |
322 |
|
241 |
/* |
323 |
/* |
242 |
* At this point we have a list of one or more IP addresses of |
324 |
* At this point we have a list of one or more IP addresses of |
243 |
* the machine to connect to. If configured, reorder this |
325 |
* the machine to connect to. If configured, reorder this |
Lines 248-255
static int proxy_connect_handler(request_rec *r, p
Link Here
|
248 |
* For now we do nothing, ie we get DNS round robin. |
330 |
* For now we do nothing, ie we get DNS round robin. |
249 |
* XXX FIXME |
331 |
* XXX FIXME |
250 |
*/ |
332 |
*/ |
251 |
failed = ap_proxy_connect_to_backend(&sock, "CONNECT", nexthop, |
333 |
failed = ap_proxy_connect_to_backend(&backend->pfd.desc.s, "CONNECT", |
252 |
connectname, conf, r); |
334 |
nexthop, connectname, conf, r); |
253 |
|
335 |
|
254 |
/* handle a permanent error from the above loop */ |
336 |
/* handle a permanent error from the above loop */ |
255 |
if (failed) { |
337 |
if (failed) { |
Lines 261-288
static int proxy_connect_handler(request_rec *r, p
Link Here
|
261 |
} |
343 |
} |
262 |
} |
344 |
} |
263 |
|
345 |
|
264 |
/* setup polling for connection */ |
|
|
265 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "setting up poll()"); |
266 |
|
267 |
if ((rv = apr_pollset_create(&pollset, 2, r->pool, 0)) != APR_SUCCESS) { |
268 |
apr_socket_close(sock); |
269 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01020) |
270 |
"error apr_pollset_create()"); |
271 |
return HTTP_INTERNAL_SERVER_ERROR; |
272 |
} |
273 |
|
274 |
/* Add client side to the poll */ |
275 |
pollfd.p = r->pool; |
276 |
pollfd.desc_type = APR_POLL_SOCKET; |
277 |
pollfd.reqevents = APR_POLLIN | APR_POLLHUP; |
278 |
pollfd.desc.s = client_socket; |
279 |
pollfd.client_data = NULL; |
280 |
apr_pollset_add(pollset, &pollfd); |
281 |
|
282 |
/* Add the server side to the poll */ |
283 |
pollfd.desc.s = sock; |
284 |
apr_pollset_add(pollset, &pollfd); |
285 |
|
286 |
/* |
346 |
/* |
287 |
* Step Three: Send the Request |
347 |
* Step Three: Send the Request |
288 |
* |
348 |
* |
Lines 289-308
static int proxy_connect_handler(request_rec *r, p
Link Here
|
289 |
* Send the HTTP/1.1 CONNECT request to the remote server |
349 |
* Send the HTTP/1.1 CONNECT request to the remote server |
290 |
*/ |
350 |
*/ |
291 |
|
351 |
|
292 |
backconn = ap_run_create_connection(c->pool, r->server, sock, |
352 |
backend->c = ap_run_create_connection(c->pool, r->server, |
293 |
c->id, c->sbh, c->bucket_alloc); |
353 |
backend->pfd.desc.s, 0, NULL, |
294 |
if (!backconn) { |
354 |
c->bucket_alloc); |
|
|
355 |
if (!backend->c) { |
295 |
/* peer reset */ |
356 |
/* peer reset */ |
296 |
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01021) |
357 |
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01021) |
297 |
"an error occurred creating a new connection " |
358 |
"an error occurred creating a new connection " |
298 |
"to %pI (%s)", nexthop, connectname); |
359 |
"to %pI (%s)", nexthop, connectname); |
299 |
apr_socket_close(sock); |
360 |
apr_socket_close(backend->pfd.desc.s); |
300 |
return HTTP_INTERNAL_SERVER_ERROR; |
361 |
return HTTP_INTERNAL_SERVER_ERROR; |
301 |
} |
362 |
} |
302 |
ap_proxy_ssl_disable(backconn); |
363 |
ap_proxy_ssl_disable(backend->c); |
303 |
rc = ap_run_pre_connection(backconn, sock); |
364 |
|
|
|
365 |
rc = ap_run_pre_connection(backend->c, backend->pfd.desc.s); |
304 |
if (rc != OK && rc != DONE) { |
366 |
if (rc != OK && rc != DONE) { |
305 |
backconn->aborted = 1; |
367 |
backend->c->aborted = 1; |
306 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01022) |
368 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01022) |
307 |
"pre_connection setup failed (%d)", rc); |
369 |
"pre_connection setup failed (%d)", rc); |
308 |
return HTTP_INTERNAL_SERVER_ERROR; |
370 |
return HTTP_INTERNAL_SERVER_ERROR; |
Lines 312-323
static int proxy_connect_handler(request_rec *r, p
Link Here
|
312 |
"connection complete to %pI (%s)", |
374 |
"connection complete to %pI (%s)", |
313 |
nexthop, connectname); |
375 |
nexthop, connectname); |
314 |
apr_table_setn(r->notes, "proxy-source-port", apr_psprintf(r->pool, "%hu", |
376 |
apr_table_setn(r->notes, "proxy-source-port", apr_psprintf(r->pool, "%hu", |
315 |
backconn->local_addr->port)); |
377 |
backend->c->local_addr->port)); |
316 |
|
378 |
|
|
|
379 |
client->bb = apr_brigade_create(p, client->c->bucket_alloc); |
380 |
backend->bb = apr_brigade_create(p, backend->c->bucket_alloc); |
317 |
|
381 |
|
318 |
bb_front = apr_brigade_create(p, c->bucket_alloc); |
|
|
319 |
bb_back = apr_brigade_create(p, backconn->bucket_alloc); |
320 |
|
321 |
/* If we are connecting through a remote proxy, we need to pass |
382 |
/* If we are connecting through a remote proxy, we need to pass |
322 |
* the CONNECT request on to it. |
383 |
* the CONNECT request on to it. |
323 |
*/ |
384 |
*/ |
Lines 326-336
static int proxy_connect_handler(request_rec *r, p
Link Here
|
326 |
*/ |
387 |
*/ |
327 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, |
388 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, |
328 |
"sending the CONNECT request to the remote proxy"); |
389 |
"sending the CONNECT request to the remote proxy"); |
329 |
ap_fprintf(backconn->output_filters, bb_back, |
390 |
ap_fprintf(backend->c->output_filters, backend->bb, |
330 |
"CONNECT %s HTTP/1.0" CRLF, r->uri); |
391 |
"CONNECT %s HTTP/1.0" CRLF, r->uri); |
331 |
ap_fprintf(backconn->output_filters, bb_back, |
392 |
ap_fprintf(backend->c->output_filters, backend->bb, |
332 |
"Proxy-agent: %s" CRLF CRLF, ap_get_server_banner()); |
393 |
"Proxy-agent: %s" CRLF CRLF, ap_get_server_banner()); |
333 |
ap_fflush(backconn->output_filters, bb_back); |
394 |
ap_fflush(backend->c->output_filters, backend->bb); |
334 |
} |
395 |
} |
335 |
else { |
396 |
else { |
336 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Returning 200 OK"); |
397 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Returning 200 OK"); |
Lines 337-349
static int proxy_connect_handler(request_rec *r, p
Link Here
|
337 |
nbytes = apr_snprintf(buffer, sizeof(buffer), |
398 |
nbytes = apr_snprintf(buffer, sizeof(buffer), |
338 |
"HTTP/1.0 200 Connection Established" CRLF); |
399 |
"HTTP/1.0 200 Connection Established" CRLF); |
339 |
ap_xlate_proto_to_ascii(buffer, nbytes); |
400 |
ap_xlate_proto_to_ascii(buffer, nbytes); |
340 |
ap_fwrite(c->output_filters, bb_front, buffer, nbytes); |
401 |
ap_fwrite(client->c->output_filters, client->bb, buffer, nbytes); |
341 |
nbytes = apr_snprintf(buffer, sizeof(buffer), |
402 |
nbytes = apr_snprintf(buffer, sizeof(buffer), |
342 |
"Proxy-agent: %s" CRLF CRLF, |
403 |
"Proxy-agent: %s" CRLF CRLF, |
343 |
ap_get_server_banner()); |
404 |
ap_get_server_banner()); |
344 |
ap_xlate_proto_to_ascii(buffer, nbytes); |
405 |
ap_xlate_proto_to_ascii(buffer, nbytes); |
345 |
ap_fwrite(c->output_filters, bb_front, buffer, nbytes); |
406 |
ap_fwrite(client->c->output_filters, client->bb, buffer, nbytes); |
346 |
ap_fflush(c->output_filters, bb_front); |
407 |
ap_fflush(client->c->output_filters, client->bb); |
347 |
#if 0 |
408 |
#if 0 |
348 |
/* This is safer code, but it doesn't work yet. I'm leaving it |
409 |
/* This is safer code, but it doesn't work yet. I'm leaving it |
349 |
* here so that I can fix it later. |
410 |
* here so that I can fix it later. |
Lines 357-362
static int proxy_connect_handler(request_rec *r, p
Link Here
|
357 |
|
418 |
|
358 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "setting up poll()"); |
419 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "setting up poll()"); |
359 |
|
420 |
|
|
|
421 |
rv = apr_pollset_create(&pollset, 2, r->pool, APR_POLLSET_NOCOPY); |
422 |
if (rv != APR_SUCCESS) { |
423 |
apr_socket_close(backend->pfd.desc.s); |
424 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01020) |
425 |
"error apr_pollset_create()"); |
426 |
return HTTP_INTERNAL_SERVER_ERROR; |
427 |
} |
428 |
apr_pollset_add(pollset, &client->pfd); |
429 |
apr_pollset_add(pollset, &backend->pfd); |
430 |
|
360 |
/* |
431 |
/* |
361 |
* Step Four: Handle Data Transfer |
432 |
* Step Four: Handle Data Transfer |
362 |
* |
433 |
* |
Lines 364-450
static int proxy_connect_handler(request_rec *r, p
Link Here
|
364 |
*/ |
435 |
*/ |
365 |
|
436 |
|
366 |
/* we are now acting as a tunnel - the input/output filter stacks should |
437 |
/* we are now acting as a tunnel - the input/output filter stacks should |
367 |
* not contain any non-connection filters. |
438 |
* not contain any non-connection or coalescing filters. |
368 |
*/ |
439 |
*/ |
|
|
440 |
ap_remove_output_filter_byhandle(client->c->output_filters, |
441 |
"SSL/TLS Coalescing Filter"); |
442 |
ap_remove_output_filter_byhandle(backend->c->output_filters, |
443 |
"SSL/TLS Coalescing Filter"); |
369 |
r->output_filters = c->output_filters; |
444 |
r->output_filters = c->output_filters; |
370 |
r->proto_output_filters = c->output_filters; |
445 |
r->proto_output_filters = c->output_filters; |
371 |
r->input_filters = c->input_filters; |
446 |
r->input_filters = c->input_filters; |
372 |
r->proto_input_filters = c->input_filters; |
447 |
r->proto_input_filters = c->input_filters; |
373 |
/* r->sent_bodyct = 1;*/ |
448 |
/* r->sent_bodyct = 1;*/ |
374 |
|
449 |
|
375 |
do { /* Loop until done (one side closes the connection, or an error) */ |
450 |
client->core_filter = client->c->output_filters; |
376 |
rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled); |
451 |
while (client->core_filter->next) { |
|
|
452 |
client->core_filter = client->core_filter->next; |
453 |
} |
454 |
client->core_output = client->core_filter->frec->filter_func.out_func; |
455 |
|
456 |
backend->core_filter = backend->c->output_filters; |
457 |
while (backend->core_filter->next) { |
458 |
backend->core_filter = backend->core_filter->next; |
459 |
} |
460 |
backend->core_output = backend->core_filter->frec->filter_func.out_func; |
461 |
|
462 |
apr_socket_timeout_get(client->pfd.desc.s, &client->timeout); |
463 |
apr_socket_timeout_get(backend->pfd.desc.s, &backend->timeout); |
464 |
timeout = client->timeout < backend->timeout ? client->timeout |
465 |
: backend->timeout; |
466 |
|
467 |
/* Loop until both sides close the connection, or a failure */ |
468 |
do { |
469 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, |
470 |
"events to poll(): client=0x%.2x, backend=0x%.2x", |
471 |
(int)client->pfd.reqevents, (int)backend->pfd.reqevents); |
472 |
|
473 |
rv = apr_pollset_poll(pollset, timeout, &pollcnt, &signalled); |
377 |
if (rv != APR_SUCCESS) { |
474 |
if (rv != APR_SUCCESS) { |
378 |
if (APR_STATUS_IS_EINTR(rv)) { |
475 |
if (APR_STATUS_IS_EINTR(rv)) { |
379 |
continue; |
476 |
continue; |
380 |
} |
477 |
} |
381 |
apr_socket_close(sock); |
478 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01023) "polling"); |
382 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01023) "error apr_poll()"); |
479 |
failed = 1; |
383 |
return HTTP_INTERNAL_SERVER_ERROR; |
480 |
break; |
384 |
} |
481 |
} |
385 |
#ifdef DEBUGGING |
|
|
386 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01024) |
387 |
"woke from poll(), i=%d", pollcnt); |
388 |
#endif |
389 |
|
482 |
|
|
|
483 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, APLOGNO(01024) |
484 |
"woke from poll(): num=%d", pollcnt); |
485 |
|
390 |
for (pi = 0; pi < pollcnt; pi++) { |
486 |
for (pi = 0; pi < pollcnt; pi++) { |
|
|
487 |
struct proxy_connect_conn *in, *out; |
391 |
const apr_pollfd_t *cur = &signalled[pi]; |
488 |
const apr_pollfd_t *cur = &signalled[pi]; |
|
|
489 |
int revents = cur->rtnevents, writable = 0; |
392 |
|
490 |
|
393 |
if (cur->desc.s == sock) { |
491 |
if (cur->desc.s != client->pfd.desc.s |
394 |
pollevent = cur->rtnevents; |
492 |
&& cur->desc.s != backend->pfd.desc.s) { |
395 |
if (pollevent & (APR_POLLIN | APR_POLLHUP)) { |
493 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01028) |
396 |
#ifdef DEBUGGING |
494 |
"unknown socket in pollset"); |
397 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01025) |
495 |
failed = 1; |
398 |
"sock was readable"); |
496 |
break; |
399 |
#endif |
497 |
} |
400 |
done |= ap_proxy_transfer_between_connections(r, backconn, |
498 |
|
401 |
c, bb_back, |
499 |
in = cur->client_data; |
402 |
bb_front, |
500 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, |
403 |
"sock", NULL, |
501 |
"loop #%i from poll(): %s=0x%.2x/0x%.2x", |
404 |
CONN_BLKSZ, 1) |
502 |
pi, in->name, (int)in->pfd.reqevents, revents); |
405 |
!= APR_SUCCESS; |
503 |
if (revents & APR_POLLOUT) { |
|
|
504 |
in = in->other; |
505 |
writable = 1; |
506 |
} |
507 |
else if (!(revents & (APR_POLLIN | APR_POLLHUP))) { |
508 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01026) |
509 |
"%s connection error, events 0x%x", |
510 |
in->name, revents); |
511 |
in->c->aborted = 1; |
512 |
failed = 1; |
513 |
break; |
514 |
} |
515 |
out = in->other; |
516 |
|
517 |
if (in->readable && (!writable || in->drain)) { |
518 |
int flush = 0; |
519 |
|
520 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, |
521 |
"%s is %s", in->name, writable ? "draining" |
522 |
: "readable"); |
523 |
|
524 |
rv = ap_proxy_transfer_between_connections(r, |
525 |
in->c, out->c, in->bb, out->bb, |
526 |
in->name, &flush, read_buf_size, |
527 |
AP_PROXY_TRANSFER_CHECK_FULL); |
528 |
if (rv != APR_SUCCESS) { |
529 |
if (APR_STATUS_IS_INCOMPLETE(rv)) { |
530 |
/* Pause POLLIN while waiting for POLLOUT on the other |
531 |
* side, hence avoid filling the output filters even |
532 |
* more and hence blocking there. |
533 |
*/ |
534 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, |
535 |
"%s wait writable", out->name); |
536 |
in->drain = 1; |
537 |
writable = 0; |
538 |
} |
539 |
else if (APR_STATUS_IS_EOF(rv)) { |
540 |
/* Stop POLLIN and wait for POLLOUT (and flush) on the |
541 |
* other side to shut it down. |
542 |
*/ |
543 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, |
544 |
"%s read shutdown", in->name); |
545 |
in->readable = in->drain = 0; |
546 |
} |
547 |
else { |
548 |
/* Real failure, bail out */ |
549 |
failed = 1; |
550 |
break; |
551 |
} |
552 |
del_pollset(pollset, in, APR_POLLIN | APR_POLLHUP); |
553 |
flush = 1; |
406 |
} |
554 |
} |
407 |
else if (pollevent & APR_POLLERR) { |
555 |
else { |
408 |
ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(01026) |
556 |
in->drain = 0; |
409 |
"err on backconn"); |
|
|
410 |
backconn->aborted = 1; |
411 |
done = 1; |
412 |
} |
557 |
} |
|
|
558 |
|
559 |
if (flush) { |
560 |
add_pollset(pollset, out, APR_POLLOUT); |
561 |
} |
413 |
} |
562 |
} |
414 |
else if (cur->desc.s == client_socket) { |
563 |
|
415 |
pollevent = cur->rtnevents; |
564 |
if (writable) { |
416 |
if (pollevent & (APR_POLLIN | APR_POLLHUP)) { |
565 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, |
417 |
#ifdef DEBUGGING |
566 |
"%s is writable", out->name); |
418 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01027) |
567 |
|
419 |
"client was readable"); |
568 |
rv = out->core_output(out->core_filter, NULL); |
420 |
#endif |
569 |
if (rv != APR_SUCCESS && !APR_STATUS_IS_EAGAIN(rv)) { |
421 |
done |= ap_proxy_transfer_between_connections(r, c, |
570 |
/* Real failure, bail out */ |
422 |
backconn, |
571 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO() |
423 |
bb_front, |
572 |
"%s output", out->name); |
424 |
bb_back, |
573 |
failed = 1; |
425 |
"client", |
574 |
break; |
426 |
NULL, |
|
|
427 |
CONN_BLKSZ, 1) |
428 |
!= APR_SUCCESS; |
429 |
} |
575 |
} |
430 |
else if (pollevent & APR_POLLERR) { |
576 |
|
431 |
ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02827) |
577 |
/* If the other conn is shutdown for read already and pending |
432 |
"err on client"); |
578 |
* data are flushed on this one, we can shutdown for write. |
433 |
c->aborted = 1; |
579 |
*/ |
434 |
done = 1; |
580 |
if (!out->c->data_in_output_filters) { |
|
|
581 |
if (in->readable) { |
582 |
add_pollset(pollset, in, APR_POLLIN | APR_POLLHUP); |
583 |
if (!in->drain) { |
584 |
del_pollset(pollset, out, APR_POLLOUT); |
585 |
} |
586 |
} |
587 |
else { |
588 |
del_pollset(pollset, out, APR_POLLOUT); |
589 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, |
590 |
"%s write shutdown", out->name); |
591 |
apr_socket_shutdown(out->pfd.desc.s, 1); |
592 |
} |
435 |
} |
593 |
} |
436 |
} |
594 |
} |
437 |
else { |
|
|
438 |
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01028) |
439 |
"unknown socket in pollset"); |
440 |
done = 1; |
441 |
} |
442 |
|
443 |
} |
595 |
} |
444 |
} while (!done); |
596 |
} while (!failed && (client->pfd.reqevents || backend->pfd.reqevents)); |
445 |
|
597 |
|
446 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, |
598 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, |
447 |
"finished with poll() - cleaning up"); |
599 |
"finished with poll(), full=%i - cleaning up", !failed); |
448 |
|
600 |
|
449 |
/* |
601 |
/* |
450 |
* Step Five: Clean Up |
602 |
* Step Five: Clean Up |
Lines 451-462
static int proxy_connect_handler(request_rec *r, p
Link Here
|
451 |
* |
603 |
* |
452 |
* Close the socket and clean up |
604 |
* Close the socket and clean up |
453 |
*/ |
605 |
*/ |
454 |
|
606 |
if (client->pfd.reqevents) { |
455 |
if (backconn->aborted) |
607 |
apr_pollset_remove(pollset, &client->pfd); |
456 |
apr_socket_close(sock); |
608 |
} |
457 |
else |
609 |
if (backend->pfd.reqevents) { |
458 |
ap_lingering_close(backconn); |
610 |
apr_pollset_remove(pollset, &backend->pfd); |
459 |
|
611 |
} |
|
|
612 |
apr_socket_close(backend->pfd.desc.s); |
460 |
c->keepalive = AP_CONN_CLOSE; |
613 |
c->keepalive = AP_CONN_CLOSE; |
461 |
|
614 |
|
462 |
return OK; |
615 |
return OK; |