Example #1
0
static void init_async(h2o_multithread_queue_t *queue, h2o_loop_t *loop)
{
#if defined(__linux__)
    /**
     * The kernel overhead of an eventfd file descriptor is
     * much lower than that of a pipe, and only one file descriptor is required
     */
    int fd;

    fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    if (fd == -1) {
        perror("eventfd");
        abort();
    }
    queue->async.write = fd;
    queue->async.read = h2o_evloop_socket_create(loop, fd, 0);
#else
    int fds[2];

    if (cloexec_pipe(fds) != 0) {
        perror("pipe");
        abort();
    }
    fcntl(fds[1], F_SETFL, O_NONBLOCK);
    queue->async.write = fds[1];
    queue->async.read = h2o_evloop_socket_create(loop, fds[0], 0);
#endif
    queue->async.read->data = queue;
    h2o_socket_read_start(queue->async.read, on_read);
}
void initialize_event_loop(bool is_main_thread,
                           global_data_t *global_data,
                           event_loop_t *loop)
{
	memset(loop, 0, sizeof(*loop));
	h2o_context_init(&loop->h2o_ctx, h2o_evloop_create(), &global_data->h2o_config);
	loop->h2o_accept_ctx.ctx = &loop->h2o_ctx;
	loop->h2o_accept_ctx.hosts = global_data->h2o_config.hosts;
	loop->h2o_accept_ctx.ssl_ctx = global_data->ssl_ctx;

	int listener_sd;

	if (is_main_thread)
		listener_sd = global_data->listener_sd;
	else {
		int flags;

		CHECK_ERRNO_RETURN(listener_sd, dup, global_data->listener_sd);
		CHECK_ERRNO_RETURN(flags, fcntl, listener_sd, F_GETFD);
		CHECK_ERRNO(fcntl, listener_sd, F_SETFD, flags | FD_CLOEXEC);
	}

	// Let all the threads race to call accept() on the socket; since the latter is
	// non-blocking, that will effectively act as load balancing.
	loop->h2o_socket = h2o_evloop_socket_create(loop->h2o_ctx.loop,
	                                            listener_sd,
	                                            H2O_SOCKET_FLAG_DONT_READ);
	loop->h2o_socket->data = loop;
	h2o_socket_read_start(loop->h2o_socket, accept_connection);
	h2o_multithread_register_receiver(loop->h2o_ctx.queue,
	                                  &loop->h2o_receiver,
	                                  process_messages);
	// libh2o's event loop does not support write polling unless it
	// controls sending the data as well, so do read polling on the
	// epoll file descriptor as a work-around.
	CHECK_ERRNO_RETURN(loop->epoll_fd, epoll_create1, EPOLL_CLOEXEC);
	loop->epoll_socket = h2o_evloop_socket_create(loop->h2o_ctx.loop,
	                                              loop->epoll_fd,
	                                              H2O_SOCKET_FLAG_DONT_READ);
	loop->epoll_socket->data = loop;
	h2o_socket_read_start(loop->epoll_socket, do_epoll_wait);

	if (is_main_thread) {
		global_data->signals = h2o_evloop_socket_create(loop->h2o_ctx.loop,
		                                                global_data->signal_fd,
		                                                H2O_SOCKET_FLAG_DONT_READ);
		global_data->signals->data = loop;
		h2o_socket_read_start(global_data->signals, shutdown_server);
	}
}
Example #3
0
static int on_config_port_complete(h2o_configurator_t *_conf, h2o_context_t *ctx)
{
    struct port_configurator_t *conf = (void*)_conf;
    struct sockaddr_in addr;
    int fd, reuseaddr_flag = 1;
    h2o_socket_t *sock;

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(0);
    addr.sin_port = htons(conf->port);

    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1
        || setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_flag, sizeof(reuseaddr_flag)) != 0
        || bind(fd, (struct sockaddr*)&addr, sizeof(addr)) != 0
        || listen(fd, SOMAXCONN) != 0) {
        fprintf(stderr, "failed to listen to port %hu:%s\n", conf->port, strerror(errno));
        return -1;
    }

    sock = h2o_evloop_socket_create(ctx->loop, fd, H2O_SOCKET_FLAG_IS_ACCEPT);
    sock->data = ctx;
    h2o_socket_read_start(sock, on_config_port_accept);

    return 0;
}
void initialize_event_loop(bool is_main_thread,
                           global_data_t *global_data,
                           h2o_multithread_receiver_t *h2o_receiver,
                           event_loop_t *loop)
{
	h2o_socket_cb accept_cb = accept_connection;
	const config_t * const config = global_data->global_thread_data->config;

	memset(loop, 0, sizeof(*loop));
	h2o_context_init(&loop->h2o_ctx, h2o_evloop_create(), &global_data->h2o_config);
	loop->h2o_accept_ctx.ctx = &loop->h2o_ctx;
	loop->h2o_accept_ctx.hosts = global_data->h2o_config.hosts;

	if (global_data->ssl_ctx) {
		loop->h2o_accept_ctx.ssl_ctx = global_data->ssl_ctx;
		start_accept_polling(config, accept_connection, true, loop);
		// Assume that the majority of the connections use HTTPS,
		// so HTTP can take a few extra operations.
		accept_cb = accept_http_connection;
	}

	start_accept_polling(config, accept_cb, false, loop);
	h2o_multithread_register_receiver(loop->h2o_ctx.queue,
	                                  h2o_receiver,
	                                  process_messages);

	if (is_main_thread) {
		global_data->signals = h2o_evloop_socket_create(loop->h2o_ctx.loop,
		                                                global_data->signal_fd,
		                                                H2O_SOCKET_FLAG_DONT_READ);
		global_data->signals->data = loop;
		h2o_socket_read_start(global_data->signals, shutdown_server);
	}
}
Example #5
0
File: main.c Project: Gwill/h2o
static int on_config_port_context_create(h2o_configurator_t *_conf, h2o_context_t *ctx)
{
    struct port_configurator_t *conf = (void*)_conf;
    h2o_socket_t *sock;

    /* FIXME use dup to support multithread? */
    sock = h2o_evloop_socket_create(ctx->loop, conf->fd, H2O_SOCKET_FLAG_IS_ACCEPT);
    sock->data = ctx;
    h2o_socket_read_start(sock, on_config_port_accept);

    return 0;
}
Example #6
0
static void init_async(h2o_multithread_queue_t *queue, h2o_loop_t *loop)
{
    int fds[2];

    if (cloexec_pipe(fds) != 0) {
        perror("pipe");
        abort();
    }
    fcntl(fds[1], F_SETFL, O_NONBLOCK);
    queue->async.write = fds[1];
    queue->async.read = h2o_evloop_socket_create(loop, fds[0], 0);
    queue->async.read->data = queue;
    h2o_socket_read_start(queue->async.read, on_read);
}
Example #7
0
File: main.c Project: Debug-Orz/h2o
static void *run_loop(void *_conf)
{
    struct config_t *conf = _conf;
    h2o_evloop_t *loop;
    h2o_context_t ctx;
    struct listener_ctx_t *listeners = alloca(sizeof(*listeners) * conf->num_listeners);
    size_t i;

    /* setup loop and context */
    loop = h2o_evloop_create();
    h2o_context_init(&ctx, loop, &conf->global_config);

    /* setup listeners */
    for (i = 0; i != conf->num_listeners; ++i) {
        listeners[i].ctx = &ctx;
        listeners[i].ssl_ctx = conf->listeners[i]->ssl_ctx;
        listeners[i].sock = h2o_evloop_socket_create(
            ctx.loop, conf->listeners[i]->fd,
            (struct sockaddr*)&conf->listeners[i]->addr, conf->listeners[i]->addrlen,
            H2O_SOCKET_FLAG_IS_ACCEPT);
        listeners[i].sock->data = listeners + i;
    }

    /* the main loop */
    while (1) {
        /* start / stop trying to accept new connections */
        if (conf->state.num_connections < conf->max_connections) {
            for (i = 0; i != conf->num_listeners; ++i) {
                if (! h2o_socket_is_reading(listeners[i].sock))
                    h2o_socket_read_start(listeners[i].sock, on_accept);
            }
        } else {
            for (i = 0; i != conf->num_listeners; ++i) {
                if (h2o_socket_is_reading(listeners[i].sock))
                    h2o_socket_read_stop(listeners[i].sock);
            }
        }
        /* run the loop once */
        h2o_evloop_run(loop);
    }

    return NULL;
}
Example #8
0
static int create_listener(void)
{
    struct sockaddr_in addr;
    int fd, reuseaddr_flag = 1;
    h2o_socket_t *sock;

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(0x7f000001);
    addr.sin_port = htons(7890);

    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ||
        setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_flag, sizeof(reuseaddr_flag)) != 0 ||
        bind(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0 || listen(fd, SOMAXCONN) != 0) {
        return -1;
    }

    sock = h2o_evloop_socket_create(ctx.loop, fd, (void *)&addr, sizeof(addr), H2O_SOCKET_FLAG_DONT_READ);
    h2o_socket_read_start(sock, on_accept);

    return 0;
}
static void start_accept_polling(const config_t *config,
                                 h2o_socket_cb accept_cb,
                                 bool is_https,
                                 event_loop_t *loop)
{
	const int listener_sd = get_listener_socket(config->bind_address,
	                                            is_https ? config->https_port : config->port);
	// Let all the threads race to call accept() on the socket; since the latter is
	// non-blocking, that will virtually act as load balancing, and SO_REUSEPORT
	// will make it efficient.
	h2o_socket_t * const h2o_socket = h2o_evloop_socket_create(loop->h2o_ctx.loop,
	                                                           listener_sd,
	                                                           H2O_SOCKET_FLAG_DONT_READ);

	if (is_https)
		loop->h2o_https_socket = h2o_socket;
	else
		loop->h2o_socket = h2o_socket;

	h2o_socket->data = loop;
	h2o_socket_read_start(h2o_socket, accept_cb);
}