1
/****************************************************************************
3
** This file is part of a Qt Solutions component.
5
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
7
** Contact: Qt Software Information (qt-info@nokia.com)
10
** Licensees holding valid Qt Commercial licenses may use this file in
11
** accordance with the Qt Solutions Commercial License Agreement provided
12
** with the Software or, alternatively, in accordance with the terms
13
** contained in a written agreement between you and Nokia.
15
** GNU Lesser General Public License Usage
16
** Alternatively, this file may be used under the terms of the GNU Lesser
17
** General Public License version 2.1 as published by the Free Software
18
** Foundation and appearing in the file LICENSE.LGPL included in the
19
** packaging of this file. Please review the following information to
20
** ensure the GNU Lesser General Public License version 2.1 requirements
21
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23
** In addition, as a special exception, Nokia gives you certain
24
** additional rights. These rights are described in the Nokia Qt LGPL
25
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
28
** GNU General Public License Usage
29
** Alternatively, this file may be used under the terms of the GNU
30
** General Public License version 3.0 as published by the Free Software
31
** Foundation and appearing in the file LICENSE.GPL included in the
32
** packaging of this file. Please review the following information to
33
** ensure the GNU General Public License version 3.0 requirements will be
34
** met: http://www.gnu.org/copyleft/gpl.html.
36
** Please note Third Party Software included with Qt Solutions may impose
37
** additional restrictions and it is the user's responsibility to ensure
38
** that they have met the licensing requirements of the GPL, LGPL, or Qt
39
** Solutions Commercial license and the relevant license of the Third
40
** Party Software they are using.
42
** If you are unsure which license is appropriate for your use, please
43
** contact the sales department at qt-sales@nokia.com.
45
****************************************************************************/
48
#include "qtlocalpeer.h"
49
#include <QtCore/QCoreApplication>
50
#include <QtCore/QTime>
54
#include <QtCore/QLibrary>
55
#include <QtCore/qt_windows.h>
56
typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*);
57
static PProcessIdToSessionId pProcessIdToSessionId = 0;
59
#if defined(Q_OS_UNIX)
63
namespace QtLP_Private {
64
#include "qtlockedfile.cpp"
66
#include "qtlockedfile_win.cpp"
68
#include "qtlockedfile_unix.cpp"
72
const char* QtLocalPeer::ack = "ack";
74
QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
75
: QObject(parent), id(appId)
79
id = QCoreApplication::applicationFilePath();
83
prefix = id.section(QLatin1Char('/'), -1);
85
prefix.remove(QRegExp("[^a-zA-Z]"));
88
QByteArray idc = id.toUtf8();
89
quint16 idNum = qChecksum(idc.constData(), idc.size());
90
socketName = QLatin1String("qtsingleapp-") + prefix
91
+ QLatin1Char('-') + QString::number(idNum, 16);
94
if (!pProcessIdToSessionId) {
95
QLibrary lib("kernel32");
96
pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId");
98
if (pProcessIdToSessionId) {
100
pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
101
socketName += QLatin1Char('-') + QString::number(sessionId, 16);
104
socketName += QLatin1Char('-') + QString::number(::getuid(), 16);
107
server = new QLocalServer(this);
108
QString lockName = QDir(QDir::tempPath()).absolutePath()
109
+ QLatin1Char('/') + socketName
110
+ QLatin1String("-lockfile");
111
lockFile.setFileName(lockName);
112
lockFile.open(QIODevice::ReadWrite);
117
bool QtLocalPeer::isClient()
119
if (lockFile.isLocked())
122
if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false))
125
bool res = server->listen(socketName);
126
#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0))
128
if (!res && server->serverError() == QAbstractSocket::AddressInUseError) {
129
QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName);
130
res = server->listen(socketName);
134
qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
135
QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection()));
140
bool QtLocalPeer::sendMessage(const QString &message, int timeout)
147
for(int i = 0; i < 2; i++) {
148
// Try twice, in case the other instance is just starting up
149
socket.connectToServer(socketName);
150
connOk = socket.waitForConnected(timeout/2);
154
#if defined(Q_OS_WIN)
157
struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
158
nanosleep(&ts, NULL);
164
QByteArray uMsg(message.toUtf8());
165
QDataStream ds(&socket);
166
ds.writeBytes(uMsg.constData(), uMsg.size());
167
bool res = socket.waitForBytesWritten(timeout);
168
res &= socket.waitForReadyRead(timeout); // wait for ack
169
res &= (socket.read(qstrlen(ack)) == ack);
174
void QtLocalPeer::receiveConnection()
176
QLocalSocket* socket = server->nextPendingConnection();
180
while (socket->bytesAvailable() < (int)sizeof(quint32))
181
socket->waitForReadyRead();
182
QDataStream ds(socket);
186
uMsg.resize(remaining);
188
char* uMsgBuf = uMsg.data();
190
got = ds.readRawData(uMsgBuf, remaining);
193
} while (remaining && got >= 0 && socket->waitForReadyRead(2000));
195
qWarning() << "QtLocalPeer: Message reception failed" << socket->errorString();
199
QString message(QString::fromUtf8(uMsg));
200
socket->write(ack, qstrlen(ack));
201
socket->waitForBytesWritten(1000);
203
emit messageReceived(message); //### (might take a long time to return)