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
|
|
|
|
mm_accept_cb(uv_stream_t *handle, int status)
|
|
|
|
{
|
|
|
|
mm_io_t *io = handle->data;
|
|
|
|
io->accept_status = status;
|
|
|
|
mm_scheduler_wakeup(io->accept_fiber);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline machine_io_t
|
|
|
|
mm_accept_client(mm_io_t *io)
|
|
|
|
{
|
|
|
|
mm_io_t *client = machine_create_io(io->machine);
|
|
|
|
if (client == NULL) {
|
|
|
|
io->accept_status = -ENOMEM;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
io->accept_status =
|
|
|
|
uv_accept((uv_stream_t*)&io->handle,
|
|
|
|
(uv_stream_t*)&client->handle);
|
|
|
|
if (io->accept_status < 0) {
|
|
|
|
machine_close(client);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
client->connected = 1;
|
|
|
|
uv_fileno((uv_handle_t*)&client->handle,
|
|
|
|
&client->fd);
|
|
|
|
return client;
|
|
|
|
}
|
|
|
|
|
|
|
|
MACHINE_API int
|
|
|
|
machine_accept(machine_io_t obj, int backlog, machine_io_t *client)
|
|
|
|
{
|
|
|
|
mm_io_t *io = obj;
|
|
|
|
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-03-21 12:30:50 +00:00
|
|
|
io->accept_status = 0;
|
|
|
|
io->accept_fiber = current;
|
|
|
|
int rc;
|
|
|
|
rc = uv_listen((uv_stream_t*)&io->handle, backlog, mm_accept_cb);
|
|
|
|
if (rc < 0) {
|
|
|
|
io->accept_fiber = NULL;
|
2017-03-29 11:58:27 +00:00
|
|
|
mm_io_set_errno_uv(io, rc);
|
|
|
|
return -1;
|
2017-03-21 12:30:50 +00:00
|
|
|
}
|
|
|
|
mm_scheduler_yield(&io->machine->scheduler);
|
|
|
|
rc = io->accept_status;
|
|
|
|
io->accept_fiber = NULL;
|
2017-03-29 11:58:27 +00:00
|
|
|
if (rc < 0) {
|
|
|
|
mm_io_set_errno_uv(io, rc);
|
|
|
|
return -1;
|
|
|
|
}
|
2017-03-21 12:30:50 +00:00
|
|
|
*client = mm_accept_client(io);
|
2017-03-29 11:58:27 +00:00
|
|
|
if (*client == NULL) {
|
|
|
|
mm_io_set_errno_uv(io, io->accept_status);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
2017-03-21 12:30:50 +00:00
|
|
|
}
|