Beispiel #1
0
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;
}
Beispiel #2
0
void *listen_thread_f(void *_){
	ok_listening=1;
	ONION_INFO("Start listening");
	onion_listen(o);
	ONION_INFO("End listening");
	ok_listening=0;
	
	return NULL;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
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();
}
Beispiel #6
0
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);
}
Beispiel #7
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;
}
Beispiel #8
0
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);
  }
}
Beispiel #9
0
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;
}
Beispiel #10
0
/**
 * @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);
	}
}
Beispiel #11
0
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;
}
Beispiel #12
0
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);
  }
}
Beispiel #13
0
/**
 * @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;
}
Beispiel #14
0
/**
 * @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();
}
Beispiel #15
0
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();
}
Beispiel #16
0
/**
 * @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);
}
Beispiel #17
0
void free_onion(int unused){
	ONION_INFO("Closing connections");
	onion_free(o);
	exit(0);
}
Beispiel #18
0
void onexit(int sig){
	ONION_INFO("Exit");
	kill(child, sig);
	if (o)
		onion_listen_stop(o);
}
Beispiel #19
0
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;
}
Beispiel #20
0
void stop(int){
	ONION_INFO("Stop");
	o.listenStop();
}
Beispiel #21
0
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();
}
Beispiel #22
0
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;
}
Beispiel #23
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;
}