Better connection handling in daemon.
[jenirok] / src / common / connectionmanager.cpp
index 174228e..14c0b0a 100644 (file)
  */
 
 #include <QDebug>
-#include <glib-object.h>
-#include <dbus/dbus-glib-lowlevel.h>
+#include <QApplication>
+#include <QtCore/QTimerEvent>
+#include <QtCore/QVariant>
+#include <icd/dbus_api.h>
 #include "connectionmanager.h"
 
-ConnectionManager* ConnectionManager::instance_ = 0;
 
-ConnectionManager::ConnectionManager(): connection_(0), connected_(false)
+ConnectionManager::ConnectionManager(QObject* parent): QObject(parent),
+ready_(false), connected_(false), timeout_(false), ignoreStateChanges_(false),
+timer_(0)
 {
-    DBusError err;
-    DBusConnection* conn;
-    dbus_error_init(&err);
-    conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
+    QDBusConnection systemBus = QDBusConnection::systemBus();
 
-    if(conn)
-    {
-        dbus_connection_setup_with_g_main(conn, NULL);
-    }
-    else
-    {
-        qDebug() << "Unable to connect to DBUS: " << err.message;
-        dbus_error_free(&err);
-    }
+    icd2interface_ = new QDBusInterface(ICD_DBUS_API_INTERFACE,
+                                        ICD_DBUS_API_PATH, ICD_DBUS_API_INTERFACE,
+                                        systemBus, this);
 
-    connection_ = con_ic_connection_new();
+    systemBus.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
+                      ICD_DBUS_API_INTERFACE, ICD_DBUS_API_STATE_SIG,
+                      this, SLOT(stateChange(const QDBusMessage&)));
 
-    g_signal_connect(G_OBJECT(connection_), "connection-event", G_CALLBACK(connectionHandler), NULL);
-
-
-}
+    systemBus.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
+                      ICD_DBUS_API_INTERFACE, ICD_DBUS_API_CONNECT_SIG,
+                      this, SLOT(connectionChange(const QDBusMessage&)));
 
-ConnectionManager& ConnectionManager::instance()
-{
-    if(!instance_)
-    {
-        instance_ = new ConnectionManager;
-    }
 
-    return *instance_;
 }
 
 bool ConnectionManager::connect()
 {
-    return con_ic_connection_connect(connection_, CON_IC_CONNECT_FLAG_NONE);
+    ready_ = false;
+    ignoreStateChanges_ = true;
+    unsigned int flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_USER_EVENT);
+    icd2interface_->call(ICD_DBUS_API_CONNECT_REQ, QVariant(flags));
+    waitSignal();
+    return connected_;
 }
 
 bool ConnectionManager::disconnect()
 {
-    return con_ic_connection_disconnect(connection_);
+    if(!connected_)
+    {
+        return false;
+    }
+
+    ready_ = false;
+    ignoreStateChanges_ = false;
+    unsigned int flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_USER_EVENT);
+    icd2interface_->call(ICD_DBUS_API_DISCONNECT_REQ, QVariant(flags));
+    connected_ = false;
+    return true;
 }
 
 bool ConnectionManager::isConnected()
 {
+    ready_ = false;
+    ignoreStateChanges_ = false;
+    QDBusMessage rep = icd2interface_->call(ICD_DBUS_API_STATE_REQ);
+
+    unsigned int numOfReplies = rep.arguments().value(0).value<unsigned int>();
+
+    if(numOfReplies == 0)
+    {
+        return false;
+    }
+
+    waitSignal();
     return connected_;
 }
-void ConnectionManager::connectionHandler(ConIcConnection *connection,
-                                          ConIcConnectionEvent *event,
-                                          gpointer user_data)
+
+void ConnectionManager::stateChange(const QDBusMessage& rep)
 {
-    Q_UNUSED(connection);
-    Q_UNUSED(user_data);
+    if(ignoreStateChanges_)
+    {
+        return;
+    }
 
-    ConIcConnectionStatus status = con_ic_connection_event_get_status(event);
+    unsigned int status = rep.arguments().value(7).value<unsigned int>();
 
     switch(status)
     {
-
-    case CON_IC_STATUS_CONNECTED:
+    case ICD_STATE_CONNECTING:
+        qDebug() << "Connecting";
+        break;
+    case ICD_STATE_CONNECTED:
+        connected_ = true;
+        ready_ = true;
         qDebug() << "Connected";
-        instance_->emit connected();
-        instance_->connected_ = true;
         break;
-
-    case CON_IC_STATUS_DISCONNECTING:
-    case CON_IC_STATUS_NETWORK_UP:
+    case ICD_STATE_DISCONNECTING:
+        qDebug() << "Disconnecting";
+        break;
+    case ICD_STATE_DISCONNECTED:
+        connected_ = false;
+        ready_ = true;
+        qDebug() << "Disconnected";
+        break;
+    case ICD_STATE_LIMITED_CONN_ENABLED:
+        connected_ = true;
+        ready_ = true;
+        qDebug() << "Limited connection enabled";
         break;
+    case ICD_STATE_LIMITED_CONN_DISABLED:
+        connected_ = false;
+        ready_ = true;
+        qDebug() << "Limited connection disabled";
+        break;
+    case ICD_STATE_SEARCH_START:
+        qDebug() << "Search start";
+        break;
+    case ICD_STATE_SEARCH_STOP:
+        qDebug() << "Search stop";
+        break;
+    case ICD_STATE_INTERNAL_ADDRESS_ACQUIRED:
+        qDebug() << "Internal address acquired";
+        break;
+    default:
+        qDebug() << "Unknown connection status";
+        break;
+    }
+
+}
+
+void ConnectionManager::connectionChange(const QDBusMessage& rep)
+{
+    unsigned int status = rep.arguments().value(6).value<unsigned int>();
 
-    case CON_IC_STATUS_DISCONNECTED:
-        ConIcConnectionError err = con_ic_connection_event_get_error(event);
-        switch(err)
-        {
-        case CON_IC_CONNECTION_ERROR_NONE:
-        case CON_IC_CONNECTION_ERROR_USER_CANCELED:
-            qDebug() << "Disconnected";
-            instance_->emit disconnected();
-            instance_->connected_ = false;
-            break;
-
-        case CON_IC_CONNECTION_ERROR_INVALID_IAP:
-            qDebug() << "Invalid IAP";
-            instance_->emit error("Invalid IAP");
-            break;
-
-        case CON_IC_CONNECTION_ERROR_CONNECTION_FAILED:
-            qDebug() << "Connection failed";
-            instance_->emit error("Connection failed");
-            break;
-
-        default:
-            break;
-        }
+    switch(status)
+    {
+    case ICD_CONNECTION_SUCCESSFUL:
+        connected_ = true;
+        ready_ = true;
+        qDebug() << "Connection successful";
+        break;
+    case ICD_CONNECTION_NOT_CONNECTED:
+        connected_ = false;
+        ready_ = true;
+        qDebug() << "Connection not connected";
+        break;
+    case ICD_CONNECTION_DISCONNECTED:
+        connected_ = false;
+        ready_ = true;
+        qDebug() << "Connection disconnected";
         break;
+    default:
+        qDebug() << "Unknown connection status";
+        break;
+    }
+}
+
+bool ConnectionManager::waitSignal()
+{
+    timeout_ = false;
+    timer_ = startTimer(TIMEOUT);
+
+    while(!ready_ && !timeout_)
+    {
+        QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
     }
+
+    killTimer(timer_);
+
+    return ready_ || !timeout_;
+}
+
+void ConnectionManager::timerEvent(QTimerEvent* event)
+{
+    Q_UNUSED(event);
+    killTimer(timer_);
+    timeout_ = true;
+    timer_ = 0;
+
+    qDebug() << "Connection request timed out";
 }