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 |
}; |
154 |
|
146 |
/* CONNECT handler */ |
155 |
/* CONNECT handler */ |
147 |
static int proxy_connect_handler(request_rec *r, proxy_worker *worker, |
156 |
static int proxy_connect_handler(request_rec *r, proxy_worker *worker, |
148 |
proxy_server_conf *conf, |
157 |
proxy_server_conf *conf, |
Lines 153-172
static int proxy_connect_handler(request_rec *r, p
Link Here
|
153 |
ap_get_module_config(r->server->module_config, &proxy_connect_module); |
162 |
ap_get_module_config(r->server->module_config, &proxy_connect_module); |
154 |
|
163 |
|
155 |
apr_pool_t *p = r->pool; |
164 |
apr_pool_t *p = r->pool; |
156 |
apr_socket_t *sock; |
|
|
157 |
conn_rec *c = r->connection; |
165 |
conn_rec *c = r->connection; |
158 |
conn_rec *backconn; |
166 |
struct proxy_connect_conn client, |
|
|
167 |
backend; |
159 |
int done = 0; |
168 |
int done = 0; |
160 |
|
|
|
161 |
apr_bucket_brigade *bb_front; |
162 |
apr_bucket_brigade *bb_back; |
163 |
apr_status_t rv; |
169 |
apr_status_t rv; |
164 |
apr_size_t nbytes; |
170 |
apr_size_t nbytes; |
165 |
char buffer[HUGE_STRING_LEN]; |
171 |
char buffer[HUGE_STRING_LEN]; |
166 |
apr_socket_t *client_socket = ap_get_conn_socket(c); |
|
|
167 |
int failed, rc; |
172 |
int failed, rc; |
168 |
apr_pollset_t *pollset; |
173 |
apr_pollset_t *pollset; |
169 |
apr_pollfd_t pollfd; |
|
|
170 |
const apr_pollfd_t *signalled; |
174 |
const apr_pollfd_t *signalled; |
171 |
apr_int32_t pollcnt, pi; |
175 |
apr_int32_t pollcnt, pi; |
172 |
apr_int16_t pollevent; |
176 |
apr_int16_t pollevent; |
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. |
242 |
* We have determined who to connect to. Now make the connection. |
239 |
*/ |
243 |
*/ |
240 |
|
244 |
|
|
|
245 |
client.c = c; |
246 |
client.pfd.p = p; |
247 |
client.pfd.client_data = NULL; |
248 |
client.pfd.reqevents = APR_POLLIN | APR_POLLHUP; |
249 |
client.pfd.desc_type = APR_POLL_SOCKET; |
250 |
client.pfd.desc.s = ap_get_conn_socket(c); |
251 |
|
252 |
backend.c = NULL; |
253 |
backend.pfd.p = p; |
254 |
backend.pfd.client_data = NULL; |
255 |
backend.pfd.reqevents = APR_POLLIN | APR_POLLHUP; |
256 |
backend.pfd.desc_type = APR_POLL_SOCKET; |
257 |
|
241 |
/* |
258 |
/* |
242 |
* At this point we have a list of one or more IP addresses of |
259 |
* At this point we have a list of one or more IP addresses of |
243 |
* the machine to connect to. If configured, reorder this |
260 |
* 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. |
265 |
* For now we do nothing, ie we get DNS round robin. |
249 |
* XXX FIXME |
266 |
* XXX FIXME |
250 |
*/ |
267 |
*/ |
251 |
failed = ap_proxy_connect_to_backend(&sock, "CONNECT", nexthop, |
268 |
failed = ap_proxy_connect_to_backend(&backend.pfd.desc.s, "CONNECT", |
252 |
connectname, conf, r); |
269 |
nexthop, connectname, conf, r); |
253 |
|
270 |
|
254 |
/* handle a permanent error from the above loop */ |
271 |
/* handle a permanent error from the above loop */ |
255 |
if (failed) { |
272 |
if (failed) { |
Lines 261-288
static int proxy_connect_handler(request_rec *r, p
Link Here
|
261 |
} |
278 |
} |
262 |
} |
279 |
} |
263 |
|
280 |
|
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 |
/* |
281 |
/* |
287 |
* Step Three: Send the Request |
282 |
* Step Three: Send the Request |
288 |
* |
283 |
* |
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 |
284 |
* Send the HTTP/1.1 CONNECT request to the remote server |
290 |
*/ |
285 |
*/ |
291 |
|
286 |
|
292 |
backconn = ap_run_create_connection(c->pool, r->server, sock, |
287 |
backend.c = ap_run_create_connection(c->pool, r->server, backend.pfd.desc.s, |
293 |
c->id, c->sbh, c->bucket_alloc); |
288 |
c->id, c->sbh, c->bucket_alloc); |
294 |
if (!backconn) { |
289 |
if (!backend.c) { |
295 |
/* peer reset */ |
290 |
/* peer reset */ |
296 |
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01021) |
291 |
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01021) |
297 |
"an error occurred creating a new connection " |
292 |
"an error occurred creating a new connection " |
298 |
"to %pI (%s)", nexthop, connectname); |
293 |
"to %pI (%s)", nexthop, connectname); |
299 |
apr_socket_close(sock); |
294 |
apr_socket_close(backend.pfd.desc.s); |
300 |
return HTTP_INTERNAL_SERVER_ERROR; |
295 |
return HTTP_INTERNAL_SERVER_ERROR; |
301 |
} |
296 |
} |
302 |
ap_proxy_ssl_disable(backconn); |
297 |
ap_proxy_ssl_disable(backend.c); |
303 |
rc = ap_run_pre_connection(backconn, sock); |
298 |
|
|
|
299 |
rc = ap_run_pre_connection(backend.c, backend.pfd.desc.s); |
304 |
if (rc != OK && rc != DONE) { |
300 |
if (rc != OK && rc != DONE) { |
305 |
backconn->aborted = 1; |
301 |
backend.c->aborted = 1; |
306 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01022) |
302 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01022) |
307 |
"pre_connection setup failed (%d)", rc); |
303 |
"pre_connection setup failed (%d)", rc); |
308 |
return HTTP_INTERNAL_SERVER_ERROR; |
304 |
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)", |
308 |
"connection complete to %pI (%s)", |
313 |
nexthop, connectname); |
309 |
nexthop, connectname); |
314 |
apr_table_setn(r->notes, "proxy-source-port", apr_psprintf(r->pool, "%hu", |
310 |
apr_table_setn(r->notes, "proxy-source-port", apr_psprintf(r->pool, "%hu", |
315 |
backconn->local_addr->port)); |
311 |
backend.c->local_addr->port)); |
316 |
|
312 |
|
|
|
313 |
client.bb = apr_brigade_create(p, client.c->bucket_alloc); |
314 |
backend.bb = apr_brigade_create(p, backend.c->bucket_alloc); |
317 |
|
315 |
|
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 |
316 |
/* If we are connecting through a remote proxy, we need to pass |
322 |
* the CONNECT request on to it. |
317 |
* the CONNECT request on to it. |
323 |
*/ |
318 |
*/ |
Lines 326-336
static int proxy_connect_handler(request_rec *r, p
Link Here
|
326 |
*/ |
321 |
*/ |
327 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, |
322 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, |
328 |
"sending the CONNECT request to the remote proxy"); |
323 |
"sending the CONNECT request to the remote proxy"); |
329 |
ap_fprintf(backconn->output_filters, bb_back, |
324 |
ap_fprintf(backend.c->output_filters, backend.bb, |
330 |
"CONNECT %s HTTP/1.0" CRLF, r->uri); |
325 |
"CONNECT %s HTTP/1.0" CRLF, r->uri); |
331 |
ap_fprintf(backconn->output_filters, bb_back, |
326 |
ap_fprintf(backend.c->output_filters, backend.bb, |
332 |
"Proxy-agent: %s" CRLF CRLF, ap_get_server_banner()); |
327 |
"Proxy-agent: %s" CRLF CRLF, ap_get_server_banner()); |
333 |
ap_fflush(backconn->output_filters, bb_back); |
328 |
ap_fflush(backend.c->output_filters, backend.bb); |
334 |
} |
329 |
} |
335 |
else { |
330 |
else { |
336 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Returning 200 OK"); |
331 |
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), |
332 |
nbytes = apr_snprintf(buffer, sizeof(buffer), |
338 |
"HTTP/1.0 200 Connection Established" CRLF); |
333 |
"HTTP/1.0 200 Connection Established" CRLF); |
339 |
ap_xlate_proto_to_ascii(buffer, nbytes); |
334 |
ap_xlate_proto_to_ascii(buffer, nbytes); |
340 |
ap_fwrite(c->output_filters, bb_front, buffer, nbytes); |
335 |
ap_fwrite(client.c->output_filters, client.bb, buffer, nbytes); |
341 |
nbytes = apr_snprintf(buffer, sizeof(buffer), |
336 |
nbytes = apr_snprintf(buffer, sizeof(buffer), |
342 |
"Proxy-agent: %s" CRLF CRLF, |
337 |
"Proxy-agent: %s" CRLF CRLF, |
343 |
ap_get_server_banner()); |
338 |
ap_get_server_banner()); |
344 |
ap_xlate_proto_to_ascii(buffer, nbytes); |
339 |
ap_xlate_proto_to_ascii(buffer, nbytes); |
345 |
ap_fwrite(c->output_filters, bb_front, buffer, nbytes); |
340 |
ap_fwrite(client.c->output_filters, client.bb, buffer, nbytes); |
346 |
ap_fflush(c->output_filters, bb_front); |
341 |
ap_fflush(client.c->output_filters, client.bb); |
347 |
#if 0 |
342 |
#if 0 |
348 |
/* This is safer code, but it doesn't work yet. I'm leaving it |
343 |
/* This is safer code, but it doesn't work yet. I'm leaving it |
349 |
* here so that I can fix it later. |
344 |
* here so that I can fix it later. |
Lines 355-362
static int proxy_connect_handler(request_rec *r, p
Link Here
|
355 |
#endif |
350 |
#endif |
356 |
} |
351 |
} |
357 |
|
352 |
|
|
|
353 |
/* setup polling for connection */ |
358 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "setting up poll()"); |
354 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "setting up poll()"); |
359 |
|
355 |
|
|
|
356 |
rv = apr_pollset_create(&pollset, 2, r->pool, APR_POLLSET_NOCOPY); |
357 |
if (rv != APR_SUCCESS) { |
358 |
apr_socket_close(backend.pfd.desc.s); |
359 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01020) |
360 |
"error apr_pollset_create()"); |
361 |
return HTTP_INTERNAL_SERVER_ERROR; |
362 |
} |
363 |
apr_pollset_add(pollset, &client.pfd); |
364 |
apr_pollset_add(pollset, &backend.pfd); |
365 |
|
360 |
/* |
366 |
/* |
361 |
* Step Four: Handle Data Transfer |
367 |
* Step Four: Handle Data Transfer |
362 |
* |
368 |
* |
Lines 370-377
static int proxy_connect_handler(request_rec *r, p
Link Here
|
370 |
r->proto_output_filters = c->output_filters; |
376 |
r->proto_output_filters = c->output_filters; |
371 |
r->input_filters = c->input_filters; |
377 |
r->input_filters = c->input_filters; |
372 |
r->proto_input_filters = c->input_filters; |
378 |
r->proto_input_filters = c->input_filters; |
373 |
/* r->sent_bodyct = 1;*/ |
379 |
/* r->sent_bodyct = 1;*/ |
374 |
|
380 |
|
|
|
381 |
client.core_filter = client.c->output_filters; |
382 |
while (client.core_filter->next) { |
383 |
client.core_filter = client.core_filter->next; |
384 |
} |
385 |
client.core_output = client.core_filter->frec->filter_func.out_func; |
386 |
|
387 |
backend.core_filter = backend.c->output_filters; |
388 |
while (backend.core_filter->next) { |
389 |
backend.core_filter = backend.core_filter->next; |
390 |
} |
391 |
backend.core_output = backend.core_filter->frec->filter_func.out_func; |
392 |
|
375 |
do { /* Loop until done (one side closes the connection, or an error) */ |
393 |
do { /* Loop until done (one side closes the connection, or an error) */ |
376 |
rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled); |
394 |
rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled); |
377 |
if (rv != APR_SUCCESS) { |
395 |
if (rv != APR_SUCCESS) { |
Lines 378-384
static int proxy_connect_handler(request_rec *r, p
Link Here
|
378 |
if (APR_STATUS_IS_EINTR(rv)) { |
396 |
if (APR_STATUS_IS_EINTR(rv)) { |
379 |
continue; |
397 |
continue; |
380 |
} |
398 |
} |
381 |
apr_socket_close(sock); |
399 |
apr_socket_close(backend.pfd.desc.s); |
382 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01023) "error apr_poll()"); |
400 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01023) "error apr_poll()"); |
383 |
return HTTP_INTERNAL_SERVER_ERROR; |
401 |
return HTTP_INTERNAL_SERVER_ERROR; |
384 |
} |
402 |
} |
Lines 390-396
static int proxy_connect_handler(request_rec *r, p
Link Here
|
390 |
for (pi = 0; pi < pollcnt; pi++) { |
408 |
for (pi = 0; pi < pollcnt; pi++) { |
391 |
const apr_pollfd_t *cur = &signalled[pi]; |
409 |
const apr_pollfd_t *cur = &signalled[pi]; |
392 |
|
410 |
|
393 |
if (cur->desc.s == sock) { |
411 |
if (cur->desc.s == backend.pfd.desc.s) { |
394 |
pollevent = cur->rtnevents; |
412 |
pollevent = cur->rtnevents; |
395 |
if (pollevent & (APR_POLLIN | APR_POLLHUP)) { |
413 |
if (pollevent & (APR_POLLIN | APR_POLLHUP)) { |
396 |
#ifdef DEBUGGING |
414 |
#ifdef DEBUGGING |
Lines 397-417
static int proxy_connect_handler(request_rec *r, p
Link Here
|
397 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01025) |
415 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01025) |
398 |
"sock was readable"); |
416 |
"sock was readable"); |
399 |
#endif |
417 |
#endif |
400 |
done |= ap_proxy_transfer_between_connections(r, backconn, |
418 |
done |= ap_proxy_transfer_between_connections(r, |
401 |
c, bb_back, |
419 |
backend.c, |
402 |
bb_front, |
420 |
client.c, |
403 |
"sock", NULL, |
421 |
backend.bb, |
404 |
CONN_BLKSZ, 1) |
422 |
client.bb, |
405 |
!= APR_SUCCESS; |
423 |
"backend", |
|
|
424 |
NULL, |
425 |
CONN_BLKSZ, |
426 |
1); |
427 |
if (!done && client.c->data_in_output_filters) { |
428 |
apr_pollset_remove(pollset, &client.pfd); |
429 |
client.pfd.reqevents = APR_POLLOUT; |
430 |
apr_pollset_add(pollset, &client.pfd); |
431 |
} |
406 |
} |
432 |
} |
|
|
433 |
else if (pollevent & APR_POLLOUT) { |
434 |
apr_pollset_remove(pollset, &client.pfd); |
435 |
client.pfd.reqevents = APR_POLLIN | APR_POLLHUP; |
436 |
apr_pollset_add(pollset, &client.pfd); |
437 |
done |= client.core_output(client.core_filter, NULL); |
438 |
} |
407 |
else if (pollevent & APR_POLLERR) { |
439 |
else if (pollevent & APR_POLLERR) { |
408 |
ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(01026) |
440 |
ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(01026) |
409 |
"err on backconn"); |
441 |
"err on backend"); |
410 |
backconn->aborted = 1; |
442 |
backend.c->aborted = 1; |
411 |
done = 1; |
443 |
done = 1; |
412 |
} |
444 |
} |
413 |
} |
445 |
} |
414 |
else if (cur->desc.s == client_socket) { |
446 |
else if (cur->desc.s == client.pfd.desc.s) { |
415 |
pollevent = cur->rtnevents; |
447 |
pollevent = cur->rtnevents; |
416 |
if (pollevent & (APR_POLLIN | APR_POLLHUP)) { |
448 |
if (pollevent & (APR_POLLIN | APR_POLLHUP)) { |
417 |
#ifdef DEBUGGING |
449 |
#ifdef DEBUGGING |
Lines 418-436
static int proxy_connect_handler(request_rec *r, p
Link Here
|
418 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01027) |
450 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01027) |
419 |
"client was readable"); |
451 |
"client was readable"); |
420 |
#endif |
452 |
#endif |
421 |
done |= ap_proxy_transfer_between_connections(r, c, |
453 |
done |= ap_proxy_transfer_between_connections(r, |
422 |
backconn, |
454 |
client.c, |
423 |
bb_front, |
455 |
backend.c, |
424 |
bb_back, |
456 |
client.bb, |
|
|
457 |
backend.bb, |
425 |
"client", |
458 |
"client", |
426 |
NULL, |
459 |
NULL, |
427 |
CONN_BLKSZ, 1) |
460 |
CONN_BLKSZ, |
428 |
!= APR_SUCCESS; |
461 |
1); |
|
|
462 |
if (!done && backend.c->data_in_output_filters) { |
463 |
apr_pollset_remove(pollset, &backend.pfd); |
464 |
backend.pfd.reqevents = APR_POLLOUT; |
465 |
apr_pollset_add(pollset, &backend.pfd); |
466 |
} |
429 |
} |
467 |
} |
|
|
468 |
else if (pollevent & APR_POLLOUT) { |
469 |
apr_pollset_remove(pollset, &backend.pfd); |
470 |
backend.pfd.reqevents = APR_POLLIN | APR_POLLHUP; |
471 |
apr_pollset_add(pollset, &backend.pfd); |
472 |
done |= backend.core_output(backend.core_filter, NULL); |
473 |
} |
430 |
else if (pollevent & APR_POLLERR) { |
474 |
else if (pollevent & APR_POLLERR) { |
431 |
ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02827) |
475 |
ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02827) |
432 |
"err on client"); |
476 |
"err on client"); |
433 |
c->aborted = 1; |
477 |
client.c->aborted = 1; |
434 |
done = 1; |
478 |
done = 1; |
435 |
} |
479 |
} |
436 |
} |
480 |
} |
Lines 452-461
static int proxy_connect_handler(request_rec *r, p
Link Here
|
452 |
* Close the socket and clean up |
496 |
* Close the socket and clean up |
453 |
*/ |
497 |
*/ |
454 |
|
498 |
|
455 |
if (backconn->aborted) |
499 |
if (backend.c->aborted) |
456 |
apr_socket_close(sock); |
500 |
apr_socket_close(backend.pfd.desc.s); |
457 |
else |
501 |
else |
458 |
ap_lingering_close(backconn); |
502 |
ap_lingering_close(backend.c); |
459 |
|
503 |
|
460 |
c->keepalive = AP_CONN_CLOSE; |
504 |
c->keepalive = AP_CONN_CLOSE; |
461 |
|
505 |
|