c4dbfb40ada4eba2d281ca97e6cbe94fac329e77
[vicar] / src / vicar-telepathy / src / connection.cpp
1 /*
2 @version: 0.5
3 @author: Sudheer K. <scifi1947 at gmail.com>
4 @license: GNU General Public License
5
6 Based on Telepathy-SNOM with copyright notice below.
7 */
8
9 /*
10  * Telepathy SNOM VoIP phone connection manager
11  * Copyright (C) 2006 by basyskom GmbH
12  *  @author Tobias Hunger <info@basyskom.de>
13  *
14  * This library is free software; you can redisQObject::tribute it and/or
15  * modify it under the terms of the GNU Lesser General Public
16  * License version 2.1 as published by the Free Software Foundation.
17  *
18  * This library is disQObject::tributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Lesser General Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public
24  * License along with this library; if not, write to the
25  * Free Software Foundation, Inc.,
26  * 51 Franklin SQObject::treet, Fifth Floor, Boston, MA  02110-1301  USA
27  */
28
29 #include "connection.h"
30 #include "connectionadaptor.h"
31 #include "connectioninterfacerequestsadaptor.h"
32 #include "connectioninterfacerequeststypes.h"
33 #include "connectioninterfacecapabilitiesadaptor.h"
34 #include "connectioninterfacecapabilitiestypes.h"
35 #include "names.h"
36 #include "vicarcallrouterproxy.h"
37
38 #include <QtCore/QDebug>
39 #include <QtCore/QCoreApplication>
40 #include <QtCore/QVariantMap>
41 #include <QDBusMessage>
42 #include <QDBusReply>
43
44
45 namespace
46 {
47 static const QString protocol_vicar("tel");
48
49 static const QString connection_service_name_prefix("org.freedesktop.Telepathy.Connection.vicar." + protocol_vicar + '.');
50 static const QString connection_object_path_prefix("/org/freedesktop/Telepathy/Connection/vicar/" + protocol_vicar + '/');
51 static const QString requests_interface("org.freedesktop.Telepathy.Connection.Interface.Requests");
52 }
53
54 using namespace org::maemo;
55
56
57 class ConnectionPrivate
58 {
59 public:
60     ConnectionPrivate(Connection * p,
61                       const QString & acc) :
62         account(acc),
63         connection_status(Connection::Disconnected),
64         adaptor(new ConnectionAdaptor(p)),
65         connIfaceReqsAdaptor(new ConnectionInterfaceRequestsAdaptor(p)),
66         parent(p)
67     {
68         Q_ASSERT(0 != adaptor);
69     }
70
71     ~ConnectionPrivate()
72     {
73         qDebug() << "VICaR: Connection Destructing";
74     }
75
76     const QString account;
77
78     Connection::Status connection_status;
79     ConnectionAdaptor * adaptor;
80     ConnectionInterfaceRequestsAdaptor * connIfaceReqsAdaptor;
81     Connection * const parent;
82 };
83
84 // ---------------------------------------------------------------------------
85
86 Connection::Connection(const QString & account,
87                         QObject * parent) :
88     QObject(parent),
89     d(new ConnectionPrivate(this, account))
90 {
91     Q_ASSERT(0 != d);
92     Q_ASSERT(!account.isEmpty());
93
94     /*  -- Set the Dynamic property "Interfaces" ---
95
96         Apparently it is not sufficient to implement an additional interface like Conn.I.Requests.
97         We have to assign the list of additional interfaces to the DBus Property Interfaces.
98
99         The actual DBus property "Interfaces" is declared in ConnectionAdaptor class,
100          which is our Connection Interface implementation.
101      */
102
103     QStringList interfaces = QStringList(requests_interface);
104     this->setProperty("Interfaces",interfaces);
105
106
107     //Set the property RequestableChannelClasses
108     org::freedesktop::Telepathy::RequestableChannelClassList requestableChannelClasses;
109
110     uint targetHandleType(1);
111
112     org::freedesktop::Telepathy::RequestableChannelClass requestableChannelClass1;
113     requestableChannelClass1.fixedProperties.insert("org.freedesktop.Telepathy.Channel.TargetHandleType",targetHandleType);
114     requestableChannelClass1.fixedProperties.insert("org.freedesktop.Telepathy.Channel.ChannelType","org.freedesktop.Telepathy.Channel.Type.StreamedMedia");
115
116     requestableChannelClass1.allowedProperties.append("org.freedesktop.Telepathy.Channel.TargetHandle");
117     requestableChannelClass1.allowedProperties.append("org.freedesktop.Telepathy.Channel.Type.StreamedMedia.InitialAudio");
118
119     requestableChannelClasses.append(requestableChannelClass1);
120
121     org::freedesktop::Telepathy::RequestableChannelClass requestableChannelClass2;
122     requestableChannelClass2.fixedProperties.insert("org.freedesktop.Telepathy.Channel.TargetHandleType",targetHandleType);
123     requestableChannelClass2.fixedProperties.insert("org.freedesktop.Telepathy.Channel.ChannelType","org.freedesktop.Telepathy.Channel.Type.StreamedMedia");
124
125     requestableChannelClass2.allowedProperties.append("com.nokia.Telepathy.Channel.Interface.Conference.InitialMembers");
126     requestableChannelClass2.allowedProperties.append("org.freedesktop.Telepathy.Channel.TargetHandleType");
127     requestableChannelClass2.allowedProperties.append("org.freedesktop.Telepathy.Channel.Type.StreamedMedia.InitialAudio");
128
129     requestableChannelClasses.append(requestableChannelClass2);
130
131
132     this->setProperty("RequestableChannelClasses",QVariant::fromValue(requestableChannelClasses));
133
134
135
136     qDebug() << "VICaR: Connection set up.";
137 }
138
139 Connection::~Connection()
140 {
141     qDebug() << "VICaR: Connection closed.";
142     delete(d);
143 }
144
145 bool Connection::registerObject()
146 {
147     if (!QDBusConnection::sessionBus().registerService(serviceName()))
148     {
149         qDebug() << "VICaR: Problem registering connection service:" << serviceName();
150         return false;
151     }
152
153     if (!QDBusConnection::sessionBus().registerObject(objectPath().path(),
154                                                       this))
155     {
156         qDebug() << "VICaR: Problem registering object path:" << objectPath().path();
157         return false;
158     }
159     return true;
160 }
161
162 void Connection::unregisterObject()
163 {
164     qDebug() << "VICaR: Unregistering Connection object from DBus";
165     QDBusConnection::sessionBus().unregisterObject(objectPath().path());
166     QDBusConnection::sessionBus().unregisterService(serviceName());
167 }
168
169 QString Connection::name() const
170 {    
171     return QString("vicar");
172 }
173
174
175 QString Connection::serviceName() const
176 { return connection_service_name_prefix + name(); }
177
178 QDBusObjectPath Connection::objectPath() const
179 { return QDBusObjectPath(connection_object_path_prefix + name()); }
180
181
182 //org.freedesktop.Telepathy.Connection
183 void Connection::Connect()
184 {
185     /*
186        Since this is not a "real" Telepathy Connection to a SIP, Chat server,
187        I am not connecting to anything.
188      */
189     qDebug() << "VICaR: Changing status to Connected...";
190     d->connection_status = Connection::Connected;
191
192     //Let all the Telepathy clients know that connection status has changed
193     qDebug() << "VICaR: Emitting StatusChanged.";
194     emit StatusChanged(d->connection_status, ReasonRequested);
195
196 }
197
198 void Connection::Disconnect()
199 {
200     qDebug() << "VICaR: Changing status to Disconnected...";
201     //We don't have any Handles to release here. So just change the status to Disconnected
202     d->connection_status = Connection::Disconnected;
203
204     qDebug() << "VICaR: Emitting StatusChanged";
205     emit StatusChanged(d->connection_status, ReasonRequested);
206
207     //As per Telepathy specfication, on disconnect we need to unregister from Dbus and destroy the object.
208     unregisterObject();
209     deleteLater();
210 }
211
212 QStringList Connection::GetInterfaces()
213 {
214     QStringList result;
215     if (d->connection_status != Connected)
216     {
217         sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
218                        "VICaR - Unable to get Interfaces List. The connection is no longer available.");
219         return result;
220     }    
221     result <<requests_interface;
222     return result;
223 }
224
225 QString Connection::GetProtocol()
226 { return protocol_vicar; }
227
228 uint Connection::GetStatus()
229 { return static_cast<uint>(d->connection_status); }
230
231 uint Connection::GetSelfHandle()
232 {
233     qDebug() << "VICaR: GetSelfHandle";
234     if (d->connection_status != Connected)
235     {
236         sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
237                        "VICaR - Unable to get Self Handle. The connection is no longer available.");
238         qDebug() << "VICaR: NOT CONNECTED when requesting selfhandle!";
239         return 0;
240     }
241
242     //WARNING: Incomplete implemenation
243     uint handle = 0;
244     qDebug() << "VICaR: Returning Handle" << handle << "as self handle.";
245     return handle;
246 }
247
248 QList<uint> Connection::RequestHandles(uint handle_type,
249                                        const QStringList & names)
250 {
251     Q_UNUSED(names);
252     QList<uint> result;
253
254     // check input:
255     if (d->connection_status != Connected)
256     {
257         sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
258                        "VICaR - Unable to process handle request. The connection is no longer available.");
259         return result;
260     }
261     if (handle_type != HandleContact)
262     {
263         sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
264                        "VICaR - Supports handles of type Contact only.");
265         return result;
266     }
267
268     //WARNING: Incomplete implementation. Create a handle and return the value here.
269     return result;
270 }
271
272 void Connection::HoldHandles(const uint handle_type, const QList<uint> &handles)
273 {
274     Q_UNUSED(handles);
275     qDebug() << "VICaR: HoldHandles.";
276     if (d->connection_status != Connected)
277     {
278         sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
279                        "VICaR - Unable to process handle request. The connection is no longer available.");
280         return;
281     }
282     if (handle_type != HandleContact)
283     {
284         sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
285                        "VICaR - Supports handles of type Contact only.");
286         return;
287     }
288
289     //WARNING: Incomplete implementation
290 }
291
292 QStringList Connection::InspectHandles(const uint handle_type,
293                                        const QList<uint> &handles)
294 {
295     Q_UNUSED(handles);
296     QStringList result;
297
298         // check input:
299     if (d->connection_status != Connected)
300     {
301         sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
302                        "VICaR - Unable to process handle request. The connection is no longer available.");
303         return result;
304     }
305     if (handle_type != HandleContact)
306     {
307         sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
308                        "VICaR - Supports handles of type Contact only.");
309         return result;
310     }
311
312     //WARNING: Incomplete implementation
313     return result;
314 }
315
316 void Connection::ReleaseHandles(const uint handle_type, const QList<uint> &handles)
317 {
318     Q_UNUSED(handles);
319     if (d->connection_status != Connected)
320     {
321         sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
322                        "VICaR - Unable to release handle. The connection is no longer available.");
323         qDebug() << "VICaR: Releasing Handle while connection is no longer connected.";
324         return;
325     }
326     if (handle_type != HandleContact)
327     {
328         sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
329                        "VICaR - Supports handles of type Contact only.");
330         qDebug() << "VICaR: Trying to release a Handle that is not a contact.";
331         return;
332     }
333
334     //WARNING: Incomplete implementation
335 }
336
337 org::freedesktop::Telepathy::ChannelInfoList Connection::ListChannels()
338 {
339     org::freedesktop::Telepathy::ChannelInfoList result;
340     if (d->connection_status != Connected)
341     {
342         sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
343                        "VICaR - Unable to list channels. The connection is no longer available.");
344         return result;
345     }
346
347     //WARNING: Incomplete implementation
348     //Btw - We never have any channels :)
349
350     return result;
351 }
352
353 QDBusObjectPath Connection::RequestChannel(const QString &type,
354                                            uint handle_type, uint handle,
355                                            bool suppress_handler)
356 {
357     Q_UNUSED(handle);
358     Q_UNUSED(suppress_handler);
359     //This method is deprecated and no longer used as per latest Telepathy spec
360
361     if (type != QString("org.freedesktop.Telepathy.Channel.Type.StreamedMedia"))
362     {
363         sendErrorReply("org.freedesktop.Telepathy.Error.NotImplemented",
364                        "VICaR: Failed to create channel: Channel type not implemented.");
365         return QDBusObjectPath();
366     }
367
368     if (handle_type != HandleContact )
369     {
370         sendErrorReply("org.freedesktop.Telepathy.Error.InvalidHandle",
371                        "VICaR: Failed to create channel: Handle type not supported.");
372         return QDBusObjectPath();
373     }
374
375     if (d->connection_status != Connected)
376     {
377         sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
378                        "VICaR: Failed to create channel: Connection is Disconnected.");
379         return QDBusObjectPath();
380     }
381
382     //TODO VICaR Specific code here
383
384     //WARNING: Incomplete implementation, we are not creating any channels here at all.
385     QDBusObjectPath channel_path;
386     return channel_path;
387 }
388
389 //org.freedesktop.Telepathy.Connection.Interface.Requests
390 QDBusObjectPath Connection::CreateChannel(const QVariantMap &request,
391                                                            QVariantMap &channel_properties)
392 {
393     Q_UNUSED(channel_properties);
394     Q_ASSERT(!request.isEmpty());
395     qDebug() << "VICaR: CreateChannel";
396     qDebug() << " Request details are: "<< request;
397
398      //Ideally we need to emit NewChannels signal here, but since we are not creating any channels we ignore it
399
400     //WARNING: VICaR - Specific implementation
401     return processChannel(request);
402
403 }
404
405 bool Connection::EnsureChannel(const QVariantMap &request,
406                                                 QDBusObjectPath &channel_object,
407                                                 QVariantMap &channel_properties)
408 {
409     Q_UNUSED(channel_object);
410     Q_UNUSED(channel_properties);
411     Q_ASSERT(!request.isEmpty());
412     qDebug() << "VICaR: EnsureChannel";
413     qDebug() << " Request details are: "<< request;
414
415     //WARNING: Incomplete implementation
416     processChannel(request);
417
418     return true;
419 }
420
421 QDBusObjectPath Connection::processChannel(const QVariantMap &request){
422
423     QDBusObjectPath channel_path;
424
425     if (!request.contains("org.freedesktop.Telepathy.Channel.TargetID")){
426         sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
427                        "VICaR - Invalid request. TargetID (Phone Number) not included.");
428         return channel_path;
429     }
430
431     QVariant vNumber = request.value("org.freedesktop.Telepathy.Channel.TargetID");
432     if (!vNumber.isValid()){
433         sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
434                        "VICaR - Invalid request. Phone Number is not valid.");
435         return channel_path;
436     }
437     QString strNumber = vNumber.toString();
438     if (strNumber.isEmpty()){
439         sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
440                        "VICaR - Invalid request. Phone Number is empty.");
441         return channel_path;
442     }
443
444     //Only allow requests with handle type as contact
445     QVariant vTargetHandleType = request.value("org.freedesktop.Telepathy.Channel.TargetHandleType");
446     uint intTargetHandleType = vTargetHandleType.toUInt();
447     if (intTargetHandleType != HandleContact)
448     {
449         QString strMessage = "VICaR - Supports handles of type Contact only. Recieved handle type ";
450         strMessage.append(vTargetHandleType.toString());
451
452         sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
453                        strMessage);
454     }
455
456     /*
457         Send an error reply to Tp Client (Mission Control) to force it to close the active channel.
458         Once it recieves the reply, the client does not bother what we return.
459
460      */
461
462     sendErrorReply("org.freedesktop.Telepathy.Error.NotAvailable",
463                    "VICaR - Creating a new channel to "+strNumber+" via Ring.");
464
465
466     //Initiate a new call to CC/Google Out/Skype-out number by requesting a new channel with Ring CM.
467
468     VicarCallRouterProxy *callRouter = new VicarCallRouterProxy(APPLICATION_DBUS_SERVICE,APPLICATION_DBUS_PATH,QDBusConnection::sessionBus(),this);
469
470     callRouter->callInternationalNumber(strNumber);
471
472     qDebug() << "VICaR: Call is processed.";
473
474     return channel_path;
475 }
476
477
478 //org.freedesktop.Telepathy.Connection.Interface.Capabilities
479 org::freedesktop::Telepathy::ContactCapabilitiesList Connection::GetCapabilities(const QList<uint> &Handles){
480     Q_UNUSED(Handles);
481     org::freedesktop::Telepathy::ContactCapabilitiesList capabilities;
482     return capabilities;
483
484 }
485
486
487 org::freedesktop::Telepathy::CapabilityPairList Connection::AdvertiseCapabilities(org::freedesktop::Telepathy::CapabilityPairList Add, const QStringList &Remove){
488     Q_UNUSED(Add);
489     Q_UNUSED(Remove);
490     org::freedesktop::Telepathy::CapabilityPairList capabilities;
491     return capabilities;
492 }