onion_connection_status random_timeout(void *_, onion_request * req, onion_response * res) { int ms = 2000 * (((float)RAND_MAX) / rand()); ONION_INFO("Wait %d ms", ms); usleep(ms * 1000); ONION_INFO("Done"); onion_response_write(res, "OK", 2); return OCS_PROCESSED; }
void *listen_thread_f(void *_){ ok_listening=1; ONION_INFO("Start listening"); onion_listen(o); ONION_INFO("End listening"); ok_listening=0; return NULL; }
bool print_reqn(int *n, reqres_t * reqres) { ONION_INFO("Writing %d to %p", *n, reqres->res); onion_response_printf(reqres->res, "%d\n", *n); int err = onion_response_flush(reqres->res); if (err < 0) { // Manually close connection free_reqres(reqres); ONION_INFO("Closed connection."); return false; } return true; }
int main() { request_list_t request_list; request_list.reqres = onion_ptr_list_new(); request_list.running = true; pthread_mutex_init(&request_list.lock, NULL); pthread_t long_process_thread; o = onion_new(O_POOL); pthread_create(&long_process_thread, NULL, (void *)&long_process, &request_list); onion_set_root_handler(o, onion_handler_new(&handler, &request_list, NULL)); ONION_INFO("Listening at http://localhost:8080"); onion_listen(o); // Close request_list.running = false; onion_ptr_list_foreach(request_list.reqres, (void *)free_reqres); onion_ptr_list_free(request_list.reqres); pthread_join(long_process_thread, NULL); onion_free(o); return 0; }
void t02_stop_listening_some_petitions(){ INIT_LOCAL(); signal(SIGTERM, shutdown_server); o=onion_new(O_POOL); pthread_t th; pthread_create(&th, NULL, listen_thread_f, NULL); sleep(2); ONION_INFO("Connecting to server"); int connfd=connect_to("localhost","8080"); FAIL_IF( connfd < 0 ); FAIL_IF_NOT(ok_listening); kill(getpid(), SIGTERM); sleep(2); FAIL_IF(ok_listening); pthread_join(th, NULL); onion_free(o); END_LOCAL(); }
void free_onion(int unused){ static int already_closing=0; if (!already_closing){ ONION_INFO("Closing connections."); onion_free(o); already_closing=1; } exit(0); }
onion_connection_status wait_random(void *_, onion_request *req, onion_response *res){ int ms=105.0 + (float)((200.0 * rand()) / ((float)RAND_MAX)); ONION_INFO("Wait %.3f seconds", ms/1000.0); usleep(ms*1000); onion_response_write(res, "OK", 3); return OCS_PROCESSED; }
void long_process(void *request_list_v) { request_list_t *request_list = request_list_v; int n = 0; while (request_list->running) { n += 1; sleep(1); ONION_INFO("%d listeners", onion_ptr_list_count(request_list->reqres)); pthread_mutex_lock(&request_list->lock); request_list->reqres = onion_ptr_list_filter(request_list->reqres, (void *)print_reqn, &n); pthread_mutex_unlock(&request_list->lock); } }
static void shutdown_server(int _){ static bool first_call=true; if (first_call){ if (last_onion){ onion_listen_stop(last_onion); ONION_INFO("Exiting onion listening (SIG%s)", _==SIGTERM ? "TERM" : "INT"); } } else{ ONION_ERROR("Aborting as onion does not stop listening."); abort(); } first_call=false; }
/** * @short Moves a resource */ onion_connection_status onion_webdav_move(const char *filename, onion_webdav *wd, onion_request *req, onion_response *res){ const char *dest=onion_request_get_header(req,"Destination"); if (!dest) return OCS_INTERNAL_ERROR; const char *dest_orig=dest; // Skip the http... part. Just 3 /. int i; for (i=0;i<3;i+=(*dest++=='/')) if (*dest==0) return OCS_INTERNAL_ERROR; dest--; const char *fullpath=onion_request_get_fullpath(req); const char *partialpath=onion_request_get_path(req); // Not the fixed URL part for this handler. int fpl=strlen(fullpath); // Full path length int ppl=strlen(onion_request_get_path(req)); // Partial, the fullpath[fpl-ppl] is the end point of the handler path if (strncmp(fullpath, dest, fpl-ppl)!=0){ char tmp[512]; int l=fpl-ppl < sizeof(tmp)-1 ? fpl-ppl : sizeof(tmp)-1; strncpy(tmp, fullpath, l); tmp[l]=0; ONION_WARNING("Move to out of this webdav share! (%s is out of %s)", dest, tmp); return onion_shortcut_response("Moving out of shared share", HTTP_FORBIDDEN, req, res); } dest=&dest[fpl-ppl]; char orig[512]; snprintf(orig, sizeof(orig), "%s/%s", wd->path, partialpath); if (wd->check_permissions(wd->path, orig, req)!=0){ return onion_shortcut_response("Forbidden", HTTP_FORBIDDEN, req, res); } const char *fdest=filename; ONION_INFO("Move %s to %s (webdav)", fullpath, dest_orig); int ok=onion_shortcut_rename(orig, fdest); if (ok==0){ ONION_DEBUG("Created %s succesfully", fdest); return onion_shortcut_response("201 Created", 201, req, res); } else{ ONION_ERROR("Could not rename %s to %s (%s)", orig, fdest, strerror(errno)); return onion_shortcut_response("Could not create resource", HTTP_FORBIDDEN, req, res); } }
onion_connection_status websocket_example_cont(void *data, onion_websocket *ws, ssize_t data_ready_len){ char tmp[256]; if (data_ready_len>sizeof(tmp)) data_ready_len=sizeof(tmp)-1; int len=onion_websocket_read(ws, tmp, data_ready_len); if (len<=0){ ONION_ERROR("Error reading data: %d: %s (%d)", errno, strerror(errno), data_ready_len); return OCS_NEED_MORE_DATA; } tmp[len]=0; onion_websocket_printf(ws, "Echo: %s", tmp); ONION_INFO("Read from websocket: %d: %s", len, tmp); return OCS_NEED_MORE_DATA; }
void do_timeout_request(){ ONION_INFO("Start timeout requests"); int i; for (i=0;i<10;i++){ int fd=connect_to("localhost","8081"); if ((i&1) == 1) usleep(500000); int w=write(fd,"GET /\n\n",7); fsync(fd); FAIL_IF_NOT_EQUAL_INT(w,7); shutdown(fd, SHUT_RDWR); // Should have closed the connection char data[256]; FAIL_IF(read(fd, data, sizeof(data))>0); close(fd); } }
/** * @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; }
/** * @short Executes each script file passed as argument. * * Optionally a -r sets the new lines to \r\n. It takes care of not changing content types. */ int main(int argc, char **argv){ server=onion_server_new(); onion_server_set_root_handler(server,onion_handler_new((void*)allinfo_handler,NULL,NULL)); onion_server_set_write(server,(void*)buffer_append); int i; int do_r=0; for (i=1;i<argc;i++){ if (strcmp(argv[i],"-r")==0){ ONION_WARNING("Setting the end of lines to \\r\\n"); do_r=1; } else{ ONION_INFO("Launching test %s",argv[i]); prerecorded(argv[i], do_r); } } onion_server_free(server); END(); }
int main(int argc, char **argv){ if (argc!=3){ ONION_ERROR("%s <certificate file> <key file>", argv[0]); exit(1); } ONION_INFO("Listening at https://localhost:8080"); Onion::Onion server(O_POOL); server.setCertificate(O_SSL_CERTIFICATE_KEY, argv[1], argv[2]); Onion::Url root(&server); root.add("", "Some static text", HTTP_OK ); root.add("lambda", [](Onion::Request &req, Onion::Response &res){ res<<"Lambda handler"; return OCS_PROCESSED; }); server.listen(); }
/** * @short Removes the allocated data * @memberof onion_t */ void onion_free(onion *onion){ ONION_DEBUG("Onion free"); #ifdef HAVE_PTHREADS if (onion->flags&O_THREADS_ENABLED){ int ntries=5; int c; for(;ntries--;){ sem_getvalue(&onion->thread_count,&c); if (c==onion->max_threads){ break; } ONION_INFO("Still some petitions on process (%d). Wait a little bit (%d).",c,ntries); sleep(1); } } #endif close(onion->listenfd); if (onion->poller) onion_poller_free(onion->poller); if (onion->username) free(onion->username); #ifdef HAVE_GNUTLS if (onion->flags&O_SSL_ENABLED){ gnutls_certificate_free_credentials (onion->x509_cred); gnutls_dh_params_deinit(onion->dh_params); gnutls_priority_deinit (onion->priority_cache); if (!(onion->flags&O_SSL_NO_DEINIT)) gnutls_global_deinit(); // This may cause problems if several characters use the gnutls on the same binary. } #endif if (onion->port) free(onion->port); if (onion->hostname) free(onion->hostname); onion_server_free(onion->server); free(onion); }
void free_onion(int unused){ ONION_INFO("Closing connections"); onion_free(o); exit(0); }
void onexit(int sig){ ONION_INFO("Exit"); kill(child, sig); if (o) onion_listen_stop(o); }
int main(int argc, char **argv){ //onion_log=onion_log_syslog; char *port="8080"; char *hostname="::"; const char *dirname="."; #ifdef HAVE_WEBDAV int withwebdav=1; #endif int i; for (i=1;i<argc;i++){ if ((strcmp(argv[i],"--port")==0) || (strcmp(argv[i],"-p")==0)){ port=argv[++i]; ONION_INFO("Listening at port %s",port); } if ((strcmp(argv[i],"--listen")==0) || (strcmp(argv[i],"-l")==0)){ hostname=argv[++i]; ONION_INFO("Listening at hostname %s",hostname); } else if (strcmp(argv[i],"--help")==0 || strcmp(argv[i],"-h")==0){ return show_help(); } #ifdef HAVE_WEBDAV else if (strcmp(argv[i],"--no-webdav")==0){ ONION_INFO("WebDAV support disabled"); withwebdav=0; } #endif else{ dirname=argv[i]; ONION_INFO("Exporting directory %s", dirname); } } onion_handler *root=onion_handler_new((onion_handler_handler)fileserver_page, (void *)dirname, NULL); #ifdef HAVE_WEBDAV if (withwebdav) onion_handler_add(root, onion_handler_webdav(dirname, NULL)); // fallback. else #endif onion_handler_add(root, onion_handler_export_local_new(dirname)); // This is the root directory where the translations are. #define W "." setenv("LANGUAGE","locale",1); // Remove LANGUAGE env var, set it to the locale name, setlocale(LC_ALL,""); bindtextdomain("locale", W); // This is necesary because of the fake name bindtextdomain("es", W); // One per language supported. bindtextdomain("zh", W); bindtextdomain("fr", W); bindtextdomain("pl", W); textdomain("C"); // Default language // All is configured now, now in hands of dgettext(LANG, txt); o=onion_new(O_POOL); onion_set_root_handler(o, root); onion_set_port(o, port); onion_set_hostname(o, hostname); signal(SIGINT, free_onion); int error=onion_listen(o); if (error){ perror("Cant create the server"); } onion_free(o); return 0; }
void stop(int){ ONION_INFO("Stop"); o.listenStop(); }
void t01_call_otemplate(){ INIT_LOCAL(); onion *s=onion_new(0); onion_set_root_handler(s, onion_handler_new((void*)_13_otemplate_html_handler_page, NULL, NULL)); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(s,NULL,NULL,lp); struct tests_call_otemplate tests; onion_request *req=onion_request_new(lp); FAIL_IF_NOT_EQUAL_INT(onion_request_write0(req, "GET /\n\n"), OCS_REQUEST_READY); FAIL_IF_NOT_EQUAL_INT(onion_request_process(req), OCS_CLOSE_CONNECTION); ONION_INFO("Got %s",onion_buffer_listen_point_get_buffer_data(req)); check_tests(onion_buffer_listen_point_get_buffer(req), &tests); FAIL_IF_NOT_EQUAL_INT(tests.ok_hello,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_list,0); FAIL_IF_NOT_EQUAL_INT(tests.ok_title,0); FAIL_IF_NOT_EQUAL_INT(tests.ok_title_title,0); FAIL_IF_NOT_EQUAL_INT(tests.ok_encoding,0); onion_dict *d=onion_dict_new(); onion_dict_add(d, "title", "TITLE",0); onion_dict_add(d, "hello", "SHOULD NOT APPEAR",0); onion_dict_add(d, "quoted", "<\"Hello>",0); onion_request_clean(req); onion_handler_free(onion_get_root_handler(s)); onion_set_root_handler(s, onion_handler_new((void*)_13_otemplate_html_handler_page, d, NULL)); FAIL_IF_NOT_EQUAL_INT(onion_request_write0(req, "GET /\n\n"), OCS_REQUEST_READY); FAIL_IF_NOT_EQUAL_INT(onion_request_process(req), OCS_CLOSE_CONNECTION); ONION_INFO("Got %s",onion_buffer_listen_point_get_buffer_data(req)); check_tests(onion_buffer_listen_point_get_buffer(req), &tests); FAIL_IF_NOT_EQUAL_INT(tests.ok_hello,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_list,0); FAIL_IF_NOT_EQUAL_INT(tests.ok_title,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_title_title,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_encoding,1); onion_dict *d2=onion_dict_new(); onion_dict_add(d2,"0","LIST 1",0); onion_dict_add(d2,"1","LIST 2",0); onion_dict_add(d2,"2","LIST 3",0); onion_dict_add(d,"list",d2, OD_DICT|OD_FREE_VALUE); onion_dict *f1=onion_dict_new(); onion_dict *f2=onion_dict_new(); onion_dict_add(f2, "0", "internal",0); onion_dict_add(f2, "1", "loop",0); onion_dict_add(f1, "loop", f2, OD_DICT|OD_FREE_VALUE); onion_dict_add(d, "loop", f1, OD_DICT|OD_FREE_VALUE); onion_request_clean(req); onion_handler_free(onion_get_root_handler(s)); onion_set_root_handler(s, onion_handler_new((void*)_13_otemplate_html_handler_page, d, (void*)onion_dict_free)); FAIL_IF_NOT_EQUAL_INT(onion_request_write0(req, "GET /\n\n"), OCS_REQUEST_READY); FAIL_IF_NOT_EQUAL_INT(onion_request_process(req), OCS_CLOSE_CONNECTION); check_tests(onion_buffer_listen_point_get_buffer(req), &tests); ONION_INFO("Got %s",onion_buffer_listen_point_get_buffer_data(req)); FAIL_IF_NOT_EQUAL_INT(tests.ok_hello,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_list,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_title,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_title_title,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_internal_loop,1); onion_request_free(req); onion_free(s); END_LOCAL(); }
int main(int argc, char **argv){ char *port="8080"; char *hostname="::"; const char *dirname="."; const char *certfile="cert.pem"; const char *pamname="login"; int i; for (i=1;i<argc;i++){ if ((strcmp(argv[i],"--port")==0) || (strcmp(argv[i],"-p")==0)){ port=argv[++i]; ONION_INFO("Listening at port %s",port); } if ((strcmp(argv[i],"--listen")==0) || (strcmp(argv[i],"-l")==0)){ hostname=argv[++i]; ONION_INFO("Listening at hostname %s",hostname); } else if (strcmp(argv[i],"--pem")==0){ if (argc<i+1) return show_help(); certfile=argv[++i]; ONION_INFO("Certificate file set to %s",certfile); } else if (strcmp(argv[i],"--pam")==0){ if (argc<i+1) return show_help(); pamname=argv[++i]; ONION_INFO("Pam name is now %s",pamname); } else if (strcmp(argv[i],"--help")==0 || strcmp(argv[i],"-h")==0){ return show_help(); } else dirname=argv[i]; } upload_file_data data={ dirname }; onion_handler *root=onion_handler_new((void*)upload_file,(void*)&data,NULL); onion_handler *dir=onion_handler_export_local_new(argc==2 ? argv[1] : "."); onion_handler_export_local_set_footer(dir, upload_file_footer); onion_handler_add(dir, onion_handler_static("<h1>404 - File not found.</h1>", 404) ); onion_handler_add(root,dir); onion_handler *pam=onion_handler_auth_pam("Onion Fileserver", pamname, root); o=onion_new(O_THREADED); onion_set_root_handler(o, pam); onion_set_certificate(o, O_SSL_CERTIFICATE_KEY, certfile, certfile); onion_set_port(o, port); onion_set_hostname(o, hostname); signal(SIGINT, free_onion); int error=onion_listen(o); if (error){ perror("Cant create the server"); } onion_free(o); return 0; }
int main(int argc, char **argv){ char *port="8080"; char *serverip="::"; const char *command="/bin/bash"; const char *certificatefile="/etc/pki/tls/certs/pound.pem"; const char *keyfile="/etc/pki/tls/certs/pound.key"; int error; int i; int ssl=1; #ifdef HAVE_PAM int use_pam=1; #endif for (i=1;i<argc;i++){ if (strcmp(argv[i],"--help")==0){ show_help(); exit(0); } else if(strcmp(argv[i],"-p")==0 || strcmp(argv[i],"--port")==0){ if (i+1>argc){ ONION_ERROR("Need to set the port number."); show_help(); exit(1); } port=argv[++i]; fprintf(stderr, "Using port %s\n",port); } else if(strcmp(argv[i],"-i")==0 || strcmp(argv[i],"--ip")==0){ if (i+1>argc){ ONION_ERROR("Need to set the ip address or hostname."); show_help(); exit(1); } serverip=argv[++i]; fprintf(stderr, "Using ip %s\n",serverip); } else if(strcmp(argv[i],"-c")==0 || strcmp(argv[i],"--cert")==0){ if (i+1>argc){ ONION_ERROR("Need to set the certificate filename"); show_help(); exit(1); } certificatefile=argv[++i]; ONION_INFO("Using certificate %s",certificatefile); } else if(strcmp(argv[i],"-k")==0 || strcmp(argv[i],"--key")==0){ if (i+1>argc){ ONION_ERROR("Need to set the certificate key filename."); show_help(); exit(1); } keyfile=argv[++i]; ONION_INFO("Using certificate key %s",keyfile); } else if(strcmp(argv[i],"-x")==0 || strcmp(argv[i],"--exec")==0){ if (i+1>argc){ ONION_ERROR("Need the command to execute."); show_help(); exit(1); } command=argv[++i]; ONION_INFO("New terminal execute the command %s",command); } else if(strcmp(argv[i],"--no-ssl")==0){ ssl=0; ONION_INFO("Disabling SSL!"); } #ifdef HAVE_PAM else if(strcmp(argv[i],"--no-pam")==0){ use_pam=0; ONION_INFO("Disabling PAM!"); } #endif } o=onion_new(O_POOL|O_SYSTEMD); // I prepare the url handler, with static, uuid and term. Also added the empty rule that redirects to static/index.html onion_url *url=onion_url_new(); onion_handler *term_handler=oterm_handler(o,command); #ifdef HAVE_PAM if (use_pam){ onion_url_add_handler(url, "^term/", onion_handler_auth_pam("Onion Terminal", "login", term_handler)); } else #endif { onion_url_add_with_data(url, "^term/", oterm_nopam, term_handler, NULL); } onion_url_add_with_data(url, "^uuid/", oterm_uuid, onion_handler_get_private_data(term_handler), NULL); #ifdef __DEBUG__ if (getenv("OTERM_DEBUG")) onion_url_add_handler(url, "^static/", onion_handler_export_local_new("static")); else #endif { onion_url_add(url, "^static/", opack_static); } onion_url_add_with_data(url, "", onion_shortcut_internal_redirect, "static/index.html", NULL); srand(time(NULL)); onion_set_root_handler(o, onion_url_to_handler(url)); if (!(onion_flags(o)&O_SSL_AVAILABLE)){ ONION_WARNING("SSL support is not available. Oterm is in unsecure mode!"); } else if (ssl){ // Not necesary the else, as onion_use_certificate would just return an error. But then it will exit. error=onion_set_certificate(o, O_SSL_CERTIFICATE_KEY, certificatefile, keyfile); if (error){ ONION_ERROR("Cant set certificate and key files (%s, %s)",certificatefile, keyfile); show_help(); exit(1); } } onion_set_port(o, port); onion_set_hostname(o, serverip); onion_set_timeout(o,5000); signal(SIGINT, free_onion); signal(SIGPIPE, SIG_IGN); fprintf(stderr, "Listening at %s\n",port); error=onion_listen(o); if (error){ ONION_ERROR("Cant create the server: %s", strerror(errno)); } onion_free(o); return 0; }