httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sandip Dongare <sandip.dong...@gmail.com>
Subject "ap_get_brigade" api is failing in "AP_MODE_SPECULATIVE" mode on Linux
Date Wed, 05 Dec 2012 11:03:48 GMT
I am writing filter for Apache/2.2.11. 
In the filter I want to read the POST data of the request. To achieve this I
written a code to read the data from brigade/bucket.
The code is working fine if "ap_get_brigade" api is called in
"AP_MODE_READBYTES" mode. I am able to read complete post data of the request.
But it is failing in case "ap_get_brigade" api is called in
"AP_MODE_SPECULATIVE" mode. Actually after reading post data in the filter, post
data should not be cleared and it should be accessible to downstream application
so I want to use AP_MODE_SPECULATIVE.
I found that in the failure case "ap_get_brigade" is returning the same chunk of
data. 

Here pasting the code snippet:


int printPost(request_rec* rqRec)
{
    apr_status_t retStatus;
    apr_bucket_brigade *bb;
    apr_bucket *bucket;
    ap_input_mode_t read_mode;
    int nread = 0;
    bool seen_eos=false;
    const char *data;
    apr_size_t len;
    int nBytes = 0;
		
    const char *contentLengthStr = apr_table_get(rqRec->headers_in,
"Content-Length");
    nBytes = atoi(contentLengthStr);
	
    fprintf(stderr,"\n URI:%s, content-length:%d", rqRec->uri,nBytes);
	
    char *  freep = (char *)malloc(nBytes + 1);
    char * qstr = freep;
    memset(qstr, 0, nBytes + 1);
	
    // Create a bucket brigade to fill data from the input filter
    bb = apr_brigade_create(rqRec->pool, rqRec->connection->bucket_alloc);

    read_mode = AP_MODE_SPECULATIVE;  //AP_MODE_READBYTES
    do
    {
    // Get the bucket brigade filled from the input filter
    retStatus = ap_get_brigade(rqRec->input_filters, bb, read_mode,
APR_BLOCK_READ, nBytes);
    if ( retStatus != APR_SUCCESS ){
       fprintf(stderr,"\n Failed ap_get_brigade");
       goto endhere; 
    }

    for (bucket = APR_BRIGADE_FIRST(bb);
	bucket != APR_BRIGADE_SENTINEL(bb);
	bucket = APR_BUCKET_NEXT(bucket)) 
     {
	data = NULL;
	len = 0;
	if (APR_BUCKET_IS_EOS(bucket)) {
    	    seen_eos = true;
       	    break;
        }

	if (APR_BUCKET_IS_FLUSH(bucket)) {
    		continue;
    	}

	// bucket_read function sets the data pointer to its internal buffer and
returns the len field
	retStatus = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
	if ( retStatus != APR_SUCCESS) {
	   fprintf(stderr,"\n Failed apr_bucket_read");
	   goto endhere; //return 0;
	}
		
        fprintf(stderr,"\n bucket->length :%d",bucket->length);
        fprintf(stderr,"\n nread:%d  len :%d op:%d, retStatus:%d", nread, (int
)len, (nread + (int )len >nBytes),(int)retStatus);
        char * tp = (char *)malloc((int )len + 1);
        memset(tp, 0, len + 1);
	memcpy(tp, data, len);
	fprintf(stderr,"\n DATA from the current bucket :%s",tp);
	free(tp);
		
    	if (nread + (int )len > nBytes) {
		fprintf(stderr,"\n Too much POST data: %s", rqRec->uri);						
		seen_eos = true;
		break;
	}

	memcpy(qstr, data, len);
	qstr += len;
	nread += len;

	if (nread == nBytes)
	{
	   seen_eos = true;
	   break;
	}
     }/* End of For loop*/
    apr_brigade_cleanup(bb);
    }
    while (!seen_eos);

endhere:
	fprintf(stderr,"\n FINAL POST DATA :%s",freep);
    free(freep);
    return nread;
}
 
 
If I post some data, output  looks like:

 URI:/test.cgi, content-length:5537
 bucket->length :764
 nread:0  len :764 op:0, retStatus:0
 DATA from the current bucket :post_data=start1111............................
 bucket->length :764
 nread:764  len :764 op:0, retStatus:0
 DATA from the current bucket :post_data=start1111............................
 bucket->length :764
 nread:1528  len :764 op:0, retStatus:0
 DATA from the current bucket :post_data=start1111............................
 bucket->length :764
 nread:2292  len :764 op:0, retStatus:0
 DATA from the current bucket :post_data=start1111............................
 bucket->length :764
 nread:3056  len :764 op:0, retStatus:0
 DATA from the current bucket :post_data=start1111............................
 bucket->length :764
 nread:3820  len :764 op:0, retStatus:0
 DATA from the current bucket :post_data=start1111............................
 bucket->length :764
 nread:4584  len :764 op:0, retStatus:0
 DATA from the current bucket :post_data=start1111............................
 bucket->length :764
 nread:5348  len :764 op:1, retStatus:0
 DATA from the current bucket :post_data=start1111............................
 Too much POST data: /test.cgi
 FINAL POST DATA
:post_data=start1111....111post_data=start11111....1111post_data=start111111.
...111post_data=start11111....1post_data=start111....111post_data=start11111.
...1111post_data=start111111......
 
 
 In the above code, If I change the read_mode to AP_MODE_READBYTES and post the
same request, output looks like:
 
 URI:/test.cgi, content-length:5537
 bucket->length :2024
 nread:0  len :2024 op:0, retStatus:0
 DATA from the current bucket :post_data=start11111............................
 bucket->length :1260
 nread:2024  len :1260 op:0, retStatus:0
 DATA from the current bucket :111111111111111.............................
 bucket->length :2253
 nread:3284  len :2253 op:0, retStatus:0
 DATA from the current bucket :111111111.........................1111111End
 FINAL POST DATA
:post_data=start11111111111111.........................1111111111111111End
 
 
Using same code and setting read_mode to AP_MODE_SPECULATIVE, on windows
platform issue is not seen.
Issue is seen on Linux & Linux64 of RHEL4 version. 
Is there anything wrong in my implementation or else anything???


Mime
View raw message