linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Shawn Nock <shawn@monadnock.ca>
To: linux-bluetooth@vger.kernel.org
Cc: Shawn Nock <shawn@monadnock.ca>
Subject: [PATCH BlueZ] shared/io-libevent2: Add support for libevent2 based IO handing
Date: Wed,  6 Feb 2019 10:30:45 -0500	[thread overview]
Message-ID: <20190206153045.14788-1-shawn@monadnock.ca> (raw)

---
 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

             reply	other threads:[~2019-02-06 15:36 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-06 15:30 Shawn Nock [this message]
2019-02-06 15:45 ` [PATCH BlueZ] shared/io-libevent2: Add support for libevent2 based IO handing Marcel Holtmann
2019-02-06 16:00   ` Shawn Nock

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190206153045.14788-1-shawn@monadnock.ca \
    --to=shawn@monadnock.ca \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).