Adding support to asynchronous connections to Maemo conic device



Hi,

find attached a patch that adds a new API to the Maemo conic device to allow asynchronous connections. This patch comes from the initial work by Philip and was lately modified by me. Basically I restored the old sync connect API (Philip just threw it away) and renamed the new async functions with the suffix _async like many other tinymail functions. I had also to fix a problem with the linker that was not including the conic symbols (due to they were not used inside libtinymail-maemo).

Br
Index: configure.ac
===================================================================
--- configure.ac	(revision 2932)
+++ configure.ac	(working copy)
@@ -67,6 +67,7 @@
 build_tests=false
 build_unittests=false
 build_tp=false
+have_conic=false
 PLATFORMDIR=libtinymail-gnome-desktop
 PLATFORM=1
 
@@ -428,26 +429,23 @@
 	if $PKG_CONFIG --exists conic; then
 		PKG_CHECK_MODULES(LIBTINYMAIL_MAEMO_CONIC,conic,HAVE_CONIC=yes,HAVE_CONIC=no)
 		AC_MSG_RESULT(conic)
-     		MAEMO_DEVICE='tny-maemo-conic-device.$(OBJEXT)'
 		AC_SUBST(LIBYINYMAIL_MAEMO_CONIC_CFLAGS)
 		AC_SUBST(LIBTINYMAIL_MAEMO_CONIC_LIBS)
-dnl HACK: unless we are building for arm, make the device a 'dummy' assuming it is always online
-dnl this is because scratcbhox-Conic does not support ethernet, and will therefore never consider
-dnl itself 'online'
+		dnl HACK: unless we are building for arm, make the device a 'dummy' assuming it is always online
+		dnl this is because scratcbhox-Conic does not support ethernet, and will therefore never consider
+		dnl itself 'online'
  		if test -z "`sb-conf show -c | grep arm`"; then
+			use_conic_device_dummy=1
  			AC_DEFINE_UNQUOTED(MAEMO_CONIC_DUMMY,1,["Whether to hack the TnyMaemoConicDevice to somewhat work in sbox"])
  		fi
+		AM_CONDITIONAL(MAEMO_CONIC_DEVICE_DUMMY, test -n "$use_conic_device_dummy")
 	fi
-	AC_SUBST([MAEMO_DEVICE])
 	AC_SUBST(LIBTINYMAIL_MAEMO_CFLAGS)
 	AC_SUBST(LIBTINYMAIL_MAEMO_LIBS)
 fi
 
-
 AM_CONDITIONAL(BUILD_MAEMO, test x$build_maemo = xtrue)
 
-
-
 dnl ### libtinymail-gpe, a platform library implementation for the GPE platform ##
 if test x$PLATFORMDIR = xlibtinymail-gpe; then
  PKG_CHECK_MODULES(LIBTINYMAIL_GPE, glib-2.0 >= 2.8 gobject-2.0 gconf-2.0 gtk+-2.0)
Index: libtinymail-maemo/tny-maemo-conic-device.h
===================================================================
--- libtinymail-maemo/tny-maemo-conic-device.h	(revision 2932)
+++ libtinymail-maemo/tny-maemo-conic-device.h	(working copy)
@@ -55,6 +55,11 @@
 TnyDevice* tny_maemo_conic_device_new (void);
 
 gboolean tny_maemo_conic_device_connect (TnyMaemoConicDevice *self, const gchar* iap_id);
+typedef void (*TnyMaemoConicDeviceConnectCallback) (TnyMaemoConicDevice *self, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data);
+void tny_maemo_conic_device_connect_async (TnyMaemoConicDevice *self, 
+					   const gchar* iap_id, 
+					   TnyMaemoConicDeviceConnectCallback callback, 
+					   gpointer user_data);
 gboolean tny_maemo_conic_device_disconnect (TnyMaemoConicDevice *self, const gchar* iap_id);
 const gchar* tny_maemo_conic_device_get_current_iap_id (TnyMaemoConicDevice *self);
 ConIcIap* tny_maemo_conic_device_get_iap (TnyMaemoConicDevice *self, const gchar *iap_id);
Index: libtinymail-maemo/Makefile.am
===================================================================
--- libtinymail-maemo/Makefile.am	(revision 2932)
+++ libtinymail-maemo/Makefile.am	(working copy)
@@ -10,7 +10,6 @@
 	-I$(top_srcdir)/libtinymail-gnomevfs \
 	-DDBUS_API_SUBJECT_TO_CHANGE
 
-
 lib_LTLIBRARIES = libtinymail-maemo-1.0.la
 
 libtinymail_maemo_1_0_headers = \
@@ -25,21 +24,20 @@
 	tny-maemo-device.c \
 	tny-maemo-platform-factory.c
 
-EXTRA_libtinymail_maemo_1_0_la_SOURCES = \
-	tny-maemo-conic-device.c				 
-					
+if MAEMO_CONIC_DEVICE_DUMMY
+libtinymail_maemo_1_0_la_SOURCES += tny-maemo-conic-dummy-device.c
+else
+libtinymail_maemo_1_0_la_SOURCES += tny-maemo-conic-device.c
+endif
+
 libtinymail_maemo_1_0_la_LIBADD = \
 	$(LIBTINYMAIL_MAEMO_LIBS) \
 	$(LIBTINYMAIL_MAEMO_CONIC_LIBS) \
-	@MAEMO_DEVICE@ \
 	$(top_builddir)/libtinymail/libtinymail-$(API_VERSION).la \
 	$(top_builddir)/libtinymailui/libtinymailui-$(API_VERSION).la \
 	$(top_builddir)/libtinymailui-gtk/libtinymailui-gtk-$(API_VERSION).la \
 	$(top_builddir)/libtinymail-camel/libtinymail-camel-$(API_VERSION).la
 
-libtinymail_maemo_1_0_la_DEPENDENCIES=\
-	@MAEMO_DEVICE@
-
 libtinymail_maemo_1_0_la_LDFLAGS = -export-dynamic \
 	-version-info $(LT_VERSION_INFO) $(LIBTOOL_EXPORT_OPTIONS)
 
Index: libtinymail-maemo/tny-maemo-conic-device.c
===================================================================
--- libtinymail-maemo/tny-maemo-conic-device.c	(revision 2932)
+++ libtinymail-maemo/tny-maemo-conic-device.c	(working copy)
@@ -1,4 +1,4 @@
-/* libtinymail-camel - The Tiny Mail base library for Camel
+/* libtinymail-camel - The Tiny Mail base library for Maemo
  * Copyright (C) 2006-2007 Philip Van Hoof <pvanhoof gnome org>
  *
  * This library is free software; you can redistribute it and/or
@@ -25,66 +25,34 @@
 #include <coniciap.h>
 #include <conicconnection.h>
 #include <conicconnectionevent.h>
+#include <string.h>
+#include <tny-error.h>
 #include <gdk/gdk.h> /* For GDK_THREAD_ENTER/LEAVE */
-#include <string.h> /* For strcmp() */
 
+static void stop_loop (TnyMaemoConicDevice *self);
 
-#ifdef MAEMO_CONIC_DUMMY 
-#include <gtk/gtkmessagedialog.h>
-#endif
-
-
-
-static gboolean
-dnsmasq_has_resolv (void)
-{
-	/* This is because silly Conic does not have a blocking API that tells
-	 * us immediately when the device is online. */
-
-	if (!g_file_test ("/var/run/resolv.conf", G_FILE_TEST_EXISTS))
-		if (!g_file_test ("/tmp/resolv.conf.wlan0", G_FILE_TEST_EXISTS))
-			if (!g_file_test ("/tmp/resolv.conf.ppp0", G_FILE_TEST_EXISTS))
-				return FALSE;
-
-	return TRUE;
-}
-
-#ifdef MAEMO_CONIC_DUMMY
-/* #include "coniciap-private.h"
- * This is not installed, so we predeclare the struct instead. Of course, this 
- * is a hack and could break if the private API changes. It would be better for 
- * libconic to support scratchbox. */
-
-struct _ConIcIap 
-{
-	GObject parent_instance;
-	gboolean dispose_has_run;
-	gchar *id;
-	gchar *name;
-	gchar *bearer;
-};
-
-#define MAEMO_CONIC_DUMMY_IAP_ID_FILENAME "maemo_conic_dummy_id"
-#define MAEMO_CONIC_DUMMY_IAP_ID_NONE "none"
-static gboolean on_dummy_connection_check (gpointer user_data);
-#endif /* MAEMO_CONIC_DUMMY */
-
 static gboolean tny_maemo_conic_device_is_online (TnyDevice *self);
 
 static GObjectClass *parent_class = NULL;
 
 typedef struct {
+	TnyMaemoConicDevice *self;
+	gchar* iap_id;
+	gpointer user_data;
+	TnyMaemoConicDeviceConnectCallback callback;
+} ConnectInfo;
+
+typedef struct {
 	ConIcConnection *cnx;
 	gboolean is_online;
 	gchar *iap;
 	gboolean forced; /* Whether the is_online value is forced rather than real. */
+	ConnectInfo *connect_slot;
 	/* When non-NULL, we are waiting for the success or failure signal. */
 	GMainLoop *loop;
-#ifdef MAEMO_CONIC_DUMMY
-	gint dummy_env_check_timeout;
-#endif /* MAEMO_CONIC_DUMMY */
 } TnyMaemoConicDevicePriv;
 
+
 #define TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE(o)	\
 	(G_TYPE_INSTANCE_GET_PRIVATE ((o), TNY_TYPE_MAEMO_CONIC_DEVICE, TnyMaemoConicDevicePriv))
 
@@ -94,12 +62,26 @@
 } EmitStatusInfo;
 
 static gboolean
+dnsmasq_has_resolv (void)
+{
+	/* This is because silly Conic does not have a blocking API that tells
+	 * us immediately when the device is online. */
+
+	if (!g_file_test ("/var/run/resolv.conf", G_FILE_TEST_EXISTS))
+		if (!g_file_test ("/tmp/resolv.conf.wlan0", G_FILE_TEST_EXISTS))
+			if (!g_file_test ("/tmp/resolv.conf.ppp0", G_FILE_TEST_EXISTS))
+				return FALSE;
+
+	return TRUE;
+}
+
+static gboolean
 conic_emit_status_idle (gpointer user_data)
 {
 	EmitStatusInfo *info = (EmitStatusInfo *) user_data;
 
-	/* We lock the gdk thread because tinymail wants implementations to do this 
-	 * before emitting _any_ signals.
+	/* We lock the gdk thread because tinymail wants implementations to do
+	 * this before emitting signals from within a g_idle_add_full callback.
 	 * See http://www.tinymail.org/trac/tinymail/wiki/HowTnyLockable */
 
 	gdk_threads_enter ();
@@ -122,46 +104,19 @@
 static void 
 conic_emit_status (TnyDevice *self, gboolean status)
 {
-	/* If there is a mainloop (if gtk_main() has been run, for instance),
-	 * then emit the signal via an idle callback, so that it is 
-	 * always emitted in the main context as required by tinymail
-	 * (libconic does not give any guarantee 
-	 * about this - it would be nice if libconic documented that).
-	 * But if there is no mainloop, then just emit it, as tinymail 
-	 * requires when there is no mainloop: */
+	/* Emit it in an idle handler: */
+	EmitStatusInfo *info = g_slice_new (EmitStatusInfo);
+	guint time = 1000;
 
-	 /* TODO: We have no way to check for this now, and 
-	  * at this time it's not even clear whether tinymail should/can really 
-	  * demand this. murrayc. 15th Aug. 2007. */
+	info->self = g_object_ref (self);
+	info->status = status;
 
-	if (TRUE) /* TODO: But NULL is not allowed here: g_main_loop_is_running (NULL)) */
-	{
-		/* Emit it in an idle handler: */
-		EmitStatusInfo *info = g_slice_new (EmitStatusInfo);
-		guint time = 5000;
+	if (!dnsmasq_has_resolv())
+		time = 5000;
 
-		info->self = g_object_ref (self);
-		info->status = status;
+	g_timeout_add_full (G_PRIORITY_DEFAULT, time, conic_emit_status_idle,
+		info, conic_emit_status_destroy);
 
-		if (!dnsmasq_has_resolv())
-			time = 5000;
-
-		g_timeout_add_full (G_PRIORITY_DEFAULT, time, conic_emit_status_idle,
-			info, conic_emit_status_destroy);
-
-	} else {
-		/* Emit it directly: */
-
-		/* We lock the gdk thread because tinymail wants implementations
-		 *  to do this before emitting _any_ signals.
-		 * See http://www.tinymail.org/trac/tinymail/wiki/HowTnyLockable */
-
-		gdk_threads_enter ();
-		g_signal_emit (self, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED],
-			0, status);
-		gdk_threads_leave ();
-	}
-
 	return;
 }
 
@@ -185,17 +140,81 @@
 	return;
 }
 
-#ifndef MAEMO_CONIC_DUMMY
-
-static void 
-stop_loop (TnyMaemoConicDevice *self)
+static void
+handle_connect (TnyMaemoConicDevice *self, int con_err, int con_state)
 {
 	TnyMaemoConicDevicePriv *priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
-	if (priv->loop)
-		g_main_loop_quit (priv->loop);
+
+	if (priv->connect_slot) 
+	{
+		GError *err = NULL;
+		gboolean canceled = FALSE;
+		ConnectInfo *info = priv->connect_slot;
+
+		/* Mark it as handled (TODO, this needs a small lock) */
+		priv->connect_slot = NULL;
+
+		switch (con_err) {
+			case CON_IC_CONNECTION_ERROR_NONE:
+				break;
+			case CON_IC_CONNECTION_ERROR_INVALID_IAP:
+				g_set_error (&err, TNY_ACCOUNT_ERROR, TNY_ERROR_UNSPEC,
+					"IAP is invalid");
+				break;
+			case CON_IC_CONNECTION_ERROR_CONNECTION_FAILED:
+				g_set_error (&err, TNY_ACCOUNT_ERROR, TNY_ERROR_UNSPEC,
+					"Connection failed");
+				break;
+			case CON_IC_CONNECTION_ERROR_USER_CANCELED:
+			default:
+				canceled = TRUE;
+				break;
+		}
+
+		if (info->callback) {
+			/* We lock the gdk thread because tinymail wants implementations to do
+			 * this before invoking callbacks from within a g_idle_add_full callback.
+			 * See http://www.tinymail.org/trac/tinymail/wiki/HowTnyLockable */
+
+			gdk_threads_enter ();
+			info->callback (info->self, info->iap_id, canceled, err, info->user_data);
+			gdk_threads_leave ();
+		}
+
+		if (err)
+			g_error_free (err);
+
+		g_object_unref (info->self);
+		g_free (info->self);
+		g_slice_free (ConnectInfo, info);
+	}
+
 	return;
 }
 
+typedef struct {
+	TnyMaemoConicDevice *self;
+	int con_err;
+	int con_state;
+} HandleConnInfo;
+
+static gboolean
+handle_con_idle (gpointer data)
+{
+	HandleConnInfo *info = (HandleConnInfo *) data;
+	handle_connect (info->self, info->con_err, info->con_state);
+	return FALSE;
+}
+
+static void 
+handle_con_idle_destroy (gpointer data) 
+{ 
+	HandleConnInfo *info = (HandleConnInfo *) data;
+	g_object_unref (info->self);
+	g_slice_free (HandleConnInfo, data); 
+}
+
+
 static void
 on_connection_event (ConIcConnection *cnx, ConIcConnectionEvent *event, gpointer user_data)
 {
@@ -203,19 +222,18 @@
 	TnyMaemoConicDevicePriv *priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (device);
 	gboolean is_online = FALSE;
 	gboolean emit = FALSE;
+	HandleConnInfo *iinfo;
+	int con_err, con_state;
 
 	/* Don't emit nor make any changes in case of forced state */
+
 	if (priv->forced)
 		return;
 
-	g_return_if_fail (CON_IC_IS_CONNECTION(cnx));
+	con_err = con_ic_connection_event_get_error (event);
+	con_state = con_ic_connection_event_get_status (event);
 
-#ifdef DEBUG
-	g_message (__FUNCTION__);
-#endif
-
-	switch (con_ic_connection_event_get_error(event)) 
-	{
+	switch (con_err) {
 		case CON_IC_CONNECTION_ERROR_NONE:
 			break;
 		case CON_IC_CONNECTION_ERROR_INVALID_IAP:
@@ -231,8 +249,7 @@
 			g_return_if_reached ();
 	}
 
-	switch (con_ic_connection_event_get_status(event)) 
-	{
+	switch (con_state) {
 		case CON_IC_STATUS_CONNECTED:
 			if (priv->iap)
 				g_free (priv->iap);
@@ -261,135 +278,87 @@
 
 	priv->is_online = is_online;
 
-#ifdef DEBUG
-	g_message ("DEBUG: %s: emitting signal CONNECTION_CHANGED: %s", 
-		   __FUNCTION__, is_online ? "online" : "offline");
-#endif
+	if (priv->connect_slot && 
+		(con_err != CON_IC_CONNECTION_ERROR_NONE || 
+		 con_state == CON_IC_STATUS_CONNECTED)) 
+	{
 
+		/* If there's an error or if we just connected, we call the
+		 * callback for tny_maemo_conic_device_connect, if any */
+
+		iinfo = g_slice_new (HandleConnInfo);
+		iinfo->self = (TnyMaemoConicDevice *) g_object_ref (device);
+		iinfo->con_err = con_err;
+		iinfo->con_state = con_state;
+
+		g_idle_add_full (G_PRIORITY_HIGH, handle_con_idle, iinfo, 
+			handle_con_idle_destroy);
+	}
+
 	if (emit)
 		conic_emit_status (TNY_DEVICE (device), is_online);
 
 	return;
 }
-#endif /* MAEMO_CONIC_DUMMY */
 
-#ifdef MAEMO_CONIC_DUMMY
 
-static gchar*
-get_dummy_filename ()
-{
-	gchar *filename = g_build_filename (
-		g_get_home_dir (), 
-		MAEMO_CONIC_DUMMY_IAP_ID_FILENAME,
-		NULL);
-	return filename;
-}
-
-static gboolean 
-dummy_con_ic_connection_connect_by_id (TnyMaemoConicDevice *self, const gchar* iap_id)
-{
-	int response = 0;
-
-	/* Show a dialog, because libconic would show a dialog here,
-	 * and give the user a chance to refuse a new connection, because libconic would allow that too.
-	 * This allows us to see roughly similar behaviour in scratchbox as on the device. */
-	GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL,
-			GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, 
-			"TnyMaemoConicDevice fake scratchbox implementation:\nThe application requested a connection. Make a fake connection?"));
-
-	response = gtk_dialog_run (dialog);
-	gtk_widget_hide (GTK_WIDGET (dialog));
-	gtk_widget_destroy (GTK_WIDGET (dialog));
-	
-	if (response == GTK_RESPONSE_OK) {
-		GError* error = NULL;
-		/* Make a connection, by setting a name in our dummy text file,
-		 * which will be read later: */
-		gchar *filename = get_dummy_filename ();
-
-		g_file_set_contents (filename, "debug id0", -1, &error);
-		if(error) {
-			g_warning("%s: error from g_file_set_contents(): %s\n", __FUNCTION__, error->message);
-			g_error_free (error);
-			error = NULL;
-		}
-
-		g_free (filename);
-
-		return TRUE;
-	}
-	else
-		return FALSE;
-}
-
-#endif /* MAEMO_CONIC_DUMMY */
-
-
 /**
  * tny_maemo_conic_device_connect:
  * @self: a #TnyDevice object
  * @iap_id: the id of the Internet Access Point (IAP), or NULL for 'any;
+ * @callback: a #TnyMaemoConicDeviceConnectCallback
+ * @user_data: user data for @callback
  * 
  * Try to connect to a specific IAP, or to any if @iap_id == NULL
  * this calls con_ic_connection_connect(_by_id).
  * This may show a dialog to allow the user to select a connection, or 
- * may otherwise take a significant amount of time. This function blocks until 
- * the connection has either succeeded or failed.
- * 
- * Returns TRUE if a connection was made, FALSE otherwise.
+ * may otherwise take a significant amount of time. 
  **/
-gboolean
-tny_maemo_conic_device_connect (TnyMaemoConicDevice *self, const gchar* iap_id)
+void 
+tny_maemo_conic_device_connect_async (TnyMaemoConicDevice *self, 
+				      const gchar* iap_id, 
+				      TnyMaemoConicDeviceConnectCallback callback, 
+				      gpointer user_data)
 {
-#ifdef MAEMO_CONIC_DUMMY 
-	return dummy_con_ic_connection_connect_by_id (self, iap_id);
-#else
 	TnyMaemoConicDevicePriv *priv = NULL;
 	gboolean request_failed = FALSE;
+	ConnectInfo *info;
+	GError *err = NULL;
 
-	g_return_val_if_fail (TNY_IS_DEVICE(self), FALSE);
 	priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
 
-	g_return_val_if_fail (priv->cnx, FALSE);
+	info = g_slice_new (ConnectInfo);
+	info->self = (TnyMaemoConicDevice *) g_object_ref (info);
+	info->callback = callback;
+	info->user_data = user_data;
+	info->iap_id = g_strdup (iap_id);
 
-#ifdef DEBUG
-	g_message (__FUNCTION__);
-	g_message ("connecting to %s", iap_id ? iap_id : "<any>");
-#endif
+	priv->connect_slot = info;
 
-	priv->loop = g_main_loop_new(NULL, FALSE /* not running immediately. */);
-
 	if (iap_id) {
 		if (!con_ic_connection_connect_by_id (priv->cnx, iap_id, CON_IC_CONNECT_FLAG_NONE)) {
-			g_warning ("could not send connect_by_id dbus message");
+			g_set_error (&err, TNY_ACCOUNT_ERROR, TNY_ERROR_UNSPEC,
+				"Could not send connect_by_id dbus message");
 			request_failed = TRUE;
 		}
 	} else {
 		if (!con_ic_connection_connect (priv->cnx, CON_IC_CONNECT_FLAG_NONE)) {
-			g_warning ("could not send connect dbus message");
+			g_set_error (&err, TNY_ACCOUNT_ERROR, TNY_ERROR_UNSPEC,
+				"Could not send connect dbus message");
 			request_failed = TRUE;
 		}
 	}
 
 	if (request_failed) {
-		g_object_unref (priv->loop);
-		priv->loop = NULL;
+		priv->connect_slot = NULL;
+		if (info->callback)
+			info->callback (info->self, iap_id, FALSE, err, info->user_data);
+		g_free (info->iap_id);
+		g_object_unref (info->self);
+		g_slice_free (ConnectInfo, info);
 	}
-	
-	/* Wait for the CON_IC_STATUS_CONNECTED (succeeded) or 
-	 * CON_IC_STATUS_DISCONNECTED event: */
-	 
-	/* This is based on code found in gtk_dialog_run(): */
-	GDK_THREADS_LEAVE();
-	/* Run until g_main_loop_quit() is called by our signal handler. */
-	g_main_loop_run (priv->loop);
-	GDK_THREADS_ENTER();
-
-	g_main_loop_unref (priv->loop);
-	priv->loop = NULL;
-
-	return priv->is_online;
-#endif /* MAEMO_CONIC_DUMMY */
+ 
+	return;
 }
 
 
@@ -406,10 +375,6 @@
 gboolean
 tny_maemo_conic_device_disconnect (TnyMaemoConicDevice *self, const gchar* iap_id)
 {
-/* don't try to disconnect if we're in dummy mode, as we're not "really"
- * connected in that case either
- */
-#ifndef MAEMO_CONIC_DUMMY 
 	TnyMaemoConicDevicePriv *priv = NULL;
 
 	g_return_val_if_fail (TNY_IS_MAEMO_CONIC_DEVICE(self), FALSE);
@@ -417,93 +382,22 @@
 	priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
 	g_return_val_if_fail (priv->cnx, FALSE);
 
-#ifdef DEBUG
-	g_message (__FUNCTION__);
-	g_message ("disconnecting from %s", iap_id ? iap_id : "<any>");
-#endif
-
 	if (iap_id) {
 		if (!con_ic_connection_disconnect_by_id (priv->cnx, iap_id)) {
-			g_warning ("could not send disconnect_by_id dbus message");
+			g_warning ("Could not send disconnect_by_id dbus message");
 			return FALSE;
 		}
 	} else {
 		/* don't try to disconnect if iap_id==NULL, or conic will crash... */
-		g_warning ("could not send disconnect dbus message");
+		g_warning ("Could not send disconnect dbus message");
 		return FALSE;
 	}
-#endif /* MAEMO_CONIC_DUMMY*/
 
 	return TRUE;
 }
 
 
-#ifdef MAEMO_CONIC_DUMMY
-static gboolean
-on_dummy_connection_check (gpointer user_data)
-{
-	TnyMaemoConicDevice *self = NULL;
-	TnyMaemoConicDevicePriv *priv = NULL;
-	gchar *filename = NULL;
-	gchar *contents = NULL;
-	GError* error = NULL;
-	gboolean test = FALSE;
-		
-	self = TNY_MAEMO_CONIC_DEVICE (user_data);
 
-	priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
-	
-	/* Check whether the enviroment variable has changed, 
-	 * so we can fake a connection change: */
-	filename = get_dummy_filename ();
-	
-	test = g_file_get_contents (filename, &contents, NULL, &error);
-
-	if(error) {
-		/* g_debug("%s: error from g_file_get_contents(): %s\n", __FUNCTION__, error->message); */
-		g_error_free (error);
-		error = NULL;
-	}
-	
-	if (!test || !contents) {
-		/* g_debug ("DEBUG1: %s: priv->iap = %s\n", priv->iap); */
-		/* Default to the first debug connection: */
-		contents = g_strdup ("debug id0");
-	}
-	
-	if (contents)
-		g_strstrip(contents);
-
-	if ((priv->iap == NULL) || (strcmp (contents, priv->iap) != 0)) {
-		if (priv->iap) {
-			g_free (priv->iap);
-			priv->iap = NULL;
-		}
-			
-		/* We store even the special "none" text, so we can detect changes. */
-		priv->iap = g_strdup (contents);
-		
-		if (strcmp (priv->iap, MAEMO_CONIC_DUMMY_IAP_ID_NONE) == 0) {
-			priv->is_online = FALSE;
-			g_debug ("DEBUG: TnyMaemoConicDevice: %s:\n  Dummy connection changed to no connection.\n", __FUNCTION__);
-		} else {
-			priv->is_online = TRUE;
-			g_debug ("DEBUG: TnyMaemoConicDevice: %s:\n  Dummy connection changed to '%s\n", __FUNCTION__, priv->iap);
-		}
-		
-		g_debug ("DEBUG1: %s: emitting is_online=%d\n", __FUNCTION__, priv->is_online);
-
-		conic_emit_status (TNY_DEVICE (self), priv->is_online);
-
-	}
-	
-	g_free (contents);
-	g_free (filename);
-	
-	return TRUE;
-}
-#endif /* MAEMO_CONIC_DUMMY */
-
 /**
  * tny_maemo_conic_device_get_current_iap_id:
  * @self: a #TnyDevice object
@@ -523,13 +417,6 @@
 
 	priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
 
-#ifdef MAEMO_CONIC_DUMMY
-	on_dummy_connection_check (self);
-	/* Handle the special "none" text: */
-	if (priv->iap && (strcmp (priv->iap, MAEMO_CONIC_DUMMY_IAP_ID_NONE) == 0))
-		return NULL;
-#endif
-
 	return priv->iap;
 }
 
@@ -550,33 +437,18 @@
 ConIcIap*
 tny_maemo_conic_device_get_iap (TnyMaemoConicDevice *self, const gchar *iap_id)
 {
-#ifdef MAEMO_CONIC_DUMMY
-	ConIcIap *iap = NULL;
-#else
 	TnyMaemoConicDevicePriv *priv = NULL;
-#endif
-
 	g_return_val_if_fail (TNY_IS_MAEMO_CONIC_DEVICE(self), NULL);
 	g_return_val_if_fail (iap_id, NULL);
-
-#ifdef MAEMO_CONIC_DUMMY 
-	/* Note that we have re-declared the private struct so that we 
-	 * can do this, which is very bad and fragile: */
-	iap = g_object_new (CON_IC_TYPE_IAP, NULL);
-	iap->id = g_strdup(iap_id);
-	iap->name = g_strdup_printf("%s name", iap->id);
-	return iap;
-#else
 	priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
 	g_return_val_if_fail (priv->cnx, NULL);
 
-	/* Note that it is very unusual to return a reference from a get_() function, 
-	 * but we must do so because that mistake has already been made in 
-	 * con_ic_connection_get_iap().
-	 * If we just unref immediately then libconic might destroy the object.
-	 */
+	/* Note that it is very unusual to return a reference from a get_() 
+	 * function, but we must do so because that mistake has already been 
+	 * made in con_ic_connection_get_iap (). If we just unref immediately 
+	 * then libconic might destroy the object. */
+
 	return con_ic_connection_get_iap (priv->cnx, iap_id);
-#endif
 }
 
 
@@ -593,56 +465,21 @@
 GSList*
 tny_maemo_conic_device_get_iap_list (TnyMaemoConicDevice *self)
 {
-#ifdef MAEMO_CONIC_DUMMY
-	GSList* result = NULL;
-	int i = 0;
-#else
 	TnyMaemoConicDevicePriv *priv = NULL;
-#endif /* MAEMO_CONIC_DUMMY */
-	
-	g_return_val_if_fail (TNY_IS_MAEMO_CONIC_DEVICE(self), NULL);
 
-#ifdef MAEMO_CONIC_DUMMY
-
-	/* libconic does not return a list of connections when running 
-	 * in scratchbox, though it might do this in future when 
-	 * "ethernet support" is implemented.
-	 * So we return a fake list so we can exercise funcationality 
-	 * that uses connections: */
-	for (i = 0; i < 10; ++i) {
-		/* con_ic_iap_new (id) would checkc for a gconf dir and 
-		 * fails, though _new() functions should just call g_object_new().
-		 *
-		gchar *id = g_strdup_printf("debug id%d", i);
-		ConIcIap *iap = con_ic_iap_new (id);
-		g_free (id);
-		*/
-		
-		/* Note that we have re-declared the private struct so that we 
-		 * can do this, which is very bad and fragile: */
-		ConIcIap *iap = g_object_new (CON_IC_TYPE_IAP, NULL);
-		iap->id = g_strdup_printf("debug id%d", i);
-		iap->name = g_strdup_printf("%s name", iap->id);
-
-		result = g_slist_append (result, iap);	
-	}
-	
-	return result;
-#else
 	priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
 	g_return_val_if_fail (priv->cnx, NULL);
 
 	return con_ic_connection_get_all_iaps (priv->cnx);
-#endif
 }
 
 
 /**
  * tny_maemo_conic_device_free_iap_list:
  * @self: a #TnyDevice object
- *  
+ * @cnx_list: a list of IAP objects
+ *
  * free a  list of IAP objects retrieved from tny_maemo_conic_device_get_iap_list
- *  
  **/
 void
 tny_maemo_conic_device_free_iap_list (TnyMaemoConicDevice *self, GSList* cnx_list)
@@ -653,10 +490,10 @@
 		cur = g_slist_next (cur);
 	}
 	g_slist_free (cnx_list);
+	return;
 }
 
 
-
 static void 
 tny_maemo_conic_device_force_online (TnyDevice *device)
 {
@@ -666,20 +503,15 @@
 	g_return_if_fail (TNY_IS_DEVICE(device));
 	self = TNY_MAEMO_CONIC_DEVICE (device);
 	priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
-	
+
 	already_online = tny_maemo_conic_device_is_online (device);
 
-#ifdef DEBUG
-	g_message (__FUNCTION__);
-	g_message ("force online, current status is: %s", already_online ? "online" : "offline");
-#endif
-
 	priv->forced = TRUE;
+	priv->is_online = TRUE;
 
 	/* Signal if it changed: */
 	if (!already_online)
-		g_signal_emit (device, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED],
-		       0, TRUE);
+		g_signal_emit (device, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED], 0, TRUE);
 }
 
 
@@ -688,24 +520,21 @@
 {
 	TnyMaemoConicDevice *self;
 	TnyMaemoConicDevicePriv *priv;
-#ifndef MAEMO_CONIC_DUMMY
 	gboolean already_offline = FALSE;
-#endif
 
 	g_return_if_fail (TNY_IS_DEVICE(device));
 	self = TNY_MAEMO_CONIC_DEVICE (device);
 	priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
 
-#ifdef MAEMO_CONIC_DUMMY
-	return;
-#else
 	already_offline = !tny_maemo_conic_device_is_online (device);
 	priv->forced = TRUE;
+	priv->is_online = FALSE;
+
 	/* Signal if it changed: */
 	if (!already_offline)
 		conic_emit_status (device, FALSE);
+
 	return;
-#endif
 }
 
 static gboolean
@@ -713,10 +542,6 @@
 {
 	g_return_val_if_fail (TNY_IS_DEVICE(self), FALSE);
 
-#ifdef MAEMO_CONIC_DUMMY
-	on_dummy_connection_check (self);
-#endif /* MAEMO_CONIC_DUMMY */
-
 	return TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self)->is_online;
 }
 
@@ -728,45 +553,31 @@
 	TnyMaemoConicDevicePriv *priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
 
 	/* We should not have a real is_online, based on what libconic has told us: */
+
 	priv->forced = FALSE;
 	priv->iap = NULL;
 	priv->is_online = dnsmasq_has_resolv ();
 
-
-#ifndef MAEMO_CONIC_DUMMY
 	priv->cnx = con_ic_connection_new ();
-	if (!priv->cnx) {
+
+	if (!priv->cnx)
 		g_warning ("con_ic_connection_new failed. The TnyMaemoConicDevice will be useless.");
-	}
 
 	/* This might be necessary to make the connection object actually emit 
 	 * the signal, though the documentation says that they should be sent 
 	 * even when this is not set, when we explicitly try to connect. The 
 	 * signal still does not seem to be emitted. */
-
 	g_object_set (priv->cnx, "automatic-connection-events", TRUE, NULL);
 
 	g_signal_connect (priv->cnx, "connection-event",
 			  G_CALLBACK(on_connection_event), self);
-	
+
 	/* This will get us in connected state only if there is already a connection.
 	 * thus, this will setup our state correctly when we receive the signals. */
-
 	if (!con_ic_connection_connect (priv->cnx, CON_IC_CONNECT_FLAG_AUTOMATICALLY_TRIGGERED))
 		g_warning ("could not send connect dbus message");
-		
-#endif /* MAEMO_CONIC_DUMMY */
 
-
-#ifdef MAEMO_CONIC_DUMMY
-
-	/* Allow debuggers to fake a connection change by setting an environment 
-	 * variable, which we check ever 1 second. This should match one of the 
-	 * fake iap IDs that we created in tny_maemo_conic_device_get_iap_list().*/
-
-	priv->dummy_env_check_timeout = 
-		g_timeout_add (1000, on_dummy_connection_check, self);
-#endif /* MAEMO_CONIC_DUMMY */
+	return;
 }
 
 
@@ -779,6 +590,7 @@
 tny_maemo_conic_device_new (void)
 {
 	TnyMaemoConicDevice *self = g_object_new (TNY_TYPE_MAEMO_CONIC_DEVICE, NULL);
+
 	return TNY_DEVICE (self);
 }
 
@@ -787,25 +599,16 @@
 {
 	TnyMaemoConicDevicePriv *priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (obj);
 
-#ifndef MAEMO_CONIC_DUMMY
 	if (priv->cnx && CON_IC_IS_CONNECTION(priv->cnx)) {
-		if (!tny_maemo_conic_device_disconnect (TNY_MAEMO_CONIC_DEVICE(obj),priv->iap))
-			g_warning ("failed to disconnect dbus message");
+		tny_maemo_conic_device_disconnect (TNY_MAEMO_CONIC_DEVICE(obj),priv->iap);
 		g_object_unref (priv->cnx);
 		priv->cnx = NULL;
 	}
-#else
-	if (priv->dummy_env_check_timeout) {
-		g_source_remove (priv->dummy_env_check_timeout);
-		priv->dummy_env_check_timeout = 0;
-	}
-#endif /* MAEMO_CONIC_DUMMY */
 
 	if (priv->iap) {
 		g_free (priv->iap);
 		priv->iap = NULL;
 	}
-	
 
 	(*parent_class->finalize) (obj);
 }
@@ -823,7 +626,6 @@
 }
 
 
-
 static void 
 tny_maemo_conic_device_class_init (TnyMaemoConicDeviceClass *class)
 {
@@ -874,3 +676,71 @@
 	}
 	return type;
 }
+
+static void 
+stop_loop (TnyMaemoConicDevice *self)
+{
+	TnyMaemoConicDevicePriv *priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
+	if (priv->loop)
+		g_main_loop_quit (priv->loop);
+	return;
+}
+
+
+/**
+ * tny_maemo_conic_device_connect:
+ * @self: a #TnyDevice object
+ * @iap_id: the id of the Internet Access Point (IAP), or NULL for 'any;
+ * 
+ * Try to connect to a specific IAP, or to any if @iap_id == NULL
+ * this calls con_ic_connection_connect(_by_id).
+ * This may show a dialog to allow the user to select a connection, or 
+ * may otherwise take a significant amount of time. This function blocks until 
+ * the connection has either succeeded or failed.
+ * 
+ * Returns TRUE if a connection was made, FALSE otherwise.
+ **/
+gboolean
+tny_maemo_conic_device_connect (TnyMaemoConicDevice *self, const gchar* iap_id)
+{
+	TnyMaemoConicDevicePriv *priv = NULL;
+	gboolean request_failed = FALSE;
+
+	g_return_val_if_fail (TNY_IS_DEVICE(self), FALSE);
+	priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
+
+	g_return_val_if_fail (priv->cnx, FALSE);
+	priv->loop = g_main_loop_new(NULL, FALSE /* not running immediately. */);
+
+	if (iap_id) {
+		if (!con_ic_connection_connect_by_id (priv->cnx, iap_id, CON_IC_CONNECT_FLAG_NONE)) {
+			g_warning ("could not send connect_by_id dbus message");
+			request_failed = TRUE;
+		}
+	} else {
+		if (!con_ic_connection_connect (priv->cnx, CON_IC_CONNECT_FLAG_NONE)) {
+			g_warning ("could not send connect dbus message");
+			request_failed = TRUE;
+		}
+	}
+
+	if (request_failed) {
+		g_object_unref (priv->loop);
+		priv->loop = NULL;
+	}
+	
+	/* Wait for the CON_IC_STATUS_CONNECTED (succeeded) or 
+	 * CON_IC_STATUS_DISCONNECTED event: */
+	 
+	/* This is based on code found in gtk_dialog_run(): */
+	GDK_THREADS_LEAVE();
+	/* Run until g_main_loop_quit() is called by our signal handler. */
+	if (priv->loop)
+		g_main_loop_run (priv->loop);
+	GDK_THREADS_ENTER();
+
+	g_main_loop_unref (priv->loop);
+	priv->loop = NULL;
+
+	return priv->is_online;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]