odyssey/lib/mm_connect.c

102 lines
2.1 KiB
C
Raw Normal View History

2016-11-25 10:00:38 +00:00
/*
* machinarium.
*
* Cooperative multitasking engine.
*/
#include <machinarium_private.h>
#include <machinarium.h>
static void
2016-12-07 14:16:38 +00:00
mm_connect_timeout_cb(uv_timer_t *handle)
2016-11-25 10:00:38 +00:00
{
mmio *io = handle->data;
io->connect_timeout = 1;
/* cancel connection request,
* connect callback will be called anyway */
2016-11-25 10:14:33 +00:00
mm_io_close_handle(io, (uv_handle_t*)&io->handle);
2016-11-25 10:00:38 +00:00
}
static void
2016-12-07 14:16:38 +00:00
mm_connect_cb(uv_connect_t *handle, int status)
2016-11-25 10:00:38 +00:00
{
mmio *io = handle->data;
if (mm_fiber_is_cancel(io->connect_fiber))
goto wakeup;
if (io->connect_timeout)
goto wakeup;
2016-11-25 10:14:33 +00:00
mm_io_timer_stop(io, &io->connect_timer);
2016-11-25 10:00:38 +00:00
wakeup:
io->connect_status = status;
mm_wakeup(io->f, io->connect_fiber);
}
static void
2016-12-07 14:16:38 +00:00
mm_connect_cancel_cb(mmfiber *fiber, void *arg)
2016-11-25 10:00:38 +00:00
{
2017-01-11 09:13:29 +00:00
(void)fiber;
2016-11-25 10:00:38 +00:00
mmio *io = arg;
io->write_timeout = 0;
2016-11-25 10:14:33 +00:00
mm_io_timer_stop(io, &io->connect_timer);
mm_io_close_handle(io, (uv_handle_t*)&io->handle);
2016-11-25 10:00:38 +00:00
}
MM_API int
mm_is_connected(mm_io_t iop)
2016-11-25 10:00:38 +00:00
{
mmio *io = iop;
return io->connected;
}
MM_API int
mm_connect(mm_io_t iop, struct sockaddr *sa, uint64_t time_ms)
2016-11-25 10:00:38 +00:00
{
mmio *io = iop;
mmfiber *current = mm_current(io->f);
if (mm_fiber_is_cancel(current))
return -ECANCELED;
if (io->connect_fiber)
return -1;
io->connect_status = 0;
io->connect_timeout = 0;
io->connect_fiber = NULL;
/* assign fiber */
io->connect_fiber = current;
/* start timer and connection */
2016-12-07 14:16:38 +00:00
mm_io_timer_start(io, &io->connect_timer, mm_connect_timeout_cb,
2016-11-25 10:00:38 +00:00
time_ms);
int rc;
rc = uv_tcp_connect(&io->connect, &io->handle,
sa, mm_connect_cb);
2016-11-25 10:00:38 +00:00
if (rc < 0) {
mm_io_timer_stop(io, &io->connect_timer);
2016-11-25 10:00:38 +00:00
io->connect_fiber = NULL;
return rc;
}
/* register cancellation procedure */
2016-12-07 14:16:38 +00:00
mm_fiber_op_begin(io->connect_fiber, mm_connect_cancel_cb, io);
2016-11-25 10:00:38 +00:00
/* yield fiber */
mm_scheduler_yield(&io->f->scheduler);
mm_fiber_op_end(io->connect_fiber);
/* result from timer or connect callback */
rc = io->connect_status;
if (rc == 0) {
assert(! io->connect_timeout);
io->connected = 1;
}
io->connect_fiber = NULL;
return rc;
}
MM_API int
mm_connect_is_timeout(mm_io_t iop)
2016-11-25 10:00:38 +00:00
{
mmio *io = iop;
return io->connect_timeout;
}