07f277e7291fcce8a7d285c2e054849cc30cb698
[jenirok] / src / common / connectionmanager.cpp
1 /*
2  * This file is part of Jenirok.
3  *
4  * Jenirok is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Jenirok is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with Jenirok.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18
19 #include <QDebug>
20 #include <QApplication>
21 #include <QtCore/QTimerEvent>
22 #include <QtCore/QVariant>
23 #include <icd/dbus_api.h>
24 #include "connectionmanager.h"
25
26
27 ConnectionManager::ConnectionManager(QObject* parent): QObject(parent),
28 ready_(false), connected_(false), timeout_(false), ignoreStateChanges_(false),
29 timer_(0)
30 {
31     QDBusConnection systemBus = QDBusConnection::systemBus();
32
33     icd2interface_ = new QDBusInterface(ICD_DBUS_API_INTERFACE,
34                                         ICD_DBUS_API_PATH, ICD_DBUS_API_INTERFACE,
35                                         systemBus, this);
36
37     systemBus.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
38                       ICD_DBUS_API_INTERFACE, ICD_DBUS_API_STATE_SIG,
39                       this, SLOT(stateChange(const QDBusMessage&)));
40
41     systemBus.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
42                       ICD_DBUS_API_INTERFACE, ICD_DBUS_API_CONNECT_SIG,
43                       this, SLOT(connectionChange(const QDBusMessage&)));
44
45
46 }
47
48 ConnectionManager::~ConnectionManager()
49 {
50     QDBusConnection systemBus = QDBusConnection::systemBus();
51
52     systemBus.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
53                          ICD_DBUS_API_INTERFACE, ICD_DBUS_API_STATE_SIG,
54                          this, SLOT(stateChange(const QDBusMessage&)));
55
56     systemBus.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH,
57                          ICD_DBUS_API_INTERFACE, ICD_DBUS_API_CONNECT_SIG,
58                          this, SLOT(connectionChange(const QDBusMessage&)));
59 }
60
61 bool ConnectionManager::connect()
62 {
63     ready_ = false;
64     ignoreStateChanges_ = true;
65     unsigned int flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_USER_EVENT);
66     icd2interface_->call(ICD_DBUS_API_CONNECT_REQ, QVariant(flags));
67     waitSignal();
68     return connected_;
69 }
70
71 bool ConnectionManager::disconnect()
72 {
73     if(!connected_)
74     {
75         return false;
76     }
77
78     ready_ = false;
79     ignoreStateChanges_ = false;
80     unsigned int flags = static_cast<unsigned int>(ICD_CONNECTION_FLAG_USER_EVENT);
81     icd2interface_->call(ICD_DBUS_API_DISCONNECT_REQ, QVariant(flags));
82     connected_ = false;
83     return true;
84 }
85
86 bool ConnectionManager::isConnected()
87 {
88     ready_ = false;
89     ignoreStateChanges_ = false;
90     QDBusMessage rep = icd2interface_->call(ICD_DBUS_API_STATE_REQ);
91
92     unsigned int numOfReplies = rep.arguments().value(0).value<unsigned int>();
93
94     if(numOfReplies == 0)
95     {
96         return false;
97     }
98
99     waitSignal();
100     return connected_;
101 }
102
103 void ConnectionManager::stateChange(const QDBusMessage& rep)
104 {
105     if(ignoreStateChanges_)
106     {
107         return;
108     }
109
110     unsigned int status = rep.arguments().value(7).value<unsigned int>();
111
112     switch(status)
113     {
114     case ICD_STATE_CONNECTING:
115         break;
116     case ICD_STATE_CONNECTED:
117         connected_ = true;
118         ready_ = true;
119         break;
120     case ICD_STATE_DISCONNECTING:
121         break;
122     case ICD_STATE_DISCONNECTED:
123         connected_ = false;
124         ready_ = true;
125         break;
126     case ICD_STATE_LIMITED_CONN_ENABLED:
127         connected_ = true;
128         ready_ = true;
129         break;
130     case ICD_STATE_LIMITED_CONN_DISABLED:
131         connected_ = false;
132         ready_ = true;
133         break;
134     case ICD_STATE_SEARCH_START:
135         break;
136     case ICD_STATE_SEARCH_STOP:
137         break;
138     case ICD_STATE_INTERNAL_ADDRESS_ACQUIRED:
139         break;
140     default:
141         qDebug() << "Unknown connection status";
142         break;
143     }
144
145 }
146
147 void ConnectionManager::connectionChange(const QDBusMessage& rep)
148 {
149     unsigned int status = rep.arguments().value(6).value<unsigned int>();
150
151     switch(status)
152     {
153     case ICD_CONNECTION_SUCCESSFUL:
154         connected_ = true;
155         ready_ = true;
156         break;
157     case ICD_CONNECTION_NOT_CONNECTED:
158         connected_ = false;
159         ready_ = true;
160         break;
161     case ICD_CONNECTION_DISCONNECTED:
162         connected_ = false;
163         ready_ = true;
164         break;
165     default:
166         qDebug() << "Unknown connection status";
167         break;
168     }
169 }
170
171 bool ConnectionManager::waitSignal()
172 {
173     timeout_ = false;
174     timer_ = startTimer(TIMEOUT);
175
176     while(!ready_ && !timeout_)
177     {
178         QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
179     }
180
181     killTimer(timer_);
182
183     return ready_ || !timeout_;
184 }
185
186 void ConnectionManager::timerEvent(QTimerEvent* event)
187 {
188     Q_UNUSED(event);
189     killTimer(timer_);
190     timeout_ = true;
191     timer_ = 0;
192
193     qDebug() << "Connection request timed out";
194 }