File indexing completed on 2024-05-12 04:50:47
0001 /* 0002 This file is part of KDSingleApplication. 0003 0004 SPDX-FileCopyrightText: 2019-2023 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> 0005 0006 SPDX-License-Identifier: MIT 0007 0008 Contact KDAB at <info@kdab.com> for commercial licensing options. 0009 */ 0010 0011 #ifndef KDSINGLEAPPLICATION_LOCALSOCKET_P_H 0012 #define KDSINGLEAPPLICATION_LOCALSOCKET_P_H 0013 0014 #include <QtCore/QObject> 0015 #include <QtCore/QByteArray> 0016 #include <QtCore/QString> 0017 0018 QT_BEGIN_NAMESPACE 0019 class QLockFile; 0020 class QLocalServer; 0021 class QLocalSocket; 0022 class QTimer; 0023 QT_END_NAMESPACE 0024 0025 #include <memory> 0026 #include <vector> 0027 0028 struct QObjectDeleteLater 0029 { 0030 void operator()(QObject *o) 0031 { 0032 o->deleteLater(); 0033 } 0034 }; 0035 0036 class QObjectConnectionHolder 0037 { 0038 Q_DISABLE_COPY(QObjectConnectionHolder) 0039 QMetaObject::Connection c; 0040 0041 public: 0042 QObjectConnectionHolder() 0043 { 0044 } 0045 0046 explicit QObjectConnectionHolder(QMetaObject::Connection _c) 0047 : c(std::move(_c)) 0048 { 0049 } 0050 0051 ~QObjectConnectionHolder() 0052 { 0053 QObject::disconnect(c); 0054 } 0055 0056 QObjectConnectionHolder(QObjectConnectionHolder &&other) noexcept 0057 : c(std::exchange(other.c, {})) 0058 { 0059 } 0060 0061 QObjectConnectionHolder &operator=(QObjectConnectionHolder &&other) noexcept 0062 { 0063 QObjectConnectionHolder moved(std::move(other)); 0064 swap(moved); 0065 return *this; 0066 } 0067 0068 void swap(QObjectConnectionHolder &other) noexcept 0069 { 0070 using std::swap; 0071 swap(c, other.c); 0072 } 0073 }; 0074 0075 class KDSingleApplicationLocalSocket : public QObject 0076 { 0077 Q_OBJECT 0078 0079 public: 0080 explicit KDSingleApplicationLocalSocket(const QString &name, 0081 QObject *parent = nullptr); 0082 ~KDSingleApplicationLocalSocket(); 0083 0084 bool isPrimaryInstance() const; 0085 0086 public Q_SLOTS: 0087 bool sendMessage(const QByteArray &message, int timeout); 0088 0089 Q_SIGNALS: 0090 void messageReceived(const QByteArray &message); 0091 0092 private: 0093 void handleNewConnection(); 0094 void readDataFromSecondary(); 0095 bool readDataFromSecondarySocket(QLocalSocket *socket); 0096 void secondaryDisconnected(); 0097 void secondarySocketDisconnected(QLocalSocket *socket); 0098 void abortConnectionToSecondary(); 0099 0100 QString m_socketName; 0101 0102 std::unique_ptr<QLockFile> m_lockFile; // protects m_localServer 0103 std::unique_ptr<QLocalServer> m_localServer; 0104 0105 struct Connection 0106 { 0107 explicit Connection(QLocalSocket *s); 0108 0109 std::unique_ptr<QLocalSocket, QObjectDeleteLater> socket; 0110 std::unique_ptr<QTimer, QObjectDeleteLater> timeoutTimer; 0111 QByteArray readData; 0112 0113 // socket/timeoutTimer are deleted via deleteLater (as we delete them 0114 // in slots connected to their signals). Before the deleteLater is acted upon, 0115 // they may emit further signals, triggering logic that it's not supposed 0116 // to be triggered (as the Connection has already been destroyed). 0117 // Use this Holder to break the connections. 0118 QObjectConnectionHolder readDataConnection; 0119 QObjectConnectionHolder secondaryDisconnectedConnection; 0120 QObjectConnectionHolder abortConnection; 0121 }; 0122 0123 std::vector<Connection> m_clients; 0124 }; 0125 0126 #endif // KDSINGLEAPPLICATION_LOCALSOCKET_P_H