2017-03-21 12:15:05 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* machinarium.
|
|
|
|
*
|
|
|
|
* cooperative multitasking engine.
|
|
|
|
*/
|
|
|
|
|
2017-03-21 12:55:23 +00:00
|
|
|
#include <machinarium.h>
|
2017-05-17 14:20:04 +00:00
|
|
|
#include <machinarium_private.h>
|
2017-03-21 12:15:05 +00:00
|
|
|
|
2017-04-19 13:38:00 +00:00
|
|
|
static void
|
2017-04-12 12:19:30 +00:00
|
|
|
mm_connect_on_write_cb(mm_fd_t *handle)
|
2017-03-21 12:15:05 +00:00
|
|
|
{
|
2017-04-12 12:19:30 +00:00
|
|
|
mm_io_t *io = handle->on_write_arg;
|
2017-06-05 12:32:29 +00:00
|
|
|
mm_call_t *call = &io->call;
|
2017-04-20 11:56:47 +00:00
|
|
|
if (mm_call_is_aborted(call))
|
|
|
|
return;
|
|
|
|
call->status = mm_socket_error(handle->fd);
|
2017-05-24 10:11:03 +00:00
|
|
|
mm_scheduler_wakeup(&mm_self->scheduler, call->coroutine);
|
2017-04-11 13:50:11 +00:00
|
|
|
}
|
|
|
|
|
2017-03-28 10:31:14 +00:00
|
|
|
static int
|
2017-05-24 13:01:55 +00:00
|
|
|
mm_connect(mm_io_t *io, struct sockaddr *sa, uint32_t time_ms)
|
2017-03-21 12:15:05 +00:00
|
|
|
{
|
2017-05-18 10:31:25 +00:00
|
|
|
mm_machine_t *machine = mm_self;
|
2017-05-30 14:00:16 +00:00
|
|
|
mm_errno_set(0);
|
2017-04-11 13:50:11 +00:00
|
|
|
|
2017-06-05 12:32:29 +00:00
|
|
|
if (mm_call_is_active(&io->call)) {
|
2017-05-30 14:00:16 +00:00
|
|
|
mm_errno_set(EINPROGRESS);
|
2017-03-21 12:15:05 +00:00
|
|
|
return -1;
|
2017-03-29 11:58:27 +00:00
|
|
|
}
|
2017-04-11 13:50:11 +00:00
|
|
|
if (io->connected) {
|
2017-05-30 14:00:16 +00:00
|
|
|
mm_errno_set(EINPROGRESS);
|
2017-04-11 13:50:11 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2017-03-21 12:15:05 +00:00
|
|
|
|
2017-04-11 13:50:11 +00:00
|
|
|
/* create socket */
|
2017-03-21 12:15:05 +00:00
|
|
|
int rc;
|
2017-04-11 14:39:20 +00:00
|
|
|
rc = mm_io_socket(io, sa);
|
2017-04-11 13:50:11 +00:00
|
|
|
if (rc == -1)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* start connection */
|
|
|
|
rc = mm_socket_connect(io->fd, sa);
|
|
|
|
if (rc == 0)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
assert(rc == -1);
|
|
|
|
if (errno != EINPROGRESS) {
|
2017-05-30 14:00:16 +00:00
|
|
|
mm_errno_set(errno);
|
2017-04-11 13:50:11 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2017-04-12 12:19:30 +00:00
|
|
|
/* add socket to event loop */
|
2017-06-13 11:49:50 +00:00
|
|
|
rc = machine_io_attach((machine_io_t*)io);
|
2017-05-26 10:48:52 +00:00
|
|
|
if (rc == -1)
|
2017-04-11 13:50:11 +00:00
|
|
|
goto error;
|
|
|
|
|
2017-04-12 12:19:30 +00:00
|
|
|
/* subscribe for connection event */
|
|
|
|
rc = mm_loop_write(&machine->loop, &io->handle,
|
|
|
|
mm_connect_on_write_cb,
|
2017-05-30 12:34:00 +00:00
|
|
|
io);
|
2017-04-12 12:19:30 +00:00
|
|
|
if (rc == -1) {
|
2017-05-30 14:00:16 +00:00
|
|
|
mm_errno_set(errno);
|
2017-04-12 12:19:30 +00:00
|
|
|
goto error;
|
2017-03-21 12:15:05 +00:00
|
|
|
}
|
|
|
|
|
2017-04-20 11:56:47 +00:00
|
|
|
/* wait for completion */
|
2017-06-05 12:32:29 +00:00
|
|
|
mm_call(&io->call, MM_CALL_CONNECT, time_ms);
|
2017-04-11 13:50:11 +00:00
|
|
|
|
2017-05-30 12:34:00 +00:00
|
|
|
rc = mm_loop_write_stop(&machine->loop, &io->handle);
|
2017-04-11 13:50:11 +00:00
|
|
|
if (rc == -1) {
|
2017-05-30 14:00:16 +00:00
|
|
|
mm_errno_set(errno);
|
2017-04-11 13:50:11 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2017-03-21 12:15:05 +00:00
|
|
|
|
2017-06-05 12:32:29 +00:00
|
|
|
rc = io->call.status;
|
2017-04-11 13:50:11 +00:00
|
|
|
if (rc != 0) {
|
2017-04-12 12:33:34 +00:00
|
|
|
mm_loop_delete(&machine->loop, &io->handle);
|
2017-05-30 14:22:44 +00:00
|
|
|
mm_errno_set(rc);
|
2017-04-11 13:50:11 +00:00
|
|
|
goto error;
|
2017-03-21 12:15:05 +00:00
|
|
|
}
|
2017-03-29 11:58:27 +00:00
|
|
|
|
2017-04-11 13:50:11 +00:00
|
|
|
done:
|
2017-06-05 12:35:27 +00:00
|
|
|
assert(! io->call.timedout);
|
2017-04-11 13:50:11 +00:00
|
|
|
io->connected = 1;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (io->fd != -1) {
|
|
|
|
close(io->fd);
|
|
|
|
io->fd = -1;
|
|
|
|
}
|
|
|
|
io->handle.fd = -1;
|
2017-05-26 10:48:52 +00:00
|
|
|
io->attached = 0;
|
2017-03-29 11:58:27 +00:00
|
|
|
return -1;
|
2017-03-21 12:15:05 +00:00
|
|
|
}
|
|
|
|
|
2017-03-28 10:31:14 +00:00
|
|
|
MACHINE_API int
|
2017-06-13 11:49:50 +00:00
|
|
|
machine_connect(machine_io_t *obj, struct sockaddr *sa, uint32_t time_ms)
|
2017-03-28 10:31:14 +00:00
|
|
|
{
|
2017-06-13 11:49:50 +00:00
|
|
|
mm_io_t *io = mm_cast(mm_io_t*, obj);
|
2017-03-28 11:51:57 +00:00
|
|
|
int rc = mm_connect(io, sa, time_ms);
|
|
|
|
if (rc == -1)
|
|
|
|
return -1;
|
|
|
|
return 0;
|
2017-03-28 10:31:14 +00:00
|
|
|
}
|
|
|
|
|
2017-03-21 12:15:05 +00:00
|
|
|
MACHINE_API int
|
2017-06-13 11:49:50 +00:00
|
|
|
machine_connected(machine_io_t *obj)
|
2017-03-21 12:15:05 +00:00
|
|
|
{
|
2017-06-13 11:49:50 +00:00
|
|
|
mm_io_t *io = mm_cast(mm_io_t*, obj);
|
2017-03-21 12:15:05 +00:00
|
|
|
return io->connected;
|
|
|
|
}
|