From 8df53c86a2c8730f36a160271bb21d3cfb6107e8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 8 Jan 2014 20:46:46 -0800 Subject: [PATCH] shared: Add support for GLib based IO handling --- src/shared/io-glib.c | 180 +++++++++++++++++++++++++++++++++++++++++++ src/shared/io.h | 22 ++++++ 2 files changed, 202 insertions(+) diff --git a/src/shared/io-glib.c b/src/shared/io-glib.c index 8a7fb9a6c..a7ac95f56 100644 --- a/src/shared/io-glib.c +++ b/src/shared/io-glib.c @@ -25,4 +25,184 @@ #include #endif +#include + #include "src/shared/io.h" + +struct io { + GIOChannel *channel; + guint read_watch; + io_callback_func_t read_callback; + io_destroy_func_t read_destroy; + void *read_data; + guint write_watch; + io_callback_func_t write_callback; + io_destroy_func_t write_destroy; + void *write_data; +}; + +struct io *io_new(int fd) +{ + struct io *io; + + if (fd < 0) + return NULL; + + io = g_try_new0(struct io, 1); + if (!io) + return NULL; + + io->channel = g_io_channel_unix_new(fd); + + g_io_channel_set_encoding(io->channel, NULL, NULL); + g_io_channel_set_buffered(io->channel, FALSE); + + g_io_channel_set_close_on_unref(io->channel, FALSE); + + io->read_watch = 0; + io->read_callback = NULL; + io->read_destroy = NULL; + io->read_data = NULL; + + io->write_watch = 0; + io->write_callback = NULL; + io->write_destroy = NULL; + io->write_data = NULL; + + return io; +} + +void io_destroy(struct io *io) +{ + if (!io) + return; + + g_io_channel_unref(io->channel); + + g_free(io); +} + +int io_get_fd(struct io *io) +{ + if (!io) + return -1; + + return g_io_channel_unix_get_fd(io->channel); +} + +bool io_set_close_on_destroy(struct io *io, bool do_close) +{ + if (!io) + return false; + + if (do_close) + g_io_channel_set_close_on_unref(io->channel, TRUE); + else + g_io_channel_set_close_on_unref(io->channel, FALSE); + + return true; +} + +static void read_watch_destroy(gpointer user_data) +{ + struct io *io = user_data; + + if (io->read_destroy) + io->read_destroy(io->read_data); + + io->read_watch = 0; + io->read_callback = NULL; + io->read_destroy = NULL; + io->read_data = NULL; +} + +static gboolean read_callback(GIOChannel *channel, GIOCondition cond, + gpointer user_data) +{ + struct io *io = user_data; + + if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) + return FALSE; + + if (io->read_callback) + io->read_callback(io, io->read_data); + + return TRUE; +} + +bool io_set_read_handler(struct io *io, io_callback_func_t callback, + void *user_data, io_destroy_func_t destroy) +{ + if (!io) + return false; + + if (io->read_watch > 0) + g_source_remove(io->read_watch); + + io->read_watch = g_io_add_watch_full(io->channel, G_PRIORITY_DEFAULT, + G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + read_callback, io, read_watch_destroy); + if (io->read_watch == 0) + return false; + + io->read_callback = callback; + io->read_destroy = destroy; + io->read_data = user_data; + + return true; +} + +static void write_watch_destroy(gpointer user_data) +{ + struct io *io = user_data; + + if (io->write_destroy) + io->write_destroy(io->write_data); + + io->write_watch = 0; + io->write_callback = NULL; + io->write_destroy = NULL; + io->write_data = NULL; +} + +static gboolean write_callback(GIOChannel *channel, GIOCondition cond, + gpointer user_data) +{ + struct io *io = user_data; + + if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) + return FALSE; + + if (io->write_callback) + io->write_callback(io, io->write_data); + + return TRUE; +} + +bool io_set_write_handler(struct io *io, io_callback_func_t callback, + void *user_data, io_destroy_func_t destroy) +{ + if (!io) + return false; + + if (io->write_watch > 0) + g_source_remove(io->write_watch); + + io->write_watch = g_io_add_watch_full(io->channel, G_PRIORITY_DEFAULT, + G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + write_callback, io, write_watch_destroy); + if (io->write_watch == 0) + return false; + + io->write_callback = callback; + io->write_destroy = destroy; + io->write_data = user_data; + + return true; +} + +bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback, + void *user_data, io_destroy_func_t destroy) +{ + return false; +} diff --git a/src/shared/io.h b/src/shared/io.h index 29ead9c18..c48a7abd9 100644 --- a/src/shared/io.h +++ b/src/shared/io.h @@ -21,3 +21,25 @@ * */ +#include + +typedef void (*io_destroy_func_t)(void *data); + +struct io; + +typedef void (*io_callback_func_t) (struct io *io, void *user_data); + +struct io *io_new(int fd); +void io_destroy(struct io *io); + +int io_get_fd(struct io *io); +bool io_set_close_on_destroy(struct io *io, bool do_close); + +typedef void (*io_callback_func_t)(struct io *io, void *user_data); + +bool io_set_read_handler(struct io *io, io_callback_func_t callback, + void *user_data, io_destroy_func_t destroy); +bool io_set_write_handler(struct io *io, io_callback_func_t callback, + void *user_data, io_destroy_func_t destroy); +bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback, + void *user_data, io_destroy_func_t destroy); -- 2.47.3