View | Details | Raw Unified | Return to bug 61616
Collapse All | Expand All

(-)modules/proxy/mod_proxy_connect.c (-70 / +114 lines)
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

Return to bug 61616