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

(-)modules/proxy/mod_proxy.h (-3 / +13 lines)
Lines 1172-1177 PROXY_DECLARE(apr_status_t) ap_proxy_buckets_lifet Link Here
1172
                                                      apr_bucket_brigade *from,
1172
                                                      apr_bucket_brigade *from,
1173
                                                      apr_bucket_brigade *to);
1173
                                                      apr_bucket_brigade *to);
1174
1174
1175
/* 
1176
 * The flags for ap_proxy_transfer_between_connections(), where for legacy and
1177
 * compatibility reasons FLUSH_EACH and FLUSH_AFTER are boolean values.
1178
 */
1179
#define AP_PROXY_TRANSFER_FLUSH_EACH  (0)
1180
#define AP_PROXY_TRANSFER_FLUSH_AFTER (1 << 0)
1181
#define AP_PROXY_TRANSFER_CHECK_FULL  (1 << 1)
1182
1175
/*
1183
/*
1176
 * Sends all data that can be read non blocking from the input filter chain of
1184
 * Sends all data that can be read non blocking from the input filter chain of
1177
 * c_i and send it down the output filter chain of c_o. For reading it uses
1185
 * c_i and send it down the output filter chain of c_o. For reading it uses
Lines 1189-1198 PROXY_DECLARE(apr_status_t) ap_proxy_buckets_lifet Link Here
1189
 * @param name  string for logging from where data was pulled
1197
 * @param name  string for logging from where data was pulled
1190
 * @param sent  if not NULL will be set to 1 if data was sent through c_o
1198
 * @param sent  if not NULL will be set to 1 if data was sent through c_o
1191
 * @param bsize maximum amount of data pulled in one iteration from c_i
1199
 * @param bsize maximum amount of data pulled in one iteration from c_i
1192
 * @param after if set flush data on c_o only once after the loop
1200
 * @param flags AP_PROXY_TRANSFER_* bitmask
1193
 * @return      apr_status_t of the operation. Could be any error returned from
1201
 * @return      apr_status_t of the operation. Could be any error returned from
1194
 *              either the input filter chain of c_i or the output filter chain
1202
 *              either the input filter chain of c_i or the output filter chain
1195
 *              of c_o. APR_EPIPE if the outgoing connection was aborted.
1203
 *              of c_o, APR_EPIPE if the outgoing connection was aborted, or
1204
 *              APR_INCOMPLETE if AP_PROXY_TRANSFER_CHECK_FULL was set and the
1205
 *              output stack gets full before the input stack is exhausted.
1196
 */
1206
 */
1197
PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections(
1207
PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections(
1198
                                                       request_rec *r,
1208
                                                       request_rec *r,
Lines 1203-1209 PROXY_DECLARE(apr_status_t) ap_proxy_transfer_betw Link Here
1203
                                                       const char *name,
1213
                                                       const char *name,
1204
                                                       int *sent,
1214
                                                       int *sent,
1205
                                                       apr_off_t bsize,
1215
                                                       apr_off_t bsize,
1206
                                                       int after);
1216
                                                       int flags);
1207
1217
1208
extern module PROXY_DECLARE_DATA proxy_module;
1218
extern module PROXY_DECLARE_DATA proxy_module;
1209
1219
(-)modules/proxy/proxy_util.c (-20 / +38 lines)
Lines 3774-3785 PROXY_DECLARE(apr_status_t) ap_proxy_transfer_betw Link Here
3774
                                                       const char *name,
3774
                                                       const char *name,
3775
                                                       int *sent,
3775
                                                       int *sent,
3776
                                                       apr_off_t bsize,
3776
                                                       apr_off_t bsize,
3777
                                                       int after)
3777
                                                       int flags)
3778
{
3778
{
3779
    apr_status_t rv;
3779
    apr_status_t rv;
3780
#ifdef DEBUGGING
3781
    apr_off_t len;
3782
#endif
3783
3780
3784
    do {
3781
    do {
3785
        apr_brigade_cleanup(bb_i);
3782
        apr_brigade_cleanup(bb_i);
Lines 3786-3810 PROXY_DECLARE(apr_status_t) ap_proxy_transfer_betw Link Here
3786
        rv = ap_get_brigade(c_i->input_filters, bb_i, AP_MODE_READBYTES,
3783
        rv = ap_get_brigade(c_i->input_filters, bb_i, AP_MODE_READBYTES,
3787
                            APR_NONBLOCK_READ, bsize);
3784
                            APR_NONBLOCK_READ, bsize);
3788
        if (rv == APR_SUCCESS) {
3785
        if (rv == APR_SUCCESS) {
3789
            if (c_o->aborted) {
3786
            if (APLOGctrace8(c_i)) {
3790
                return APR_EPIPE;
3787
                apr_off_t len = -1;
3788
                apr_brigade_length(bb_i, 0, &len);
3789
                ap_log_cerror(APLOG_MARK, APLOG_TRACE8, 0, c_i,
3790
                              "ap_proxy_transfer_between_connections: "
3791
                              "%" APR_OFF_T_FMT " bytes read", len);
3791
            }
3792
            }
3792
            if (APR_BRIGADE_EMPTY(bb_i)) {
3793
            if (APR_BRIGADE_EMPTY(bb_i)) {
3793
                break;
3794
                break;
3794
            }
3795
            }
3795
#ifdef DEBUGGING
3796
            if (c_o->aborted) {
3796
            len = -1;
3797
                flags &= ~AP_PROXY_TRANSFER_FLUSH_AFTER;
3797
            apr_brigade_length(bb_i, 0, &len);
3798
                rv = APR_EPIPE;
3798
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03306)
3799
                break;
3799
                          "ap_proxy_transfer_between_connections: "
3800
            }
3800
                          "read %" APR_OFF_T_FMT
3801
                          " bytes from %s", len, name);
3802
#endif
3803
            if (sent) {
3801
            if (sent) {
3804
                *sent = 1;
3802
                *sent = 1;
3805
            }
3803
            }
3806
            ap_proxy_buckets_lifetime_transform(r, bb_i, bb_o);
3804
            ap_proxy_buckets_lifetime_transform(r, bb_i, bb_o);
3807
            if (!after) {
3805
            /*
3806
             * Compat: since FLUSH_EACH is zero for legacy reasons, we must
3807
             * check for no FLUSH_AFTER nor CHECK_FULL flags, the latter
3808
             * because flushing here would defeat the purpose of checking for
3809
             * buffered data (i.e. c_o->data_in_output_filters) hence determine
3810
             * whether or not the output chain/stack is full to stop.
3811
             */
3812
            if (!(flags & (AP_PROXY_TRANSFER_FLUSH_AFTER |
3813
                           AP_PROXY_TRANSFER_CHECK_FULL))) {
3808
                apr_bucket *b;
3814
                apr_bucket *b;
3809
3815
3810
                /*
3816
                /*
Lines 3811-3817 PROXY_DECLARE(apr_status_t) ap_proxy_transfer_betw Link Here
3811
                 * Do not use ap_fflush here since this would cause the flush
3817
                 * Do not use ap_fflush here since this would cause the flush
3812
                 * bucket to be sent in a separate brigade afterwards which
3818
                 * bucket to be sent in a separate brigade afterwards which
3813
                 * causes some filters to set aside the buckets from the first
3819
                 * causes some filters to set aside the buckets from the first
3814
                 * brigade and process them when the flush arrives in the second
3820
                 * brigade and process them when FLUSH arrives in the second
3815
                 * brigade. As set asides of our transformed buckets involve
3821
                 * brigade. As set asides of our transformed buckets involve
3816
                 * memory copying we try to avoid this. If we have the flush
3822
                 * memory copying we try to avoid this. If we have the flush
3817
                 * bucket in the first brigade they directly process the
3823
                 * bucket in the first brigade they directly process the
Lines 3826-3833 PROXY_DECLARE(apr_status_t) ap_proxy_transfer_betw Link Here
3826
                              "ap_proxy_transfer_between_connections: "
3832
                              "ap_proxy_transfer_between_connections: "
3827
                              "error on %s - ap_pass_brigade",
3833
                              "error on %s - ap_pass_brigade",
3828
                              name);
3834
                              name);
3835
                flags &= ~AP_PROXY_TRANSFER_FLUSH_AFTER;
3829
            }
3836
            }
3830
        } else if (!APR_STATUS_IS_EAGAIN(rv) && !APR_STATUS_IS_EOF(rv)) {
3837
            else if (flags & AP_PROXY_TRANSFER_CHECK_FULL
3838
                     && c_o->data_in_output_filters) {
3839
                ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
3840
                              "ap_proxy_transfer_between_connections: "
3841
                              "output filters full");
3842
                flags &= ~AP_PROXY_TRANSFER_FLUSH_AFTER;
3843
                rv = APR_INCOMPLETE;
3844
            }
3845
            apr_brigade_cleanup(bb_o);
3846
        }
3847
        else if (!APR_STATUS_IS_EAGAIN(rv) && !APR_STATUS_IS_EOF(rv)) {
3831
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(03308)
3848
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(03308)
3832
                          "ap_proxy_transfer_between_connections: "
3849
                          "ap_proxy_transfer_between_connections: "
3833
                          "error on %s - ap_get_brigade",
3850
                          "error on %s - ap_get_brigade",
Lines 3835-3851 PROXY_DECLARE(apr_status_t) ap_proxy_transfer_betw Link Here
3835
        }
3852
        }
3836
    } while (rv == APR_SUCCESS);
3853
    } while (rv == APR_SUCCESS);
3837
3854
3838
    if (after) {
3855
    if (flags & AP_PROXY_TRANSFER_FLUSH_AFTER) {
3839
        ap_fflush(c_o->output_filters, bb_o);
3856
        ap_fflush(c_o->output_filters, bb_o);
3857
        apr_brigade_cleanup(bb_o);
3840
    }
3858
    }
3859
    apr_brigade_cleanup(bb_i);
3841
3860
3842
    ap_log_rerror(APLOG_MARK, APLOG_TRACE2, rv, r,
3861
    ap_log_rerror(APLOG_MARK, APLOG_TRACE2, rv, r,
3843
                  "ap_proxy_transfer_between_connections complete");
3862
                  "ap_proxy_transfer_between_connections finished");
3844
3863
3845
    if (APR_STATUS_IS_EAGAIN(rv)) {
3864
    if (APR_STATUS_IS_EAGAIN(rv)) {
3846
        rv = APR_SUCCESS;
3865
        rv = APR_SUCCESS;
3847
    }
3866
    }
3848
3849
    return rv;
3867
    return rv;
3850
}
3868
}
3851
3869
(-)modules/proxy/mod_proxy_connect.c (-114 / +267 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
    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;

Return to bug 61616