~ubuntu-branches/ubuntu/trusty/serf/trusty-security

« back to all changes in this revision

Viewing changes to outgoing.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2013-12-31 13:17:16 UTC
  • mfrom: (1.1.8) (3.3.2 sid)
  • Revision ID: package-import@ubuntu.com-20131231131716-s862wc4uwdzxmrr1
Tags: 1.3.3-1
* Add myself to Uploaders.
* Change the watch file to better handle code.google.com.
* New upstream release.  (Closes: #716793)
  + Refresh patches/libtool
  + Update symbols
* Adapt packaging for the upstream switch to SCons.
  + control: + scons, - autotools-dev, autoconf
  + rules: Change configure/make calls to scons
* Rename libserf1 to libserf-1-1, following standard naming conventions.
* Enable hardening flags.
* Strip unnecessary RPATH from libserf.
* Honor DEB_BUILD_OPTIONS=parallel=X

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
#include <apr_pools.h>
17
17
#include <apr_poll.h>
18
18
#include <apr_version.h>
 
19
#include <apr_portable.h>
19
20
 
20
21
#include "serf.h"
21
22
#include "serf_bucket_util.h"
29
30
    apr_status_t status = APR_SUCCESS;
30
31
 
31
32
    if (conn->skt) {
 
33
        serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt, "cleanup - ");
32
34
        status = apr_socket_close(conn->skt);
33
35
        conn->skt = NULL;
 
36
        serf__log_nopref(SOCK_VERBOSE, "closed socket, status %d\n", status);
34
37
    }
35
38
 
36
39
    return status;
71
74
{
72
75
    serf_connection_t *conn = data;
73
76
 
 
77
    serf__log(CONN_VERBOSE, __FILE__, "cleaning up connection 0x%x\n",
 
78
              conn);
74
79
    serf_connection_close(conn);
75
80
 
76
81
    return APR_SUCCESS;
77
82
}
78
83
 
 
84
/* Check if there is data waiting to be sent over the socket. This can happen
 
85
   in two situations:
 
86
   - The connection queue has atleast one request with unwritten data.
 
87
   - All requests are written and the ssl layer wrote some data while reading
 
88
     the response. This can happen when the server triggers a renegotiation,
 
89
     e.g. after the first and only request on that connection was received.
 
90
   Returns 1 if data is pending on CONN, NULL if not.
 
91
   If NEXT_REQ is not NULL, it will be filled in with the next available request
 
92
   with unwritten data. */
 
93
static int
 
94
request_or_data_pending(serf_request_t **next_req, serf_connection_t *conn)
 
95
{
 
96
    serf_request_t *request = conn->requests;
 
97
 
 
98
    while (request != NULL && request->req_bkt == NULL &&
 
99
           request->writing_started)
 
100
        request = request->next;
 
101
 
 
102
    if (next_req)
 
103
        *next_req = request;
 
104
 
 
105
    if (request != NULL) {
 
106
        return 1;
 
107
    } else if (conn->ostream_head) {
 
108
        const char *dummy;
 
109
        apr_size_t len;
 
110
        apr_status_t status;
 
111
 
 
112
        status = serf_bucket_peek(conn->ostream_head, &dummy,
 
113
                                  &len);
 
114
        if (!SERF_BUCKET_READ_ERROR(status) && len) {
 
115
            serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
 
116
                          "All requests written but still data pending.\n");
 
117
            return 1;
 
118
        }
 
119
    }
 
120
 
 
121
    return 0;
 
122
}
 
123
 
79
124
/* Update the pollset for this connection. We tweak the pollset based on
80
125
 * whether we want to read and/or write, given conditions within the
81
126
 * connection. If the connection is not (yet) in the pollset, then it
103
148
 
104
149
    /* Now put it back in with the correct read/write values. */
105
150
    desc.reqevents = APR_POLLHUP | APR_POLLERR;
106
 
    if (conn->requests) {
 
151
    if (conn->requests &&
 
152
        conn->state != SERF_CONN_INIT) {
107
153
        /* If there are any outstanding events, then we want to read. */
108
154
        /* ### not true. we only want to read IF we have sent some data */
109
155
        desc.reqevents |= APR_POLLIN;
110
156
 
111
 
        /* If the connection has unwritten data, or there are any requests
112
 
         * that still have buckets to write out, then we want to write.
113
 
         */
114
 
        if (conn->vec_len)
115
 
            desc.reqevents |= APR_POLLOUT;
116
 
        else {
117
 
            serf_request_t *request = conn->requests;
118
 
 
119
 
            if ((conn->probable_keepalive_limit &&
120
 
                 conn->completed_requests > conn->probable_keepalive_limit) ||
121
 
                (conn->max_outstanding_requests &&
122
 
                 conn->completed_requests - conn->completed_responses >=
 
157
        /* Don't write if OpenSSL told us that it needs to read data first. */
 
158
        if (conn->stop_writing != 1) {
 
159
 
 
160
            /* If the connection is not closing down and
 
161
             *   has unwritten data or
 
162
             *   there are any requests that still have buckets to write out,
 
163
             *     then we want to write.
 
164
             */
 
165
            if (conn->vec_len &&
 
166
                conn->state != SERF_CONN_CLOSING)
 
167
                desc.reqevents |= APR_POLLOUT;
 
168
            else {
 
169
 
 
170
                if ((conn->probable_keepalive_limit &&
 
171
                     conn->completed_requests > conn->probable_keepalive_limit) ||
 
172
                    (conn->max_outstanding_requests &&
 
173
                     conn->completed_requests - conn->completed_responses >=
123
174
                     conn->max_outstanding_requests)) {
124
 
                /* we wouldn't try to write any way right now. */
125
 
            }
126
 
            else {
127
 
                while (request != NULL && request->req_bkt == NULL &&
128
 
                       request->written)
129
 
                    request = request->next;
130
 
                if (request != NULL)
 
175
                        /* we wouldn't try to write any way right now. */
 
176
                }
 
177
                else if (request_or_data_pending(NULL, conn)) {
131
178
                    desc.reqevents |= APR_POLLOUT;
 
179
                }
132
180
            }
133
181
        }
134
182
    }
169
217
 
170
218
#endif
171
219
 
 
220
static void destroy_ostream(serf_connection_t *conn)
 
221
{
 
222
    if (conn->ostream_head != NULL) {
 
223
        serf_bucket_destroy(conn->ostream_head);
 
224
        conn->ostream_head = NULL;
 
225
        conn->ostream_tail = NULL;
 
226
    }
 
227
}
 
228
 
 
229
static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket)
 
230
{
 
231
    serf_connection_t *conn = baton;
 
232
    conn->hit_eof = 1;
 
233
    return APR_EAGAIN;
 
234
}
 
235
 
 
236
static apr_status_t do_conn_setup(serf_connection_t *conn)
 
237
{
 
238
    apr_status_t status;
 
239
    serf_bucket_t *ostream;
 
240
 
 
241
    if (conn->ostream_head == NULL) {
 
242
        conn->ostream_head = serf_bucket_aggregate_create(conn->allocator);
 
243
    }
 
244
 
 
245
    if (conn->ostream_tail == NULL) {
 
246
        conn->ostream_tail = serf__bucket_stream_create(conn->allocator,
 
247
                                                        detect_eof,
 
248
                                                        conn);
 
249
    }
 
250
 
 
251
    ostream = conn->ostream_tail;
 
252
 
 
253
    status = (*conn->setup)(conn->skt,
 
254
                            &conn->stream,
 
255
                            &ostream,
 
256
                            conn->setup_baton,
 
257
                            conn->pool);
 
258
    if (status) {
 
259
        /* extra destroy here since it wasn't added to the head bucket yet. */
 
260
        serf_bucket_destroy(conn->ostream_tail);
 
261
        destroy_ostream(conn);
 
262
        return status;
 
263
    }
 
264
 
 
265
    serf_bucket_aggregate_append(conn->ostream_head,
 
266
                                 ostream);
 
267
 
 
268
    return status;
 
269
}
 
270
 
 
271
/* Set up the input and output stream buckets.
 
272
 When a tunnel over an http proxy is needed, create a socket bucket and
 
273
 empty aggregate bucket for sending and receiving unencrypted requests
 
274
 over the socket.
 
275
 
 
276
 After the tunnel is there, or no tunnel was needed, ask the application
 
277
 to create the input and output buckets, which should take care of the
 
278
 [en/de]cryption.
 
279
 */
 
280
 
 
281
static apr_status_t prepare_conn_streams(serf_connection_t *conn,
 
282
                                         serf_bucket_t **istream,
 
283
                                         serf_bucket_t **ostreamt,
 
284
                                         serf_bucket_t **ostreamh)
 
285
{
 
286
    apr_status_t status;
 
287
 
 
288
    if (conn->stream == NULL) {
 
289
        conn->latency = apr_time_now() - conn->connect_time;
 
290
    }
 
291
 
 
292
    /* Do we need a SSL tunnel first? */
 
293
    if (conn->state == SERF_CONN_CONNECTED) {
 
294
        /* If the connection does not have an associated bucket, then
 
295
         * call the setup callback to get one.
 
296
         */
 
297
        if (conn->stream == NULL) {
 
298
            status = do_conn_setup(conn);
 
299
            if (status) {
 
300
                return status;
 
301
            }
 
302
        }
 
303
        *ostreamt = conn->ostream_tail;
 
304
        *ostreamh = conn->ostream_head;
 
305
        *istream = conn->stream;
 
306
    } else {
 
307
        /* SSL tunnel needed and not set up yet, get a direct unencrypted
 
308
         stream for this socket */
 
309
        if (conn->stream == NULL) {
 
310
            *istream = serf_bucket_socket_create(conn->skt,
 
311
                                                 conn->allocator);
 
312
        }
 
313
        /* Don't create the ostream bucket chain including the ssl_encrypt
 
314
         bucket yet. This ensure the CONNECT request is sent unencrypted
 
315
         to the proxy. */
 
316
        *ostreamt = *ostreamh = conn->ssltunnel_ostream;
 
317
    }
 
318
 
 
319
    return APR_SUCCESS;
 
320
}
 
321
 
172
322
/* Create and connect sockets for any connections which don't have them
173
323
 * yet. This is the core of our lazy-connect behavior.
174
324
 */
178
328
 
179
329
    for (i = ctx->conns->nelts; i--; ) {
180
330
        serf_connection_t *conn = GET_CONN(ctx, i);
 
331
        serf__authn_info_t *authn_info;
181
332
        apr_status_t status;
182
333
        apr_socket_t *skt;
183
 
        apr_sockaddr_t *serv_addr;
184
334
 
185
335
        conn->seen_in_pollset = 0;
186
336
 
199
349
        apr_pool_clear(conn->skt_pool);
200
350
        apr_pool_cleanup_register(conn->skt_pool, conn, clean_skt, clean_skt);
201
351
 
202
 
        /* Do we have to connect to a proxy server? */
203
 
        if (ctx->proxy_address)
204
 
            serv_addr = ctx->proxy_address;
205
 
        else
206
 
            serv_addr = conn->address;
207
 
 
208
 
        if ((status = apr_socket_create(&skt, serv_addr->family,
209
 
                                        SOCK_STREAM,
 
352
        status = apr_socket_create(&skt, conn->address->family,
 
353
                                   SOCK_STREAM,
210
354
#if APR_MAJOR_VERSION > 0
211
 
                                        APR_PROTO_TCP,
 
355
                                   APR_PROTO_TCP,
212
356
#endif
213
 
                                        conn->skt_pool)) != APR_SUCCESS)
 
357
                                   conn->skt_pool);
 
358
        serf__log(SOCK_VERBOSE, __FILE__,
 
359
                  "created socket for conn 0x%x, status %d\n", conn, status);
 
360
        if (status != APR_SUCCESS)
214
361
            return status;
215
362
 
216
363
        /* Set the socket to be non-blocking */
225
372
        /* Configured. Store it into the connection now. */
226
373
        conn->skt = skt;
227
374
 
 
375
        /* Remember time when we started connecting to server to calculate
 
376
           network latency. */
 
377
        conn->connect_time = apr_time_now();
 
378
 
228
379
        /* Now that the socket is set up, let's connect it. This should
229
380
         * return immediately.
230
381
         */
231
 
        if ((status = apr_socket_connect(skt,
232
 
                                         serv_addr)) != APR_SUCCESS) {
 
382
        status = apr_socket_connect(skt, conn->address);
 
383
        serf__log_skt(SOCK_VERBOSE, __FILE__, skt,
 
384
                      "connected socket for conn 0x%x, status %d\n",
 
385
                      conn, status);
 
386
        if (status != APR_SUCCESS) {
233
387
            if (!APR_STATUS_IS_EINPROGRESS(status))
234
388
                return status;
235
389
        }
242
396
           prepare this connection (it might be possible to skip some
243
397
           part of the handshaking). */
244
398
        if (ctx->proxy_address) {
245
 
            if (conn->ctx->proxy_authn_info.scheme)
246
 
                conn->ctx->proxy_authn_info.scheme->init_conn_func(407, conn,
247
 
                                                                   conn->pool);
 
399
            authn_info = &ctx->proxy_authn_info;
 
400
            if (authn_info->scheme) {
 
401
                authn_info->scheme->init_conn_func(authn_info->scheme, 407,
 
402
                                                   conn, conn->pool);
 
403
            }
248
404
        }
249
405
 
250
 
        if (conn->ctx->authn_info.scheme)
251
 
            conn->ctx->authn_info.scheme->init_conn_func(401, conn,
252
 
                                                         conn->pool);
 
406
        authn_info = serf__get_authn_info_for_server(conn);
 
407
        if (authn_info->scheme) {
 
408
            authn_info->scheme->init_conn_func(authn_info->scheme, 401,
 
409
                                               conn, conn->pool);
 
410
        }
253
411
 
254
412
        /* Does this connection require a SSL tunnel over the proxy? */
255
413
        if (ctx->proxy_address && strcmp(conn->host_info.scheme, "https") == 0)
256
414
            serf__ssltunnel_connect(conn);
257
 
        else
 
415
        else {
 
416
            serf_bucket_t *dummy1, *dummy2;
 
417
 
258
418
            conn->state = SERF_CONN_CONNECTED;
 
419
 
 
420
            status = prepare_conn_streams(conn, &conn->stream,
 
421
                                          &dummy1, &dummy2);
 
422
            if (status) {
 
423
                return status;
 
424
            }
 
425
        }
259
426
    }
260
427
 
261
428
    return APR_SUCCESS;
262
429
}
263
430
 
264
 
static apr_status_t no_more_writes(serf_connection_t *conn,
265
 
                                   serf_request_t *request)
 
431
static apr_status_t no_more_writes(serf_connection_t *conn)
266
432
{
267
433
    /* Note that we should hold new requests until we open our new socket. */
268
434
    conn->state = SERF_CONN_CLOSING;
269
 
 
270
 
    /* We can take the *next* request in our list and assume it hasn't
271
 
     * been written yet and 'save' it for the new socket.
272
 
     */
273
 
    conn->hold_requests = request->next;
274
 
    conn->hold_requests_tail = conn->requests_tail;
275
 
    request->next = NULL;
276
 
    conn->requests_tail = request;
 
435
    serf__log(CONN_VERBOSE, __FILE__, "stop writing on conn 0x%x\n",
 
436
              conn);
277
437
 
278
438
    /* Clear our iovec. */
279
439
    conn->vec_len = 0;
390
550
                           &desc, conn);
391
551
}
392
552
 
393
 
static void destroy_ostream(serf_connection_t *conn)
394
 
{
395
 
    if (conn->ostream_head != NULL) {
396
 
        serf_bucket_destroy(conn->ostream_head);
397
 
        conn->ostream_head = NULL;
398
 
        conn->ostream_tail = NULL;
399
 
    }
400
 
}
401
 
 
402
553
/* A socket was closed, inform the application. */
403
554
static void handle_conn_closed(serf_connection_t *conn, apr_status_t status)
404
555
{
411
562
{
412
563
    serf_context_t *ctx = conn->ctx;
413
564
    apr_status_t status;
414
 
    serf_request_t *old_reqs, *held_reqs, *held_reqs_tail;
 
565
    serf_request_t *old_reqs;
415
566
 
416
567
    conn->probable_keepalive_limit = conn->completed_responses;
417
568
    conn->completed_requests = 0;
418
569
    conn->completed_responses = 0;
419
570
 
420
571
    old_reqs = conn->requests;
421
 
    held_reqs = conn->hold_requests;
422
 
    held_reqs_tail = conn->hold_requests_tail;
423
 
 
424
 
    if (conn->state == SERF_CONN_CLOSING) {
425
 
        conn->hold_requests = NULL;
426
 
        conn->hold_requests_tail = NULL;
427
 
    }
428
572
 
429
573
    conn->requests = NULL;
430
574
    conn->requests_tail = NULL;
431
575
 
 
576
    /* Handle all outstanding requests. These have either not been written yet,
 
577
       or have been written but the expected reply wasn't received yet. */
432
578
    while (old_reqs) {
433
579
        /* If we haven't started to write the connection, bring it over
434
 
         * unchanged to our new socket.  Otherwise, call the cancel function.
 
580
         * unchanged to our new socket.
 
581
         * Do not copy a CONNECT request to the new connection, the ssl tunnel
 
582
         * setup code will create a new CONNECT request already.
435
583
         */
436
 
        if (requeue_requests && !old_reqs->written) {
 
584
        if (requeue_requests && !old_reqs->writing_started &&
 
585
            !old_reqs->ssltunnel) {
 
586
 
437
587
            serf_request_t *req = old_reqs;
438
588
            old_reqs = old_reqs->next;
439
589
            req->next = NULL;
440
590
            link_requests(&conn->requests, &conn->requests_tail, req);
441
591
        }
442
592
        else {
 
593
            /* Request has been consumed, or we don't want to requeue the
 
594
               request. Either way, inform the application that the request
 
595
               is cancelled. */
443
596
            cancel_request(old_reqs, &old_reqs, requeue_requests);
444
597
        }
445
598
    }
446
599
 
447
 
    if (conn->requests_tail) {
448
 
        conn->requests_tail->next = held_reqs;
449
 
    }
450
 
    else {
451
 
        conn->requests = held_reqs;
452
 
    }
453
 
    if (held_reqs_tail) {
454
 
        conn->requests_tail = held_reqs_tail;
455
 
    }
456
 
 
 
600
    /* Requests queue has been prepared for a new socket, close the old one. */
457
601
    if (conn->skt != NULL) {
458
602
        remove_connection(ctx, conn);
459
603
        status = apr_socket_close(conn->skt);
 
604
        serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt,
 
605
                      "closed socket, status %d\n", status);
460
606
        if (conn->closed != NULL) {
461
607
            handle_conn_closed(conn, status);
462
608
        }
477
623
    conn->ctx->dirty_pollset = 1;
478
624
    conn->state = SERF_CONN_INIT;
479
625
 
 
626
    serf__log(CONN_VERBOSE, __FILE__, "reset connection 0x%x\n", conn);
 
627
 
480
628
    conn->status = APR_SUCCESS;
481
629
 
482
630
    /* Let our context know that we've 'reset' the socket already. */
493
641
 
494
642
    status = apr_socket_sendv(conn->skt, conn->vec,
495
643
                              conn->vec_len, &written);
 
644
    if (status && !APR_STATUS_IS_EAGAIN(status))
 
645
        serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt,
 
646
                      "socket_sendv error %d\n", status);
496
647
 
497
648
    /* did we write everything? */
498
649
    if (written) {
499
650
        apr_size_t len = 0;
500
651
        int i;
501
652
 
 
653
        serf__log_skt(SOCK_MSG_VERBOSE, __FILE__, conn->skt,
 
654
                      "--- socket_sendv:\n");
 
655
 
502
656
        for (i = 0; i < conn->vec_len; i++) {
503
657
            len += conn->vec[i].iov_len;
504
658
            if (written < len) {
 
659
                serf__log_nopref(SOCK_MSG_VERBOSE, "%.*s",
 
660
                                   conn->vec[i].iov_len - (len - written),
 
661
                                   conn->vec[i].iov_base);
505
662
                if (i) {
506
663
                    memmove(conn->vec, &conn->vec[i],
507
664
                            sizeof(struct iovec) * (conn->vec_len - i));
510
667
                conn->vec[0].iov_base = (char *)conn->vec[0].iov_base + (conn->vec[0].iov_len - (len - written));
511
668
                conn->vec[0].iov_len = len - written;
512
669
                break;
 
670
            } else {
 
671
                serf__log_nopref(SOCK_MSG_VERBOSE, "%.*s",
 
672
                                   conn->vec[i].iov_len, conn->vec[i].iov_base);
513
673
            }
514
674
        }
515
675
        if (len == written) {
516
676
            conn->vec_len = 0;
517
677
        }
 
678
        serf__log_nopref(SOCK_MSG_VERBOSE, "-(%d)-\n", written);
518
679
 
519
680
        /* Log progress information */
520
681
        serf__context_progress_delta(conn->ctx, 0, written);
523
684
    return status;
524
685
}
525
686
 
526
 
static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket)
527
 
{
528
 
    serf_connection_t *conn = baton;
529
 
    conn->hit_eof = 1;
530
 
    return APR_EAGAIN;
531
 
}
532
 
 
533
 
static apr_status_t do_conn_setup(serf_connection_t *conn)
534
 
{
 
687
static apr_status_t setup_request(serf_request_t *request)
 
688
{
 
689
    serf_connection_t *conn = request->conn;
535
690
    apr_status_t status;
536
 
    serf_bucket_t *ostream;
537
 
 
538
 
    if (conn->ostream_head == NULL) {
539
 
        conn->ostream_head = serf_bucket_aggregate_create(conn->allocator);
540
 
    }
541
 
 
542
 
    if (conn->ostream_tail == NULL) {
543
 
        conn->ostream_tail = serf__bucket_stream_create(conn->allocator,
544
 
                                                        detect_eof,
545
 
                                                        conn);
546
 
    }
547
 
 
548
 
    ostream = conn->ostream_tail;
549
 
 
550
 
    status = (*conn->setup)(conn->skt,
551
 
                            &conn->stream,
552
 
                            &ostream,
553
 
                            conn->setup_baton,
554
 
                            conn->pool);
555
 
    if (status) {
556
 
        /* extra destroy here since it wasn't added to the head bucket yet. */
557
 
        serf_bucket_destroy(conn->ostream_tail);
558
 
        destroy_ostream(conn);
559
 
        return status;
560
 
    }
561
 
 
562
 
    serf_bucket_aggregate_append(conn->ostream_head,
563
 
                                 ostream);
564
 
 
 
691
 
 
692
    /* Now that we are about to serve the request, allocate a pool. */
 
693
    apr_pool_create(&request->respool, conn->pool);
 
694
    request->allocator = serf_bucket_allocator_create(request->respool,
 
695
                                                      NULL, NULL);
 
696
    apr_pool_cleanup_register(request->respool, request,
 
697
                              clean_resp, clean_resp);
 
698
 
 
699
    /* Fill in the rest of the values for the request. */
 
700
    status = request->setup(request, request->setup_baton,
 
701
                            &request->req_bkt,
 
702
                            &request->acceptor,
 
703
                            &request->acceptor_baton,
 
704
                            &request->handler,
 
705
                            &request->handler_baton,
 
706
                            request->respool);
565
707
    return status;
566
708
}
567
709
 
568
 
/* Set up the input and output stream buckets.
569
 
   When a tunnel over an http proxy is needed, create a socket bucket and
570
 
   empty aggregate bucket for sending and receiving unencrypted requests
571
 
   over the socket.
572
 
 
573
 
   After the tunnel is there, or no tunnel was needed, ask the application
574
 
   to create the input and output buckets, which should take care of the
575
 
   [en/de]cryption.
576
 
*/
577
 
 
578
 
static apr_status_t prepare_conn_streams(serf_connection_t *conn,
579
 
                                         serf_bucket_t **istream,
580
 
                                         serf_bucket_t **ostreamt,
581
 
                                         serf_bucket_t **ostreamh)
582
 
{
583
 
    apr_status_t status;
584
 
 
585
 
    /* Do we need a SSL tunnel first? */
586
 
    if (conn->state == SERF_CONN_CONNECTED) {
587
 
        /* If the connection does not have an associated bucket, then
588
 
         * call the setup callback to get one.
589
 
         */
590
 
        if (conn->stream == NULL) {
591
 
            status = do_conn_setup(conn);
592
 
            if (status) {
593
 
                return status;
594
 
            }
595
 
        }
596
 
        *ostreamt = conn->ostream_tail;
597
 
        *ostreamh = conn->ostream_head;
598
 
        *istream = conn->stream;
599
 
    } else {
600
 
        /* SSL tunnel needed and not set up yet, get a direct unencrypted
601
 
           stream for this socket */
602
 
        if (conn->stream == NULL) {
603
 
            *istream = serf_bucket_socket_create(conn->skt,
604
 
                                                 conn->allocator);
605
 
        }
606
 
        /* Don't create the ostream bucket chain including the ssl_encrypt
607
 
           bucket yet. This ensure the CONNECT request is sent unencrypted
608
 
           to the proxy. */
609
 
        *ostreamt = *ostreamh = conn->ssltunnel_ostream;
610
 
    }
611
 
 
612
 
    return APR_SUCCESS;
613
 
}
614
 
 
615
710
/* write data out to the connection */
616
711
static apr_status_t write_to_connection(serf_connection_t *conn)
617
712
{
618
 
    serf_request_t *request = conn->requests;
619
 
 
620
713
    if (conn->probable_keepalive_limit &&
621
714
        conn->completed_requests > conn->probable_keepalive_limit) {
622
715
 
627
720
        return APR_SUCCESS;
628
721
    }
629
722
 
630
 
    /* Find a request that has data which needs to be delivered. */
631
 
    while (request != NULL &&
632
 
           request->req_bkt == NULL && request->written)
633
 
        request = request->next;
634
 
 
635
 
    /* assert: request != NULL || conn->vec_len */
636
 
 
637
723
    /* Keep reading and sending until we run out of stuff to read, or
638
724
     * writing would block.
639
725
     */
640
726
    while (1) {
 
727
        serf_request_t *request;
641
728
        int stop_reading = 0;
642
729
        apr_status_t status;
643
730
        apr_status_t read_status;
644
 
        serf_bucket_t *ostreamt, *ostreamh;
 
731
        serf_bucket_t *ostreamt;
 
732
        serf_bucket_t *ostreamh;
645
733
        int max_outstanding_requests = conn->max_outstanding_requests;
646
734
 
647
735
        /* If we're setting up an ssl tunnel, we can't send real requests
667
755
             */
668
756
            if (APR_STATUS_IS_EAGAIN(status))
669
757
                return APR_SUCCESS;
670
 
            if (APR_STATUS_IS_EPIPE(status))
671
 
                return no_more_writes(conn, request);
 
758
            if (APR_STATUS_IS_EPIPE(status) ||
 
759
                APR_STATUS_IS_ECONNRESET(status) ||
 
760
                APR_STATUS_IS_ECONNABORTED(status))
 
761
                return no_more_writes(conn);
672
762
            if (status)
673
763
                return status;
674
764
        }
679
769
        /* We may need to move forward to a request which has something
680
770
         * to write.
681
771
         */
682
 
        while (request != NULL &&
683
 
               request->req_bkt == NULL && request->written)
684
 
            request = request->next;
685
 
 
686
 
        if (request == NULL) {
 
772
        if (!request_or_data_pending(&request, conn)) {
687
773
            /* No more requests (with data) are registered with the
688
 
             * connection. Let's update the pollset so that we don't
689
 
             * try to write to this socket again.
 
774
             * connection, and no data is pending on the outgoing stream.
 
775
             * Let's update the pollset so that we don't try to write to this
 
776
             * socket again.
690
777
             */
691
778
            conn->dirty_conn = 1;
692
779
            conn->ctx->dirty_pollset = 1;
698
785
            return status;
699
786
        }
700
787
 
701
 
        if (request->req_bkt == NULL) {
702
 
            /* Now that we are about to serve the request, allocate a pool. */
703
 
            apr_pool_create(&request->respool, conn->pool);
704
 
            request->allocator = serf_bucket_allocator_create(request->respool,
705
 
                                                              NULL, NULL);
706
 
            apr_pool_cleanup_register(request->respool, request,
707
 
                                      clean_resp, clean_resp);
708
 
 
709
 
            /* Fill in the rest of the values for the request. */
710
 
            read_status = request->setup(request, request->setup_baton,
711
 
                                         &request->req_bkt,
712
 
                                         &request->acceptor,
713
 
                                         &request->acceptor_baton,
714
 
                                         &request->handler,
715
 
                                         &request->handler_baton,
716
 
                                         request->respool);
717
 
 
718
 
            if (read_status) {
719
 
                /* Something bad happened. Propagate any errors. */
720
 
                return read_status;
721
 
            }
722
 
 
723
 
            request->written = 1;
724
 
            serf_bucket_aggregate_append(ostreamt, request->req_bkt);
 
788
        if (request) {
 
789
            if (request->req_bkt == NULL) {
 
790
                read_status = setup_request(request);
 
791
                if (read_status) {
 
792
                    /* Something bad happened. Propagate any errors. */
 
793
                    return read_status;
 
794
                }
 
795
            }
 
796
 
 
797
            if (!request->writing_started) {
 
798
                request->writing_started = 1;
 
799
                serf_bucket_aggregate_append(ostreamt, request->req_bkt);
 
800
            }
725
801
        }
726
802
 
727
803
        /* ### optimize at some point by using read_for_sendfile */
 
804
        /* TODO: now that read_iovec will effectively try to return as much
 
805
           data as available, we probably don't want to read ALL_AVAIL, but
 
806
           a lower number, like the size of one or a few TCP packets, the
 
807
           available TCP buffer size ... */
728
808
        read_status = serf_bucket_read_iovec(ostreamh,
729
809
                                             SERF_READ_ALL_AVAIL,
730
810
                                             IOV_MAX,
732
812
                                             &conn->vec_len);
733
813
 
734
814
        if (!conn->hit_eof) {
735
 
            if (APR_STATUS_IS_EAGAIN(read_status) ||
736
 
                read_status == SERF_ERROR_WAIT_CONN) {
 
815
            if (APR_STATUS_IS_EAGAIN(read_status)) {
737
816
                /* We read some stuff, but should not try to read again. */
738
817
                stop_reading = 1;
 
818
            }
 
819
            else if (read_status == SERF_ERROR_WAIT_CONN) {
 
820
                /* The bucket told us that it can't provide more data until
 
821
                   more data is read from the socket. This normally happens
 
822
                   during a SSL handshake.
739
823
 
740
 
                /* ### we should avoid looking for writability for a while so
741
 
                   ### that (hopefully) something will appear in the bucket so
742
 
                   ### we can actually write something. otherwise, we could
743
 
                   ### end up in a CPU spin: socket wants something, but we
744
 
                   ### don't have anything (and keep returning EAGAIN)
745
 
                */
 
824
                   We should avoid looking for writability for a while so
 
825
                   that (hopefully) something will appear in the bucket so
 
826
                   we can actually write something. otherwise, we could
 
827
                   end up in a CPU spin: socket wants something, but we
 
828
                   don't have anything (and keep returning EAGAIN)
 
829
                 */
 
830
                conn->stop_writing = 1;
 
831
                conn->dirty_conn = 1;
 
832
                conn->ctx->dirty_pollset = 1;
746
833
            }
747
834
            else if (read_status && !APR_STATUS_IS_EOF(read_status)) {
748
835
                /* Something bad happened. Propagate any errors. */
761
848
            if (APR_STATUS_IS_EAGAIN(status))
762
849
                return APR_SUCCESS;
763
850
            if (APR_STATUS_IS_EPIPE(status))
764
 
                return no_more_writes(conn, request);
765
 
            if (APR_STATUS_IS_ECONNRESET(status)) {
766
 
                return no_more_writes(conn, request);
 
851
                return no_more_writes(conn);
 
852
            if (APR_STATUS_IS_ECONNRESET(status) ||
 
853
                APR_STATUS_IS_ECONNABORTED(status)) {
 
854
                return no_more_writes(conn);
767
855
            }
768
856
            if (status)
769
857
                return status;
771
859
 
772
860
        if (read_status == SERF_ERROR_WAIT_CONN) {
773
861
            stop_reading = 1;
 
862
            conn->stop_writing = 1;
 
863
            conn->dirty_conn = 1;
 
864
            conn->ctx->dirty_pollset = 1;
774
865
        }
775
 
        else if (read_status && conn->hit_eof && conn->vec_len == 0) {
 
866
        else if (request && read_status && conn->hit_eof &&
 
867
                 conn->vec_len == 0) {
776
868
            /* If we hit the end of the request bucket and all of its data has
777
869
             * been written, then clear it out to signify that we're done
778
870
             * sending the request. On the next iteration through this loop:
836
928
 
837
929
         If the authentication was tried, but failed, pass the response
838
930
         to the application, maybe it can do better. */
839
 
      if (APR_STATUS_IS_EOF(status) ||
840
 
          APR_STATUS_IS_EAGAIN(status)) {
 
931
      if (status) {
841
932
          return status;
842
933
      }
843
934
    }
876
967
    return status;
877
968
}
878
969
 
 
970
 
 
971
apr_status_t
 
972
serf__provide_credentials(serf_context_t *ctx,
 
973
                          char **username,
 
974
                          char **password,
 
975
                          serf_request_t *request, void *baton,
 
976
                          int code, const char *authn_type,
 
977
                          const char *realm,
 
978
                          apr_pool_t *pool)
 
979
{
 
980
    serf_connection_t *conn = request->conn;
 
981
    serf_request_t *authn_req = request;
 
982
    apr_status_t status;
 
983
 
 
984
    if (request->ssltunnel == 1 &&
 
985
        conn->state == SERF_CONN_SETUP_SSLTUNNEL) {
 
986
        /* This is a CONNECT request to set up an SSL tunnel over a proxy.
 
987
           This request is created by serf, so if the proxy requires
 
988
           authentication, we can't ask the application for credentials with
 
989
           this request.
 
990
 
 
991
           Solution: setup the first request created by the application on
 
992
           this connection, and use that request and its handler_baton to
 
993
           call back to the application. */
 
994
 
 
995
        authn_req = request->next;
 
996
        /* assert: app_request != NULL */
 
997
        if (!authn_req)
 
998
            return APR_EGENERAL;
 
999
 
 
1000
        if (!authn_req->req_bkt) {
 
1001
            apr_status_t status;
 
1002
 
 
1003
            status = setup_request(authn_req);
 
1004
            /* If we can't setup a request, don't bother setting up the
 
1005
               ssl tunnel. */
 
1006
            if (status)
 
1007
                return status;
 
1008
        }
 
1009
    }
 
1010
 
 
1011
    /* Ask the application. */
 
1012
    status = (*ctx->cred_cb)(username, password,
 
1013
                             authn_req, authn_req->handler_baton,
 
1014
                             code, authn_type, realm, pool);
 
1015
    if (status)
 
1016
        return status;
 
1017
 
 
1018
    return APR_SUCCESS;
 
1019
}
 
1020
 
879
1021
/* read data from the connection */
880
1022
static apr_status_t read_from_connection(serf_connection_t *conn)
881
1023
{
888
1030
     */
889
1031
    serf_request_t *request = conn->requests;
890
1032
 
 
1033
    /* If the stop_writing flag was set on the connection, reset it now because
 
1034
       there is some data to read. */
 
1035
    if (conn->stop_writing) {
 
1036
        conn->stop_writing = 0;
 
1037
        conn->dirty_conn = 1;
 
1038
        conn->ctx->dirty_pollset = 1;
 
1039
    }
 
1040
 
891
1041
    /* assert: request != NULL */
892
1042
 
893
1043
    if ((status = apr_pool_create(&tmppool, conn->pool)) != APR_SUCCESS)
929
1079
         * 2) Doing the initial SSL handshake - we'll get EAGAIN
930
1080
         *    as the SSL buckets will hide the handshake from us
931
1081
         *    but not return any data.
 
1082
         * 3) When the server sends us an SSL alert.
932
1083
         *
933
1084
         * In these cases, we should not receive any actual user data.
934
1085
         *
935
 
         * If we see an EOF (due to an expired timeout), we'll reset the
 
1086
         * 4) When the server sends a error response, like 408 Request timeout.
 
1087
         *    This response should be passed to the application.
 
1088
         *
 
1089
         * If we see an EOF (due to either an expired timeout or the server
 
1090
         * sending the SSL 'close notify' shutdown alert), we'll reset the
936
1091
         * connection and open a new one.
937
1092
         */
938
 
        if (request->req_bkt || !request->written) {
 
1093
        if (request->req_bkt || !request->writing_started) {
939
1094
            const char *data;
940
1095
            apr_size_t len;
941
1096
 
942
 
            status = serf_bucket_read(conn->stream, SERF_READ_ALL_AVAIL,
943
 
                                      &data, &len);
 
1097
            status = serf_bucket_peek(conn->stream, &data, &len);
944
1098
 
945
 
            if (!status && len) {
946
 
                status = APR_EGENERAL;
947
 
            }
948
 
            else if (APR_STATUS_IS_EOF(status)) {
 
1099
            if (APR_STATUS_IS_EOF(status)) {
949
1100
                reset_connection(conn, 1);
950
1101
                status = APR_SUCCESS;
 
1102
                goto error;
951
1103
            }
952
 
            else if (APR_STATUS_IS_EAGAIN(status)) {
 
1104
            else if (APR_STATUS_IS_EAGAIN(status) && !len) {
953
1105
                status = APR_SUCCESS;
 
1106
                goto error;
 
1107
            } else if (status && !APR_STATUS_IS_EAGAIN(status)) {
 
1108
                /* Read error */
 
1109
                goto error;
954
1110
            }
955
1111
 
956
 
            goto error;
 
1112
            /* Unexpected response from the server */
 
1113
 
957
1114
        }
958
1115
 
959
1116
        /* If the request doesn't have a response bucket, then call the
969
1126
        status = handle_response(request, tmppool);
970
1127
 
971
1128
        /* Some systems will not generate a HUP poll event so we have to
972
 
         * handle the ECONNRESET issue here.
 
1129
         * handle the ECONNRESET issue and ECONNABORT here.
973
1130
         */
974
1131
        if (APR_STATUS_IS_ECONNRESET(status) ||
 
1132
            APR_STATUS_IS_ECONNABORTED(status) ||
975
1133
            status == SERF_ERROR_REQUEST_LOST) {
976
 
            reset_connection(conn, 1);
977
 
            status = APR_SUCCESS;
 
1134
            /* If the connection had ever been good, be optimistic & try again.
 
1135
             * If it has never tried again (incl. a retry), fail.
 
1136
             */
 
1137
            if (conn->completed_responses) {
 
1138
                reset_connection(conn, 1);
 
1139
                status = APR_SUCCESS;
 
1140
            }
 
1141
            else if (status == SERF_ERROR_REQUEST_LOST) {
 
1142
                status = SERF_ERROR_ABORTED_CONNECTION;
 
1143
            }
978
1144
            goto error;
979
1145
        }
980
1146
 
982
1148
         * treat that as a success.
983
1149
         */
984
1150
        if (APR_STATUS_IS_EAGAIN(status)) {
 
1151
            /* It is possible that while reading the response, the ssl layer
 
1152
               has prepared some data to send. If this was the last request,
 
1153
               serf will not check for socket writability, so force this here.
 
1154
             */
 
1155
            if (request_or_data_pending(&request, conn) && !request) {
 
1156
                conn->dirty_conn = 1;
 
1157
                conn->ctx->dirty_pollset = 1;
 
1158
            }
985
1159
            status = APR_SUCCESS;
986
1160
            goto error;
987
1161
        }
1001
1175
            goto error;
1002
1176
        }
1003
1177
 
1004
 
        /* The request has been fully-delivered, and the response has
1005
 
         * been fully-read. Remove it from our queue and loop to read
1006
 
         * another response.
 
1178
        /* The response has been fully-read, so that means the request has
 
1179
         * either been fully-delivered (most likely), or that we don't need to
 
1180
         * write the rest of it anymore, e.g. when a 408 Request timeout was
 
1181
         $ received.
 
1182
         * Remove it from our queue and loop to read another response.
1007
1183
         */
1008
1184
        conn->requests = request->next;
1009
1185
 
1044
1220
         * update the pollset. We don't want to read from this socket any
1045
1221
         * more. We are definitely done with this loop, too.
1046
1222
         */
1047
 
        if (request == NULL || !request->written) {
 
1223
        if (request == NULL || !request->writing_started) {
1048
1224
            conn->dirty_conn = 1;
1049
1225
            conn->ctx->dirty_pollset = 1;
1050
1226
            status = APR_SUCCESS;
1081
1257
    if ((events & APR_POLLHUP) != 0) {
1082
1258
        /* The connection got reset by the server. On Windows this can happen
1083
1259
           when all data is read, so just cleanup the connection and open
1084
 
           a new one. */
1085
 
        return reset_connection(conn, 1);
 
1260
           a new one.
 
1261
           If we haven't had any successful responses on this connection,
 
1262
           then error out as it is likely a server issue. */
 
1263
        if (conn->completed_responses) {
 
1264
            return reset_connection(conn, 1);
 
1265
        }
 
1266
        return SERF_ERROR_ABORTED_CONNECTION;
1086
1267
    }
1087
1268
    if ((events & APR_POLLERR) != 0) {
1088
1269
        /* We might be talking to a buggy HTTP server that doesn't
1095
1276
        if (conn->completed_requests && !conn->probable_keepalive_limit) {
1096
1277
            return reset_connection(conn, 1);
1097
1278
        }
 
1279
#ifdef SO_ERROR
 
1280
        /* If possible, get the error from the platform's socket layer and
 
1281
           convert it to an APR status code. */
 
1282
        {
 
1283
            apr_os_sock_t osskt;
 
1284
            if (!apr_os_sock_get(&osskt, conn->skt)) {
 
1285
                int error;
 
1286
                apr_socklen_t l = sizeof(error);
 
1287
 
 
1288
                if (!getsockopt(osskt, SOL_SOCKET, SO_ERROR, (char*)&error,
 
1289
                                &l)) {
 
1290
                    status = APR_FROM_OS_ERROR(error);
 
1291
 
 
1292
                    /* Handle fallback for multi-homed servers.
 
1293
                     
 
1294
                       ### Improve algorithm to find better than just 'next'?
 
1295
 
 
1296
                       Current Windows versions already handle re-ordering for
 
1297
                       api users by using statistics on the recently failed
 
1298
                       connections to order the list of addresses. */
 
1299
                    if (conn->completed_requests == 0
 
1300
                        && conn->address->next != NULL
 
1301
                        && (APR_STATUS_IS_ECONNREFUSED(status)
 
1302
                            || APR_STATUS_IS_TIMEUP(status)
 
1303
                            || APR_STATUS_IS_ENETUNREACH(status))) {
 
1304
 
 
1305
                        conn->address = conn->address->next;
 
1306
                        return reset_connection(conn, 1);
 
1307
                    }
 
1308
 
 
1309
                    return status;
 
1310
                  }
 
1311
            }
 
1312
        }
 
1313
#endif
1098
1314
        return APR_EGENERAL;
1099
1315
    }
1100
1316
    if ((events & APR_POLLOUT) != 0) {
1117
1333
 
1118
1334
    conn->ctx = ctx;
1119
1335
    conn->status = APR_SUCCESS;
1120
 
    conn->address = address;
 
1336
    /* Ignore server address if proxy was specified. */
 
1337
    conn->address = ctx->proxy_address ? ctx->proxy_address : address;
1121
1338
    conn->setup = setup;
1122
1339
    conn->setup_baton = setup_baton;
1123
1340
    conn->closed = closed;
1131
1348
    conn->baton.u.conn = conn;
1132
1349
    conn->hit_eof = 0;
1133
1350
    conn->state = SERF_CONN_INIT;
 
1351
    conn->latency = -1; /* unknown */
1134
1352
 
1135
1353
    /* Create a subpool for our connection. */
1136
1354
    apr_pool_create(&conn->skt_pool, conn->pool);
1137
1355
 
1138
1356
    /* register a cleanup */
1139
 
    apr_pool_cleanup_register(conn->pool, conn, clean_conn, apr_pool_cleanup_null);
 
1357
    apr_pool_cleanup_register(conn->pool, conn, clean_conn,
 
1358
                              apr_pool_cleanup_null);
1140
1359
 
1141
1360
    /* Add the connection to the context. */
1142
1361
    *(serf_connection_t **)apr_array_push(ctx->conns) = conn;
1143
1362
 
 
1363
    serf__log(CONN_VERBOSE, __FILE__, "created connection 0x%x\n",
 
1364
              conn);
 
1365
 
1144
1366
    return conn;
1145
1367
}
1146
1368
 
1154
1376
    void *closed_baton,
1155
1377
    apr_pool_t *pool)
1156
1378
{
1157
 
    apr_status_t status;
 
1379
    apr_status_t status = APR_SUCCESS;
1158
1380
    serf_connection_t *c;
1159
 
    apr_sockaddr_t *host_address;
1160
 
 
1161
 
    /* Parse the url, store the address of the server. */
1162
 
    status = apr_sockaddr_info_get(&host_address,
1163
 
                                   host_info.hostname,
1164
 
                                   APR_UNSPEC, host_info.port, 0, pool);
1165
 
    if (status)
1166
 
        return status;
 
1381
    apr_sockaddr_t *host_address = NULL;
 
1382
 
 
1383
    /* Set the port number explicitly, needed to create the socket later. */
 
1384
    if (!host_info.port) {
 
1385
        host_info.port = apr_uri_port_of_scheme(host_info.scheme);
 
1386
    }
 
1387
 
 
1388
    /* Only lookup the address of the server if no proxy server was
 
1389
       configured. */
 
1390
    if (!ctx->proxy_address) {
 
1391
        status = apr_sockaddr_info_get(&host_address,
 
1392
                                       host_info.hostname,
 
1393
                                       APR_UNSPEC, host_info.port, 0, pool);
 
1394
        if (status)
 
1395
            return status;
 
1396
    }
1167
1397
 
1168
1398
    c = serf_connection_create(ctx, host_address, setup, setup_baton,
1169
1399
                               closed, closed_baton, pool);
1171
1401
    /* We're not interested in the path following the hostname. */
1172
1402
    c->host_url = apr_uri_unparse(c->pool,
1173
1403
                                  &host_info,
1174
 
                                  APR_URI_UNP_OMITPATHINFO);
1175
 
    c->host_info = host_info;
 
1404
                                  APR_URI_UNP_OMITPATHINFO |
 
1405
                                  APR_URI_UNP_OMITUSERINFO);
 
1406
 
 
1407
    /* Store the host info without the path on the connection. */
 
1408
    (void)apr_uri_parse(c->pool, c->host_url, &(c->host_info));
 
1409
    if (!c->host_info.port) {
 
1410
        c->host_info.port = apr_uri_port_of_scheme(c->host_info.scheme);
 
1411
    }
1176
1412
 
1177
1413
    *conn = c;
1178
1414
 
1203
1439
            if (conn->skt != NULL) {
1204
1440
                remove_connection(ctx, conn);
1205
1441
                status = apr_socket_close(conn->skt);
 
1442
                serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt,
 
1443
                              "closed socket, status %d\n",
 
1444
                              status);
1206
1445
                if (conn->closed != NULL) {
1207
1446
                    handle_conn_closed(conn, status);
1208
1447
                }
1213
1452
                conn->stream = NULL;
1214
1453
            }
1215
1454
 
 
1455
            destroy_ostream(conn);
 
1456
 
1216
1457
            /* Remove the connection from the context. We don't want to
1217
1458
             * deal with it any more.
1218
1459
             */
1225
1466
            }
1226
1467
            --ctx->conns->nelts;
1227
1468
 
 
1469
            serf__log(CONN_VERBOSE, __FILE__, "closed connection 0x%x\n",
 
1470
                      conn);
 
1471
 
1228
1472
            /* Found the connection. Closed it. All done. */
1229
1473
            return APR_SUCCESS;
1230
1474
        }
1240
1484
    serf_connection_t *conn,
1241
1485
    unsigned int max_requests)
1242
1486
{
 
1487
    if (max_requests == 0)
 
1488
        serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
 
1489
                      "Set max. nr. of outstanding requests for this "
 
1490
                      "connection to unlimited.\n");
 
1491
    else
 
1492
        serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
 
1493
                      "Limit max. nr. of outstanding requests for this "
 
1494
                      "connection to %u.\n", max_requests);
 
1495
 
1243
1496
    conn->max_outstanding_requests = max_requests;
1244
1497
}
1245
1498
 
1258
1511
    conn->async_handler_baton = handler_baton;
1259
1512
}
1260
1513
 
 
1514
static serf_request_t *
 
1515
create_request(serf_connection_t *conn,
 
1516
               serf_request_setup_t setup,
 
1517
               void *setup_baton,
 
1518
               int priority,
 
1519
               int ssltunnel)
 
1520
{
 
1521
    serf_request_t *request;
 
1522
 
 
1523
    request = serf_bucket_mem_alloc(conn->allocator, sizeof(*request));
 
1524
    request->conn = conn;
 
1525
    request->setup = setup;
 
1526
    request->setup_baton = setup_baton;
 
1527
    request->handler = NULL;
 
1528
    request->respool = NULL;
 
1529
    request->req_bkt = NULL;
 
1530
    request->resp_bkt = NULL;
 
1531
    request->priority = priority;
 
1532
    request->writing_started = 0;
 
1533
    request->ssltunnel = ssltunnel;
 
1534
    request->next = NULL;
 
1535
    request->auth_baton = NULL;
 
1536
 
 
1537
    return request;
 
1538
}
1261
1539
 
1262
1540
serf_request_t *serf_connection_request_create(
1263
1541
    serf_connection_t *conn,
1266
1544
{
1267
1545
    serf_request_t *request;
1268
1546
 
1269
 
    request = serf_bucket_mem_alloc(conn->allocator, sizeof(*request));
1270
 
    request->conn = conn;
1271
 
    request->setup = setup;
1272
 
    request->setup_baton = setup_baton;
1273
 
    request->handler = NULL;
1274
 
    request->respool = NULL;
1275
 
    request->req_bkt = NULL;
1276
 
    request->resp_bkt = NULL;
1277
 
    request->priority = 0;
1278
 
    request->written = 0;
1279
 
    request->next = NULL;
 
1547
    request = create_request(conn, setup, setup_baton,
 
1548
                             0, /* priority */
 
1549
                             0  /* ssl tunnel */);
1280
1550
 
1281
1551
    /* Link the request to the end of the request chain. */
1282
 
    if (conn->state == SERF_CONN_CLOSING) {
1283
 
        link_requests(&conn->hold_requests, &conn->hold_requests_tail, request);
1284
 
    }
1285
 
    else {
1286
 
        link_requests(&conn->requests, &conn->requests_tail, request);
1287
 
 
1288
 
        /* Ensure our pollset becomes writable in context run */
1289
 
        conn->ctx->dirty_pollset = 1;
1290
 
        conn->dirty_conn = 1;
1291
 
    }
 
1552
    link_requests(&conn->requests, &conn->requests_tail, request);
 
1553
    
 
1554
    /* Ensure our pollset becomes writable in context run */
 
1555
    conn->ctx->dirty_pollset = 1;
 
1556
    conn->dirty_conn = 1;
1292
1557
 
1293
1558
    return request;
1294
1559
}
1295
1560
 
1296
 
 
1297
 
serf_request_t *serf_connection_priority_request_create(
1298
 
    serf_connection_t *conn,
1299
 
    serf_request_setup_t setup,
1300
 
    void *setup_baton)
 
1561
static serf_request_t *
 
1562
priority_request_create(serf_connection_t *conn,
 
1563
                        int ssltunnelreq,
 
1564
                        serf_request_setup_t setup,
 
1565
                        void *setup_baton)
1301
1566
{
1302
1567
    serf_request_t *request;
1303
1568
    serf_request_t *iter, *prev;
1304
1569
 
1305
 
    request = serf_bucket_mem_alloc(conn->allocator, sizeof(*request));
1306
 
    request->conn = conn;
1307
 
    request->setup = setup;
1308
 
    request->setup_baton = setup_baton;
1309
 
    request->handler = NULL;
1310
 
    request->respool = NULL;
1311
 
    request->req_bkt = NULL;
1312
 
    request->resp_bkt = NULL;
1313
 
    request->priority = 1;
1314
 
    request->written = 0;
1315
 
    request->next = NULL;
 
1570
    request = create_request(conn, setup, setup_baton,
 
1571
                             1, /* priority */
 
1572
                             ssltunnelreq);
1316
1573
 
1317
 
    /* Link the new request after the last written request, but before all
1318
 
       upcoming requests. */
1319
 
    if (conn->state == SERF_CONN_CLOSING) {
1320
 
        iter = conn->hold_requests;
1321
 
    }
1322
 
    else {
1323
 
        iter = conn->requests;
1324
 
    }
 
1574
    /* Link the new request after the last written request. */
 
1575
    iter = conn->requests;
1325
1576
    prev = NULL;
1326
1577
 
1327
1578
    /* Find a request that has data which needs to be delivered. */
1328
 
    while (iter != NULL && iter->req_bkt == NULL && iter->written) {
 
1579
    while (iter != NULL && iter->req_bkt == NULL && iter->writing_started) {
1329
1580
        prev = iter;
1330
1581
        iter = iter->next;
1331
1582
    }
1332
1583
 
1333
 
    /* Advance to next non priority request */
1334
 
    while (iter != NULL && iter->priority) {
1335
 
        prev = iter;
1336
 
        iter = iter->next;
 
1584
    /* A CONNECT request to setup an ssltunnel has absolute priority over all
 
1585
       other requests on the connection, so:
 
1586
       a. add it first to the queue 
 
1587
       b. ensure that other priority requests are added after the CONNECT
 
1588
          request */
 
1589
    if (!request->ssltunnel) {
 
1590
        /* Advance to next non priority request */
 
1591
        while (iter != NULL && iter->priority) {
 
1592
            prev = iter;
 
1593
            iter = iter->next;
 
1594
        }
1337
1595
    }
1338
1596
 
1339
1597
    if (prev) {
1341
1599
        prev->next = request;
1342
1600
    } else {
1343
1601
        request->next = iter;
1344
 
        if (conn->state == SERF_CONN_CLOSING) {
1345
 
            conn->hold_requests = request;
1346
 
        }
1347
 
        else {
1348
 
            conn->requests = request;
1349
 
        }
 
1602
        conn->requests = request;
1350
1603
    }
1351
1604
 
1352
 
    if (conn->state != SERF_CONN_CLOSING) {
1353
 
        /* Ensure our pollset becomes writable in context run */
1354
 
        conn->ctx->dirty_pollset = 1;
1355
 
        conn->dirty_conn = 1;
1356
 
    }
 
1605
    /* Ensure our pollset becomes writable in context run */
 
1606
    conn->ctx->dirty_pollset = 1;
 
1607
    conn->dirty_conn = 1;
1357
1608
 
1358
1609
    return request;
1359
1610
}
1360
1611
 
 
1612
serf_request_t *serf_connection_priority_request_create(
 
1613
    serf_connection_t *conn,
 
1614
    serf_request_setup_t setup,
 
1615
    void *setup_baton)
 
1616
{
 
1617
    return priority_request_create(conn,
 
1618
                                   0, /* not a ssltunnel CONNECT request */
 
1619
                                   setup, setup_baton);
 
1620
}
 
1621
 
 
1622
serf_request_t *serf__ssltunnel_request_create(serf_connection_t *conn,
 
1623
                                               serf_request_setup_t setup,
 
1624
                                               void *setup_baton)
 
1625
{
 
1626
    return priority_request_create(conn,
 
1627
                                   1, /* This is a ssltunnel CONNECT request */
 
1628
                                   setup, setup_baton);
 
1629
}
1361
1630
 
1362
1631
apr_status_t serf_request_cancel(serf_request_t *request)
1363
1632
{
1364
1633
    return cancel_request(request, &request->conn->requests, 0);
1365
1634
}
1366
1635
 
 
1636
apr_status_t serf_request_is_written(serf_request_t *request)
 
1637
{
 
1638
    if (request->writing_started && !request->req_bkt)
 
1639
        return APR_SUCCESS;
 
1640
 
 
1641
    return APR_EBUSY;
 
1642
}
1367
1643
 
1368
1644
apr_pool_t *serf_request_get_pool(const serf_request_t *request)
1369
1645
{
1405
1681
    serf_bucket_t *req_bkt, *hdrs_bkt;
1406
1682
    serf_connection_t *conn = request->conn;
1407
1683
    serf_context_t *ctx = conn->ctx;
 
1684
    int ssltunnel;
 
1685
 
 
1686
    ssltunnel = ctx->proxy_address &&
 
1687
                (strcmp(conn->host_info.scheme, "https") == 0);
1408
1688
 
1409
1689
    req_bkt = serf_bucket_request_create(method, uri, body, allocator);
1410
1690
    hdrs_bkt = serf_bucket_request_get_headers(req_bkt);
1411
1691
 
1412
 
    /* Proxy? */
1413
 
    if (ctx->proxy_address && conn->host_url)
 
1692
    /* Use absolute uri's in requests to a proxy. USe relative uri's in
 
1693
       requests directly to a server or sent through an SSL tunnel. */
 
1694
    if (ctx->proxy_address && conn->host_url &&
 
1695
        !(ssltunnel && !request->ssltunnel)) {
 
1696
 
1414
1697
        serf_bucket_request_set_root(req_bkt, conn->host_url);
 
1698
    }
1415
1699
 
1416
1700
    if (conn->host_info.hostinfo)
1417
1701
        serf_bucket_headers_setn(hdrs_bkt, "Host",
1418
1702
                                 conn->host_info.hostinfo);
1419
1703
 
1420
 
    /* Setup server authorization headers */
1421
 
    if (ctx->authn_info.scheme)
1422
 
        ctx->authn_info.scheme->setup_request_func(401, conn, method, uri,
 
1704
    /* Setup server authorization headers, unless this is a CONNECT request. */
 
1705
    if (!request->ssltunnel) {
 
1706
        serf__authn_info_t *authn_info;
 
1707
        authn_info = serf__get_authn_info_for_server(conn);
 
1708
        if (authn_info->scheme)
 
1709
            authn_info->scheme->setup_request_func(HOST, 0, conn, request,
 
1710
                                                   method, uri,
1423
1711
                                                   hdrs_bkt);
 
1712
    }
1424
1713
 
1425
 
    /* Setup proxy authorization headers */
1426
 
    if (ctx->proxy_authn_info.scheme)
1427
 
        ctx->proxy_authn_info.scheme->setup_request_func(407, conn, method,
1428
 
                                                         uri, hdrs_bkt);
 
1714
    /* Setup proxy authorization headers.
 
1715
       Don't set these headers on the requests to the server if we're using
 
1716
       an SSL tunnel, only on the CONNECT request to setup the tunnel. */
 
1717
    if (ctx->proxy_authn_info.scheme) {
 
1718
        if (strcmp(conn->host_info.scheme, "https") == 0) {
 
1719
            if (request->ssltunnel)
 
1720
                ctx->proxy_authn_info.scheme->setup_request_func(PROXY, 0, conn,
 
1721
                                                                 request,
 
1722
                                                                 method, uri,
 
1723
                                                                 hdrs_bkt);
 
1724
        } else {
 
1725
            ctx->proxy_authn_info.scheme->setup_request_func(PROXY, 0, conn,
 
1726
                                                             request,
 
1727
                                                             method, uri,
 
1728
                                                             hdrs_bkt);
 
1729
        }
 
1730
    }
1429
1731
 
1430
1732
    return req_bkt;
1431
1733
}
 
1734
 
 
1735
apr_interval_time_t serf_connection_get_latency(serf_connection_t *conn)
 
1736
{
 
1737
    if (conn->ctx->proxy_address) {
 
1738
        /* Detecting network latency for proxied connection is not implemented
 
1739
           yet. */
 
1740
        return -1;
 
1741
    }
 
1742
 
 
1743
    return conn->latency;
 
1744
}