/* * machinarium. * * cooperative multitasking engine. */ #include #include #if 0 MACHINE_API int machine_getsockname(machine_io_t obj, struct sockaddr *sa, int *salen) { mm_io_t *io = obj; mm_io_set_errno(io, 0); int rc = uv_tcp_getsockname(&io->handle, sa, salen); if (rc < 0) { mm_io_set_errno_uv(io, rc); return -1; } return 0; } MACHINE_API int machine_getpeername(machine_io_t obj, struct sockaddr *sa, int *salen) { mm_io_t *io = obj; mm_io_set_errno(io, 0); int rc = uv_tcp_getpeername(&io->handle, sa, salen); if (rc < 0) { mm_io_set_errno_uv(io, rc); return -1; } return 0; } static void mm_getaddrinfo_timeout_cb(uv_timer_t *handle) { (void)handle; mm_io_t *io = handle->data; io->gai_timedout = 1; /* cancel request, * callback will be called anyway */ uv_cancel((uv_req_t*)&io->gai); } static void mm_getaddrinfo_cancel_cb(void *obj, void *arg) { (void)obj; mm_io_t *io = arg; io->gai_timedout = 0; mm_io_timer_stop(&io->gai_timer); uv_cancel((uv_req_t*)&io->gai); } static void mm_getaddrinfo_cb(uv_getaddrinfo_t *handle, int status, struct addrinfo *res) { mm_io_t *io = handle->data; if (mm_fiber_is_cancelled(io->gai_fiber)) goto wakeup; if (io->gai_timedout) goto wakeup; mm_io_timer_stop(&io->gai_timer); wakeup: mm_io_req_unref(io); io->gai_status = status; io->gai_result = res; mm_scheduler_wakeup(io->gai_fiber); } MACHINE_API int machine_getaddrinfo(machine_io_t obj, char *addr, char *service, struct addrinfo *hints, struct addrinfo **res, uint64_t time_ms) { mm_io_t *io = obj; mm_fiber_t *current = mm_scheduler_current(&io->machine->scheduler); mm_io_set_errno(io, 0); if (mm_fiber_is_cancelled(current)) { mm_io_set_errno(io, ECANCELED); return -1; } if (io->gai_fiber) { mm_io_set_errno(io, EINPROGRESS); return -1; } io->gai_status = 0; io->gai_timedout = 0; io->gai_result = NULL; io->gai_fiber = current; mm_io_timer_start(&io->gai_timer, mm_getaddrinfo_timeout_cb, time_ms); int rc; rc = uv_getaddrinfo(&io->machine->loop, &io->gai, mm_getaddrinfo_cb, addr, service, hints); if (rc < 0) { mm_io_timer_stop(&io->gai_timer); io->gai_fiber = NULL; mm_io_set_errno_uv(io, rc); return -1; } mm_io_req_ref(io); mm_call_begin(¤t->call, mm_getaddrinfo_cancel_cb, io); mm_scheduler_yield(&io->machine->scheduler); mm_call_end(¤t->call); rc = io->gai_status; io->gai_fiber = NULL; *res = io->gai_result; io->gai_result = NULL; if (rc < 0) { mm_io_set_errno_uv(io, rc); return -1; } return 0; } #endif MACHINE_API int machine_getaddrinfo(machine_io_t obj, char *addr, char *service, struct addrinfo *hints, struct addrinfo **res, uint64_t time_ms) { mm_io_t *io = obj; mm_io_set_errno(io, 0); int rc = mm_socket_getaddrinfo(addr, service, hints, res); if (rc < 0) { mm_io_set_errno(io, errno); return -1; } (void)time_ms; return 0; } MACHINE_API int machine_getsockname(machine_io_t obj, struct sockaddr *sa, int *salen) { mm_io_t *io = obj; mm_io_set_errno(io, 0); socklen_t slen = *salen; int rc = mm_socket_getsockname(io->fd, sa, &slen); if (rc < 0) { mm_io_set_errno(io, errno); return -1; } *salen = slen; return 0; } MACHINE_API int machine_getpeername(machine_io_t obj, struct sockaddr *sa, int *salen) { mm_io_t *io = obj; mm_io_set_errno(io, 0); socklen_t slen = *salen; int rc = mm_socket_getpeername(io->fd, sa, &slen); if (rc < 0) { mm_io_set_errno(io, errno); return -1; } *salen = slen; return 0; }