2 ******************************************************************************
4 * @file qtlocalpeer.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
8 * @see The GNU Public License (GPL) Version 3
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "qtlocalpeer.h"
31 #include <QtCore/QCoreApplication>
32 #include <QtCore/QTime>
35 #include <QtCore/QLibrary>
36 #include <QtCore/qt_windows.h>
37 typedef BOOL (WINAPI
* PProcessIdToSessionId
)(DWORD
, DWORD
*);
38 static PProcessIdToSessionId pProcessIdToSessionId
= 0;
41 #if defined(Q_OS_UNIX)
46 namespace SharedTools
{
47 const char *QtLocalPeer::ack
= "ack";
49 QtLocalPeer::QtLocalPeer(QObject
*parent
, const QString
&appId
)
50 : QObject(parent
), id(appId
)
53 id
= QCoreApplication::applicationFilePath(); // ### On win, check if this returns .../argv[0] without casefolding; .\MYAPP == .\myapp on Win
55 QByteArray idc
= id
.toUtf8();
56 quint16 idNum
= qChecksum(idc
.constData(), idc
.size());
57 // ### could do: two 16bit checksums over separate halves of id, for a 32bit result - improved uniqeness probability. Every-other-char split would be best.
59 socketName
= QLatin1String("qtsingleapplication-")
60 + QString::number(idNum
, 16);
62 if (!pProcessIdToSessionId
) {
63 QLibrary
lib("kernel32");
64 pProcessIdToSessionId
= (PProcessIdToSessionId
)lib
.resolve("ProcessIdToSessionId");
66 if (pProcessIdToSessionId
) {
68 pProcessIdToSessionId(GetCurrentProcessId(), &sessionId
);
69 socketName
+= QLatin1Char('-') + QString::number(sessionId
, 16);
72 socketName
+= QLatin1Char('-') + QString::number(::getuid(), 16);
75 server
= new QLocalServer(this);
76 QString lockName
= QDir(QDir::tempPath()).absolutePath()
77 + QLatin1Char('/') + socketName
78 + QLatin1String("-lockfile");
79 lockFile
.setFileName(lockName
);
80 lockFile
.open(QIODevice::ReadWrite
);
83 bool QtLocalPeer::isClient()
85 if (lockFile
.isLocked()) {
89 if (!lockFile
.lock(QtLockedFile::WriteLock
, false)) {
93 if (!QLocalServer::removeServer(socketName
)) {
94 qWarning("QtSingleCoreApplication: could not cleanup socket");
96 bool res
= server
->listen(socketName
);
98 qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server
->errorString()));
100 QObject::connect(server
, SIGNAL(newConnection()), SLOT(receiveConnection()));
104 bool QtLocalPeer::sendMessage(const QString
&message
, int timeout
)
112 for (int i
= 0; i
< 2; i
++) {
113 // Try twice, in case the other instance is just starting up
114 socket
.connectToServer(socketName
);
115 connOk
= socket
.waitForConnected(timeout
/ 2);
120 #if defined(Q_OS_WIN)
123 struct timespec ts
= { ms
/ 1000, (ms
% 1000) * 1000 * 1000 };
124 nanosleep(&ts
, NULL
);
131 QByteArray
uMsg(message
.toUtf8());
132 QDataStream
ds(&socket
);
133 ds
.writeBytes(uMsg
.constData(), uMsg
.size());
134 bool res
= socket
.waitForBytesWritten(timeout
);
135 res
&= socket
.waitForReadyRead(timeout
); // wait for ack
136 res
&= (socket
.read(qstrlen(ack
)) == ack
);
140 void QtLocalPeer::receiveConnection()
142 QLocalSocket
*socket
= server
->nextPendingConnection();
148 // Why doesn't Qt have a blocking stream that takes care of this shait???
149 while (socket
->bytesAvailable() < static_cast<int>(sizeof(quint32
))) {
150 socket
->waitForReadyRead();
152 QDataStream
ds(socket
);
156 uMsg
.resize(remaining
);
158 char *uMsgBuf
= uMsg
.data();
159 // qDebug() << "RCV: remaining" << remaining;
161 got
= ds
.readRawData(uMsgBuf
, remaining
);
164 // qDebug() << "RCV: got" << got << "remaining" << remaining;
165 } while (remaining
&& got
>= 0 && socket
->waitForReadyRead(2000));
166 // ### error check: got<0
168 qWarning() << "QtLocalPeer: Message reception failed" << socket
->errorString();
173 QString message
= QString::fromUtf8(uMsg
.constData(), uMsg
.size());
174 socket
->write(ack
, qstrlen(ack
));
175 socket
->waitForBytesWritten(1000);
177 emit
messageReceived(message
); // ##(might take a long time to return)
179 } // namespace SharedTools