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