Akonadi

bridgeconnection.cpp
1 /***************************************************************************
2  * SPDX-FileCopyrightText: 2010 Volker Krause <[email protected]> *
3  * *
4  * SPDX-License-Identifier: LGPL-2.0-or-later *
5  ***************************************************************************/
6 
7 #include "bridgeconnection.h"
8 
9 #include <private/standarddirs_p.h>
10 
11 #include <QDebug>
12 #include <QLocalSocket>
13 #include <QMetaObject>
14 #include <QRegularExpression>
15 #include <QSettings>
16 #include <QTcpSocket>
17 
18 #ifdef Q_OS_UNIX
19 #include <sys/socket.h>
20 #include <sys/un.h>
21 #endif
22 
23 BridgeConnection::BridgeConnection(QTcpSocket *remoteSocket, QObject *parent)
24  : QObject(parent)
25  , m_remoteSocket(remoteSocket)
26 {
27  // wait for the vtable to be complete
28  QMetaObject::invokeMethod(this, &BridgeConnection::doConnects, Qt::QueuedConnection);
29  QMetaObject::invokeMethod(this, &BridgeConnection::connectLocal, Qt::QueuedConnection);
30 }
31 
32 BridgeConnection::~BridgeConnection()
33 {
34  delete m_remoteSocket;
35 }
36 
37 void BridgeConnection::slotDataAvailable()
38 {
39  if (m_localSocket->bytesAvailable() > 0) {
40  m_remoteSocket->write(m_localSocket->read(m_localSocket->bytesAvailable()));
41  }
42  if (m_remoteSocket->bytesAvailable() > 0) {
43  m_localSocket->write(m_remoteSocket->read(m_remoteSocket->bytesAvailable()));
44  }
45 }
46 
47 AkonadiBridgeConnection::AkonadiBridgeConnection(QTcpSocket *remoteSocket, QObject *parent)
48  : BridgeConnection(remoteSocket, parent)
49 {
50  m_localSocket = new QLocalSocket(this);
51 }
52 
53 void AkonadiBridgeConnection::connectLocal()
54 {
55  const QSettings connectionSettings(Akonadi::StandardDirs::connectionConfigFile(), QSettings::IniFormat);
56 #ifdef Q_OS_WIN // krazy:exclude=cpp
57  const QString namedPipe = connectionSettings.value(QLatin1String("Data/NamedPipe"), QLatin1String("Akonadi")).toString();
58  (static_cast<QLocalSocket *>(m_localSocket))->connectToServer(namedPipe);
59 #else
60  const QString defaultSocketDir = Akonadi::StandardDirs::saveDir("data");
61  const QString path =
62  connectionSettings.value(QStringLiteral("Data/UnixPath"), QString(defaultSocketDir + QLatin1String("/akonadiserver.socket"))).toString();
63  (static_cast<QLocalSocket *>(m_localSocket))->connectToServer(path);
64 #endif
65 }
66 
67 DBusBridgeConnection::DBusBridgeConnection(QTcpSocket *remoteSocket, QObject *parent)
68  : BridgeConnection(remoteSocket, parent)
69 {
70  m_localSocket = new QLocalSocket(this);
71 }
72 
73 void DBusBridgeConnection::connectLocal()
74 {
75  // TODO: support for !Linux
76 #ifdef Q_OS_UNIX
77  const QByteArray sessionBusAddress = qgetenv("DBUS_SESSION_BUS_ADDRESS");
78  const QRegularExpression rx(QStringLiteral("=(.*)[,$]"));
79  QRegularExpressionMatch match = rx.match(QString::fromLatin1(sessionBusAddress));
80  if (match.hasMatch()) {
81  const QString dbusPath = match.captured(1);
82  qDebug() << dbusPath;
83  if (sessionBusAddress.contains("abstract")) {
84  const int fd = socket(PF_UNIX, SOCK_STREAM, 0);
85  Q_ASSERT(fd >= 0);
86  struct sockaddr_un dbus_socket_addr;
87  dbus_socket_addr.sun_family = PF_UNIX;
88  dbus_socket_addr.sun_path[0] = '\0'; // this marks an abstract unix socket on linux, something QLocalSocket doesn't support
89  memcpy(dbus_socket_addr.sun_path + 1, dbusPath.toLatin1().data(), dbusPath.toLatin1().size() + 1);
90  /*sizeof(dbus_socket_addr) gives me a too large value for some reason, although that's what QLocalSocket uses*/
91  const int result = ::connect(fd,
92  reinterpret_cast<struct sockaddr *>(&dbus_socket_addr),
93  sizeof(dbus_socket_addr.sun_family) + dbusPath.size() + 1 /* for the leading \0 */);
94  Q_ASSERT(result != -1);
95  Q_UNUSED(result) // in release mode
96  (static_cast<QLocalSocket *>(m_localSocket))->setSocketDescriptor(fd, QLocalSocket::ConnectedState, QLocalSocket::ReadWrite);
97  } else {
98  (static_cast<QLocalSocket *>(m_localSocket))->connectToServer(dbusPath);
99  }
100  }
101 #endif
102 }
103 
104 void BridgeConnection::doConnects()
105 {
106  connect(m_localSocket, &QLocalSocket::disconnected, this, &BridgeConnection::deleteLater);
107  connect(m_remoteSocket, &QAbstractSocket::disconnected, this, &QObject::deleteLater);
108  connect(m_localSocket, &QIODevice::readyRead, this, &BridgeConnection::slotDataAvailable);
109  connect(m_remoteSocket, &QIODevice::readyRead, this, &BridgeConnection::slotDataAvailable);
110  connect(m_localSocket, &QLocalSocket::connected, this, &BridgeConnection::slotDataAvailable);
111 }
int size() const const
QByteArray toLatin1() const const
void connected()
void deleteLater()
void disconnected()
void readyRead()
QueuedConnection
bool contains(char ch) const const
QString fromLatin1(const char *str, int size)
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
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)
int size() const const
char * data()
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu Jun 30 2022 03:51:45 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.