* [PATCH BlueZ] shared/io-libevent2: Add support for libevent2 based IO handing
@ 2019-02-06 15:30 Shawn Nock
2019-02-06 15:45 ` Marcel Holtmann
0 siblings, 1 reply; 3+ messages in thread
From: Shawn Nock @ 2019-02-06 15:30 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Shawn Nock
---
src/shared/io-libevent2.c | 247 ++++++++++++++++++++++++++++++++++++++
src/shared/io.h | 1 +
2 files changed, 248 insertions(+)
create mode 100644 src/shared/io-libevent2.c
diff --git a/src/shared/io-libevent2.c b/src/shared/io-libevent2.c
new file mode 100644
index 000000000..584e1a021
--- /dev/null
+++ b/src/shared/io-libevent2.c
@@ -0,0 +1,247 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2019 Shawn Nock <shawn@monadnock.ca>
+ * Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+
+#include <event2/event.h>
+
+#include "src/shared/io.h"
+#include "src/shared/util.h"
+
+struct io {
+ struct event *event;
+ io_callback_func_t read_callback;
+ io_destroy_func_t read_destroy;
+ void *read_data;
+ 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 event_base *g_event_base = NULL;
+
+void io_set_context(void *v) {
+ g_event_base = v;
+}
+
+void io_callback(int fd, short which, void* arg)
+{
+ struct io *io = arg;
+ if (which & EV_READ && io->read_callback) {
+ io->read_callback(io, io->read_data);
+ }
+
+ if (which & EV_WRITE && io->write_callback){
+ io->write_callback(io, io->write_data);
+ }
+
+ if (which & EV_CLOSED && io->disconnect_callback) {
+ io->disconnect_callback(io, io->disconnect_data);
+ }
+}
+
+struct io *io_new(int fd)
+{
+ if (fd < 0) {
+ return NULL;
+ }
+
+ struct io *io = new0(struct io, 1);
+
+ io->event = event_new(g_event_base, fd, EV_READ | EV_WRITE | EV_PERSIST, io_callback, io);
+ if (!io->event) {
+ free(io);
+ return NULL;
+ }
+ event_add(io->event, NULL);
+ return io;
+}
+
+void io_destroy(struct io *io)
+{
+ if (!io)
+ return;
+
+ if (io->event)
+ event_del(io->event);
+ event_free(io->event);
+
+ free(io);
+}
+
+int io_get_fd(struct io *io)
+{
+ if (!io || !io->event)
+ return -ENOTCONN;
+
+ return event_get_fd(io->event);
+}
+
+bool io_set_close_on_destroy(struct io *io, bool do_close)
+{
+ if (!io || !io->event)
+ return false;
+
+ return true;
+}
+
+static short io_get_events(struct io* io)
+{
+ short which;
+ event_get_assignment(io->event, NULL, NULL, &which, NULL, NULL);
+ return which;
+}
+
+static void io_set_events(struct io* io, short events)
+{
+ struct event_base *base;
+ int fd;
+ event_callback_fn cb;
+ void *arg;
+
+ event_get_assignment(io->event, &base, &fd, NULL, &cb, &arg);
+ int pending = event_pending(io->event, EV_READ | EV_WRITE | EV_CLOSED, NULL);
+
+ if (pending) {
+ event_del(io->event);
+ }
+ event_assign(io->event, base, fd, events, cb, arg);
+ event_add(io->event, NULL);
+}
+
+static void io_update_events(struct io* io, short events, bool enable)
+{
+ short new_ev;
+ short cur = io_get_events(io);
+ if (enable) {
+ new_ev = cur | events;
+ } else {
+ new_ev = cur & ~events;
+ }
+ if (events != new_ev) {
+ io_set_events(io, new_ev);
+ }
+}
+
+bool io_set_read_handler(struct io *io, io_callback_func_t callback,
+ void *user_data, io_destroy_func_t destroy)
+{
+ if (!io || !io->event)
+ return false;
+
+ if (io->read_destroy) {
+ io->read_destroy(io->read_data);
+ }
+
+ io->read_callback = callback;
+ io->read_destroy = destroy;
+ io->read_data = user_data;
+
+ io_update_events(io, EV_READ, (bool)callback);
+
+ 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 || !io->event)
+ return false;
+
+ if (io->write_destroy) {
+ io->write_destroy(io->write_data);
+ }
+
+ io->write_callback = callback;
+ io->write_destroy = destroy;
+ io->write_data = user_data;
+
+ io_update_events(io, EV_WRITE, (bool)callback);
+
+ return true;
+}
+
+bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback,
+ void *user_data, io_destroy_func_t destroy)
+{
+ if (!io || !io->event)
+ return false;
+
+ if (io->disconnect_destroy) {
+ io->disconnect_destroy(io->disconnect_data);
+ }
+
+ io->disconnect_callback = callback;
+ io->disconnect_destroy = destroy;
+ io->disconnect_data = user_data;
+
+ io_update_events(io, EV_CLOSED, (bool)callback);
+
+ return true;
+}
+
+ssize_t io_send(struct io *io, const struct iovec *iov, int iovcnt)
+{
+ ssize_t ret;
+ int fd;
+
+ if (!io || !io->event)
+ return -ENOTCONN;
+
+ fd = io_get_fd(io);
+ if (fd < 0)
+ return -ENOTCONN;
+
+ do {
+ ret = writev(fd, iov, iovcnt);
+ } while (ret < 0 && errno == EINTR);
+
+ if (ret < 0)
+ return -errno;
+
+ return ret;
+}
+
+bool io_shutdown(struct io *io)
+{
+ int fd;
+
+ if (!io || !io->event)
+ return false;
+
+ fd = io_get_fd(io);
+ if (fd < 0)
+ return false;
+
+ return shutdown(fd, SHUT_RDWR) == 0;
+}
diff --git a/src/shared/io.h b/src/shared/io.h
index 8bc1111d0..9a8d54062 100644
--- a/src/shared/io.h
+++ b/src/shared/io.h
@@ -45,3 +45,4 @@ 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);
+void io_set_context(void *);
\ No newline at end of file
--
2.20.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2019-02-06 16:01 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-06 15:30 [PATCH BlueZ] shared/io-libevent2: Add support for libevent2 based IO handing Shawn Nock
2019-02-06 15:45 ` Marcel Holtmann
2019-02-06 16:00 ` Shawn Nock
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).