Maemo: Added basic connect/disconnect functionality to frontend.
authorTobias Brunner <tobias@strongswan.org>
Tue, 21 Sep 2010 13:35:27 +0000 (15:35 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 14 Oct 2010 15:36:18 +0000 (17:36 +0200)
src/frontends/maemo/src/strongswan-status.c

index 24f2442..21ca651 100644 (file)
 #define ICON_SIZE_STATUS 18
 #define ICON_SIZE_BUTTON 48
 
+typedef enum
+{
+       STATUS_DISCONNECTED,
+       STATUS_CONNECTING,
+       STATUS_CONNECTED,
+} StrongswanConnectionStatus;
+
 struct _StrongswanStatusPrivate
 {
        struct {
@@ -51,6 +58,7 @@ struct _StrongswanStatusPrivate
 
        StrongswanConnections *conns;
 
+       StrongswanConnectionStatus status;
        gchar *current;
 };
 
@@ -60,6 +68,45 @@ HD_DEFINE_PLUGIN_MODULE_EXTENDED (StrongswanStatus, strongswan_status, \
                        strongswan_connections_register (G_TYPE_MODULE (plugin)); }, {});
 
 static void
+update_status_menu (StrongswanStatus *plugin)
+{
+       StrongswanStatusPrivate *priv = plugin->priv;
+       switch (priv->status)
+       {
+               case STATUS_DISCONNECTED:
+               {
+                       hildon_button_set_value (HILDON_BUTTON (priv->button),
+                                                                        "Not connected");
+                       hd_status_plugin_item_set_status_area_icon (
+                                                                                       HD_STATUS_PLUGIN_ITEM (plugin),
+                                                                                       priv->icons.status_open);
+                       gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image),
+                                                                          priv->icons.button_open);
+                       break;
+               }
+               case STATUS_CONNECTING:
+               {
+                       gchar *msg = g_strdup_printf ("Connecting to %s...", priv->current);
+                       hildon_button_set_value (HILDON_BUTTON (priv->button), msg);
+                       g_free (msg);
+                       break;
+               }
+               case STATUS_CONNECTED:
+               {
+                       gchar *msg = g_strdup_printf ("Connected to %s", priv->current);
+                       hildon_button_set_value (HILDON_BUTTON (priv->button), msg);
+                       g_free (msg);
+                       hd_status_plugin_item_set_status_area_icon (
+                                                                                       HD_STATUS_PLUGIN_ITEM (plugin),
+                                                                                       priv->icons.status_close);
+                       gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image),
+                                                                          priv->icons.button_close);
+                       break;
+               }
+       }
+}
+
+static void
 dialog_response (GtkDialog *dialog, gint response_id, StrongswanStatus *plugin)
 {
        StrongswanStatusPrivate *priv = plugin->priv;
@@ -68,20 +115,234 @@ dialog_response (GtkDialog *dialog, gint response_id, StrongswanStatus *plugin)
 }
 
 static void
+connect_callback (const gchar* interface, const gchar* method,
+                                 osso_rpc_t *retval, StrongswanStatus *plugin)
+{
+       gchar *msg = NULL;
+       StrongswanStatusPrivate *priv = plugin->priv;
+
+       if (retval->type == DBUS_TYPE_STRING)
+       {       /* unfortunately, this is the only indication that an error occured
+                * for asynchronous calls */
+               msg = g_strdup_printf ("Failed to initiate connection: %s",
+                                                          retval->value.s);
+       }
+       else if (retval->type != DBUS_TYPE_BOOLEAN)
+       {
+               msg = g_strdup_printf ("Failed to initiate connection: return type");
+       }
+       else if (!retval->value.b)
+       {
+               msg = g_strdup_printf ("Failed to connect to %s", priv->current);
+       }
+
+       if (msg)
+       {
+               /* connecting failed */
+               priv->current = (g_free (priv->current), NULL);
+               priv->status = STATUS_DISCONNECTED;
+       }
+       else
+       {
+               msg = g_strdup_printf ("Successfully connected to %s", priv->current);
+               priv->status = STATUS_CONNECTED;
+       }
+
+       hildon_banner_show_information (NULL, NULL, msg);
+       g_free (msg);
+
+       update_status_menu (plugin);
+
+       if (priv->dialog)
+       {
+               gtk_widget_set_sensitive (priv->box, TRUE);
+               hildon_gtk_window_set_progress_indicator (GTK_WINDOW (priv->dialog), 0);
+
+               gtk_dialog_response (GTK_DIALOG (priv->dialog), GTK_RESPONSE_OK);
+       }
+}
+
+static void
+update_dialog_connecting (StrongswanStatus *plugin)
+{
+       StrongswanStatusPrivate *priv = plugin->priv;
+
+       gtk_widget_set_sensitive (priv->box, FALSE);
+       hildon_gtk_window_set_progress_indicator (GTK_WINDOW (priv->dialog), 1);
+}
+
+static void
 connect_clicked (HildonButton *button, StrongswanStatus *plugin)
 {
        StrongswanStatusPrivate *priv = plugin->priv;
-       gtk_dialog_response (GTK_DIALOG (priv->dialog), GTK_RESPONSE_OK);
+
+       priv->current = hildon_touch_selector_get_current_text (
+                                                                       HILDON_TOUCH_SELECTOR (priv->selector));
+       priv->status = STATUS_CONNECTING;
+       update_dialog_connecting (plugin);
+       update_status_menu (plugin);
+
+       StrongswanConnection *conn = strongswan_connections_get_connection (
+                                                                                                                       priv->conns,
+                                                                                                                       priv->current);
+       if (!conn)
+       {       /* emulate a callback call */
+               osso_rpc_t retval;
+               retval.type = DBUS_TYPE_STRING;
+               retval.value.s = g_strdup ("not found");
+               connect_callback (NULL, NULL, &retval, plugin);
+               osso_rpc_free_val (&retval);
+               return;
+       }
+
+       /* this call on the system bus is only needed to start charon as root */
+       osso_rpc_t retval;
+       osso_return_t result;
+       result = osso_rpc_run_system (priv->context,
+                                                                 OSSO_CHARON_SERVICE,
+                                                                 OSSO_CHARON_OBJECT,
+                                                                 OSSO_CHARON_IFACE,
+                                                                 "Start",
+                                                                 &retval,
+                                                                 DBUS_TYPE_INVALID);
+       osso_rpc_free_val (&retval);
+       if (result != OSSO_OK)
+       {
+               retval.type = DBUS_TYPE_STRING;
+               retval.value.s = g_strdup ("couldn't connect to charon");
+               connect_callback (NULL, NULL, &retval, plugin);
+               osso_rpc_free_val (&retval);
+               return;
+       }
+
+       gchar *c_host, *c_cert, *c_user, *c_pass;
+       g_object_get (conn,
+                                 "host", &c_host,
+                                 "cert", &c_cert,
+                                 "user", &c_user,
+                                 "pass", &c_pass,
+                                 NULL);
+
+       osso_rpc_async_run (priv->context,
+                                               OSSO_CHARON_SERVICE,
+                                               OSSO_CHARON_OBJECT,
+                                               OSSO_CHARON_IFACE,
+                                               "Connect",
+                                               (osso_rpc_async_f*)connect_callback,
+                                               plugin,
+                                               DBUS_TYPE_STRING, priv->current,
+                                               DBUS_TYPE_STRING, c_host,
+                                               DBUS_TYPE_STRING, c_cert,
+                                               DBUS_TYPE_STRING, c_user,
+                                               DBUS_TYPE_STRING, c_pass,
+                                               DBUS_TYPE_INVALID);
+
+       g_free (c_host);
+       g_free (c_cert);
+       g_free (c_user);
+       g_free (c_pass);
 }
 
 static void
 disconnect_clicked (HildonButton *button, StrongswanStatus *plugin)
 {
+       osso_return_t result;
+       osso_rpc_t retval;
+       gchar *msg;
        StrongswanStatusPrivate *priv = plugin->priv;
+
+       gtk_widget_set_sensitive (priv->box, FALSE);
+       hildon_gtk_window_set_progress_indicator (GTK_WINDOW (priv->dialog), 1);
+
+       result = osso_rpc_run_system (priv->context,
+                                               OSSO_CHARON_SERVICE,
+                                               OSSO_CHARON_OBJECT,
+                                               OSSO_CHARON_IFACE,
+                                               "Disconnect",
+                                               &retval,
+                                               DBUS_TYPE_INVALID);
+
+       gtk_widget_set_sensitive (priv->box, TRUE);
+       hildon_gtk_window_set_progress_indicator (GTK_WINDOW (priv->dialog), 0);
+
+       if (result == OSSO_OK)
+       {
+               msg = g_strdup_printf ("Successfully disconnected from %s",
+                                                          priv->current);
+       }
+       else
+       {
+               msg = g_strdup_printf ("Failed to disconnect from %s", priv->current);
+       }
+       hildon_banner_show_information (NULL, NULL, msg);
+       g_free (msg);
+
+       priv->current = (g_free (priv->current), NULL);
+       priv->status = STATUS_DISCONNECTED;
+
+       update_status_menu (plugin);
+
        gtk_dialog_response (GTK_DIALOG (priv->dialog), GTK_RESPONSE_OK);
 }
 
 static void
+setup_dialog_disconnected (StrongswanStatus *plugin)
+{
+       StrongswanStatusPrivate *priv = plugin->priv;
+
+       GtkWidget *vbox = GTK_DIALOG (priv->dialog)->vbox;
+       GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
+       priv->box = hbox;
+       GtkWidget *button = hildon_picker_button_new (
+                                                       HILDON_SIZE_FINGER_HEIGHT |
+                                                       HILDON_SIZE_AUTO_WIDTH,
+                                                       HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
+       hildon_button_set_title (HILDON_BUTTON (button), "Connection:");
+       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+
+       GtkWidget *selector = hildon_touch_selector_new ();
+       priv->selector = selector;
+       GtkTreeModel *model = strongswan_connections_get_model (priv->conns);
+       hildon_touch_selector_append_text_column (
+                                                       HILDON_TOUCH_SELECTOR (selector),
+                                                       model,
+                                                       TRUE);
+       hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button),
+                                                                          HILDON_TOUCH_SELECTOR (selector));
+
+       button = hildon_button_new_with_text (
+                                                       HILDON_SIZE_FINGER_HEIGHT |
+                                                       HILDON_SIZE_AUTO_WIDTH,
+                                                       HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
+                                                       "Connect", NULL);
+       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+       g_signal_connect (button, "clicked", G_CALLBACK (connect_clicked),
+                                         plugin);
+}
+
+static void
+setup_dialog_connected (StrongswanStatus *plugin)
+{
+       StrongswanStatusPrivate *priv = plugin->priv;
+
+       GtkWidget *vbox = GTK_DIALOG (priv->dialog)->vbox;
+       GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
+       priv->box = hbox;
+       GtkWidget *button = hildon_button_new_with_text (
+                                                       HILDON_SIZE_FINGER_HEIGHT |
+                                                       HILDON_SIZE_AUTO_WIDTH,
+                                                       HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
+                                                       "Disconnect", priv->current);
+       hildon_button_set_style (HILDON_BUTTON (button),
+                                                        HILDON_BUTTON_STYLE_PICKER);
+       g_signal_connect (button, "clicked", G_CALLBACK (disconnect_clicked),
+                                         plugin);
+       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+}
+
+static void
 button_clicked (HildonButton *button,  StrongswanStatus *plugin)
 {
        StrongswanStatusPrivate *priv = plugin->priv;
@@ -91,56 +352,18 @@ button_clicked (HildonButton *button,  StrongswanStatus *plugin)
        g_signal_connect (priv->dialog, "response",
                                          G_CALLBACK (dialog_response), plugin);
 
-       GtkWidget *vbox = GTK_DIALOG (priv->dialog)->vbox;
-
-       if (priv->current)
-       {
-               /* connected case */
-               GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
-               priv->box = hbox;
-               GtkWidget *button = hildon_button_new_with_text (
-                                                               HILDON_SIZE_FINGER_HEIGHT |
-                                                               HILDON_SIZE_AUTO_WIDTH,
-                                                               HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
-                                                               "Disconnect", priv->current);
-               hildon_button_set_style (HILDON_BUTTON (button),
-                                                                HILDON_BUTTON_STYLE_PICKER);
-               g_signal_connect (button, "clicked", G_CALLBACK (disconnect_clicked),
-                                                 plugin);
-               gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
-               gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-       }
-       else
+       switch (priv->status)
        {
-               /* unconnected case */
-               GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
-               priv->box = hbox;
-               GtkWidget *button = hildon_picker_button_new (
-                                                               HILDON_SIZE_FINGER_HEIGHT |
-                                                               HILDON_SIZE_AUTO_WIDTH,
-                                                               HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
-               hildon_button_set_title (HILDON_BUTTON (button), "Connection:");
-               gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
-
-               GtkWidget *selector = hildon_touch_selector_new ();
-               priv->selector = selector;
-               GtkTreeModel *model = strongswan_connections_get_model (priv->conns);
-               hildon_touch_selector_append_text_column (
-                                                               HILDON_TOUCH_SELECTOR (selector),
-                                                               model,
-                                                               TRUE);
-               hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button),
-                                                                                  HILDON_TOUCH_SELECTOR (selector));
-
-               button = hildon_button_new_with_text (
-                                                               HILDON_SIZE_FINGER_HEIGHT |
-                                                               HILDON_SIZE_AUTO_WIDTH,
-                                                               HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
-                                                               "Connect", NULL);
-               gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
-               gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-               g_signal_connect (button, "clicked", G_CALLBACK (connect_clicked),
-                                                 plugin);
+               case STATUS_DISCONNECTED:
+                       setup_dialog_disconnected (plugin);
+                       break;
+               case STATUS_CONNECTING:
+                       setup_dialog_disconnected (plugin);
+                       update_dialog_connecting (plugin);
+                       break;
+               case STATUS_CONNECTED:
+                       setup_dialog_connected (plugin);
+                       break;
        }
 
        gtk_widget_show_all (priv->dialog);