43#include <QCoreApplication>
49#if defined(Q_OS_LINUX) && !defined(DISABLE_DBUS)
55#include <qt_windows.h>
56typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*);
57static PProcessIdToSessionId pProcessIdToSessionId = 0;
75#include <QDBusConnection>
76#include <QDBusConnectionInterface>
77#include <QDBusAbstractAdaptor>
79class QtSingleAppDBusInterface :
public QDBusAbstractAdaptor
82 Q_CLASSINFO(
"D-Bus Interface",
"org.kde.QtSingleApplication")
85 explicit QtSingleAppDBusInterface(QObject *parent)
86 : QDBusAbstractAdaptor(parent)
91 void SendMessage(
const QString &message)
93 Q_EMIT messageReceived(message);
97 void messageReceived(
const QString &message);
101const char* QtLocalPeer::ack =
"ack";
104 : QObject(parent), id(appId)
108 id = QCoreApplication::applicationFilePath();
112 prefix =
id.section(QLatin1Char(
'/'), -1);
114 prefix = QRegExp(QStringLiteral(
"[^a-zA-Z]")).removeIn(prefix);
117 QByteArray idc =
id.toUtf8();
118 quint16 idNum = qChecksum(QByteArrayView(idc.constData(), idc.size()));
119 socketName = QLatin1String(
"qtsingleapp-") + prefix
120 + QLatin1Char(
'-') + QString::number(idNum, 16);
123 if (!pProcessIdToSessionId) {
124 QLibrary lib(
"kernel32");
125 pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve(
"ProcessIdToSessionId");
127 if (pProcessIdToSessionId) {
129 pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
130 socketName += QLatin1Char(
'-') + QString::number(sessionId, 16);
133 socketName += QLatin1Char(
'-') + QString::number(::getuid(), 16);
137 if (!QDBusConnection::sessionBus().isConnected()) {
138 qCritical(
"Failed to connect to session bus!");
140 m_dbusRegistered = QDBusConnection::sessionBus().registerService(
id);
141 if (m_dbusRegistered) {
142 auto *iface =
new QtSingleAppDBusInterface(
this);
144 QDBusConnection::sessionBus().registerObject(QStringLiteral(
"/"),
this);
147 server =
new QLocalServer(
this);
148 QString lockName = QDir(QDir::tempPath()).absolutePath()
150 + QLatin1String(
"-lockfile");
161 if (m_dbusRegistered) {
164 return QDBusConnection::sessionBus().interface()->isServiceRegistered(
id).value();
173#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0))
175 if (!res &&
server->serverError() == QAbstractSocket::AddressInUseError) {
176 QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char(
'/')+
socketName);
181 qWarning(
"QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(
server->errorString()));
194 QDBusMessage msg = QDBusMessage::createMethodCall(
id, QStringLiteral(
"/"),
195 QStringLiteral(
"org.kde.QtSingleApplication"),
196 QStringLiteral(
"SendMessage"));
198 return QDBusConnection::sessionBus().call(msg, QDBus::Block, timeout).type() == QDBusMessage::ReplyMessage;
202 for(
int i = 0;
i < 2;
i++) {
205 connOk = socket.waitForConnected(timeout/2);
212 struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
213 nanosleep(&ts, NULL);
219 QByteArray uMsg(message.toUtf8());
220 QDataStream ds(&socket);
221 ds.writeBytes(uMsg.constData(), uMsg.size());
222 bool res = socket.waitForBytesWritten(timeout);
224 res &= socket.waitForReadyRead(timeout);
226 res &= (socket.read(qstrlen(ack)) == ack);
242 QLocalSocket* socket =
server->nextPendingConnection();
247 if (socket->state() == QLocalSocket::UnconnectedState) {
248 qWarning(
"QtLocalPeer: Peer disconnected");
252 if (socket->bytesAvailable() >= qint64(
sizeof(quint32)))
254 socket->waitForReadyRead();
257 QDataStream ds(socket);
261 uMsg.resize(remaining);
263 char* uMsgBuf = uMsg.data();
265 got = ds.readRawData(uMsgBuf, remaining);
268 }
while (remaining && got >= 0 && socket->waitForReadyRead(2000));
270 qWarning(
"QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData());
274 QString message(QString::fromUtf8(uMsg));
275 socket->write(ack, qstrlen(ack));
276 socket->waitForBytesWritten(1000);
277 socket->waitForDisconnected(1000);
283#include "qtlocalpeer.moc"
bool open(OpenMode mode) override
bool lock(LockMode mode, bool block=true)
void messageReceived(const QString &message)
bool sendMessage(const QString &message, int timeout)
QtLocalPeer(QObject *parent=nullptr, const QString &appId=QString())
QtLP_Private::QtLockedFile lockFile