2017-03-21 12:41:01 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* machinarium.
|
|
|
|
*
|
|
|
|
* cooperative multitasking engine.
|
2020-04-02 11:00:56 +00:00
|
|
|
*/
|
2017-03-21 12:41:01 +00:00
|
|
|
|
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:41:01 +00:00
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
static void mm_read_cb(mm_fd_t *handle)
|
2018-11-29 15:04:13 +00:00
|
|
|
{
|
2019-01-23 15:43:52 +00:00
|
|
|
mm_io_t *io = handle->on_read_arg;
|
|
|
|
if (io->on_read)
|
2020-04-02 11:00:56 +00:00
|
|
|
mm_cond_signal((mm_cond_t *)io->on_read, &mm_self->scheduler);
|
2018-11-29 15:04:13 +00:00
|
|
|
}
|
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
static inline int mm_read_start(mm_io_t *io, machine_cond_t *on_read)
|
2018-11-29 15:04:13 +00:00
|
|
|
{
|
|
|
|
mm_machine_t *machine = mm_self;
|
2020-12-28 10:43:31 +00:00
|
|
|
io->on_read = on_read;
|
2019-01-24 15:25:46 +00:00
|
|
|
/*
|
|
|
|
Check situation when there are buffered TLS data, since this
|
|
|
|
will not generate any poller event we must
|
|
|
|
check it right away.
|
|
|
|
*/
|
|
|
|
if (mm_tls_is_active(io) && mm_tls_read_pending(io))
|
2020-04-02 11:00:56 +00:00
|
|
|
mm_cond_signal((mm_cond_t *)io->on_read, &mm_self->scheduler);
|
2019-01-24 15:25:46 +00:00
|
|
|
|
2020-11-23 08:22:17 +00:00
|
|
|
/* Also check for buffered compressed data, since this also won't
|
|
|
|
* generate any poller event. */
|
|
|
|
if (mm_compression_is_active(io) && mm_compression_read_pending(io)) {
|
|
|
|
mm_cond_signal((mm_cond_t *)io->on_read, &mm_self->scheduler);
|
|
|
|
}
|
|
|
|
|
2018-11-29 15:04:13 +00:00
|
|
|
int rc;
|
2019-01-23 15:43:52 +00:00
|
|
|
rc = mm_loop_read(&machine->loop, &io->handle, mm_read_cb, io);
|
2018-11-29 15:04:13 +00:00
|
|
|
if (rc == -1) {
|
2019-01-23 15:43:52 +00:00
|
|
|
io->on_read = NULL;
|
2018-11-29 15:04:13 +00:00
|
|
|
mm_errno_set(errno);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
static inline int mm_read_stop(mm_io_t *io)
|
2017-04-18 12:02:28 +00:00
|
|
|
{
|
2019-01-23 15:43:52 +00:00
|
|
|
mm_machine_t *machine = mm_self;
|
2020-12-28 10:43:31 +00:00
|
|
|
io->on_read = NULL;
|
2017-04-18 12:02:28 +00:00
|
|
|
int rc;
|
2019-01-23 15:43:52 +00:00
|
|
|
rc = mm_loop_read_stop(&machine->loop, &io->handle);
|
|
|
|
return rc;
|
2017-04-18 12:02:28 +00:00
|
|
|
}
|
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
MACHINE_API int machine_read_start(machine_io_t *obj, machine_cond_t *on_read)
|
2017-04-18 12:02:28 +00:00
|
|
|
{
|
2020-04-02 11:00:56 +00:00
|
|
|
mm_io_t *io = mm_cast(mm_io_t *, obj);
|
2019-01-23 15:43:52 +00:00
|
|
|
mm_errno_set(0);
|
|
|
|
if (mm_call_is_active(&io->call)) {
|
|
|
|
mm_errno_set(EINPROGRESS);
|
2017-04-18 12:02:28 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2020-04-02 11:00:56 +00:00
|
|
|
if (!io->attached) {
|
2019-01-23 15:43:52 +00:00
|
|
|
mm_errno_set(ENOTCONN);
|
2017-04-18 12:02:28 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-01-23 15:43:52 +00:00
|
|
|
return mm_read_start(io, on_read);
|
|
|
|
}
|
2017-04-18 12:02:28 +00:00
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
MACHINE_API int machine_read_stop(machine_io_t *obj)
|
2019-01-23 15:43:52 +00:00
|
|
|
{
|
2020-04-02 11:00:56 +00:00
|
|
|
mm_io_t *io = mm_cast(mm_io_t *, obj);
|
2019-01-23 15:43:52 +00:00
|
|
|
mm_errno_set(0);
|
|
|
|
if (mm_call_is_active(&io->call)) {
|
|
|
|
mm_errno_set(EINPROGRESS);
|
2017-04-20 11:56:47 +00:00
|
|
|
return -1;
|
2017-03-21 12:41:01 +00:00
|
|
|
}
|
2020-04-02 11:00:56 +00:00
|
|
|
if (!io->attached) {
|
2019-01-23 15:43:52 +00:00
|
|
|
mm_errno_set(ENOTCONN);
|
2017-04-20 11:56:47 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-01-23 15:43:52 +00:00
|
|
|
return mm_read_stop(io);
|
2017-03-21 12:41:01 +00:00
|
|
|
}
|
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
MACHINE_API ssize_t machine_read_raw(machine_io_t *obj, void *buf, size_t size)
|
2018-11-29 15:04:13 +00:00
|
|
|
{
|
2020-04-02 11:00:56 +00:00
|
|
|
mm_io_t *io = mm_cast(mm_io_t *, obj);
|
2020-11-23 13:57:56 +00:00
|
|
|
#ifdef MM_BUILD_COMPRESSION
|
2020-11-23 08:22:17 +00:00
|
|
|
/* If streaming compression is enabled then use correspondent compression
|
|
|
|
* read function. */
|
|
|
|
if (mm_compression_is_active(io)) {
|
|
|
|
return mm_zpq_read(io->zpq_stream, buf, size);
|
2018-11-29 15:04:13 +00:00
|
|
|
}
|
2020-11-23 11:55:42 +00:00
|
|
|
#endif
|
2020-11-23 08:22:17 +00:00
|
|
|
return mm_io_read(io, buf, size);
|
2018-11-29 15:04:13 +00:00
|
|
|
}
|
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
static inline int machine_read_to(machine_io_t *obj, machine_msg_t *msg,
|
|
|
|
size_t size, uint32_t time_ms)
|
2018-11-29 15:04:13 +00:00
|
|
|
{
|
2020-04-02 11:00:56 +00:00
|
|
|
mm_io_t *io = mm_cast(mm_io_t *, obj);
|
2019-01-23 15:43:52 +00:00
|
|
|
mm_errno_set(0);
|
2018-11-29 15:04:13 +00:00
|
|
|
|
2020-04-02 11:00:56 +00:00
|
|
|
if (!io->attached) {
|
2019-01-23 15:43:52 +00:00
|
|
|
mm_errno_set(ENOTCONN);
|
2018-11-29 15:04:13 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2020-04-02 11:00:56 +00:00
|
|
|
if (!io->connected) {
|
2019-01-23 15:43:52 +00:00
|
|
|
mm_errno_set(ENOTCONN);
|
2018-11-29 15:04:13 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-01-23 15:43:52 +00:00
|
|
|
if (io->on_read) {
|
|
|
|
mm_errno_set(EINPROGRESS);
|
2018-11-29 15:04:13 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-01-23 15:43:52 +00:00
|
|
|
mm_cond_t on_read;
|
|
|
|
mm_cond_init(&on_read);
|
|
|
|
int rc;
|
2020-04-02 11:00:56 +00:00
|
|
|
rc = mm_read_start(io, (machine_cond_t *)&on_read);
|
2018-11-29 15:04:13 +00:00
|
|
|
if (rc == -1)
|
|
|
|
return -1;
|
|
|
|
|
2019-01-23 15:43:52 +00:00
|
|
|
int offset = machine_msg_size(msg);
|
2020-12-28 10:43:31 +00:00
|
|
|
rc = machine_msg_write(msg, NULL, size);
|
2019-01-23 15:43:52 +00:00
|
|
|
if (rc == -1) {
|
|
|
|
mm_read_stop(io);
|
2017-05-26 10:48:52 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2017-04-18 12:02:28 +00:00
|
|
|
|
2021-03-05 05:45:22 +00:00
|
|
|
char *dest = (char *)machine_msg_data(msg) + offset;
|
2019-01-23 15:43:52 +00:00
|
|
|
size_t total = 0;
|
2020-04-02 11:00:56 +00:00
|
|
|
while (total != size) {
|
|
|
|
rc = machine_cond_wait((machine_cond_t *)&on_read, time_ms);
|
2019-01-23 15:43:52 +00:00
|
|
|
if (rc == -1) {
|
|
|
|
mm_read_stop(io);
|
2017-09-06 13:38:05 +00:00
|
|
|
return -1;
|
2019-01-23 15:43:52 +00:00
|
|
|
}
|
|
|
|
rc = machine_read_raw(obj, dest + total, size - total);
|
|
|
|
if (rc > 0) {
|
|
|
|
total += rc;
|
|
|
|
continue;
|
|
|
|
}
|
2018-08-23 13:32:57 +00:00
|
|
|
|
2019-01-23 15:43:52 +00:00
|
|
|
/* error or eof */
|
|
|
|
if (rc == -1) {
|
|
|
|
int errno_ = machine_errno();
|
2020-12-28 10:43:31 +00:00
|
|
|
if (errno_ == EAGAIN || errno_ == EWOULDBLOCK ||
|
|
|
|
errno_ == EINTR)
|
2019-01-23 15:43:52 +00:00
|
|
|
continue;
|
|
|
|
}
|
2017-11-29 11:41:07 +00:00
|
|
|
|
2019-01-23 15:43:52 +00:00
|
|
|
mm_read_stop(io);
|
2017-04-18 12:02:28 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-01-23 15:43:52 +00:00
|
|
|
|
|
|
|
mm_read_stop(io);
|
2017-04-18 12:02:28 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2018-01-17 14:26:14 +00:00
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
MACHINE_API machine_msg_t *machine_read(machine_io_t *obj, size_t size,
|
|
|
|
uint32_t time_ms)
|
2018-01-17 14:26:14 +00:00
|
|
|
{
|
|
|
|
mm_errno_set(0);
|
2019-01-23 15:43:52 +00:00
|
|
|
machine_msg_t *msg = machine_msg_create(0);
|
|
|
|
if (msg == NULL)
|
|
|
|
return NULL;
|
|
|
|
int rc = machine_read_to(obj, msg, size, time_ms);
|
|
|
|
if (rc == -1) {
|
|
|
|
machine_msg_free(msg);
|
|
|
|
return NULL;
|
2018-11-29 15:04:13 +00:00
|
|
|
}
|
2019-01-23 15:43:52 +00:00
|
|
|
return msg;
|
2018-01-17 14:26:14 +00:00
|
|
|
}
|
2019-06-13 08:55:01 +00:00
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
MACHINE_API int machine_read_active(machine_io_t *obj)
|
2019-06-13 08:55:01 +00:00
|
|
|
{
|
2020-04-02 11:00:56 +00:00
|
|
|
mm_io_t *io = mm_cast(mm_io_t *, obj);
|
2019-06-13 08:55:01 +00:00
|
|
|
return io->on_read != NULL;
|
|
|
|
}
|