4 #include <QCoreApplication>
7 #include <QLocalServer>
8 #include <QLocalSocket>
11 #if TTK_QT_VERSION_CHECK(5,0,0)
12 # include <QRegularExpression>
17 # define WIN32_LEAN_AND_MEAN
18 # include <qt_windows.h>
19 typedef BOOL (WINAPI *PProcessIdToSessionId)(DWORD, DWORD*);
20 static PProcessIdToSessionId pProcessIdToSessionId = 0;
22 #if defined(Q_OS_UNIX)
23 # include <sys/types.h>
73 QString prefix = d->m_id = id;
76 d->m_id = QCoreApplication::applicationFilePath();
78 d->m_id = d->m_id.toLower();
80 prefix = d->m_id.section(QLatin1Char(
'/'), -1);
82 #if TTK_QT_VERSION_CHECK(5,0,0)
83 prefix.remove(QRegularExpression(
"[^a-zA-Z]"));
85 prefix.remove(QRegExp(
"[^a-zA-Z]"));
89 const QByteArray &idc = d->m_id.toUtf8();
90 #if TTK_QT_VERSION_CHECK(6,0,0)
91 quint16 idNum = qChecksum(QByteArrayView(idc.constData(), idc.length()));
93 quint16 idNum = qChecksum(idc.constData(), idc.length());
95 d->m_socketName = QLatin1String(
"qtsingleapp-") + prefix + QLatin1Char(
'-') + QString::number(idNum, 16);
98 if(!pProcessIdToSessionId)
100 QLibrary lib(
"kernel32");
101 pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve(
"ProcessIdToSessionId");
103 if(pProcessIdToSessionId)
106 pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
107 d->m_socketName += QLatin1Char(
'-') + QString::number(sessionId, 16);
110 d->m_socketName += QLatin1Char(
'-') + QString::number(::getuid(), 16);
113 d->m_server =
new QLocalServer(
this);
114 const QString &lockName = QDir(QDir::tempPath()).absolutePath() + QLatin1Char(
'/') + d->m_socketName + QLatin1String(
"-lockfile");
115 d->m_lockFile.setFileName(lockName);
116 d->m_lockFile.open(QIODevice::ReadWrite);
122 if(d->m_lockFile.isLocked())
132 bool res = d->m_server->listen(d->m_socketName);
133 #if defined(Q_OS_UNIX) && TTK_QT_VERSION_CHECK(4,5,0)
135 if(!res && d->m_server->serverError() == QAbstractSocket::AddressInUseError)
137 QFile::remove(QDir::cleanPath(QDir::tempPath()) + QLatin1Char(
'/') + d->m_socketName);
138 res = d->m_server->listen(d->m_socketName);
160 for(
int i = 0; i < 2; ++i)
163 socket.connectToServer(d->m_socketName);
164 connOk = socket.waitForConnected(timeout / 2);
170 constexpr
int ms = 250;
171 #if defined(Q_OS_WIN)
174 struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
175 nanosleep(&ts,
nullptr);
183 const QByteArray uMsg(message.toUtf8());
184 QDataStream ds(&socket);
185 ds.writeBytes(uMsg.constData(), uMsg.length());
187 bool res = socket.waitForBytesWritten(timeout);
190 res &= socket.waitForReadyRead(timeout);
193 res &= (socket.read(qstrlen(d->m_ack)) == d->m_ack);
208 QLocalSocket *socket = d->m_server->nextPendingConnection();
216 if(socket->state() == QLocalSocket::UnconnectedState)
223 if(socket->bytesAvailable() >= qint64(
sizeof(quint32)))
227 socket->waitForReadyRead();
230 QDataStream ds(socket);
234 uMsg.resize(remaining);
237 char *uMsgBuf = uMsg.data();
240 got = ds.readRawData(uMsgBuf, remaining);
243 }
while(remaining && got >= 0 && socket->waitForReadyRead(2000));
247 TTK_WARN_STREAM(
"TTKLocalPeer: Message reception failed " << socket->errorString().toLatin1().constData());
252 const QString message(QString::fromUtf8(uMsg));
253 socket->write(d->m_ack, qstrlen(d->m_ack));
254 socket->waitForBytesWritten(1000);
255 socket->waitForDisconnected(1000);
The namespace of locked private.
The class of the ttk local file.
TTKLocalPeer(QObject *parent=nullptr, const QString &id={})
The class of the ttk local peer.
The class of the ttk local peer private.
static const char * m_ack
#define TTK_WARN_STREAM(msg)
TTKLockedPrivate::TTKLockedFile m_lockFile
void messageReceived(const QString &message)
QString applicationId() const
#define TTK_INIT_PRIVATE(Class)
The class of the ttk private base.
bool sendMessage(const QString &message, int timeout) const