All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.