2017-03-21 12:30:50 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* machinarium.
|
|
|
|
*
|
|
|
|
* cooperative multitasking engine.
|
|
|
|
*/
|
|
|
|
|
2017-03-21 12:55:23 +00:00
|
|
|
#include <machinarium_private.h>
|
|
|
|
#include <machinarium.h>
|
2017-03-21 12:30:50 +00:00
|
|
|
|
|
|
|
static void
|
2017-04-13 18:08:21 +00:00
|
|
|
mm_accept_timer_cb(mm_timer_t *handle)
|
2017-03-21 12:30:50 +00:00
|
|
|
{
|
2017-04-13 18:08:21 +00:00
|
|
|
mm_io_t *io = handle->arg;
|
|
|
|
(void)io;
|
|
|
|
io->accept_status = ETIMEDOUT;
|
|
|
|
io->accept_timedout = 1;
|
2017-03-21 12:30:50 +00:00
|
|
|
mm_scheduler_wakeup(io->accept_fiber);
|
|
|
|
}
|
|
|
|
|
2017-04-13 18:08:21 +00:00
|
|
|
static void
|
|
|
|
mm_accept_cancel_cb(void *obj, void *arg)
|
2017-03-21 12:30:50 +00:00
|
|
|
{
|
2017-04-13 18:08:21 +00:00
|
|
|
mm_io_t *io = arg;
|
|
|
|
(void)obj;
|
|
|
|
io->accept_status = ECANCELED;
|
|
|
|
mm_scheduler_wakeup(io->accept_fiber);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
mm_accept_on_read_cb(mm_fd_t *handle)
|
|
|
|
{
|
|
|
|
mm_io_t *io = handle->on_read_arg;
|
2017-04-13 18:36:17 +00:00
|
|
|
io->accept_status = 0;
|
|
|
|
mm_scheduler_wakeup(io->accept_fiber);
|
2017-04-13 18:08:21 +00:00
|
|
|
return 0;
|
2017-03-21 12:30:50 +00:00
|
|
|
}
|
|
|
|
|
2017-03-31 14:02:16 +00:00
|
|
|
static int
|
2017-04-13 18:10:42 +00:00
|
|
|
mm_accept(mm_io_t *io, int backlog, machine_io_t *client, uint64_t time_ms)
|
2017-03-21 12:30:50 +00:00
|
|
|
{
|
2017-04-13 18:08:21 +00:00
|
|
|
mm_t *machine = machine = io->machine;
|
2017-03-21 12:30:50 +00:00
|
|
|
mm_fiber_t *current = mm_scheduler_current(&io->machine->scheduler);
|
2017-03-29 11:58:27 +00:00
|
|
|
mm_io_set_errno(io, 0);
|
|
|
|
if (mm_fiber_is_cancelled(current)) {
|
|
|
|
mm_io_set_errno(io, ECANCELED);
|
2017-03-21 12:30:50 +00:00
|
|
|
return -1;
|
2017-03-29 11:58:27 +00:00
|
|
|
}
|
|
|
|
if (io->accept_fiber) {
|
|
|
|
mm_io_set_errno(io, EINPROGRESS);
|
|
|
|
return -1;
|
|
|
|
}
|
2017-04-13 18:08:21 +00:00
|
|
|
if (io->connected) {
|
|
|
|
mm_io_set_errno(io, EINPROGRESS);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (io->fd == -1) {
|
|
|
|
mm_io_set_errno(io, EBADF);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
io->accept_status = 0;
|
|
|
|
io->accept_fiber = NULL;
|
|
|
|
io->accept_timedout = 0;
|
|
|
|
|
2017-03-21 12:30:50 +00:00
|
|
|
int rc;
|
2017-04-13 18:08:21 +00:00
|
|
|
if (! io->accept_listen) {
|
|
|
|
rc = mm_socket_listen(io->fd, backlog);
|
|
|
|
if (rc == -1) {
|
|
|
|
mm_io_set_errno(io, errno);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* subscribe for accept event */
|
|
|
|
rc = mm_loop_read(&machine->loop, &io->handle,
|
|
|
|
mm_accept_on_read_cb,
|
|
|
|
io, 1);
|
|
|
|
if (rc == -1) {
|
|
|
|
mm_io_set_errno(io, errno);
|
2017-03-29 11:58:27 +00:00
|
|
|
return -1;
|
2017-03-21 12:30:50 +00:00
|
|
|
}
|
2017-04-13 18:08:21 +00:00
|
|
|
|
|
|
|
/* wait for timedout, cancel or execution status */
|
|
|
|
mm_timer_start(&machine->loop.clock, &io->accept_timer,
|
2017-04-13 18:10:42 +00:00
|
|
|
mm_accept_timer_cb, io, time_ms);
|
2017-04-13 18:08:21 +00:00
|
|
|
mm_call_begin(¤t->call, mm_accept_cancel_cb, io);
|
|
|
|
io->accept_fiber = current;
|
|
|
|
mm_scheduler_yield(&machine->scheduler);
|
2017-03-21 12:30:50 +00:00
|
|
|
io->accept_fiber = NULL;
|
2017-04-13 18:08:21 +00:00
|
|
|
mm_call_end(¤t->call);
|
|
|
|
mm_timer_stop(&io->accept_timer);
|
|
|
|
|
|
|
|
rc = mm_loop_read(&machine->loop, &io->handle, NULL, NULL, 0);
|
|
|
|
if (rc == -1) {
|
|
|
|
mm_io_set_errno(io, errno);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = io->accept_status;
|
|
|
|
if (rc != 0) {
|
|
|
|
mm_io_set_errno(io, rc);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-04-13 18:36:17 +00:00
|
|
|
/* setup client io */
|
2017-04-13 18:08:21 +00:00
|
|
|
*client = machine_create_io(io->machine);
|
|
|
|
if (client == NULL) {
|
|
|
|
mm_io_set_errno(io, ENOMEM);
|
2017-03-29 11:58:27 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2017-04-13 18:36:17 +00:00
|
|
|
mm_io_t *client_io = (mm_io_t*)*client;
|
|
|
|
client_io->opt_nodelay = io->opt_nodelay;
|
|
|
|
client_io->opt_keepalive = io->opt_keepalive;
|
|
|
|
client_io->opt_keepalive_delay = io->opt_keepalive_delay;
|
|
|
|
client_io->accepted = 1;
|
|
|
|
client_io->connected = 1;
|
2017-04-13 18:08:21 +00:00
|
|
|
rc = mm_socket_accept(io->fd, NULL, NULL);
|
|
|
|
if (rc == -1) {
|
|
|
|
mm_io_set_errno(io, errno);
|
|
|
|
machine_free_io(*client);
|
|
|
|
*client = NULL;
|
2017-03-29 11:58:27 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2017-04-13 18:36:17 +00:00
|
|
|
rc = mm_io_socket_set(client_io, rc);
|
|
|
|
if (rc == -1) {
|
|
|
|
machine_close(*client);
|
|
|
|
machine_free_io(*client);
|
|
|
|
*client = NULL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
rc = mm_loop_add(&machine->loop, &client_io->handle, 0);
|
|
|
|
if (rc == -1) {
|
|
|
|
mm_io_set_errno(io, errno);
|
|
|
|
machine_close(*client);
|
|
|
|
machine_free_io(*client);
|
|
|
|
*client = NULL;
|
|
|
|
return -1;
|
|
|
|
}
|
2017-03-29 11:58:27 +00:00
|
|
|
return 0;
|
2017-03-21 12:30:50 +00:00
|
|
|
}
|
2017-03-31 14:02:16 +00:00
|
|
|
|
2017-04-13 18:36:17 +00:00
|
|
|
MACHINE_API int
|
|
|
|
machine_accept(machine_io_t obj, machine_io_t *client, int backlog, uint64_t time_ms)
|
2017-03-31 14:02:16 +00:00
|
|
|
{
|
|
|
|
mm_io_t *io = obj;
|
|
|
|
int rc;
|
2017-04-13 18:36:17 +00:00
|
|
|
rc = mm_accept(io, backlog, client, time_ms);
|
2017-03-31 14:02:16 +00:00
|
|
|
if (rc == -1)
|
2017-04-13 18:36:17 +00:00
|
|
|
return -1;
|
|
|
|
return 0;
|
2017-03-31 14:02:16 +00:00
|
|
|
if (! io->tls_obj)
|
|
|
|
return 0;
|
|
|
|
mm_io_t *io_client = *client;
|
|
|
|
io_client->tls_obj = io->tls_obj;
|
|
|
|
rc = mm_tlsio_accept(&io_client->tls, io->tls_obj);
|
|
|
|
if (rc == -1) {
|
|
|
|
io->errno_ = io_client->errno_;
|
|
|
|
io->tls.error = io_client->tls.error;
|
|
|
|
memcpy(io->tls.error_msg, io_client->tls.error_msg,
|
|
|
|
sizeof(io->tls.error_msg));
|
|
|
|
|
|
|
|
/* todo: close */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|