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