diff options
author | Szymon Janc <szymon.janc@tieto.com> | 2014-02-22 22:09:21 +0100 |
---|---|---|
committer | Szymon Janc <szymon.janc@tieto.com> | 2014-02-24 10:49:38 +0100 |
commit | c956068c094b567dd4b80671fd54d307e4489080 (patch) | |
tree | d8ee2ba6f54ca5a98eacd9ac8a1760fe46f17027 /src | |
parent | 0e3660abb30bce9dcd6fcab572663f6fc66540ce (diff) | |
download | bluez-c956068c094b567dd4b80671fd54d307e4489080.tar.gz |
shared: Add support for disconnect handler to mainloop based IO
Diffstat (limited to 'src')
-rw-r--r-- | src/shared/io-mainloop.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/src/shared/io-mainloop.c b/src/shared/io-mainloop.c index d84d8d21c..3fe1a88db 100644 --- a/src/shared/io-mainloop.c +++ b/src/shared/io-mainloop.c @@ -42,6 +42,9 @@ struct io { io_callback_func_t write_callback; io_destroy_func_t write_destroy; void *write_data; + io_callback_func_t disconnect_callback; + io_destroy_func_t disconnect_destroy; + void *disconnect_data; }; static struct io *io_ref(struct io *io) @@ -75,6 +78,9 @@ static void io_cleanup(void *user_data) if (io->read_destroy) io->read_destroy(io->read_data); + if (io->disconnect_destroy) + io->disconnect_destroy(io->disconnect_data); + if (io->close_on_destroy) close(io->fd); @@ -122,6 +128,21 @@ static void io_callback(int fd, uint32_t events, void *user_data) mainloop_modify_fd(io->fd, io->events); } } + + if ((events & EPOLLRDHUP) && io->disconnect_callback) { + if (!io->disconnect_callback(io, io->disconnect_data)) { + if (io->disconnect_destroy) + io->disconnect_destroy(io->disconnect_data); + + io->disconnect_callback = NULL; + io->disconnect_destroy = NULL; + io->disconnect_data = NULL; + + io->events &= ~EPOLLRDHUP; + + mainloop_modify_fd(io->fd, io->events); + } + } } struct io *io_new(int fd) @@ -246,5 +267,30 @@ bool io_set_write_handler(struct io *io, io_callback_func_t callback, bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback, void *user_data, io_destroy_func_t destroy) { - return false; + uint32_t events; + + if (!io || io->fd < 0) + return false; + + if (io->disconnect_destroy) + io->disconnect_destroy(io->disconnect_data); + + if (callback) + events = io->events | EPOLLRDHUP; + else + events = io->events & ~EPOLLRDHUP; + + io->disconnect_callback = callback; + io->disconnect_destroy = destroy; + io->disconnect_data = user_data; + + if (events == io->events) + return true; + + if (mainloop_modify_fd(io->fd, events) < 0) + return false; + + io->events = events; + + return true; } |