File indexing completed on 2024-05-12 05:52:02
0001 // The MIT License (MIT) 0002 // 0003 // Copyright (c) Itay Grudev 2015 - 2020 0004 // 0005 // Permission is hereby granted, free of charge, to any person obtaining a copy 0006 // of this software and associated documentation files (the "Software"), to deal 0007 // in the Software without restriction, including without limitation the rights 0008 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 0009 // copies of the Software, and to permit persons to whom the Software is 0010 // furnished to do so, subject to the following conditions: 0011 // 0012 // The above copyright notice and this permission notice shall be included in 0013 // all copies or substantial portions of the Software. 0014 // 0015 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 0016 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 0017 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 0018 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 0019 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 0020 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 0021 // THE SOFTWARE. 0022 0023 // 0024 // W A R N I N G !!! 0025 // ----------------- 0026 // 0027 // This file is not part of the SingleApplication API. It is used purely as an 0028 // implementation detail. This header file may change from version to 0029 // version without notice, or may even be removed. 0030 // 0031 0032 #pragma once 0033 0034 #include <QtCore/QSharedMemory> 0035 #include <QtNetwork/QLocalServer> 0036 #include <QtNetwork/QLocalSocket> 0037 #include "singleapplication.h" 0038 0039 struct InstancesInfo { 0040 bool primary; 0041 quint32 secondary; 0042 qint64 primaryPid; 0043 char primaryUser[128]; 0044 quint16 checksum; // Must be the last field 0045 }; 0046 0047 struct ConnectionInfo { 0048 qint64 msgLen = 0; 0049 quint32 instanceId = 0; 0050 quint8 stage = 0; 0051 }; 0052 0053 class SingleApplicationPrivate : public QObject { 0054 Q_OBJECT 0055 public: 0056 enum ConnectionType : quint8 { 0057 InvalidConnection = 0, 0058 NewInstance = 1, 0059 SecondaryInstance = 2, 0060 Reconnect = 3 0061 }; 0062 enum ConnectionStage : quint8 { 0063 StageInitHeader = 0, 0064 StageInitBody = 1, 0065 StageConnectedHeader = 2, 0066 StageConnectedBody = 3, 0067 }; 0068 Q_DECLARE_PUBLIC(SingleApplication) 0069 0070 SingleApplicationPrivate( SingleApplication *q_ptr ); 0071 ~SingleApplicationPrivate() override; 0072 0073 static QString getUsername(); 0074 void genBlockServerName(); 0075 void initializeMemoryBlock() const; 0076 void startPrimary(); 0077 void startSecondary(); 0078 bool connectToPrimary( int msecs, ConnectionType connectionType ); 0079 quint16 blockChecksum() const; 0080 qint64 primaryPid() const; 0081 QString primaryUser() const; 0082 bool isFrameComplete(QLocalSocket *sock); 0083 void readMessageHeader(QLocalSocket *socket, ConnectionStage nextStage); 0084 void readInitMessageBody(QLocalSocket *socket); 0085 void writeAck(QLocalSocket *sock); 0086 bool writeConfirmedFrame(int msecs, const QByteArray &msg); 0087 bool writeConfirmedMessage(int msecs, const QByteArray &msg, SingleApplication::SendMode sendMode = SingleApplication::NonBlocking); 0088 static void randomSleep(); 0089 void addAppData(const QString &data); 0090 QStringList appData() const; 0091 0092 SingleApplication *q_ptr; 0093 QSharedMemory *memory; 0094 QLocalSocket *socket; 0095 QLocalServer *server; 0096 quint32 instanceNumber; 0097 QString blockServerName; 0098 SingleApplication::Options options; 0099 QMap<QLocalSocket*, ConnectionInfo> connectionMap; 0100 QStringList appDataList; 0101 0102 public Q_SLOTS: 0103 void slotConnectionEstablished(); 0104 void slotDataAvailable( QLocalSocket*, quint32 ); 0105 void slotClientConnectionClosed( QLocalSocket*, quint32 ); 0106 }; 0107