/** * @short Cleans a request object to reuse it. * @memberof onion_request_t */ void onion_request_clean(onion_request* req){ ONION_DEBUG0("Clean request %p", req); onion_dict_free(req->headers); req->headers=onion_dict_new(); if (req->parser_data){ onion_request_parser_data_free(req->parser_data); req->parser_data=NULL; } req->parser=NULL; req->flags&=0x0F00; // I keep server flags. if (req->fullpath){ free(req->fullpath); req->path=req->fullpath=NULL; } if (req->GET){ onion_dict_free(req->GET); req->GET=NULL; } if (req->POST){ onion_dict_free(req->POST); req->POST=NULL; } if (req->FILES){ onion_dict_preorder(req->FILES, unlink_files, NULL); onion_dict_free(req->FILES); req->FILES=NULL; } if (req->data){ onion_block_free(req->data); req->data=NULL; } }
void t16_soft_dup_dict_in_dict(){ INIT_LOCAL(); onion_dict *orig=onion_dict_new(); char tmp[9]; int i; for (i=0;i<256;i++){ sprintf(tmp,"%08X",rand()); onion_dict_add(orig, tmp, tmp, OD_DUP_ALL); } onion_dict_add(orig, "0", "no frees", 0); onion_dict *subdict=onion_dict_new(); onion_dict_add(subdict,"subdict","test",0); onion_dict_add(orig, "subdict", subdict, OD_DICT|OD_FREE_VALUE); onion_dict *dest=onion_dict_dup(orig); FAIL_IF_NOT(orig==dest); /// Check they have exactly the same keys. onion_dict_preorder(orig, cmpdict, dest); onion_dict_preorder(dest, cmpdict, orig); onion_dict_free(orig); onion_dict_free(dest); END_LOCAL(); }
/** * @short Deletes a request and all its data * @memberof onion_request_t */ void onion_request_free(onion_request *req){ ONION_DEBUG0("Free request %p", req); onion_dict_free(req->headers); if (req->parser_data){ onion_request_parser_data_free(req->parser_data); req->parser_data=NULL; } if (req->fullpath) free(req->fullpath); if (req->GET) onion_dict_free(req->GET); if (req->POST) onion_dict_free(req->POST); if (req->FILES){ onion_dict_preorder(req->FILES, unlink_files, NULL); onion_dict_free(req->FILES); } if (req->parser_data) free(req->parser_data); if (req->client_info) free(req->client_info); if (req->session_id) free(req->session_id); if (req->session) onion_dict_free(req->session); // Not really remove, just dereference if (req->data) onion_block_free(req->data); free(req); }
void t12_dict_in_dict(){ INIT_LOCAL(); onion_dict *A=onion_dict_new(); onion_dict *B=onion_dict_new(); onion_dict *C=onion_dict_new(); onion_dict *D=onion_dict_new(); int i; for (i=0;i<16;i++){ char tmp[9]; sprintf(tmp,"%08X",rand()); onion_dict_add(A, tmp, tmp, OD_DUP_ALL); sprintf(tmp,"%08X",rand()); onion_dict_add(B, tmp, tmp, OD_DUP_ALL); sprintf(tmp,"%08X",rand()); onion_dict_add(C, tmp, tmp, OD_DUP_ALL); sprintf(tmp,"%08X",rand()); onion_dict_add(D, tmp, tmp, OD_DUP_ALL); } onion_dict_add(A, "B", B, OD_DICT|OD_FREE_VALUE); onion_dict_add(A, "C", C, OD_DICT|OD_FREE_VALUE); onion_dict_add(A, "D", D, OD_DICT|OD_FREE_VALUE); FAIL_IF_NOT_EQUAL((onion_dict*)onion_dict_get(A, "B"), NULL); FAIL_IF_NOT_EQUAL((onion_dict*)onion_dict_get(A, "C"), NULL); FAIL_IF_NOT_EQUAL((onion_dict*)onion_dict_get(A, "D"), NULL); FAIL_IF_NOT_EQUAL((onion_dict*)onion_dict_get_dict(A, "B"), B); FAIL_IF_NOT_EQUAL((onion_dict*)onion_dict_get_dict(A, "C"), C); FAIL_IF_NOT_EQUAL((onion_dict*)onion_dict_get_dict(A, "D"), D); { onion_block *tmpA=onion_dict_to_json(A); onion_block *tmpB=onion_dict_to_json(B); onion_block *tmpC=onion_dict_to_json(C); onion_block *tmpD=onion_dict_to_json(D); /* ONION_DEBUG("Json is: %s",tmpA); ONION_DEBUG("Json is: %s",tmpB); ONION_DEBUG("Json is: %s",tmpC); ONION_DEBUG("Json is: %s",tmpD); */ FAIL_IF_EQUAL( strstr(onion_block_data(tmpA), onion_block_data(tmpB)), NULL); FAIL_IF_EQUAL( strstr(onion_block_data(tmpA), onion_block_data(tmpC)), NULL); FAIL_IF_EQUAL( strstr(onion_block_data(tmpA), onion_block_data(tmpD)), NULL); onion_block_free(tmpA); onion_block_free(tmpB); onion_block_free(tmpC); onion_block_free(tmpD); } B=onion_dict_hard_dup(A); onion_dict_free(A); onion_dict_free(B); END_LOCAL(); }
/// Frees memory used by the handler void oterm_free(oterm_data *data){ // Free all sessions. onion_dict_preorder(data->sessions, oterm_session_free_dict_helper, NULL); onion_dict_free(data->sessions); onion_dict_free(data->processes); free(data->exec_command); free(data); }
void t01_create_add_free(){ INIT_LOCAL(); onion_dict *dict; const char *value; dict=onion_dict_new(); FAIL_IF_EQUAL(dict,NULL); // Get before anything in value=onion_dict_get(dict, "Request"); FAIL_IF_NOT_EQUAL(value,NULL); // basic add onion_dict_add(dict, "Request", "GET /", OD_DUP_ALL); value=onion_dict_get(dict, "Request"); FAIL_IF_NOT_EQUAL_STR(value,"GET /"); // basic remove onion_dict_remove(dict, "Request"); value=onion_dict_get(dict, "Request"); FAIL_IF_NOT_EQUAL(value,NULL); onion_dict_free(dict); END_LOCAL(); }
/* Return raw file if found. Security risk?! Check of filename/path required?! */ int search_file(onion_dict *context, onion_request *req, onion_response *res){ //const char* path = onion_request_get_path(req);//empty?! const char* path = onion_request_get_fullpath(req); printf("Request of %s %i.\n",path, strlen(path)); char filename[strlen(path)+8]; //sprintf(filename,"./%s",path); sprintf(filename,"./html/%s",path); //read file if( FILE *f=fopen(filename,"rb") ){ fseek(f,0,SEEK_END); long len=ftell(f); fseek(f,0,SEEK_SET); char *data=(char*)malloc(len+1); fread(data,1,len,f); fclose(f); if (context) onion_dict_add(context, "LANG", onion_request_get_language_code(req), OD_FREE_VALUE); onion_response_set_length(res, len); onion_response_write(res, data, len); if (context) onion_dict_free(context); free(data); }else{ onion_response_set_length(res, 24); onion_response_write(res, "<h1>File not found</h1>", 24); } return OCS_PROCESSED; }
void *t08_thread_write(onion_dict *d){ int n=0; while (n!=N_READERS){ int i; n=0; //ONION_DEBUG("Lock read"); onion_dict_lock_read(d); //ONION_DEBUG("Got read lock"); for (i=0;i<N_READERS;i++){ char tmp[16]; snprintf(tmp,16,"%d",i+1); const char *r=onion_dict_get(d,tmp); if (r) n++; } //ONION_DEBUG("Unlock"); onion_dict_unlock(d); //ONION_DEBUG("Lock write"); onion_dict_lock_write(d); //ONION_DEBUG("Got write lock"); onion_dict_add(d, "test", "test", OD_DUP_ALL|OD_REPLACE); //ONION_DEBUG("Unlock"); onion_dict_unlock(d); ONION_DEBUG("Found %d answers, should be %d.", n, N_READERS); usleep(200); } onion_dict_free(d); return (char*)1; }
char *t08_thread_read(onion_dict *d){ char done=0; char *ret=NULL; while (!done){ //ONION_DEBUG("Lock read"); onion_dict_lock_write(d); //ONION_DEBUG("Got read lock"); const char *test=onion_dict_get(d,"test"); if (test){ //ONION_DEBUG("Unlock"); //onion_dict_lock_write(d); //ONION_DEBUG("Got write lock"); char tmp[16]; snprintf(tmp,16,"%d",onion_dict_count(d)); onion_dict_remove(d,"test"); onion_dict_add(d,tmp,"test",OD_DUP_ALL); ONION_DEBUG("Write answer %d", onion_dict_count(d)); done=1; //ONION_DEBUG("Unlock"); onion_dict_unlock(d); ret=(char*)1; break; } //ONION_DEBUG("Unlock"); onion_dict_unlock(d); usleep(200); } //ONION_DEBUG("dict free"); onion_dict_free(d); return ret; }
/** * @short Assigns the reference to the ditionary, from a C onion_dict. */ Dict &operator=(const onion_dict *o){ // ONION_DEBUG0("%p = %p (~%p)", this, o, ptr); onion_dict *ptr2=ptr; ptr=onion_dict_dup((onion_dict*)(o)); onion_dict_free(ptr2); return *this; }
void t17_merge(){ INIT_LOCAL(); onion_dict *a=onion_dict_from_json("{\"hello\":\"world\"}"); onion_dict *b=onion_dict_from_json("{\"bye\":\"_world_\", \"sub\": { \"hello\": \"world!\" } }"); onion_dict_merge(a,b); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(a,"bye"), "_world_"); FAIL_IF_NOT_EQUAL_STR(onion_dict_rget(a,"sub","hello",NULL), "world!"); onion_dict_free(b); FAIL_IF_NOT_EQUAL_STR(onion_dict_rget(a,"sub","hello",NULL), "world!"); onion_dict_free(a); END_LOCAL(); }
/** * @short Assings the reference to the dictionary. */ Dict &operator=(const Dict &o){ // ONION_DEBUG0("= %p:%p (~%p:%p)", &o, o.ptr, this, ptr); onion_dict *ptr2=ptr; ptr=onion_dict_dup((onion_dict*)(o.ptr)); onion_dict_free(ptr2); // ONION_DEBUG0("Done"); return *this; }
onion_connection_status index_html_template(onion_dict *context){ char *lang = (char*)malloc (3*sizeof(char)); strcpy(lang,"en\0"); ONION_DEBUG("Add to dict"); if (context) onion_dict_add(context, "LANG", lang, OD_FREE_VALUE); ONION_DEBUG("Free dict"); if (context) onion_dict_free(context); // if you remove this line, it works correctly return OCS_PROCESSED; }
onion_connection_status base_html_template(onion_dict *context, onion_request *req, onion_response *res){ if (context) onion_dict_add(context, "LANG", onion_request_get_language_code(req), OD_FREE_VALUE); base_html(context, res); if (context) onion_dict_free(context); return OCS_PROCESSED; }
/** * @short Creates a new session and returns the sessionId. * @memberof onion_sessions_t * @ingroup sessions * * @returns the name. Must be freed by user. */ char *onion_sessions_create(onion_sessions *sessions){ if (!sessions) return NULL; char *sessionId=onion_sessions_generate_id(); onion_dict *data=onion_dict_new(); sessions->save(sessions, sessionId, data); onion_dict_free(data); ONION_DEBUG("Created the session '%s'",sessionId); return sessionId; }
void t03_create_and_free_a_lot_random(unsigned int n){ INIT_LOCAL(); onion_dict *dict; const char *value; unsigned int i; dict=onion_dict_new(); FAIL_IF_EQUAL(dict,NULL); // Linear add for (i=0;i<n;i++){ char key[16], val[16]; sprintf(key,"key %d",R1(i)); sprintf(val,"val %d",R2(i)); onion_dict_add(dict, key, val, OD_DUP_ALL); } // Linear get for (i=0;i<n;i++){ char key[16], val[16]; sprintf(key,"key %d",R1(i)); sprintf(val,"val %d",R2(i)); value=onion_dict_get(dict, key); FAIL_IF_NOT_EQUAL_STR(val,value); } // remove all for (i=n;i>0;i--){ char key[16]; int removed; sprintf(key,"key %d",R1(i-1)); //fprintf(stderr,"%s %d\n",key,i-1); removed=onion_dict_remove(dict, key); FAIL_IF_NOT_EQUAL(removed,1); } // check removed all for (i=0;i<n;i++){ char key[16], val[16]; sprintf(key,"key %d",R1(i)); sprintf(val,"val %d",R1(i)); value=onion_dict_get(dict, key); //fprintf(stderr,"%s %s\n",key,value); FAIL_IF_NOT_EQUAL(NULL,value); FAIL_IF_NOT_EQUAL_STR(NULL,value); } onion_dict_free(dict); END_LOCAL(); }
/** * @short Shortcut to answer some json data * * It converts to json the passed dict and returns it. The dict is freed before returning. */ onion_connection_status onion_shortcut_response_json(onion_dict *d, onion_request *req, onion_response *res){ onion_response_set_header(res, "Content-Type", "application/json"); onion_block *bl=onion_dict_to_json(d); onion_dict_free(d); char tmp[16]; snprintf(tmp,sizeof(tmp),"%ld",(long)onion_block_size(bl)); int ret=onion_shortcut_response_extra_headers(onion_block_data(bl), HTTP_OK, req, res, "Content-Length", tmp, NULL); onion_block_free(bl); return ret; }
void base_html(onion_dict *context, onion_response *res){ #line 1 #line 1 int has_context=(context!=NULL); #line 1 if (!has_context) #line 1 context=onion_dict_new(); #line 1 #line 1 base_html_blocks_init(context); onion_response_write(res, "<!DOCTYPE html>\n" "<html>\n" " <head>\n" " <title>", 43); #line 4 { #line 4 const char *tmp; #line 4 tmp=onion_dict_get(context, "title"); #line 4 if (tmp) #line 4 onion_response_write_html_safe(res, tmp); #line 4 } onion_response_write(res, "</title>\n" " </head>\n" " <body>\n" "", 28); #line 7 { #line 7 void (*f)(onion_dict *context, onion_response *res); #line 7 f=(void*)onion_dict_get(context, "__block_content__"); #line 7 if (f) #line 7 f(context, res); #line 7 } onion_response_write(res, " \n" " </body>\n" "</html>\n" "", 21); #line 10 if (!has_context) #line 10 onion_dict_free(context); #line 1 }
/** * @short Frees the session dictionary. * @memberof onion_request_t * * If data is under onion_dict scope (just dicts into dicts and strings), all data is freed. * If the user has set some custom data, THAT MEMORY IS LEAKED. */ void onion_request_session_free(onion_request *req){ if (!req->session_id) onion_request_guess_session_id(req); if (req->session_id){ onion_sessions_remove(req->server->sessions, req->session_id); onion_dict_free(req->session); req->session=NULL; free(req->session_id); req->session_id=NULL; } }
void t18_json_escape_codes(){ INIT_LOCAL(); onion_dict *d=onion_dict_from_json("{ \"hello\": \"Hello\\nworld\", \"second\":\"second\" }"); FAIL_IF_NOT_STRSTR(onion_dict_get(d, "hello"), "Hello\nworld"); FAIL_IF_NOT_STRSTR(onion_dict_get(d, "second"), "second"); onion_dict_free(d); d=onion_dict_from_json("{ \"hello\": \"\\uD83D\\uDE02\" }"); FAIL_IF_NOT_STRSTR(onion_dict_get(d, "hello"), "😂"); onion_dict_free(d); d=onion_dict_from_json("{ \"hello\": \"\\uD83D\\uDE03\" }"); // Another code point FAIL_IF_STRSTR(onion_dict_get(d, "hello"), "😂"); onion_dict_free(d); d=onion_dict_from_json("{ \"hello\": \"\\u007b\" }"); // simple unicode FAIL_IF_NOT_STRSTR(onion_dict_get(d, "hello"), "{"); onion_dict_free(d); d=onion_dict_from_json("{ \"hello\": \"\\\"Quote\" }"); // Escape quote FAIL_IF_NOT_STRSTR(onion_dict_get(d, "hello"), "\"Quote"); onion_dict_free(d); d=onion_dict_from_json("{ \"hello\": \"\"Quote\" }"); // Must fail FAIL_IF_NOT_EQUAL(d, NULL); d=onion_dict_new(); onion_dict_add(d, "hello", "Hello\nWorld\\", 0); onion_dict_add(d, "second", "123", 0); onion_block *b=onion_dict_to_json(d); FAIL_IF_NOT_EQUAL_STR(onion_block_data(b),"{\"hello\":\"Hello\\nWorld\\\\\", \"second\":\"123\"}"); onion_block_free(b); onion_dict_free(d); d=onion_dict_new(); onion_dict_add(d, "hello", "😂\t\n😂", 0); b=onion_dict_to_json(d); FAIL_IF_NOT_EQUAL_STR(onion_block_data(b),"{\"hello\":\"😂\\t\\n😂\"}"); onion_block_free(b); onion_dict_free(d); d=onion_dict_new(); onion_dict_add(d, "hello", "\02\03\x7f", 0); b=onion_dict_to_json(d); FAIL_IF_NOT_EQUAL_STR(onion_block_data(b),"{\"hello\":\"\\u0002\\u0003\\u007F\"}"); onion_block_free(b); onion_dict_free(d); END_LOCAL(); }
/// Frees the memory, if necesary of key and value static void onion_dict_node_data_free(onion_dict_node_data *data){ if (data->flags&OD_FREE_KEY){ onion_low_free((char*)data->key); } if (data->flags&OD_FREE_VALUE){ if (data->flags&OD_DICT){ onion_dict_free((onion_dict*)data->value); } else onion_low_free((char*)data->value); } }
/** * @short Frees the session dictionary. * @memberof onion_request_t * * It removes the session from the sessions dictionary, so this session does not exist anymore. * * If data is under onion_dict scope (just dicts into dicts and strings), all data is freed. * If the user has set some custom data, THAT MEMORY IS LEAKED. */ void onion_request_session_free(onion_request *req) { if (!req->session_id) onion_request_guess_session_id(req); if (req->session_id) { ONION_DEBUG("Removing from session storage session id: %s",req->session_id); onion_sessions_remove(req->connection.listen_point->server->sessions, req->session_id); onion_dict_free(req->session); req->session=NULL; onion_low_free(req->session_id); req->session_id=NULL; } }
/** * @short Creates a dict from a json * * Onion dicts do not support full json semantics, soit will do the translations as possible; * sometimes information may be lost. * * Anyway dicts created by onion are ensured to be readable by onion. * * If the data is invalid NULL is returned. */ onion_dict *onion_dict_from_json(const char *data){ if (!data) return NULL; const char *_data[1]={ data }; onion_dict *ret=onion_dict_from_json_(_data); while (is_json_space(*_data[0])) ++_data[0]; if (*_data[0]){ ONION_DEBUG("Invalid JSON, not ends at end"); onion_dict_free(ret); return NULL; } return ret; }
/** * @short Cleans a request object to reuse it. * @memberof onion_request_t */ void onion_request_clean(onion_request* req) { ONION_DEBUG0("Clean request %p", req); onion_dict_free(req->headers); req->headers=onion_dict_new(); onion_dict_set_flags(req->headers, OD_ICASE); req->flags&=OR_NO_KEEP_ALIVE; // I keep keep alive. if (req->parser_data) { onion_request_parser_data_free(req->parser_data); req->parser_data=NULL; } if (req->fullpath) { onion_low_free(req->fullpath); req->path=req->fullpath=NULL; } if (req->GET) { onion_dict_free(req->GET); req->GET=NULL; } if (req->POST) { onion_dict_free(req->POST); req->POST=NULL; } if (req->FILES) { onion_dict_preorder(req->FILES, unlink_files, NULL); onion_dict_free(req->FILES); req->FILES=NULL; } if (req->session_id) { if (onion_dict_count(req->session)==0) { onion_request_session_free(req); } else { onion_sessions_save(req->connection.listen_point->server->sessions, req->session_id, req->session); onion_dict_free(req->session); // Not really remove, just dereference req->session=NULL; onion_low_free(req->session_id); req->session_id=NULL; } } if (req->data) { onion_block_free(req->data); req->data=NULL; } if (req->connection.cli_info) { onion_low_free(req->connection.cli_info); req->connection.cli_info=NULL; } if (req->cookies) { onion_dict_free(req->cookies); req->cookies=NULL; } if (req->free_list) { onion_ptr_list_foreach(req->free_list, onion_low_free); onion_ptr_list_free(req->free_list); req->free_list=NULL; } }
void t14_dict_case_insensitive(){ INIT_LOCAL(); onion_dict *d=onion_dict_new(); onion_dict_add(d,"Test","OK", 0); FAIL_IF_NOT_EQUAL(onion_dict_get(d,"test"),NULL); onion_dict_set_flags(d,OD_ICASE); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(d,"test"),"OK"); onion_dict_free(d); END_LOCAL(); }
void t11_hard_dup(){ INIT_LOCAL(); onion_dict *orig=onion_dict_new(); char tmp[9]; int i; for (i=0;i<256;i++){ sprintf(tmp,"%08X",rand()); onion_dict_add(orig, tmp, tmp, OD_DUP_ALL); } onion_dict_add(orig, "0", "no frees", 0); onion_dict *dest=onion_dict_hard_dup(orig); /// Check they have exactly the same keys. onion_dict_preorder(orig, cmpdict, dest); onion_dict_preorder(dest, cmpdict, orig); onion_dict_free(orig); onion_dict_free(dest); END_LOCAL(); }
void t06_null_add(){ INIT_LOCAL(); onion_dict *dict; dict=onion_dict_new(); onion_dict_add(dict,"b",NULL,0); onion_dict_add(dict,"a",NULL,0); onion_dict_add(dict,"c","1",0); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(dict,"c"),"1"); FAIL_IF_NOT_EQUAL(onion_dict_get(dict,"a"),NULL); onion_dict_free(dict); END_LOCAL(); }
void t13_dict_rget(){ INIT_LOCAL(); onion_dict *A=onion_dict_new(); onion_dict *B=onion_dict_new(); onion_dict *C=onion_dict_new(); onion_dict *D=onion_dict_new(); int i; for (i=0;i<16;i++){ char tmp[9]; sprintf(tmp,"%08X",rand()); onion_dict_add(A, tmp, tmp, OD_DUP_ALL); sprintf(tmp,"%08X",rand()); onion_dict_add(B, tmp, tmp, OD_DUP_ALL); sprintf(tmp,"%08X",rand()); onion_dict_add(C, tmp, tmp, OD_DUP_ALL); sprintf(tmp,"%08X",rand()); onion_dict_add(D, tmp, tmp, OD_DUP_ALL); } onion_dict_add(A, "B", B, OD_DICT|OD_FREE_VALUE); onion_dict_add(A, "C", C, OD_DICT|OD_FREE_VALUE); onion_dict_add(A, "D", D, OD_DICT|OD_FREE_VALUE); onion_dict_add(B, "C", C, OD_DICT); onion_dict_add(C, "a", "hello", 0); FAIL_IF_NOT_EQUAL(onion_dict_rget(A, "B", NULL), NULL); FAIL_IF_NOT_EQUAL(onion_dict_rget(A, "C", NULL), NULL); FAIL_IF_NOT_EQUAL(onion_dict_rget(A, "B", "C", NULL), NULL); FAIL_IF_NOT_EQUAL(onion_dict_rget_dict(A, "B", NULL), B); FAIL_IF_NOT_EQUAL(onion_dict_rget_dict(A, "C", NULL), C); FAIL_IF_NOT_EQUAL(onion_dict_rget_dict(A, "B", "C", NULL), C); FAIL_IF_NOT_EQUAL_STR(onion_dict_rget(A, "B", "C", "a", NULL), "hello"); FAIL_IF_NOT_EQUAL(onion_dict_rget_dict(A, "B", "C", "a", NULL), NULL); // This should remove all the others, as they hang from it. onion_dict_free(A); END_LOCAL(); }
void t09_thread_war_thread(onion_dict *d){ int i; char tmp[16]; for (i=0;i<WARLOOPS;i++){ snprintf(tmp,16,"%04X",i); if (rand()%1){ onion_dict_lock_read(d); onion_dict_get(d,tmp); onion_dict_unlock(d); } else{ onion_dict_lock_write(d); onion_dict_add(d,tmp,tmp,OD_DUP_ALL|OD_REPLACE); onion_dict_unlock(d); } } onion_dict_free(d); }
/** * @short Frees the memory consumed by this object * @memberof onion_response_t * @ingroup response * * This function returns the close status: OR_KEEP_ALIVE or OR_CLOSE_CONNECTION as needed. * * @returns Whether the connection should be closed or not, or an error status to be handled by server. * @see onion_connection_status */ onion_connection_status onion_response_free(onion_response * res) { // write pending data. if (!(res->flags & OR_HEADER_SENT) && res->buffer_pos < sizeof(res->buffer)) onion_response_set_length(res, res->buffer_pos); if (!(res->flags & OR_HEADER_SENT)) onion_response_write_headers(res); onion_response_flush(res); onion_request *req = res->request; if (res->flags & OR_CHUNKED) { // Set the chunked data end. req->connection.listen_point->write(req, "0\r\n\r\n", 5); } int r = OCS_CLOSE_CONNECTION; // it is a rare ocasion that there is no request, but although unlikely, it may happen if (req) { // keep alive only on HTTP/1.1. ONION_DEBUG0 ("keep alive [req wants] %d && ([skip] %d || [lenght ok] %d==%d || [chunked] %d)", onion_request_keep_alive(req), res->flags & OR_SKIP_CONTENT, res->length, res->sent_bytes, res->flags & OR_CHUNKED); if (onion_request_keep_alive(req) && (res->flags & OR_SKIP_CONTENT || res->length == res->sent_bytes || res->flags & OR_CHUNKED) ) r = OCS_KEEP_ALIVE; if ((onion_log_flags & OF_NOINFO) != OF_NOINFO) // FIXME! This is no proper logging at all. Maybe use a handler. ONION_INFO("[%s] \"%s %s\" %d %d (%s)", onion_request_get_client_description(res->request), onion_request_methods[res->request->flags & OR_METHODS], res->request->fullpath, res->code, res->sent_bytes, (r == OCS_KEEP_ALIVE) ? "Keep-Alive" : "Close connection"); } onion_dict_free(res->headers); onion_low_free(res); return r; }