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

« back to all changes in this revision

Viewing changes to outgoing.c

  • Committer: Bazaar Package Importer
  • Author(s): Peter Samuelson
  • Date: 2011-06-27 18:09:28 UTC
  • mfrom: (1.2.5 upstream)
  • mto: (3.3.1 sid)
  • mto: This revision was merged to the branch mainline in revision 11.
  • Revision ID: james.westby@ubuntu.com-20110627180928-ybwzd3hmx82nu3ir
Tags: 1.0.0~0+svn1514-1
* New upstream snapshot.
  - patches/abi-0.x: Remove as obsolete.
  - patches/kqueue: Forward-port.
  - Bump ABI: libserf0.7{,-dbg} -> libserf1{,-dbg}
  - patches/ip6-localhost: New patch: temporary (I hope) workaround for
    IPv4 / IPv6 confusion in testsuite.
* Implement Multi-Arch: same.
* libserf-dev Conflicts: libserf-0-0-dev, not Breaks.  Thanks, lintian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
 
39
39
static apr_status_t clean_resp(void *data)
40
40
{
41
 
    serf_request_t *req = data;
 
41
    serf_request_t *request = data;
 
42
 
 
43
    /* The request's RESPOOL is being cleared.  */
 
44
 
 
45
    /* If the response has allocated some buckets, then destroy them (since
 
46
       the bucket may hold resources other than memory in RESPOOL). Also
 
47
       make sure to set their fields to NULL so connection closure does
 
48
       not attempt to free them again.  */
 
49
    if (request->resp_bkt) {
 
50
        serf_bucket_destroy(request->resp_bkt);
 
51
        request->resp_bkt = NULL;
 
52
    }
 
53
    if (request->req_bkt) {
 
54
        serf_bucket_destroy(request->req_bkt);
 
55
        request->req_bkt = NULL;
 
56
    }
 
57
 
 
58
    /* ### should we worry about debug stuff, like that performed in
 
59
       ### destroy_request()? should we worry about calling req->handler
 
60
       ### to notify this "cancellation" due to pool clearing?  */
42
61
 
43
62
    /* This pool just got cleared/destroyed. Don't try to destroy the pool
44
 
     * (again) when the request is canceled.
45
 
     */
46
 
    req->respool = NULL;
 
63
       (again) when the request is canceled.  */
 
64
    request->respool = NULL;
47
65
 
48
66
    return APR_SUCCESS;
49
67
}
232
250
        if (conn->ctx->authn_info.scheme)
233
251
            conn->ctx->authn_info.scheme->init_conn_func(401, conn,
234
252
                                                         conn->pool);
 
253
 
 
254
        /* Does this connection require a SSL tunnel over the proxy? */
 
255
        if (ctx->proxy_address && strcmp(conn->host_info.scheme, "https") == 0)
 
256
            serf__ssltunnel_connect(conn);
 
257
        else
 
258
            conn->state = SERF_CONN_CONNECTED;
235
259
    }
236
260
 
237
261
    return APR_SUCCESS;
241
265
                                   serf_request_t *request)
242
266
{
243
267
    /* Note that we should hold new requests until we open our new socket. */
244
 
    conn->closing = 1;
 
268
    conn->state = SERF_CONN_CLOSING;
245
269
 
246
270
    /* We can take the *next* request in our list and assume it hasn't
247
271
     * been written yet and 'save' it for the new socket.
304
328
    if (request->resp_bkt) {
305
329
        serf_debug__closed_conn(request->resp_bkt->allocator);
306
330
        serf_bucket_destroy(request->resp_bkt);
 
331
        request->resp_bkt = NULL;
307
332
    }
308
333
    if (request->req_bkt) {
309
334
        serf_debug__closed_conn(request->req_bkt->allocator);
310
335
        serf_bucket_destroy(request->req_bkt);
 
336
        request->req_bkt = NULL;
311
337
    }
312
338
 
313
339
    serf_debug__bucket_alloc_check(request->allocator);
314
340
    if (request->respool) {
 
341
        /* ### unregister the pool cleanup for self?  */
315
342
        apr_pool_destroy(request->respool);
316
343
    }
317
344
 
394
421
    held_reqs = conn->hold_requests;
395
422
    held_reqs_tail = conn->hold_requests_tail;
396
423
 
397
 
    if (conn->closing) {
 
424
    if (conn->state == SERF_CONN_CLOSING) {
398
425
        conn->hold_requests = NULL;
399
426
        conn->hold_requests_tail = NULL;
400
 
        conn->closing = 0;
401
427
    }
402
428
 
403
429
    conn->requests = NULL;
449
475
 
450
476
    conn->dirty_conn = 1;
451
477
    conn->ctx->dirty_pollset = 1;
 
478
    conn->state = SERF_CONN_INIT;
452
479
 
453
480
    conn->status = APR_SUCCESS;
454
481
 
538
565
    return status;
539
566
}
540
567
 
 
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
 
541
615
/* write data out to the connection */
542
616
static apr_status_t write_to_connection(serf_connection_t *conn)
543
617
{
545
619
 
546
620
    if (conn->probable_keepalive_limit &&
547
621
        conn->completed_requests > conn->probable_keepalive_limit) {
 
622
 
 
623
        conn->dirty_conn = 1;
 
624
        conn->ctx->dirty_pollset = 1;
 
625
 
548
626
        /* backoff for now. */
549
627
        return APR_SUCCESS;
550
628
    }
563
641
        int stop_reading = 0;
564
642
        apr_status_t status;
565
643
        apr_status_t read_status;
566
 
 
567
 
        if (conn->max_outstanding_requests &&
 
644
        serf_bucket_t *ostreamt, *ostreamh;
 
645
        int max_outstanding_requests = conn->max_outstanding_requests;
 
646
 
 
647
        /* If we're setting up an ssl tunnel, we can't send real requests
 
648
           at yet, as they need to be encrypted and our encrypt buckets
 
649
           aren't created yet as we still need to read the unencrypted
 
650
           response of the CONNECT request. */
 
651
        if (conn->state != SERF_CONN_CONNECTED)
 
652
            max_outstanding_requests = 1;
 
653
 
 
654
        if (max_outstanding_requests &&
568
655
            conn->completed_requests -
569
 
                conn->completed_responses >= conn->max_outstanding_requests) {
 
656
                conn->completed_responses >= max_outstanding_requests) {
570
657
            /* backoff for now. */
571
658
            return APR_SUCCESS;
572
659
        }
606
693
            return APR_SUCCESS;
607
694
        }
608
695
 
609
 
        /* If the connection does not have an associated bucket, then
610
 
         * call the setup callback to get one.
611
 
         */
612
 
        if (conn->stream == NULL) {
613
 
            status = do_conn_setup(conn);
614
 
            if (status) {
615
 
                return status;
616
 
            }
 
696
        status = prepare_conn_streams(conn, &conn->stream, &ostreamt, &ostreamh);
 
697
        if (status) {
 
698
            return status;
617
699
        }
618
700
 
619
701
        if (request->req_bkt == NULL) {
639
721
            }
640
722
 
641
723
            request->written = 1;
642
 
            serf_bucket_aggregate_append(conn->ostream_tail, request->req_bkt);
 
724
            serf_bucket_aggregate_append(ostreamt, request->req_bkt);
643
725
        }
644
726
 
645
727
        /* ### optimize at some point by using read_for_sendfile */
646
 
        read_status = serf_bucket_read_iovec(conn->ostream_head,
 
728
        read_status = serf_bucket_read_iovec(ostreamh,
647
729
                                             SERF_READ_ALL_AVAIL,
648
730
                                             IOV_MAX,
649
731
                                             conn->vec,
650
732
                                             &conn->vec_len);
651
733
 
652
734
        if (!conn->hit_eof) {
653
 
            if (APR_STATUS_IS_EAGAIN(read_status)) {
 
735
            if (APR_STATUS_IS_EAGAIN(read_status) ||
 
736
                read_status == SERF_ERROR_WAIT_CONN) {
654
737
                /* We read some stuff, but should not try to read again. */
655
738
                stop_reading = 1;
656
739
 
686
769
                return status;
687
770
        }
688
771
 
689
 
        if (conn->hit_eof &&
690
 
            conn->vec_len == 0) {
 
772
        if (read_status == SERF_ERROR_WAIT_CONN) {
 
773
            stop_reading = 1;
 
774
        }
 
775
        else if (read_status && conn->hit_eof && conn->vec_len == 0) {
691
776
            /* If we hit the end of the request bucket and all of its data has
692
777
             * been written, then clear it out to signify that we're done
693
778
             * sending the request. On the next iteration through this loop:
697
782
             * ("pipelining").
698
783
             */
699
784
            conn->hit_eof = 0;
 
785
            serf_bucket_destroy(request->req_bkt);
700
786
            request->req_bkt = NULL;
701
787
 
702
788
            /* If our connection has async responses enabled, we're not
728
814
static apr_status_t handle_response(serf_request_t *request,
729
815
                                    apr_pool_t *pool)
730
816
{
731
 
    apr_status_t status;
 
817
    apr_status_t status = APR_SUCCESS;
732
818
    int consumed_response = 0;
733
819
 
734
820
    /* Only enable the new authentication framework if the program has
809
895
 
810
896
    /* Invoke response handlers until we have no more work. */
811
897
    while (1) {
 
898
        serf_bucket_t *dummy1, *dummy2;
 
899
 
812
900
        apr_pool_clear(tmppool);
813
901
 
814
 
        /* If the connection does not have an associated bucket, then
815
 
         * call the setup callback to get one.
816
 
         */
817
 
        if (conn->stream == NULL) {
818
 
            status = do_conn_setup(conn);
819
 
            if (status) {
820
 
                goto error;
821
 
            }
 
902
        /* Only interested in the input stream here. */
 
903
        status = prepare_conn_streams(conn, &conn->stream, &dummy1, &dummy2);
 
904
        if (status) {
 
905
            goto error;
822
906
        }
823
907
 
824
908
        /* We have a different codepath when we can have async responses. */
934
1018
 
935
1019
        conn->completed_responses++;
936
1020
 
 
1021
        /* We've to rebuild pollset since completed_responses is changed. */
 
1022
        conn->dirty_conn = 1;
 
1023
        conn->ctx->dirty_pollset = 1;
 
1024
 
937
1025
        /* This means that we're being advised that the connection is done. */
938
1026
        if (close_connection == SERF_ERROR_CLOSING) {
939
1027
            reset_connection(conn, 1);
991
1079
        }
992
1080
    }
993
1081
    if ((events & APR_POLLHUP) != 0) {
994
 
        return APR_ECONNRESET;
 
1082
        /* The connection got reset by the server. On Windows this can happen
 
1083
           when all data is read, so just cleanup the connection and open
 
1084
           a new one. */
 
1085
        return reset_connection(conn, 1);
995
1086
    }
996
1087
    if ((events & APR_POLLERR) != 0) {
997
1088
        /* We might be talking to a buggy HTTP server that doesn't
1001
1092
         *
1002
1093
         * http://issues.apache.org/bugzilla/show_bug.cgi?id=35292
1003
1094
         */
1004
 
        if (!conn->probable_keepalive_limit) {
 
1095
        if (conn->completed_requests && !conn->probable_keepalive_limit) {
1005
1096
            return reset_connection(conn, 1);
1006
1097
        }
1007
1098
        return APR_EGENERAL;
1039
1130
    conn->baton.type = SERF_IO_CONN;
1040
1131
    conn->baton.u.conn = conn;
1041
1132
    conn->hit_eof = 0;
 
1133
    conn->state = SERF_CONN_INIT;
1042
1134
 
1043
1135
    /* Create a subpool for our connection. */
1044
1136
    apr_pool_create(&conn->skt_pool, conn->pool);
1066
1158
    serf_connection_t *c;
1067
1159
    apr_sockaddr_t *host_address;
1068
1160
 
1069
 
    /* Support for HTTPS proxies is not implemented yet. */
1070
 
    if (ctx->proxy_address && strcmp(host_info.scheme, "https") == 0)
1071
 
        return APR_ENOTIMPL;
1072
 
 
1073
1161
    /* Parse the url, store the address of the server. */
1074
1162
    status = apr_sockaddr_info_get(&host_address,
1075
1163
                                   host_info.hostname,
1186
1274
    request->respool = NULL;
1187
1275
    request->req_bkt = NULL;
1188
1276
    request->resp_bkt = NULL;
 
1277
    request->priority = 0;
1189
1278
    request->written = 0;
1190
1279
    request->next = NULL;
1191
1280
 
1192
1281
    /* Link the request to the end of the request chain. */
1193
 
    if (conn->closing) {
 
1282
    if (conn->state == SERF_CONN_CLOSING) {
1194
1283
        link_requests(&conn->hold_requests, &conn->hold_requests_tail, request);
1195
1284
    }
1196
1285
    else {
1221
1310
    request->respool = NULL;
1222
1311
    request->req_bkt = NULL;
1223
1312
    request->resp_bkt = NULL;
 
1313
    request->priority = 1;
1224
1314
    request->written = 0;
1225
1315
    request->next = NULL;
1226
1316
 
1227
1317
    /* Link the new request after the last written request, but before all
1228
1318
       upcoming requests. */
1229
 
    if (conn->closing) {
 
1319
    if (conn->state == SERF_CONN_CLOSING) {
1230
1320
        iter = conn->hold_requests;
1231
1321
    }
1232
1322
    else {
1240
1330
        iter = iter->next;
1241
1331
    }
1242
1332
 
 
1333
    /* Advance to next non priority request */
 
1334
    while (iter != NULL && iter->priority) {
 
1335
        prev = iter;
 
1336
        iter = iter->next;
 
1337
    }
 
1338
 
1243
1339
    if (prev) {
1244
1340
        request->next = iter;
1245
1341
        prev->next = request;
1246
1342
    } else {
1247
1343
        request->next = iter;
1248
 
        if (conn->closing) {
 
1344
        if (conn->state == SERF_CONN_CLOSING) {
1249
1345
            conn->hold_requests = request;
1250
1346
        }
1251
1347
        else {
1253
1349
        }
1254
1350
    }
1255
1351
 
1256
 
    if (! conn->closing) {
 
1352
    if (conn->state != SERF_CONN_CLOSING) {
1257
1353
        /* Ensure our pollset becomes writable in context run */
1258
1354
        conn->ctx->dirty_pollset = 1;
1259
1355
        conn->dirty_conn = 1;