示例#1
0
文件: onion.c 项目: arunsirrpi/onion
/**
 * @short Internal accept of just one request. 
 * 
 * It might be called straight from listen, or from the epoller.
 * 
 * @returns 0 if ok, <0 if error.
 */
static int onion_accept_request(onion *o){
  struct sockaddr_storage cli_addr;
  socklen_t cli_len;
  int clientfd=onion_accept(o, &cli_addr, &cli_len);
  
  if (clientfd<0)
    return -1;
  
	if (o->flags&O_POLL){
		onion_request *req=onion_connection_start(o, clientfd, &cli_addr, cli_len);
		if (!req){
      shutdown(clientfd,SHUT_RDWR); // Socket must be destroyed.
      close(clientfd);
			return 0;
		}
		onion_poller_slot *slot=onion_poller_slot_new(clientfd, (void*)onion_connection_read, req);
		onion_poller_slot_set_shutdown(slot, (void*)onion_connection_shutdown, req);
		onion_poller_slot_set_timeout(slot, o->timeout);
		
		onion_poller_add(o->poller, slot);
	}
	else{
		onion_process_request(o, clientfd, &cli_addr, cli_len);
	}
	return 0;
}
示例#2
0
/**
 * @short Called when a new connection appears on the listenfd
 * @memberof onion_listen_point_t
 * 
 * When the new connection appears, creates the request and adds it to the pollers.
 * 
 * It returns always 1 as any <0 would detach from the poller and close the listen point, 
 * and not accepting a request does not mean the connection point is corrupted. If a 
 * connection point may become corrupted should be the connection point itself who detaches 
 * from the poller.
 * 
 * @param op The listen point from where the request must be built
 * @returns 1 always. 
 */
int onion_listen_point_accept(onion_listen_point *op){
	onion_request *req=onion_request_new(op);
	if (req){
		if (req->connection.fd>0){
			onion_poller_slot *slot=onion_poller_slot_new(req->connection.fd, (void*)onion_listen_point_read_ready, req);
			if (!slot)
				return 1;
			onion_poller_slot_set_timeout(slot, req->connection.listen_point->server->timeout);
			onion_poller_slot_set_shutdown(slot, (void*)onion_request_free, req);
			onion_poller_add(req->connection.listen_point->server->poller, slot);
			return 1;
		}
		if (req->connection.fd<0)
			ONION_ERROR("Error creating connection");
		// else, no need for fd... no use case yet.
	}

	return 1;
}
示例#3
0
/**
 * @short Called when a new connection appears on the listenfd
 * @memberof onion_listen_point_t
 * 
 * When the new connection appears, creates the request and adds it to the pollers.
 * 
 * It returns always 1 as any <0 would detach from the poller and close the listen point, 
 * and not accepting a request does not mean the connection point is corrupted. If a 
 * connection point may become corrupted should be the connection point itself who detaches 
 * from the poller.
 * 
 * @param op The listen point from where the request must be built
 * @returns 1 always. The poller needs one to keep listening for connections.
 */
int onion_listen_point_accept(onion_listen_point *op){
	onion_request *req=onion_request_new(op);
	if (req){
		if (req->connection.fd>0){
			onion_poller_slot *slot=onion_poller_slot_new(req->connection.fd, (void*)onion_listen_point_read_ready, req);
			if (!slot)
				return 1;
			onion_poller_slot_set_timeout(slot, req->connection.listen_point->server->timeout);
			onion_poller_slot_set_shutdown(slot, (void*)onion_request_free, req);
			onion_poller_add(req->connection.listen_point->server->poller, slot);
			return 1;
		}
		// No fd. This could mean error, or not fd based. Normally error would not return a req.
		onion_request_free(req);
		ONION_ERROR("Error creating connection");
		return 1;
	}

	return 1;
}
示例#4
0
/**
 * @short Launches one handler for the given request
 * @ingroup request
 *
 * Once the request is ready, launch it.
 *
 * @returns The connection status: if it should be closed, error codes...
 */
onion_connection_status onion_request_process(onion_request *req){
	onion_response *res=onion_response_new(req);
	if (!req->path){
		onion_request_polish(req);
	}
	// Call the main handler.
	onion_connection_status hs=onion_handler_handle(req->connection.listen_point->server->root_handler, req, res);

	if (hs==OCS_INTERNAL_ERROR ||
		hs==OCS_NOT_IMPLEMENTED ||
		hs==OCS_NOT_PROCESSED){
		if (hs==OCS_INTERNAL_ERROR)
			req->flags|=OR_INTERNAL_ERROR;
		if (hs==OCS_NOT_IMPLEMENTED)
			req->flags|=OR_NOT_IMPLEMENTED;
		if (hs==OCS_NOT_PROCESSED)
			req->flags|=OR_NOT_FOUND;
		if (hs==OCS_FORBIDDEN)
			req->flags|=OR_FORBIDDEN;

		hs=onion_handler_handle(req->connection.listen_point->server->internal_error_handler, req, res);
	}

	if (hs==OCS_YIELD){
		// Remove from the poller, and yield thread to poller. From now on it will be processed somewhere else (longpoll thread).
		onion_poller *poller=onion_get_poller(req->connection.listen_point->server);
		onion_poller_slot *slot=onion_poller_get(poller, req->connection.fd);
		onion_poller_slot_set_shutdown(slot, NULL, NULL);

		return hs;
	}
	int rs=onion_response_free(res);
	if (hs>=0 && rs==OCS_KEEP_ALIVE) // if keep alive, reset struct to get the new petition.
		onion_request_clean(req);
	return hs>0 ? rs : hs;
}