1 // The MIT License (MIT)
2 //
3 // Copyright (c) Itay Grudev 2015 - 2020
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // THE SOFTWARE.
22 
23 //
24 //  W A R N I N G !!!
25 //  -----------------
26 //
27 // This is a modified version of SingleApplication,
28 // The original version is at:
29 //
30 // https://github.com/itay-grudev/SingleApplication
31 //
32 //
33 
34 #ifndef SINGLECOREAPPLICATION_P_H
35 #define SINGLECOREAPPLICATION_P_H
36 
37 #include <QtGlobal>
38 #include <QObject>
39 #include <QString>
40 #include <QHash>
41 
42 #include "singlecoreapplication.h"
43 
44 class QLocalServer;
45 class QLocalSocket;
46 class QSharedMemory;
47 
48 struct InstancesInfo {
49   bool primary;
50   quint32 secondary;
51   qint64 primaryPid;
52   char primaryUser[128];
53   quint16 checksum;
54 };
55 
56 struct ConnectionInfo {
ConnectionInfoConnectionInfo57   explicit ConnectionInfo() : msgLen(0), instanceId(0), stage(0) {}
58   qint64 msgLen;
59   quint32 instanceId;
60   quint8 stage;
61 };
62 
63 class SingleCoreApplicationPrivate : public QObject {
64   Q_OBJECT
65 
66  public:
67   enum ConnectionType : quint8 {
68     InvalidConnection = 0,
69     NewInstance = 1,
70     SecondaryInstance = 2,
71     Reconnect = 3
72   };
73   enum ConnectionStage : quint8 {
74     StageHeader = 0,
75     StageBody = 1,
76     StageConnected = 2,
77   };
78   Q_DECLARE_PUBLIC(SingleCoreApplication)
79 
80   explicit SingleCoreApplicationPrivate(SingleCoreApplication *ptr);
81   ~SingleCoreApplicationPrivate() override;
82 
83   static QString getUsername();
84   void genBlockServerName();
85   void initializeMemoryBlock() const;
86   void startPrimary();
87   void startSecondary();
88   bool connectToPrimary(const int timeout, const ConnectionType connectionType);
89   quint16 blockChecksum() const;
90   qint64 primaryPid() const;
91   QString primaryUser() const;
92   void readInitMessageHeader(QLocalSocket *socket);
93   void readInitMessageBody(QLocalSocket *socket);
94   static void randomSleep();
95 
96   SingleCoreApplication *q_ptr;
97   QSharedMemory *memory_;
98   QLocalSocket *socket_;
99   QLocalServer *server_;
100   quint32 instanceNumber_;
101   QString blockServerName_;
102   SingleCoreApplication::Options options_;
103   QHash<QLocalSocket*, ConnectionInfo> connectionMap_;
104 
105  public slots:
106   void slotConnectionEstablished();
107   void slotDataAvailable(QLocalSocket*, const quint32);
108   void slotClientConnectionClosed(QLocalSocket*, const quint32);
109 };
110 
111 #endif  // SINGLECOREAPPLICATION_P_H
112