Add fd input (such as socket) event to shill_event
It's understood that the main event loop is changing, but
here's a first cut at describing the sort of things we will
need in that respect. I'm using this facility for my RTNL
prototype.
BUG=n0ne (this will likely be overwritten)
TEST=Unit tests added to unittest.cc and pass
Change-Id: I4ee89fc4119da0871e9f852707cce9341a5018c0
Reviewed-on: http://gerrit.chromium.org/gerrit/605
Reviewed-by: Chris Masone <cmasone@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/shill_event.cc b/shill_event.cc
index 6b1356a..b78680c 100644
--- a/shill_event.cc
+++ b/shill_event.cc
@@ -50,4 +50,60 @@
}
}
+static gboolean DispatchIOHandler(GIOChannel *chan, GIOCondition cond,
+ gpointer data);
+
+class GlibIOInputHandler : public IOInputHandler {
+public:
+ GIOChannel *channel_;
+ Callback<InputData *> *callback_;
+ guint source_id_;
+ EventDispatcher *dispatcher_;
+
+ GlibIOInputHandler(EventDispatcher *dispatcher, int fd,
+ Callback<InputData *> *callback) :
+ dispatcher_(dispatcher), callback_(callback) {
+ channel_ = g_io_channel_unix_new(fd);
+ g_io_channel_set_close_on_unref(channel_, TRUE);
+ source_id_ = g_io_add_watch(channel_,
+ (GIOCondition)(G_IO_IN | G_IO_NVAL |
+ G_IO_HUP | G_IO_ERR),
+ DispatchIOHandler, this);
+ }
+
+ ~GlibIOInputHandler() {
+ g_source_remove(source_id_);
+ g_io_channel_shutdown(channel_, TRUE, NULL);
+ g_io_channel_unref(channel_);
+ }
+};
+
+static gboolean DispatchIOHandler(GIOChannel *chan, GIOCondition cond,
+ gpointer data) {
+ GlibIOInputHandler *handler = static_cast<GlibIOInputHandler *>(data);
+ unsigned char buf[4096];
+ gsize len;
+ GIOError err;
+
+ if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
+ return FALSE;
+
+ err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len);
+ if (err) {
+ if (err == G_IO_ERROR_AGAIN)
+ return TRUE;
+ return FALSE;
+ }
+
+ InputData input_data = { buf, len };
+ handler->callback_->Run(&input_data);
+
+ return TRUE;
+}
+
+IOInputHandler *EventDispatcher::CreateInputHandler(int fd,
+ Callback<InputData *> *callback) {
+ return new GlibIOInputHandler(this, fd, callback);
+}
+
} // namespace shill