void t08_server_with_error_404(){ INIT_LOCAL(); onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_url *urls=onion_url_new(); onion_set_root_handler(server, onion_url_to_handler(urls)); onion_request *req=onion_request_new(lp); #define S "GET / HTTP/1.1" onion_request_write(req, S,sizeof(S)-1); // send it all, but the final 0. #undef S const char *buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_NOT_EQUAL_STR(buffer,""); onion_request_write(req, "\n",1); // finish this request. no \n\n before to check possible bugs. onion_request_write(req, "\n",1); // finish this request. no \n\n before to check possible bugs. The last \n was not processed, as was overflowing. buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_EQUAL_STR(buffer,""); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 404 NOT FOUND\r\n"); FAIL_IF_NOT_STRSTR(buffer, "libonion"); onion_request_free(req); onion_free(server); END_LOCAL(); }
void t04_server_overflow(){ INIT_LOCAL(); onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_set_root_handler(server, onion_handler_static("Succedded", 200)); onion_block *long_req=onion_block_new(); onion_block_add_str(long_req,"GET / HTTP/1.1\n"); int i; for(i=0;i<1000;i++){ onion_block_add_str(long_req,"Header-1: This is header1 Header-2: This is header 2 "); } onion_request *req=onion_request_new(lp); onion_request_write(req, onion_block_data(long_req),onion_block_size(long_req)-1); // send it all, but the final 0. const char *buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_NOT_EQUAL_STR(buffer,""); onion_request_write(req, "\n\n",2); // finish this request. no \n\n before to check possible bugs. buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_EQUAL_STR(buffer,""); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 200 OK\r\n"); FAIL_IF_NOT_STRSTR(buffer, "\r\nContent-Length: 9\r\n"); FAIL_IF_NOT_STRSTR(buffer, "libonion"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nSuccedded"); onion_block_free(long_req); onion_request_free(req); onion_free(server); END_LOCAL(); }
void t02_server_full(){ INIT_LOCAL(); onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_set_root_handler(server, onion_handler_static("Succedded", 200)); onion_request *req=onion_request_new(lp); #define S "GET / HTTP/1.1\r\nHeader-1: This is header1\r\nHeader-2: This is header 2\r\n" onion_request_write(req, S,sizeof(S)-1); // send it all, but the final 0. #undef S const char *buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_NOT_EQUAL_STR(buffer,""); onion_request_write(req, "\n",1); // finish this request. no \n\n before to check possible bugs. buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_EQUAL_STR(buffer,""); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 200 OK\r\n"); FAIL_IF_NOT_STRSTR(buffer, "\r\nContent-Length: 9\r\n"); FAIL_IF_NOT_STRSTR(buffer, "libonion"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nSuccedded"); onion_request_free(req); onion_free(server); END_LOCAL(); }
void t01_server_min(){ INIT_LOCAL(); onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_set_root_handler(server, onion_handler_static("Succedded", 200)); onion_request *req=onion_request_new(lp); onion_request_write(req, "GET ",4); onion_request_write(req, "/",1); onion_request_write(req, " HTTP/1.1\r\n",11); onion_request_write(req, "\r\n",2); const char *buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_EQUAL_STR(buffer,""); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 200 OK\r\n"); FAIL_IF_NOT_STRSTR(buffer, "\r\nContent-Length: 9\r\n"); FAIL_IF_NOT_STRSTR(buffer, "libonion"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nSuccedded"); onion_request_free(req); onion_free(server); END_LOCAL(); }
void t05_post_content_json(){ INIT_LOCAL(); onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); json_response post_json = { 0 }; onion_add_listen_point(server,NULL,NULL,lp); onion_set_root_handler(server, onion_handler_new((void*)&post_json_check,&post_json,NULL)); onion_request *req=onion_request_new(lp); #define POST_HEADER "POST / HTTP/1.1\nContent-Type: application/json\nContent-Length: %d\n\n" char tmp[1024]; int json_length=sizeof(JSON_EXAMPLE); ONION_DEBUG("Post size is about %d",json_length); snprintf(tmp, sizeof(tmp), POST_HEADER, json_length); // ONION_DEBUG("%s",tmp); onion_request_write(req,tmp,strlen(tmp)); onion_request_write(req,JSON_EXAMPLE,json_length); // ONION_DEBUG("%s",JSON_EXAMPLE); FAIL_IF_NOT_EQUAL_INT(post_json.processed, 2); onion_request_free(req); onion_free(server); END_LOCAL(); }
void t01_url() { INIT_LOCAL(); onion_url *url = onion_url_new(); onion_url_add_handler(url, "^handler1.$", onion_handler_new((onion_handler_handler) handler1, NULL, NULL)); onion_url_add(url, "handler2/", handler2); onion_url_add_with_data(url, "^handler(3|4)/", handler3, NULL, NULL); onion_set_root_handler(server, onion_url_to_handler(url)); onion_request *req = onion_request_new(onion_get_listen_point(server, 0)); #define R "GET /handler1/ HTTP/1.1\n\n" onion_request_write(req, R, sizeof(R)); onion_request_process(req); FAIL_IF_NOT_EQUAL_INT(handler_called, 1); FAIL_IF_NOT_EQUAL_STR(urltxt, ""); free(urltxt); urltxt = NULL; onion_request_clean(req); onion_request_write(req, "GET /handler2/ HTTP/1.1\n\n", sizeof(R)); onion_request_process(req); FAIL_IF_NOT_EQUAL_INT(handler_called, 2); ONION_DEBUG("%s", urltxt); FAIL_IF_NOT_EQUAL_STR(urltxt, ""); free(urltxt); urltxt = NULL; onion_request_clean(req); onion_request_write(req, "GET /handler3/hello HTTP/1.1\n\n", sizeof(R) + 5); onion_request_process(req); FAIL_IF_NOT_EQUAL_INT(handler_called, 3); FAIL_IF_NOT_EQUAL_STR(urltxt, "hello"); free(urltxt); urltxt = NULL; handler_called = 0; onion_request_clean(req); onion_request_write(req, "GET /handler2/hello HTTP/1.1\n\n", sizeof(R) + 5); onion_request_process(req); FAIL_IF_NOT_EQUAL_INT(handler_called, 0); FAIL_IF_EQUAL_STR(urltxt, ""); free(urltxt); urltxt = NULL; onion_request_free(req); onion_url_free(url); onion_set_root_handler(server, NULL); END_LOCAL(); }
// This fixes that whenever a session is created, but no new data is added, it does not set the proper cookie void t04_lot_of_sessionid(){ INIT_LOCAL(); onion *o=onion_new(O_ONE_LOOP); onion_server_set_write(o->server, empty_write); onion_url *url=onion_root_url(o); onion_url_add(url, "^.*", ask_session); char sessionid[256]; char tmp[1024]; char tmp2[4096]; onion_request *req; int i; set_data_on_session=1; req=onion_request_new(o->server, NULL, NULL); req->fullpath="/"; onion_request_process(req); FAIL_IF_NOT_EQUAL_INT(onion_dict_count(o->server->sessions->sessions), 1); FAIL_IF_EQUAL_STR(lastsessionid,""); strcpy(sessionid, lastsessionid); req->fullpath=NULL; onion_request_free(req); req=onion_request_new(o->server, NULL, NULL); req->fullpath="/"; snprintf(tmp,sizeof(tmp)," sessionid=xx%sxx;",lastsessionid); strcpy(tmp2,"Cookie:"); for(i=0;i<64;i++) strncat(tmp2, tmp, sizeof(tmp2)); snprintf(tmp,sizeof(tmp)," sessionid=%s\n",lastsessionid); strncat(tmp2, tmp, sizeof(tmp2)); ONION_DEBUG("Set cookies (%d bytes): %s",strlen(tmp2),tmp2); strcpy(tmp,"GET /\n"); onion_request_write(req,tmp,strlen(tmp)); // Here is the problem, at parsing too long headers onion_request_write(req,tmp2,strlen(tmp2)); // Here is the problem, at parsing too long headers onion_request_write(req,"\n",1); //onion_dict_add(req->headers, "Cookie", tmp2, 0); onion_request_process(req); FAIL_IF_NOT_EQUAL_INT(onion_dict_count(o->server->sessions->sessions), 1); FAIL_IF_EQUAL_STR(lastsessionid,""); FAIL_IF_NOT_EQUAL_STR(lastsessionid, sessionid); FAIL_IF_NOT(has_set_cookie); onion_request_free(req); onion_free(o); END_LOCAL(); }
void t10_repeated_header(){ INIT_LOCAL(); onion_request *req; int ok; onion_set_max_post_size(server, 1024); req=onion_request_new(custom_io); FAIL_IF_EQUAL(req,NULL); FAIL_IF_NOT_EQUAL(req->connection.fd, -1); { const char *query="GET / HTTP/1.0\n" "Content-Type: application/x-www-form-urlencoded\n" "Host: 127.0.0.1\n\r" "Content-Length: 24\n" "Accept-Language: en\n" "Content-Type: application/x-www-form-urlencoded-bis\n\n"; ok=onion_request_write(req,query,strlen(query)); } FAIL_IF_EQUAL(ok,OCS_INTERNAL_ERROR); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req,"Host"),"127.0.0.1"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req,"Content-Length"),"24"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req,"Content-Type"),"application/x-www-form-urlencoded"); onion_request_free(req); END_LOCAL(); }
/// A BUG were detected: transformed \n to \r\n on files. void t03_post_carriage_return_new_lines_file(){ INIT_LOCAL(); buffer *b=buffer_new(1024); expected_post post={};; post.filename="file.dat"; post.test_ok=0; // Not ok as not called processor yet post.tmpfilename=NULL; post.size=3; onion_server *server=onion_server_new(); onion_server_set_write(server, (void*)&buffer_append); onion_server_set_root_handler(server, onion_handler_new((void*)&post_check,&post,NULL)); onion_request *req=onion_request_new(server,b,"test"); #define POST_EMPTY "POST / HTTP/1.1\nContent-Type: multipart/form-data; boundary=end\nContent-Length:81\n\n--end\nContent-Disposition: text/plain; name=\"file\"; filename=\"file.dat\"\n\n\n\r\n\n--end--" //ONION_DEBUG("%s",POST_EMPTY); onion_request_write(req,POST_EMPTY,sizeof(POST_EMPTY)); FAIL_IF_NOT_EQUAL(post.test_ok,1); #undef POST_EMPTY onion_request_clean(req); post.test_ok=0; // Not ok as not called processor yet #define POST_EMPTYR "POST / HTTP/1.1\r\nContent-Type: multipart/form-data; boundary=end\r\nContent-Length:85\r\n\r\n--end\r\nContent-Disposition: text/plain; name=\"file\"; filename=\"file.dat\"\r\n\r\n\n\r\n\r\n--end--" onion_request_write(req,POST_EMPTYR,sizeof(POST_EMPTYR)); FAIL_IF_NOT_EQUAL(post.test_ok,1); #undef POST_EMPTYR onion_request_free(req); if (post.tmpfilename){ struct stat st; FAIL_IF_EQUAL(stat(post.tmpfilename,&st), 0); // Should not exist free(post.tmpfilename); } if (post.tmplink) free(post.tmplink); onion_server_free(server); buffer_free(b); END_LOCAL(); }
/// A BUG were detected: transformed \n to \r\n on files. void t02_post_new_lines_file(){ INIT_LOCAL(); expected_post post={};; post.filename="file.dat"; post.test_ok=0; // Not ok as not called processor yet post.tmpfilename=NULL; post.size=1; onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_set_root_handler(server, onion_handler_new((void*)&post_check,&post,NULL)); onion_request *req=onion_request_new(lp); #define POST_EMPTY "POST / HTTP/1.1\nContent-Type: multipart/form-data; boundary=end\nContent-Length:81\n\n--end\nContent-Disposition: text/plain; name=\"file\"; filename=\"file.dat\"\n\n\n\n--end--" onion_request_write(req,POST_EMPTY,sizeof(POST_EMPTY)); FAIL_IF_NOT_EQUAL(post.test_ok,1); #undef POST_EMPTY onion_request_clean(req); post.test_ok=0; // Not ok as not called processor yet #define POST_EMPTYR "POST / HTTP/1.1\r\nContent-Type: multipart/form-data; boundary=end\r\nContent-Length:85\r\n\r\n--end\r\nContent-Disposition: text/plain; name=\"file\"; filename=\"file.dat\"\r\n\r\n\n\r\n--end--" onion_request_write(req,POST_EMPTYR,sizeof(POST_EMPTYR)); FAIL_IF_NOT_EQUAL(post.test_ok,1); #undef POST_EMPTYR onion_request_free(req); if (post.tmpfilename){ struct stat st; FAIL_IF_EQUAL(stat(post.tmpfilename,&st), 0); // Should not exist free(post.tmpfilename); } if (post.tmplink) free(post.tmplink); onion_free(server); END_LOCAL(); }
void t07_multiline_headers(){ INIT_LOCAL(); onion_request *req; int ok; onion_set_max_post_size(server, 1024); req=onion_request_new(custom_io); FAIL_IF_EQUAL(req,NULL); FAIL_IF_NOT_EQUAL(req->connection.fd, -1); { const char *query="GET / HTTP/1.0\n" "Host: 127.0.0.1\n\rContent-Length: 24\n" "Other-Header: My header is very long and with several\n lines\n" "Extra-Other-Header: My header is very long and with several\n \n lines\n" "My-Other-Header: My header is very long and with several\n\tlines\n\n"; ok=onion_request_write(req,query,strlen(query)); } FAIL_IF_EQUAL(ok,OCS_INTERNAL_ERROR); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req,"other-header"),"My header is very long and with several lines"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req,"extra-other-header"),"My header is very long and with several lines"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req,"My-other-header"),"My header is very long and with several lines"); onion_request_clean(req); { const char *query="GET / HTTP/1.0\n" "Host: 127.0.0.1\n\rContent-Length: 24\n" "Other-Header: My header is very long and with several\n lines\n" "My-Other-Header: My header is very long and with several\nlines\n\n"; ok=onion_request_write(req,query,strlen(query)); } FAIL_IF_NOT_EQUAL(ok,OCS_INTERNAL_ERROR); // No \t at my-other-header onion_request_free(req); END_LOCAL(); }
void t00_server_empty(){ INIT_LOCAL(); onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_request *req=onion_request_new(lp); onion_request_write(req, "GET ",4); onion_request_write(req, "/",1); onion_request_write(req, " HTTP/1.1\r\n",11); onion_request_write(req, "\r\n",2); const char *buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_EQUAL_STR(buffer,""); FAIL_IF_NOT_STRSTR(buffer,"404"); onion_request_free(req); onion_free(server); END_LOCAL(); }
/** * @short HTTP client has data ready to be readen * @memberof onion_http_t */ int onion_http_read_ready(onion_request *con){ char buffer[1500]; ssize_t len=con->connection.listen_point->read(con, buffer, sizeof(buffer)); if (len<=0) return OCS_CLOSE_CONNECTION; onion_connection_status st=onion_request_write(con, buffer, len); if (st!=OCS_NEED_MORE_DATA){ if (st<0) return st; } return OCS_PROCESSED; }
void t05_server_with_pipes(){ INIT_LOCAL(); onion_server *server=onion_server_new(); onion_server_set_write(server, (onion_write)write_p); onion_server_set_root_handler(server, onion_handler_static("Works with pipes", 200)); int p[2]; int error=pipe(p); if (error){ FAIL("Could not create pipe."); END_LOCAL(); } onion_request *req=onion_request_new(server, &p[1], NULL); #define S "GET / HTTP/1.1\n\n" onion_request_write(req, S,sizeof(S)-1); // send it all, but the final 0. #undef S close(p[1]); //fcntl(p[0],F_SETFL, O_NONBLOCK); // read from the pipe char buffer[1024]; memset(buffer,0,sizeof(buffer)); // better clean it, because if this does not work, it might get an old value int r=read(p[0], buffer, sizeof(buffer)); if (r<0){ ONION_DEBUG("Read %d bytes",r); perror("Error"); } FAIL_IF_EQUAL_STR(buffer,""); FAIL_IF_NOT_STRSTR(buffer,"HTTP/1.1 200 OK\r\n"); FAIL_IF_NOT_STRSTR(buffer,"Content-Length: 16\r\n"); FAIL_IF_NOT_STRSTR(buffer,"\r\n\r\nWorks with pipes"); onion_request_free(req); onion_server_free(server); END_LOCAL(); }
void t09_very_long_header(){ INIT_LOCAL(); onion_request *req; int ok; onion_set_max_post_size(server, 1024); req=onion_request_new(custom_io); FAIL_IF_EQUAL(req,NULL); FAIL_IF_NOT_EQUAL(req->connection.fd, -1); { const char *query_t="GET / HTTP/1.0\n" "Content-Type: application/x-www-form-urlencoded\n" "Host: 127.0.0.1\n\r" "Content-Length: 24\n" "Accept-Language: en\n" "Content-Type: "; const int longsize=strlen(query_t)+16; char *query=malloc(longsize); // 1MB enought? strcpy(query, query_t); int i; for (i=strlen(query); i<longsize -2; i++) // fill with crap query[i]='a'+(i%30); query[longsize-3]='\n'; query[longsize-2]='\n'; query[longsize-1]=0; FAIL_IF_NOT_EQUAL_INT(strlen(query), longsize-1); ok=onion_request_write(req, query, longsize); free(query); } FAIL_IF_EQUAL_INT(ok,OCS_INTERNAL_ERROR); onion_request_free(req); END_LOCAL(); }
void t11_cookies(){ INIT_LOCAL(); onion_request *req; int ok; req=onion_request_new(custom_io); FAIL_IF_EQUAL(req,NULL); FAIL_IF_NOT_EQUAL(req->connection.fd, -1); { const char *query="GET / HTTP/1.0\n" "Content-Type: application/x-www-form-urlencoded\n" "Host: 127.0.0.1\n\r" "Cookie: key1=value1; key2=value2;\n" "Accept-Language: en\n"; // Missing \n caused memleak, to check with valgrind ok=onion_request_write(req,query,strlen(query)); } FAIL_IF_EQUAL(ok,OCS_INTERNAL_ERROR); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req,"Host"),"127.0.0.1"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req,"Cookie"), "key1=value1; key2=value2;"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_cookie(req,"key1"), "value1"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_cookie(req,"key2"), "value2"); FAIL_IF_EQUAL_STR(onion_request_get_cookie(req," key2"), "value2"); onion_dict *cookies=onion_request_get_cookies_dict(req); FAIL_IF_EQUAL(cookies, NULL); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(cookies,"key1"), "value1"); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(cookies,"key2"), "value2"); onion_request_free(req); END_LOCAL(); }
/// There is a bug when posting large files. Introduced when change write 1 by 1, to write by blocks on the FILE parser void t04_post_largefile(){ INIT_LOCAL(); int postfd=open(BIG_FILE, O_RDONLY); off_t filesize=lseek(postfd, 0, SEEK_END); lseek(postfd, 0, SEEK_SET); expected_post post={};; post.filename=BIG_FILE_BASE; post.test_ok=0; // Not ok as not called processor yet post.tmpfilename=NULL; post.size=filesize; onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_set_root_handler(server, onion_handler_new((void*)&post_check,&post,NULL)); onion_request *req=onion_request_new(lp); #define POST_HEADER "POST / HTTP/1.1\nContent-Type: multipart/form-data; boundary=end\nContent-Length: %d\n\n--end\nContent-Disposition: text/plain; name=\"file\"; filename=\"" BIG_FILE_BASE "\"\n\n" char tmp[1024]; ONION_DEBUG("Post size is about %d",filesize+73); snprintf(tmp, sizeof(tmp), POST_HEADER, (int)filesize+73); ONION_DEBUG("%s",tmp); onion_request_write(req,tmp,strlen(tmp)); int r=read(postfd, tmp, sizeof(tmp)); while ( r>0 ){ onion_request_write(req, tmp, r); r=read(postfd, tmp, sizeof(tmp)); } onion_request_write(req,"\n--end--",8); FAIL_IF_NOT_EQUAL_INT(post.test_ok,1); #undef POST_HEADER onion_request_clean(req); //post.test_ok=0; // Not ok as not called processor yet lseek(postfd, 0, SEEK_SET); int difffd=open(post.tmpfilename, O_RDONLY); FAIL_IF_NOT_EQUAL_INT(difffd,-1); // Orig file is removed at handler returns. But i have a copy difffd=open(post.tmplink, O_RDONLY); FAIL_IF_EQUAL_INT(difffd,-1); ONION_DEBUG("tmp filename %s",post.tmpfilename); int r1=1, r2=1; char c1=0, c2=0; int p=0; while ( r1 && r2 && c1==c2){ r1=read(difffd, &c1, 1); r2=read(postfd, &c2, 1); //ONION_DEBUG("%d %d",c1,c2); FAIL_IF_NOT_EQUAL_INT(c1,c2); p++; } if ( r1 || r2 ){ ONION_ERROR("At %d",p); FAIL_IF_NOT_EQUAL_INT(r1,0); FAIL_IF_NOT_EQUAL_INT(r2,0); FAIL_IF_NOT_EQUAL_INT(c1,c2); FAIL("Files are different"); } else ONION_DEBUG("Files are ok"); close(difffd); close(postfd); onion_request_free(req); if (post.tmpfilename){ struct stat st; FAIL_IF_EQUAL(stat(post.tmpfilename,&st), 0); // Should not exist } onion_free(server); if (post.tmpfilename) free(post.tmpfilename); if (post.tmplink) free(post.tmplink); END_LOCAL(); }
/** * @short Tells the server to write something on that request. * @memberof onion_server_t * * It takes care of moments when it has to process the request, and maybe there was an error, so * it calls the error handlers. */ onion_connection_status onion_server_write_to_request(onion_server *server, onion_request *request, const char *data, size_t len){ // This is one maybe unnecesary indirection, but helps when creating new "onion" like classes. onion_connection_status connection_status=onion_request_write(request, data, len); return connection_status; }
/** * @short Opens a script file, and executes it. */ void prerecorded(const char *oscript, int do_r){ INIT_LOCAL(); FILE *fd=fopen(oscript, "r"); if (!fd){ FAIL("Could not open script file"); END_LOCAL(); return; } const char *script=basename((char*)oscript); buffer *buffer=buffer_new(1024*1024); onion_request *req=onion_request_new(server, buffer, "test"); ssize_t r; const size_t LINE_SIZE=1024; char *line=malloc(LINE_SIZE); size_t len=LINE_SIZE; onion_connection_status ret; int ntest=0; int linen=0; while (!feof(fd)){ ntest++; ret=OCS_NEED_MORE_DATA; ONION_DEBUG("Test %d",ntest); // Read request while ( (r=getline(&line, &len, fd)) != -1 ){ linen++; if (strcmp(line,"-- --\n")==0){ break; } if (do_r){ line[r-1]='\r'; line[r]='\n'; r++; } if (ret==OCS_NEED_MORE_DATA) ret=onion_request_write(req, line, r); //line[r]='\0'; //ONION_DEBUG0("Write: %s\\n (%d). Ret %d",line,r,ret); len=LINE_SIZE; } if (r<0){ buffer_free(buffer); fclose(fd); onion_request_free(req); free(line); END_LOCAL(); return; } if (r==0){ FAIL_IF("Found end of file before end of request"); buffer_free(buffer); fclose(fd); onion_request_free(req); free(line); END_LOCAL(); return; } // Check response buffer->data[buffer->pos]='\0'; if (buffer->pos==0){ ONION_DEBUG("Empty response"); } else{ ONION_DEBUG0("Response: %s",buffer->data); } while ( (r=getline(&line, &len, fd)) != -1 ){ linen++; if (strcmp(line,"++ ++\n")==0){ break; } line[strlen(line)-1]='\0'; if (strcmp(line,"INTERNAL_ERROR")==0){ // Checks its an internal error ONION_DEBUG("%s:%d Check INTERNAL_ERROR",script,linen); ONION_DEBUG0("Returned %d",ret); FAIL_IF_NOT_EQUAL(ret, OCS_INTERNAL_ERROR); } else if (strcmp(line,"NOT_IMPLEMENTED")==0){ // Checks its an internal error ONION_DEBUG("Check NOT_IMPLEMENTED"); ONION_DEBUG0("Returned %d",ret); FAIL_IF_NOT_EQUAL(ret, OCS_NOT_IMPLEMENTED); } else{ regex_t re; regmatch_t match[1]; int l=strlen(line)-1; int _not=line[0]=='!'; if (_not){ ONION_DEBUG("Oposite regexp"); memmove(line, line+1, l); l--; } memmove(line+1,line,l+1); line[0]='^'; line[l+2]='$'; line[l+3]='\0'; ONION_DEBUG("%s:%d Check regexp: '%s'",script, linen, line); int r; r=regcomp(&re, line, REG_EXTENDED); if ( r !=0 ){ char error[1024]; regerror(r, &re, error, sizeof(error)); ONION_ERROR("%s:%d Error compiling regular expression %s: %s",script, linen, line, error); FAIL(line); } else{ int _match=regexec_multiline(&re, buffer->data, 1, match, 0); if ( (_not && _match==0) || (!_not && _match!=0) ){ ONION_ERROR("%s:%d cant find %s",script, linen, line); FAIL(line); } else{ ONION_DEBUG0("Found at %d-%d",match[0].rm_so, match[0].rm_eo); FAIL_IF(0); // To mark a passed test } } regfree(&re); } len=1024; } buffer_clean(buffer); onion_request_clean(req); } free(line); onion_request_free(req); buffer_free(buffer); fclose(fd); END_LOCAL(); }
int onion_request_write0(onion_request * req, const char *data) { return onion_request_write(req, data, strlen(data)); }
static int onion_request_write0(onion_request *req, const char *str){ //ONION_DEBUG("Write %d bytes", strlen(str)); return onion_request_write(req,str,strlen(str)); }