summaryrefslogtreecommitdiffstats
path: root/debian/perl-framework/c-modules/test_pass_brigade/mod_test_pass_brigade.c
blob: 99bc95a8c4dd88fac39f64201fa1a982b83bd54d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#define HTTPD_TEST_REQUIRE_APACHE 2

#if CONFIG_FOR_HTTPD_TEST

<Location /test_pass_brigade>
   SetHandler test_pass_brigade
</Location>

#endif

#define APACHE_HTTPD_TEST_HANDLER test_pass_brigade_handler

#include "apache_httpd_test.h"

#include "apr_buckets.h"

#define WANT_HTTPD_TEST_SPLIT_QS_NUMBERS
#include "httpd_test_util.c"

/*
 * mainly for testing / researching core_output_filter buffering
 */

static int test_pass_brigade_handler(request_rec *r)
{
    conn_rec *c = r->connection;
    size_t total=0, remaining=1;
    char *buff;
    size_t buff_size = 8192;
    apr_bucket_brigade *bb;

    if (strcmp(r->handler, "test_pass_brigade")) {
        return DECLINED;
    }
    if (r->method_number != M_GET) {
        return DECLINED;
    }

    httpd_test_split_qs_numbers(r, &buff_size, &remaining, NULL);

    ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
                  "going to echo %" APR_SIZE_T_FMT " bytes with "
                  "buffer size=%" APR_SIZE_T_FMT "",
                  remaining, buff_size);

    buff = malloc(buff_size);
    memset(buff, 'a', buff_size);
    bb = apr_brigade_create(r->pool, c->bucket_alloc);

    while (total < remaining) {
        int left = (remaining - total);
        int len = left <= buff_size ? left : buff_size;
        apr_bucket *bucket = apr_bucket_transient_create(buff, len, 
                                                         c->bucket_alloc);
        apr_status_t status;

        apr_brigade_cleanup(bb);
        APR_BRIGADE_INSERT_TAIL(bb, bucket);
        if (len + total == remaining) {
            bucket = apr_bucket_eos_create(c->bucket_alloc);
            APR_BRIGADE_INSERT_TAIL(bb, bucket);

#if 0
            /* ###### A FLUSH should not be strictly necessary here
             * but inserting one apears to work around intermittent
             * failures when running t/apache/pass_brigade.t under
             * worker. */
            bucket = apr_bucket_flush_create(c->bucket_alloc);
            APR_BRIGADE_INSERT_TAIL(bb, bucket);
#endif

            ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
                          "[mod_test_pass_brigade] sending EOS");
        }

        status = ap_pass_brigade(r->output_filters->next, bb);

        if (status != APR_SUCCESS) {
            apr_brigade_destroy(bb);
            ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
                          "[mod_test_pass_brigade] ap_pass_brigade failed");
            free(buff);
            return HTTP_INTERNAL_SERVER_ERROR;
        }

        total += len;

        ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
                      "[mod_test_pass_brigade] wrote %d of %d bytes",
                      len, len);
    }
    
    apr_brigade_destroy(bb);
    ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
                  "[mod_test_pass_brigade] done writing %" APR_SIZE_T_FMT 
                  " of %" APR_SIZE_T_FMT " bytes",
                 total, remaining);

    free(buff);    
    return OK;
}

APACHE_HTTPD_TEST_MODULE(test_pass_brigade);