=== modified file 'common/ntrack.c'
--- a/common/ntrack.c	2009-10-10 16:12:24 +0000
+++ b/common/ntrack.c	2009-10-11 03:32:50 +0000
@@ -130,16 +130,30 @@ ntrack_monitor_process_data (NTrackMonit
 }
 
 static void
 dispatch_monitor_event (NTrackMonitor *self,
                         NTrackMonitorEvent event)
 {
 	int i;
 
+	switch (event) {
+	case NTRACK_MONITOR_EVENT_CONNECT:
+		self->state = NTRACK_MONITOR_STATE_ONLINE;
+		break;
+	case NTRACK_MONITOR_EVENT_DISCONNECT:
+		self->state = NTRACK_MONITOR_STATE_OFFLINE;
+		break;
+	case NTRACK_MONITOR_EVENT_RECONNECT:
+		self->state = NTRACK_MONITOR_STATE_ONLINE;
+		break;
+	default:
+		self->state = NTRACK_MONITOR_STATE_UNKNOWN;
+	}
+
 	for (i = 0; i < self->pack_len; i++) {
 		struct ListenerPack *pack = self->packs[i];
 		pack->callback (self, event, pack->user_data);
 	}
 }
 
 static void
 NTrackMonitorArchEventFunc_cb (NTrackMonitor *self,
@@ -162,11 +176,13 @@ NTrackMonitorArchEventFunc_cb (NTrackMon
 		assert (FALSE);
 	}
 }
 
 /* private/static funcs */
 static NTrackMonitor*
 __new ()
 {
-	/* delegate to arch specific implementation */
-	return _ntrack_arch_new (NTrackMonitorArchEventFunc_cb, NULL);
+	/*delegate to arch specific implementation */
+	NTrackMonitor *arch = _ntrack_arch_new (NTrackMonitorArchEventFunc_cb, NULL);
+	arch->state = NTRACK_MONITOR_STATE_UNKNOWN;
+	return arch;
 }

=== modified file 'common/ntrack.h'
--- a/common/ntrack.h	2009-10-10 16:12:24 +0000
+++ b/common/ntrack.h	2009-10-10 23:19:43 +0000
@@ -16,23 +16,32 @@
  *  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 ntrack.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include "ntrack_macros.h"
 #include "ntrackcompare.h"
+#include "ntracklist.h"
+#include "ntrackidpool.h"
 
 #ifndef __NTRACK_H__
 #define __NTRACK_H__
 
 NTRACK_BEGIN_DECLS
 
 typedef enum {
+	NTRACK_MONITOR_STATE_ONLINE,
+	NTRACK_MONITOR_STATE_OFFLINE,
+	NTRACK_MONITOR_STATE_BLOCKED,
+	NTRACK_MONITOR_STATE_UNKNOWN
+} NTrackMonitorState;
+
+typedef enum {
 	NTRACK_MONITOR_EVENT_CONNECT,
 	NTRACK_MONITOR_EVENT_DISCONNECT,
 	NTRACK_MONITOR_EVENT_RECONNECT
 } NTrackMonitorEvent;
 
 typedef struct _NTrackMonitor NTrackMonitor;
 
 typedef void (*NTrackMonitorCallback) (NTrackMonitor *monitor, NTrackMonitorEvent event, ntrackpointer user_data);
@@ -51,11 +60,13 @@ ntrackpointer ntrack_monitor_register_fu
 
 int ntrack_monitor_remove (NTrackMonitor *self,
                            ntrackpointer handle);
 
 int* ntrack_monitor_get_rfds (NTrackMonitor *self);
 
 int ntrack_monitor_process_data (NTrackMonitor *self, int* fds);
 
+NTrackMonitorState ntrack_monitor_get_state (NTrackMonitor *self);
+
 NTRACK_END_DECLS
 
 #endif /* __NTRACK_H__ */

=== modified file 'common/ntrack_arch.h'
--- a/common/ntrack_arch.h	2009-10-10 16:12:24 +0000
+++ b/common/ntrack_arch.h	2009-10-10 23:20:31 +0000
@@ -36,16 +36,18 @@ typedef void (*NTrackMonitorArchEventFun
                                             NTrackMonitorArchEvent event,
                                             ntrackpointer user_data);
 
 struct _NTrackMonitor
 {
 	struct ListenerPack **packs;
 	int pack_len;
 	int pack_size;
+
+	NTrackMonitorState state;
 };
 
 struct NTrackMonitorArch {
 	NTrackMonitor parent;
 
 	ntrackpointer data;
 
 	NTrackMonitorArchEventFunc cb;

=== modified file 'glib/Makefile.am'
--- a/glib/Makefile.am	2009-10-10 16:12:24 +0000
+++ b/glib/Makefile.am	2009-10-10 20:27:15 +0000
@@ -18,16 +18,17 @@
 #   You should have received a copy of the GNU Lesser General Public
 #   License along with ntrack.  If not, see <http://www.gnu.org/licenses/>.
 #
 
 AM_CFLAGS = \
 	-Wall \
 	-Werror \
 	-pedantic \
+	-I$(srcdir)/../common/ \
 	$(NULL)
 
 lib_LTLIBRARIES = libgntrack.la
 
 libgntrack_la_SOURCES = \
 	gntrack.h gntrack.c \
 	$(NULL)
 

=== modified file 'glib/gntrack.c'
--- a/glib/gntrack.c	2009-10-10 16:12:24 +0000
+++ b/glib/gntrack.c	2009-10-11 03:09:48 +0000
@@ -15,33 +15,219 @@
  *  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 ntrack.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include "gntrack.h"
+#include "ntrack.h"
 
-gboolean
-g_ntrack_init (gint *argc, char ***argv)
+/* *
+ * * GNTrackSource implementation for flexible multi-fds main loop integration
+ * */
+
+struct __GNTrackSource
+{
+	GSource parent;
+	NTrackList *poll_fds;
+	NTrackList *up_event_queue;
+};
+
+static gboolean
+__gntrack_source_prepare (GSource    *source,
+                          gint       *timeout)
 {
+	/* don't register for any timeouts; this will
+	 * keep this source silence when there are
+	 * no fds polls */
+	*timeout = -1;
+
+	/* we are a pure fd source; means: always FALSE
+	 * see glib docs for GSourceFuncs in general and
+	 * GSourceFunc::prepare */
+	return FALSE;
+}
+
+static gboolean 
+__gntrack_source_check (GSource *source)
+{
+	struct __GNTrackSource *self = (struct __GNTrackSource*) source;
+	NTrackList *i = self->poll_fds;
+	gint *rfds = self->poll_fds ? g_new0(gint, *(self->poll_fds->len)) : NULL;
+	gint rfds_count = 0;
+	NTrackMonitor *monitor = ntrack_get_monitor ();
+	while (i) {
+		GPollFD *poll_fd = i->data;
+		if ((poll_fd->revents & G_IO_IN) != 0) {
+			rfds[rfds_count++] = poll_fd->fd;
+		}
+		i = i->next;
+	}
+	if (rfds_count > 0) {
+		ntrack_monitor_process_data (monitor, rfds);
+		g_free (rfds);
+	}
+	return !!self->up_event_queue;
+}
+
+static gboolean
+__gntrack_source_dispatch (GSource *source,
+                           GSourceFunc callback,
+                           gpointer user_data)
+{
+	GNTrackSourceFunc func = (GNTrackSourceFunc) callback;
+	struct __GNTrackSource *self = (struct __GNTrackSource*) source;
+
+	/* dispatch all events accumulated during _source_check */
+	while (self->up_event_queue) {
+		func ((NTrackMonitorEvent) self->up_event_queue->data, user_data);
+		self->up_event_queue = ntrack_list_remove (self->up_event_queue,
+		                                           self->up_event_queue);
+	}
+
+	/* this is a meta source, that never should
+	 * remove it self; because we use timeout=-1 above
+	 * this source will not be called if no pollids
+	 * are registered, so keeping it active should
+	 * be of minimal maintenance overhead. */
 	return TRUE;
 }
 
-gint
-g_ntrack_add_listener (GNTrackStateChangeFunc func, gpointer data)
+static void
+__gntrack_source_remove_one_poll_fd (struct __GNTrackSource* source,
+                                     GPollFD *poll_fd)
 {
-	return 0;
+	g_assert (poll_fd);
+
+	g_source_remove_poll ((GSource*) source, poll_fd);
+	g_free (poll_fd);
 }
 
-GNTrackState
-g_ntrack_get_state ()
+static void
+__gntrack_source_finalize (GSource *source)
 {
-	return G_NTRACK_STATE_UNKNOWN;
+	while (source->poll_fds) {
+		struct __GNTrackSource* self = (struct __GNTrackSource*) source;
+
+		__gntrack_source_remove_one_poll_fd (self, source->poll_fds->data);
+
+		self->poll_fds = ntrack_list_remove (self->poll_fds,
+		                                     self->poll_fds);
+	}
 }
 
-gboolean
-g_ntrack_remove (gint listener_id)
+static void
+__gntrack_source_add_one_poll_fd (struct __GNTrackSource* source,
+                               int fd,
+                               GIOCondition condition)
 {
-	return FALSE;
+	GPollFD *poll_fd = g_new0 (GPollFD, 1);
+
+	poll_fd->fd = fd;
+	poll_fd->events  = condition;
+	poll_fd->revents = 0;
+
+	/* register and remember */
+	g_source_add_poll ((GSource*) source, poll_fd);
+	source->poll_fds = ntrack_list_append (source->poll_fds, poll_fd);
+}
+
+static void
+__gntrack_source_update_poll_fds (struct __GNTrackSource* source, int *rfds, int *wfds)
+{
+	while (source->poll_fds)
+	{
+		__gntrack_source_remove_one_poll_fd (source, source->poll_fds->data);
+
+		source->poll_fds = ntrack_list_remove (source->poll_fds,
+		                                       source->poll_fds);
+	}
+
+	/* create all initial polls for read-fds and register/remember them */
+	while (*rfds) {
+		__gntrack_source_add_one_poll_fd (source,
+		                               *rfds,
+		                               G_IO_IN | G_IO_HUP | G_IO_ERR);
+		rfds++;
+	}
+
+	/* create all initial polls for write-fds and register/remember them */
+	while (*wfds) {
+		__gntrack_source_add_one_poll_fd (source,
+		                               *wfds,
+		                               G_IO_OUT | G_IO_ERR);
+		wfds++;
+	}
+}
+
+static GSourceFuncs
+__gntrack_source_funcs = {
+	/* .prepare  = */ __gntrack_source_prepare,
+	/* .check    = */ __gntrack_source_check,
+	/* .dispatch = */ __gntrack_source_dispatch,
+	/* .finalize = */ __gntrack_source_finalize,
+	/* Note: closures are gobject world, so keep them NULL */
+	/* .closure_callback = */ NULL,
+	/* .closure_marshal = */ NULL
+};
+
+GSource*
+gntrack_source_new ()
+{
+	GSourceFuncs *source_funcs;
+	struct __GNTrackSource *source;
+	NTrackMonitor *monitor = ntrack_get_monitor ();
+	gint* rfds = ntrack_monitor_get_rfds (monitor);
+	int wfds[] = { 0 };
+
+	source_funcs = g_new0 (GSourceFuncs, 1);
+	*source_funcs = __gntrack_source_funcs;
+
+	source = (struct __GNTrackSource *)
+		g_source_new (source_funcs, sizeof (struct __GNTrackSource));
+
+	__gntrack_source_update_poll_fds (source, rfds, wfds);
+
+	return (GSource*) source;
+}
+
+guint
+gntrack_source_add_full (gint priority,
+                         GNTrackSourceFunc func,
+                         gpointer data,
+                         GDestroyNotify notify)
+{
+	struct __GNTrackSource *source = (struct __GNTrackSource *)
+		gntrack_source_new ();
+
+	g_source_set_priority ((GSource*) source, priority);
+	g_source_set_callback ((GSource*) source,
+	                       (GSourceFunc) func,
+	                       data,
+	                       notify);
+
+#ifdef THREAD_EXPERIMENT
+	return g_source_attach ((GSource*) source, g_main_context_get_thread_default ());
+#else
+	return g_source_attach ((GSource*) source, g_main_context_default ());
+#endif
+}
+
+guint
+gntrack_source_add (GNTrackSourceFunc func, gpointer data)
+{
+
+	return gntrack_source_add_full (G_PRIORITY_DEFAULT,
+	                                func,
+	                                data,
+	                                NULL);
+}
+
+GNTrackState
+g_ntrack_get_state ()
+{
+	NTrackMonitor *monitor = ntrack_get_monitor();
+
+	return ntrack_monitor_get_state (monitor);
 }
 

=== modified file 'glib/gntrack.h'
--- a/glib/gntrack.h	2009-10-10 16:12:24 +0000
+++ b/glib/gntrack.h	2009-10-11 03:08:02 +0000
@@ -31,25 +31,29 @@ typedef enum {
 	G_NTRACK_STATE_BLOCKED,
 	G_NTRACK_STATE_OFFLINE,
 	G_NTRACK_STATE_UNKNOWN
 } GNTrackState;
 
 typedef enum {
 	G_NTRACK_EVENT_ONLINE,
 	G_NTRACK_EVENT_OFFLINE,
-	G_NTRACK_EVENT_REROUTE
+	G_NTRACK_EVENT_REROUTE,
+	G_NTRACK_EVENT_LINK_DOWN,
+	G_NTRACK_EVENT_LINK_UP
 } GNTrackEvent;
 
-typedef struct _GNTrackStatus GNTrackStatus;
+typedef gboolean (*GNTrackSourceFunc) (GNTrackEvent event, gpointer user_data);
 
-typedef void (*GNTrackStateChangeFunc) (GNTrackState old_state,
-                                        GNTrackState new_state,
-                                        gpointer user_data);
+GSource* gntrack_source_new ();
+
+guint gntrack_source_add_full (gint priority,
+                               GNTrackSourceFunc func,
+                               gpointer data,
+                               GDestroyNotify notify);
+
+guint gntrack_source_add (GNTrackSourceFunc func, gpointer data);
 
-gboolean g_ntrack_init (gint *argc, char ***argv);
-gint g_ntrack_add_listener (GNTrackStateChangeFunc func, gpointer data);
 GNTrackState g_ntrack_get_state ();
-gboolean g_ntrack_remove (gint listener);
 
 G_END_DECLS
 
 #endif /* __GNTRACK_H__ */

