Example #1
0
/// Initializes the connection, create request, sets up the SSL...
static onion_request *onion_connection_start(onion *o, int clientfd, struct sockaddr_storage *cli_addr, socklen_t cli_len){
  signal(SIGPIPE, SIG_IGN); // FIXME. remove the thread better. Now it will try to write and fail on it.
  
	// sorry all the ifdefs, but here is the worst case where i would need it.. and both are almost the same.
#ifdef HAVE_GNUTLS
	gnutls_session_t session=NULL;
	if (o->flags&O_SSL_ENABLED){
		session=onion_prepare_gnutls_session(o, clientfd);
		if (session==NULL){
			ONION_ERROR("Could not create session");
			return NULL;
		}
	}
#endif

	onion_request *req;
#ifdef HAVE_GNUTLS
	if (o->flags&O_SSL_ENABLED){
		onion_server_set_write(o->server, (onion_write)gnutls_record_send); // Im lucky, has the same signature.
		onion_server_set_read(o->server, (onion_read)gnutls_record_recv); // Im lucky, has the same signature.
		onion_server_set_close(o->server, (onion_close)onion_ssl_close);
		req=onion_request_new_from_socket(o->server, session, cli_addr, cli_len);
	}
	else
#endif
	{
		onion_server_set_write(o->server, (onion_write)onion_write_to_socket);
		onion_server_set_read(o->server, (onion_read)onion_read_from_socket);
		onion_server_set_close(o->server, (onion_close)onion_close_socket);
		req=onion_request_new_from_socket(o->server, (void*)(long int)clientfd, cli_addr, cli_len);
	}
	req->fd=clientfd;
	if (!( (o->flags&O_THREADED) || (o->flags&O_POLL) ))
		onion_request_set_no_keep_alive(req);
	
	return req;
}
Example #2
0
/**
 * @short Performs the listening with the given mode
 * @memberof onion_t
 *
 * This is the main loop for the onion server.
 * 
 * It initiates the listening on all the selected ports and addresses.
 *
 * @returns !=0 if there is any error. It returns actualy errno from the network operations. See socket for more information.
 */
int onion_listen(onion *o){
#ifdef HAVE_PTHREADS
	if (!(o->flags&O_DETACHED) && (o->flags&O_DETACH_LISTEN)){ // Must detach and return
		o->flags|=O_DETACHED;
		pthread_create(&o->listen_thread,NULL, (void*)onion_listen, o);
		return 0;
	}
#endif
	
	if (!o->listen_points){
		onion_add_listen_point(o,NULL,NULL,onion_http_new());
		ONION_DEBUG("Created default HTTP listen port");
	}

	/// Start listening
	size_t successful_listened_points=0;
	onion_listen_point **lp=o->listen_points;
	while (*lp){
		int listen_result=onion_listen_point_listen(*lp);
		if (!listen_result) {
			successful_listened_points++;
		}
		lp++;
	}
	if (!successful_listened_points){
		ONION_ERROR("There are no available listen points");
		return 1;
	}

	
	if (o->flags&O_ONE){
		onion_listen_point **listen_points=o->listen_points;
		if (listen_points[1]!=NULL){
			ONION_WARNING("Trying to use non-poll and non-thread mode with several listen points. Only the first will be listened");
		}
		onion_listen_point *op=listen_points[0];
		do{
			onion_request *req=onion_request_new(op);
			if (!req)
				continue;
			ONION_DEBUG("Accepted request %p", req);
			onion_request_set_no_keep_alive(req);
			int ret;
			do{
				ret=req->connection.listen_point->read_ready(req);
			}while(ret>=0);
			ONION_DEBUG("End of request %p", req);
			onion_request_free(req);
			//req->connection.listen_point->close(req);
		}while(((o->flags&O_ONE_LOOP) == O_ONE_LOOP) && op->listenfd>0);
	}
	else{
		onion_listen_point **listen_points=o->listen_points;
		while (*listen_points){
			onion_listen_point *p=*listen_points;
			ONION_DEBUG("Adding listen point fd %d to poller", p->listenfd);
			onion_poller_slot *slot=onion_poller_slot_new(p->listenfd, (void*)onion_listen_point_accept, p);
			onion_poller_slot_set_type(slot, O_POLL_ALL);
			onion_poller_add(o->poller, slot);
			listen_points++;
		}

#ifdef HAVE_PTHREADS
		ONION_DEBUG("Start polling / listening %p, %p, %p", o->listen_points, *o->listen_points, *(o->listen_points+1));
		if (o->flags&O_THREADED){
			o->threads=malloc(sizeof(pthread_t)*(o->nthreads-1));
			int i;
			for (i=0;i<o->nthreads-1;i++){
				pthread_create(&o->threads[i],NULL,(void*)onion_poller_poll, o->poller);
			}
			
			// Here is where it waits.. but eventually it will exit at onion_listen_stop
			onion_poller_poll(o->poller);
			ONION_DEBUG("Closing onion_listen");
			
			for (i=0;i<o->nthreads-1;i++){
				pthread_join(o->threads[i],NULL);
			}
		}
		else
#endif
			onion_poller_poll(o->poller);

		listen_points=o->listen_points;
		while (*listen_points){
			onion_listen_point *p=*listen_points;
			if (p->listenfd>0){
				ONION_DEBUG("Removing %d from poller", p->listenfd);
				onion_poller_remove(o->poller, p->listenfd);
			}
			listen_points++;
		}
	}
	return 0;
}