Hello,

My name is Arnaud and I'm new to this forum. I'm a web developer / java and I work in France Nantes.

I am currently developing an Apache module to extract files from http requests multipart / form-data.

I made ??good progress but I am currently stuck on a problem that I think is related to incomprehension on my part of the Apache Portable Runtime API.

I am a beginner in c language, which does not help

This is why I am asking for your help.

In order to parse my http request I use the API apr_req.

http://httpd.apache.org/apreq/docs/libapreq2/apreq__parser_8h.html#3c00aa3a31daba2c06110d5fc8edf1fe


The problem is in this part of code :
Code:
static apr_status_t upload_filter(ap_filter_t *f, apr_bucket_brigade *bbout, ap_input_mode_t mode, apr_read_type_e block, apr_off_t nbytes) {
upload_ctx* ctx = (upload_ctx*) f->ctx; 
if ((f->r->method_number != M_GET) &&
   (f->r->method_number != M_POST)) { 	
    return HTTP_METHOD_NOT_ALLOWED; 
}  	
if(f->r->method_number == M_POST)  	{   		      apreq_parser_function_t f_parser_function; 		f_parser_function = apreq_parser(MFD_ENCTYPE); 		apr_table_t* formd = apr_table_make(f->r->pool, APREQ_DEFAULT_NELTS); 
apr_table_t* filed = apr_table_make(f->r->pool, APREQ_DEFAULT_NELTS); 
const char *str;
apr_size_t j,len = 0;
apr_bucket  *e,*b; 
apr_status_t rv;  		/** Allocation of a structure used to iterate over  uploaded files and make writing treatments */
swo_params_t* uploaded_files = apr_palloc(f->r->pool, sizeof(swo_params_t)) ;  
apr_bucket_brigade* bbin = apr_brigade_create(f->r->pool,f->r->connection->bucket_alloc);
if (strcmp(f->r->method,"POST") == 0){ 			apreq_parser_t * psr = apreq_parser_make(  				f->r->pool, 				f->r->connection->bucket_alloc, 				apr_table_get(f->r->headers_in,"Content-Type"),  				apreq_parser(apr_table_get(f->r->headers_in,"Content-Type")), 				0, /* FORCE TO SPOOL FILES */ 	
NUXEO_CACHE_DIR_PATH, 				NULL, 				NULL);   
int s = APR_SUCCESS; 
while(s = ap_get_brigade(f->next, bbin, AP_MODE_READBYTES, APR_BLOCK_READ, HUGE_STRING_LEN)== APR_SUCCESS)  
{ 			

for(e = APR_BRIGADE_FIRST(bbin); 
e != APR_BRIGADE_SENTINEL(bbin); 					e =  APR_BUCKET_NEXT(e)) 				{                                                                              		if (APR_BUCKET_IS_FLUSH(e))  					{ 						continue; 
}   
if (APR_BUCKET_IS_EOS(e))  					{ 						APR_BRIGADE_INSERT_TAIL(bbout, apr_bucket_eos_create(bbout->bucket_alloc));                                                                             					}  					
if (!APR_BUCKET_IS_EOS(e))  					{
if ((rv = apr_bucket_read(e, &str, &len,APR_NONBLOCK_READ)) == APR_SUCCESS)  						{ 							ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, "BUCKET DATA= %s", str);   						}    						apr_bucket_copy(e,&b);  						APR_BRIGADE_INSERT_TAIL(bbout, b);  
}  				}    			 				apreq_parser_run(psr,formd,bbin); 	
i++; 	
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bbin)))  			{ 
ap_remove_input_filter(f);break;}
}
//apr_brigade_cleanup(bbin) ;      			//apr_brigade_destroy(bbin) ; 
filed =apreq_uploads(formd,f->r->pool);                           			uploaded_files->upload_files_names=filed; 			uploaded_files->formd=formd; 			uploaded_files->rec=f->r;                                          			apr_table_do(iterate_uploaded_files, uploaded_files, filed, NULL); 			 			ap_remove_input_filter(f) ; 			return ap_pass_brigade(f->next, bbout);	 		
}   }
return APR_SUCCESS ; 
}
This code works with very small request. When I send a request larger, server memory consumption increases to swap on disk and fail. Consumption is related to the use of the instruction apr_bucket_copy(e,&b);

I use this instruction in order to fulfill the 'bbou' and pass to the next filter. This is the only solution that I found. However, I think this "Bucket copy" duplicates the data in memory and is the origin of the server crash. Do you have any knowledge on the development of apache module ? Do you understand my problem?

I hope my message is understandable because as you probably have seen my English is very approximate.

Good Day Arnaud.