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
|
|
|
{
|
|
|
|
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
|
2016-11-29 12:21:38 +00:00
|
|
|
mm_is_connected(mm_io_t iop)
|
2016-11-25 10:00:38 +00:00
|
|
|
{
|
|
|
|
mmio *io = iop;
|
|
|
|
return io->connected;
|
|
|
|
}
|
|
|
|
|
|
|
|
MM_API int
|
2016-11-29 12:21:38 +00:00
|
|
|
mm_connect(mm_io_t iop, char *addr, int port, 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;
|
|
|
|
|
|
|
|
struct sockaddr_in saddr;
|
|
|
|
int rc;
|
|
|
|
rc = uv_ip4_addr(addr, port, &saddr);
|
|
|
|
if (rc < 0)
|
|
|
|
return rc;
|
|
|
|
/* 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);
|
|
|
|
rc = uv_tcp_connect(&io->connect,
|
|
|
|
&io->handle,
|
|
|
|
(const struct sockaddr*)&saddr,
|
2016-12-07 14:16:38 +00:00
|
|
|
mm_connect_cb);
|
2016-11-25 10:00:38 +00:00
|
|
|
if (rc < 0) {
|
2016-11-25 15:02:23 +00:00
|
|
|
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
|
2016-11-29 12:21:38 +00:00
|
|
|
mm_connect_is_timeout(mm_io_t iop)
|
2016-11-25 10:00:38 +00:00
|
|
|
{
|
|
|
|
mmio *io = iop;
|
|
|
|
return io->connect_timeout;
|
|
|
|
}
|