odyssey/sources/connect.c

115 lines
2.0 KiB
C
Raw Normal View History

2017-03-21 12:15:05 +00:00
/*
* machinarium.
*
* cooperative multitasking engine.
*/
#include <machinarium.h>
#include <machinarium_private.h>
2017-03-21 12:15:05 +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;
mm_call_t *call = &io->call;
if (mm_call_is_aborted(call))
return;
call->status = mm_socket_error(handle->fd);
mm_scheduler_wakeup(&mm_self->scheduler, call->coroutine);
}
static int
mm_connect(mm_io_t *io, struct sockaddr *sa, uint32_t time_ms)
2017-03-21 12:15:05 +00:00
{
mm_machine_t *machine = mm_self;
2017-05-30 14:00:16 +00:00
mm_errno_set(0);
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
}
if (io->connected) {
2017-05-30 14:00:16 +00:00
mm_errno_set(EINPROGRESS);
return -1;
}
2017-03-21 12:15:05 +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);
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);
goto error;
}
2017-04-12 12:19:30 +00:00
/* add socket to event loop */
rc = machine_io_attach((machine_io_t*)io);
if (rc == -1)
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,
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
}
/* wait for completion */
mm_call(&io->call, MM_CALL_CONNECT, time_ms);
rc = mm_loop_write_stop(&machine->loop, &io->handle);
if (rc == -1) {
2017-05-30 14:00:16 +00:00
mm_errno_set(errno);
goto error;
}
2017-03-21 12:15:05 +00:00
rc = io->call.status;
if (rc != 0) {
mm_loop_delete(&machine->loop, &io->handle);
mm_errno_set(rc);
goto error;
2017-03-21 12:15:05 +00:00
}
2017-03-29 11:58:27 +00:00
done:
2017-06-05 12:35:27 +00:00
assert(! io->call.timedout);
io->connected = 1;
return 0;
error:
if (io->fd != -1) {
close(io->fd);
io->fd = -1;
}
io->handle.fd = -1;
io->attached = 0;
2017-03-29 11:58:27 +00:00
return -1;
2017-03-21 12:15:05 +00:00
}
MACHINE_API int
machine_connect(machine_io_t *obj, struct sockaddr *sa, uint32_t time_ms)
{
mm_io_t *io = mm_cast(mm_io_t*, obj);
int rc = mm_connect(io, sa, time_ms);
if (rc == -1)
return -1;
return 0;
}
2017-03-21 12:15:05 +00:00
MACHINE_API int
machine_connected(machine_io_t *obj)
2017-03-21 12:15:05 +00:00
{
mm_io_t *io = mm_cast(mm_io_t*, obj);
2017-03-21 12:15:05 +00:00
return io->connected;
}