Akonadi

bridgeconnection.cpp
1 /***************************************************************************
2  * Copyright (C) 2010 by Volker Krause <[email protected]> *
3  * *
4  * This program is free software; you can redistribute it and/or modify *
5  * it under the terms of the GNU Library General Public License as *
6  * published by the Free Software Foundation; either version 2 of the *
7  * License, or (at your option) any later version. *
8  * *
9  * This program 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 Library General Public *
15  * License along with this program; if not, write to the *
16  * Free Software Foundation, Inc., *
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18  ***************************************************************************/
19 
20 #include "bridgeconnection.h"
21 
22 #include <private/standarddirs_p.h>
23 
24 #include <QDebug>
25 #include <QMetaObject>
26 #include <QRegExp>
27 #include <QSettings>
28 #include <QLocalSocket>
29 #include <QTcpSocket>
30 
31 #ifdef Q_OS_UNIX
32 #include <sys/socket.h>
33 #include <sys/un.h>
34 #endif
35 
36 BridgeConnection::BridgeConnection(QTcpSocket *remoteSocket, QObject *parent)
37  : QObject(parent)
38  , m_localSocket(nullptr)
39  , m_remoteSocket(remoteSocket)
40 {
41  // wait for the vtable to be complete
42  QMetaObject::invokeMethod(this, &BridgeConnection::doConnects, Qt::QueuedConnection);
43  QMetaObject::invokeMethod(this, &BridgeConnection::connectLocal, Qt::QueuedConnection);
44 }
45 
46 BridgeConnection::~BridgeConnection()
47 {
48  delete m_remoteSocket;
49 }
50 
51 void BridgeConnection::slotDataAvailable()
52 {
53  if (m_localSocket->bytesAvailable() > 0) {
54  m_remoteSocket->write(m_localSocket->read(m_localSocket->bytesAvailable()));
55  }
56  if (m_remoteSocket->bytesAvailable() > 0) {
57  m_localSocket->write(m_remoteSocket->read(m_remoteSocket->bytesAvailable()));
58  }
59 }
60 
61 AkonadiBridgeConnection::AkonadiBridgeConnection(QTcpSocket *remoteSocket, QObject *parent)
62  : BridgeConnection(remoteSocket, parent)
63 {
64  m_localSocket = new QLocalSocket(this);
65 }
66 
67 void AkonadiBridgeConnection::connectLocal()
68 {
69  const QSettings connectionSettings(Akonadi::StandardDirs::connectionConfigFile(), QSettings::IniFormat);
70 #ifdef Q_OS_WIN //krazy:exclude=cpp
71  const QString namedPipe = connectionSettings.value(QLatin1String("Data/NamedPipe"), QLatin1String("Akonadi")).toString();
72  (static_cast<QLocalSocket *>(m_localSocket))->connectToServer(namedPipe);
73 #else
74  const QString defaultSocketDir = Akonadi::StandardDirs::saveDir("data");
75  const QString path = connectionSettings.value(QStringLiteral("Data/UnixPath"), QString(defaultSocketDir + QLatin1String("/akonadiserver.socket"))).toString();
76  (static_cast<QLocalSocket *>(m_localSocket))->connectToServer(path);
77 #endif
78 }
79 
80 DBusBridgeConnection::DBusBridgeConnection(QTcpSocket *remoteSocket, QObject *parent)
81  : BridgeConnection(remoteSocket, parent)
82 {
83  m_localSocket = new QLocalSocket(this);
84 }
85 
86 void DBusBridgeConnection::connectLocal()
87 {
88  // TODO: support for !Linux
89 #ifdef Q_OS_UNIX
90  const QByteArray sessionBusAddress = qgetenv("DBUS_SESSION_BUS_ADDRESS");
91  QRegExp rx(QStringLiteral("=(.*)[,$]"));
92  if (rx.indexIn(QString::fromLatin1(sessionBusAddress)) >= 0) {
93  const QString dbusPath = rx.cap(1);
94  qDebug() << dbusPath;
95  if (sessionBusAddress.contains("abstract")) {
96  const int fd = socket(PF_UNIX, SOCK_STREAM, 0);
97  Q_ASSERT(fd >= 0);
98  struct sockaddr_un dbus_socket_addr;
99  dbus_socket_addr.sun_family = PF_UNIX;
100  dbus_socket_addr.sun_path[0] = '\0'; // this marks an abstract unix socket on linux, something QLocalSocket doesn't support
101  memcpy(dbus_socket_addr.sun_path + 1, dbusPath.toLatin1().data(), dbusPath.toLatin1().size() + 1);
102  /*sizeof(dbus_socket_addr) gives me a too large value for some reason, although that's what QLocalSocket uses*/
103  const int result = ::connect(fd, (struct sockaddr *) &dbus_socket_addr, sizeof(dbus_socket_addr.sun_family) + dbusPath.size() + 1 /* for the leading \0 */);
104  Q_ASSERT(result != -1);
105  Q_UNUSED(result); // in release mode
106  (static_cast<QLocalSocket *>(m_localSocket))->setSocketDescriptor(fd, QLocalSocket::ConnectedState, QLocalSocket::ReadWrite);
107  } else {
108  (static_cast<QLocalSocket *>(m_localSocket))->connectToServer(dbusPath);
109  }
110  }
111 #endif
112 }
113 
114 void BridgeConnection::doConnects()
115 {
116  connect(m_localSocket, &QLocalSocket::disconnected, this, &BridgeConnection::deleteLater);
117  connect(m_remoteSocket, &QAbstractSocket::disconnected, this, &QObject::deleteLater);
118  connect(m_localSocket, &QIODevice::readyRead, this, &BridgeConnection::slotDataAvailable);
119  connect(m_remoteSocket, &QIODevice::readyRead, this, &BridgeConnection::slotDataAvailable);
120  connect(m_localSocket, &QLocalSocket::connected, this, &BridgeConnection::slotDataAvailable);
121 }
void connected()
int size() const const
void deleteLater()
bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9)
QByteArray toLatin1() const const
void disconnected()
bool contains(char ch) const const
char * data()
QString fromLatin1(const char *str, int size)
void readyRead()
int size() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon May 25 2020 22:46:08 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.