Akonadi

bridgeconnection.cpp
1/***************************************************************************
2 * SPDX-FileCopyrightText: 2010 Volker Krause <vkrause@kde.org> *
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
23BridgeConnection::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
32BridgeConnection::~BridgeConnection()
33{
34 delete m_remoteSocket;
35}
36
37void 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
47AkonadiBridgeConnection::AkonadiBridgeConnection(QTcpSocket *remoteSocket, QObject *parent)
48 : BridgeConnection(remoteSocket, parent)
49{
50 m_localSocket = new QLocalSocket(this);
51}
52
53void 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(QLatin1StringView("Data/NamedPipe"), QLatin1StringView("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 + QLatin1StringView("/akonadiserver.socket"))).toString();
63 (static_cast<QLocalSocket *>(m_localSocket))->connectToServer(path);
64#endif
65}
66
67DBusBridgeConnection::DBusBridgeConnection(QTcpSocket *remoteSocket, QObject *parent)
68 : BridgeConnection(remoteSocket, parent)
69{
70 m_localSocket = new QLocalSocket(this);
71}
72
73void 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
104void BridgeConnection::doConnects()
105{
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}
112
113#include "moc_bridgeconnection.cpp"
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
QString path(const QString &relativePath)
virtual qint64 bytesAvailable() const const override
bool contains(QByteArrayView bv) const const
char * data()
qsizetype size() const const
QByteArray read(qint64 maxSize)
void readyRead()
qint64 write(const QByteArray &data)
virtual qint64 bytesAvailable() const const override
void connected()
void disconnected()
bool invokeMethod(QObject *context, Functor &&function, FunctorReturnType *ret)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
QString fromLatin1(QByteArrayView str)
qsizetype size() const const
QByteArray toLatin1() const const
QueuedConnection
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:31:58 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.