Version 0.7-0
[vicar] / src / vicar-telepathy / cpp / connection.cpp
diff --git a/src/vicar-telepathy/cpp/connection.cpp b/src/vicar-telepathy/cpp/connection.cpp
new file mode 100644 (file)
index 0000000..58bbe92
--- /dev/null
@@ -0,0 +1,614 @@
+/*
+@version: 0.6
+@author: Sudheer K. <scifi1947 at gmail.com>
+@license: GNU General Public License
+
+Based on Telepathy-SNOM with copyright notice below.
+*/
+
+/*
+ * Telepathy SNOM VoIP phone connection manager
+ * Copyright (C) 2006 by basyskom GmbH
+ *  @author Tobias Hunger <info@basyskom.de>
+ *
+ * This library is free software; you can redisQObject::tribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is disQObject::tributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "connection.h"
+#include "connectionadaptor.h"
+#include "connectioninterfacerequestsadaptor.h"
+#include "connectioninterfacerequeststypes.h"
+#include "connectioninterfacecapabilitiesadaptor.h"
+#include "connectioninterfacecapabilitiestypes.h"
+#include "names.h"
+#include "vicarcallrouterproxy.h"
+#include <logutility.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QVariantMap>
+#include <QDBusMessage>
+#include <QDBusReply>
+
+
+namespace
+{
+static const QString protocol_vicar("tel");
+
+static const QString connection_service_name_prefix("org.freedesktop.Telepathy.Connection.vicar." + protocol_vicar + '.');
+static const QString connection_object_path_prefix("/org/freedesktop/Telepathy/Connection/vicar/" + protocol_vicar + '/');
+static const QString requests_interface("org.freedesktop.Telepathy.Connection.Interface.Requests");
+}
+
+using namespace org::maemo;
+
+
+class ConnectionPrivate
+{
+public:
+    ConnectionPrivate(Connection * p,
+                      const QString & acc) :
+        account(acc),
+        connection_status(Connection::Disconnected),
+        adaptor(new ConnectionAdaptor(p)),
+        connIfaceReqsAdaptor(new ConnectionInterfaceRequestsAdaptor(p)),
+        logUtility(new LogUtility("/var/log/vicar/vicar.log",p)),
+        parent(p)
+    {
+        Q_ASSERT(0 != adaptor);
+    }
+
+    ~ConnectionPrivate()
+    {
+        qDebug() << "VICaR Connection: Connection Destructing";
+    }
+
+    const QString account;
+
+    Connection::Status connection_status;
+    ConnectionAdaptor * adaptor;
+    ConnectionInterfaceRequestsAdaptor * connIfaceReqsAdaptor;
+    LogUtility * const logUtility;
+    Connection * const parent;
+};
+
+// ---------------------------------------------------------------------------
+
+Connection::Connection(const QString & account,
+                        QObject * parent) :
+    QObject(parent),
+    d(new ConnectionPrivate(this, account))
+{
+
+    QString strMessage;
+    strMessage = "DEBUG: In Connection Constructor";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+
+    Q_ASSERT(0 != d);
+    Q_ASSERT(!account.isEmpty());
+
+    /*  -- Set the Dynamic property "Interfaces" ---
+
+        Apparently it is not sufficient to implement an additional interface like Conn.I.Requests.
+        We have to assign the list of additional interfaces to the DBus Property Interfaces.
+
+        The actual DBus property "Interfaces" is declared in ConnectionAdaptor class,
+         which is our Connection Interface implementation.
+     */
+
+    QStringList interfaces = QStringList(requests_interface);
+    this->setProperty("Interfaces",interfaces);
+
+    // Set the Dynamic property "HasImmortalHandles" to true as per telepathy Connection spec 0.21.6
+    //The handles for vicar connection are expected to last throughout the lifetime of the connection
+    this->setProperty("HasImmortalHandles",true);
+
+    this->setProperty("Status",org::freedesktop::Telepathy::CONNECTION_STATUS_CONNECTED);
+    this->setProperty("SelfHandle",org::freedesktop::Telepathy::HANDLE_TYPE_CONTACT);
+
+    //Set the property RequestableChannelClasses
+    org::freedesktop::Telepathy::RequestableChannelClassList requestableChannelClasses;
+
+    uint targetHandleType(1);
+
+    org::freedesktop::Telepathy::RequestableChannelClass requestableChannelClass1;
+    requestableChannelClass1.fixedProperties.insert("org.freedesktop.Telepathy.Channel.TargetHandleType",targetHandleType);
+    requestableChannelClass1.fixedProperties.insert("org.freedesktop.Telepathy.Channel.ChannelType","org.freedesktop.Telepathy.Channel.Type.StreamedMedia");
+
+    requestableChannelClass1.allowedProperties.append("org.freedesktop.Telepathy.Channel.TargetHandle");
+    requestableChannelClass1.allowedProperties.append("org.freedesktop.Telepathy.Channel.Type.StreamedMedia.InitialAudio");
+
+    requestableChannelClasses.append(requestableChannelClass1);
+
+    org::freedesktop::Telepathy::RequestableChannelClass requestableChannelClass2;
+    requestableChannelClass2.fixedProperties.insert("org.freedesktop.Telepathy.Channel.TargetHandleType",targetHandleType);
+    requestableChannelClass2.fixedProperties.insert("org.freedesktop.Telepathy.Channel.ChannelType","org.freedesktop.Telepathy.Channel.Type.StreamedMedia");
+
+    requestableChannelClass2.allowedProperties.append("com.nokia.Telepathy.Channel.Interface.Conference.InitialMembers");
+    requestableChannelClass2.allowedProperties.append("org.freedesktop.Telepathy.Channel.TargetHandleType");
+    requestableChannelClass2.allowedProperties.append("org.freedesktop.Telepathy.Channel.Type.StreamedMedia.InitialAudio");
+
+    requestableChannelClasses.append(requestableChannelClass2);
+
+
+    this->setProperty("RequestableChannelClasses",QVariant::fromValue(requestableChannelClasses));
+
+    //Set the property Channels
+    org::freedesktop::Telepathy::ChannelDetailsList channelDetails;
+    this->setProperty("Channels",QVariant::fromValue(channelDetails));
+
+    //Set the connection status to Connected (default for Vicar)
+    d->connection_status = Connection::Connected;
+
+
+    strMessage = "VICaR Connection: Connection set up.";
+
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+}
+
+Connection::~Connection()
+{
+    qDebug() << "VICaR Connection: Connection closed.";
+    delete(d);
+}
+
+bool Connection::registerObject()
+{
+    QString strMessage;
+
+    if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName())){
+        if (!QDBusConnection::sessionBus().registerService(serviceName()))
+        {
+            strMessage = "VICaR Connection: Problem registering connection service:" + serviceName();
+            qDebug() << strMessage;
+            d->logUtility->logMessage(strMessage);
+            return false;
+        }
+
+        if (!QDBusConnection::sessionBus().registerObject(objectPath().path(),
+                                                          this))
+        {
+            strMessage = "VICaR Connection: Problem registering object path:" + objectPath().path();
+            qDebug() << strMessage;
+            d->logUtility->logMessage(strMessage);
+            return false;
+        }
+    }
+    else{
+        strMessage = "VICaR Connection: " + serviceName()+" is already registered on DBus";
+        qDebug() << strMessage;
+        d->logUtility->logMessage(strMessage);
+    }
+    return true;
+}
+
+void Connection::unregisterObject()
+{
+    QString strMessage = "VICaR Connection: Unregistering Connection object from DBus";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+    QDBusConnection::sessionBus().unregisterObject(objectPath().path());
+    QDBusConnection::sessionBus().unregisterService(serviceName());
+}
+
+QString Connection::name() const
+{    
+    return QString("vicar");
+}
+
+
+QString Connection::serviceName() const
+{ return connection_service_name_prefix + name(); }
+
+QDBusObjectPath Connection::objectPath() const
+{ return QDBusObjectPath(connection_object_path_prefix + name()); }
+
+
+//org.freedesktop.Telepathy.Connection
+void Connection::Connect()
+{
+    /*
+       Since this is not a "real" Telepathy Connection to a SIP, Chat server,
+       I am not connecting to anything.
+     */
+    QString strMessage = "VICaR Connection: Changing status to Connected...";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+    d->connection_status = Connection::Connected;
+
+    //Let all the Telepathy clients know that connection status has changed
+    strMessage = "VICaR Connection: Emitting StatusChanged.";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+    emit StatusChanged(d->connection_status, ReasonRequested);
+}
+
+void Connection::Disconnect()
+{
+    QString strMessage = "VICaR Connection: Changing status to Disconnected...";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+    //We don't have any Handles to release here. So just change the status to Disconnected
+    d->connection_status = Connection::Disconnected;
+
+    strMessage = "VICaR Connection: Emitting StatusChanged";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+    emit StatusChanged(d->connection_status, ReasonRequested);
+
+    //As per Telepathy specfication, on disconnect we need to unregister from Dbus and destroy the object.
+    unregisterObject();
+    deleteLater();
+}
+
+QStringList Connection::GetInterfaces()
+{
+    QStringList result;
+    if (d->connection_status != Connected)
+    {
+        sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
+                       "VICaR - Unable to get Interfaces List. The connection is no longer available.");
+        return result;
+    }    
+    result <<requests_interface;
+    return result;
+}
+
+QString Connection::GetProtocol()
+{ return protocol_vicar; }
+
+uint Connection::GetStatus()
+{ return static_cast<uint>(d->connection_status); }
+
+uint Connection::GetSelfHandle()
+{
+    QString strMessage = "VICaR Connection: GetSelfHandle";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+    if (d->connection_status != Connected)
+    {
+        sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
+                       "VICaR - Unable to get Self Handle. The connection is no longer available.");
+        strMessage = "VICaR Connection: NOT CONNECTED when requesting selfhandle!";
+        qDebug() << strMessage;
+        d->logUtility->logMessage(strMessage);
+        return 0;
+    }
+
+    //WARNING: Incomplete implemenation
+    uint handle = 0;
+    strMessage = "VICaR Connection: Returning Handle " + QString(handle) + "as self handle.";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+    return handle;
+}
+
+QList<uint> Connection::RequestHandles(uint handle_type,
+                                       const QStringList & names)
+{
+    Q_UNUSED(names);
+    QList<uint> result;
+
+    // check input:
+    if (d->connection_status != Connected)
+    {
+        sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
+                       "VICaR - Unable to process handle request. The connection is no longer available.");
+        return result;
+    }
+    if (handle_type != HandleContact)
+    {
+        sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
+                       "VICaR - Supports handles of type Contact only.");
+        return result;
+    }
+
+    //WARNING: Incomplete implementation. Create a handle and return the value here.
+    return result;
+}
+
+void Connection::HoldHandles(const uint handle_type, const QList<uint> &handles)
+{
+    Q_UNUSED(handles);
+    QString strMessage = "VICaR Connection: HoldHandles.";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+    if (d->connection_status != Connected)
+    {
+
+        strMessage = "VICaR Connection: HoldHandles - Not Connected.";
+        qDebug() << strMessage;
+        d->logUtility->logMessage(strMessage);
+
+        sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
+                       "VICaR - Unable to process handle request. The connection is no longer available.");
+        return;
+    }
+    if (handle_type != HandleContact)
+    {
+
+        strMessage = "VICaR Connection: HoldHandles - Invalid Handle Type.";
+        qDebug() << strMessage;
+        d->logUtility->logMessage(strMessage);
+
+        sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
+                       "VICaR - Supports handles of type Contact only.");
+        return;
+    }
+
+    //WARNING: Incomplete implementation
+}
+
+QStringList Connection::InspectHandles(const uint handle_type,
+                                       const QList<uint> &handles)
+{
+    Q_UNUSED(handles);
+    QStringList handlesList;
+
+    QString strMessage = "VICaR Connection: InspectHandles.";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+
+        // check input:
+    if (d->connection_status != Connected)
+    {
+        sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
+                       "VICaR - Unable to process handle request. The connection is no longer available.");
+        return handlesList;
+    }
+    if (handle_type != HandleContact)
+    {
+        sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
+                       "VICaR - Supports handles of type Contact only.");
+        return handlesList;
+    }
+
+    uint handle = 0;
+    for (int i = 0 ; i < handles.length(); i++) {
+        handle = handles.at(i);
+        strMessage = "VICaR Connection: Inspecting handle "+QString(handle);
+        qDebug() << strMessage;
+        d->logUtility->logMessage(strMessage);
+        handlesList.append(QString(handle));
+    }
+
+    //WARNING: Incomplete implementation
+    return handlesList;
+}
+
+void Connection::ReleaseHandles(const uint handle_type, const QList<uint> &handles)
+{
+    Q_UNUSED(handles);
+    QString strMessage;
+    if (d->connection_status != Connected)
+    {
+        sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
+                       "VICaR - Unable to release handle. The connection is no longer available.");
+        strMessage = "VICaR Connection: Releasing Handle while connection is no longer connected.";
+        qDebug() << strMessage;
+        d->logUtility->logMessage(strMessage);
+        return;
+    }
+    if (handle_type != HandleContact)
+    {
+        sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
+                       "VICaR - Supports handles of type Contact only.");
+        strMessage =  "VICaR Connection: Trying to release a Handle that is not a contact.";
+        qDebug() << strMessage;
+        d->logUtility->logMessage(strMessage);
+        return;
+    }
+
+    //WARNING: Incomplete implementation
+}
+
+org::freedesktop::Telepathy::ChannelInfoList Connection::ListChannels()
+{
+    org::freedesktop::Telepathy::ChannelInfoList result;
+    if (d->connection_status != Connected)
+    {
+        sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
+                       "VICaR - Unable to list channels. The connection is no longer available.");
+        return result;
+    }
+
+    //WARNING: Incomplete implementation
+    //Btw - We never have any channels :)
+
+    return result;
+}
+
+QDBusObjectPath Connection::RequestChannel(const QString &type,
+                                           uint handle_type, uint handle,
+                                           bool suppress_handler)
+{
+    Q_UNUSED(handle);
+    Q_UNUSED(suppress_handler);
+    //This method is deprecated and no longer used as per latest Telepathy spec
+
+    if (type != QString("org.freedesktop.Telepathy.Channel.Type.StreamedMedia"))
+    {
+        sendErrorReply("org.freedesktop.Telepathy.Error.NotImplemented",
+                       "VICaR Connection: Failed to create channel: Channel type not implemented.");
+        return QDBusObjectPath();
+    }
+
+    if (handle_type != HandleContact )
+    {
+        sendErrorReply("org.freedesktop.Telepathy.Error.InvalidHandle",
+                       "VICaR Connection: Failed to create channel: Handle type not supported.");
+        return QDBusObjectPath();
+    }
+
+    if (d->connection_status != Connected)
+    {
+        sendErrorReply("org.freedesktop.Telepathy.Error.Disconnected",
+                       "VICaR Connection: Failed to create channel: Connection is Disconnected.");
+        return QDBusObjectPath();
+    }
+
+    //WARNING: Incomplete implementation, we are not creating any channels here at all.
+    QDBusObjectPath channel_path;
+    return channel_path;
+}
+
+//org.freedesktop.Telepathy.Connection.Interface.Requests
+QDBusObjectPath Connection::CreateChannel(const QVariantMap &request,
+                                                           QVariantMap &channel_properties)
+{
+    Q_UNUSED(channel_properties);
+    Q_ASSERT(!request.isEmpty());
+    QString strMessage;
+    strMessage = "VICaR Connection: CreateChannel";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+    qDebug() << " Request details are: "<< request;
+
+     //Ideally we need to emit NewChannels signal here, but since we are not creating any channels we ignore it
+
+    //WARNING: VICaR - Specific implementation
+    return processChannel(request);
+
+}
+
+bool Connection::EnsureChannel(const QVariantMap &request,
+                                                QDBusObjectPath &channel_object,
+                                                QVariantMap &channel_properties)
+{
+    Q_UNUSED(channel_object);
+    Q_UNUSED(channel_properties);
+    Q_ASSERT(!request.isEmpty());
+    QString strMessage = "VICaR Connection: EnsureChannel";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+    qDebug() << " Request details are: "<< request;
+
+    //WARNING: Incomplete implementation
+    processChannel(request);
+
+    return true;
+}
+
+QDBusObjectPath Connection::processChannel(const QVariantMap &request){
+
+    QString strMessage = "VICaR Connection: ProcessChannel";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+
+    QDBusObjectPath channel_path;
+
+    if (!request.contains("org.freedesktop.Telepathy.Channel.TargetID")){
+        sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
+                       "VICaR - Invalid request. TargetID (Phone Number) not included.");
+        return channel_path;
+    }
+
+    QVariant vNumber = request.value("org.freedesktop.Telepathy.Channel.TargetID");
+    if (!vNumber.isValid()){
+        sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
+                       "VICaR - Invalid request. Phone Number is not valid.");
+        return channel_path;
+    }
+    QString strNumber = vNumber.toString();
+    if (strNumber.isEmpty()){
+        sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
+                       "VICaR - Invalid request. Phone Number is empty.");
+        return channel_path;
+    }
+    else if (strNumber == "publish" || strNumber == "subscribe"){
+    //Deny the persistent Mission control requests to publish and subscribe
+        QString strError = "VICaR - Invalid request. " + strNumber + " is not supported.";
+        sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
+                       strError);
+        return channel_path;
+
+    }
+
+    //Only allow requests with handle type as contact
+    QVariant vTargetHandleType = request.value("org.freedesktop.Telepathy.Channel.TargetHandleType");
+    uint intTargetHandleType = vTargetHandleType.toUInt();
+    if (intTargetHandleType != HandleContact)
+    {
+        strMessage = "VICaR - Supports handles of type Contact only. Recieved handle type ";
+        strMessage.append(vTargetHandleType.toString());
+
+        sendErrorReply("org.freedesktop.Telepathy.Error.InvalidArgument",
+                       strMessage);
+        return channel_path;
+    }
+
+
+    /*
+        Send an error reply to Tp Client (Mission Control) to force it to close the active channel.
+        Once it recieves the reply, the client does not bother what we return.
+
+     */
+
+    sendErrorReply("org.freedesktop.Telepathy.Error.NotAvailable",
+                   "VICaR - Creating a new channel to "+strNumber+" via Ring.");
+
+
+    //Initiate a new call to CC/Google Out/Skype-out number by requesting a new channel with Ring CM.
+
+    VicarCallRouterProxy *callRouter = new VicarCallRouterProxy(APPLICATION_DBUS_SERVICE,APPLICATION_DBUS_PATH,QDBusConnection::sessionBus(),this);
+
+    callRouter->callInternationalNumber(strNumber);
+
+    strMessage = "VICaR Connection: Call is processed.";
+
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+
+    return channel_path;
+}
+
+
+void Connection::AddClientInterest(const QStringList &tokens){
+    //WARNING: Incomplete implementation
+    Q_UNUSED(tokens);    
+    QString strMessage;
+
+    strMessage = "VICaR Connection: AddClientInterest";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+}
+
+void Connection::RemoveClientInterest(const QStringList &tokens){
+    //WARNING: Incomplete implementation
+    Q_UNUSED(tokens);    
+    QString strMessage;
+
+    strMessage = "VICaR Connection: RemoveClientInterest";
+    qDebug() << strMessage;
+    d->logUtility->logMessage(strMessage);
+}
+
+//org.freedesktop.Telepathy.Connection.Interface.Capabilities
+org::freedesktop::Telepathy::ContactCapabilitiesList Connection::GetCapabilities(const QList<uint> &Handles){
+    Q_UNUSED(Handles);
+    org::freedesktop::Telepathy::ContactCapabilitiesList capabilities;
+    return capabilities;
+
+}
+
+
+org::freedesktop::Telepathy::CapabilityPairList Connection::AdvertiseCapabilities(org::freedesktop::Telepathy::CapabilityPairList Add, const QStringList &Remove){
+    Q_UNUSED(Add);
+    Q_UNUSED(Remove);
+    org::freedesktop::Telepathy::CapabilityPairList capabilities;
+    return capabilities;
+}