1 /*******************************************************************************************************
2  DkNetwork.h
3  Created on:	20.07.2011
4 
5  nomacs is a fast and small image viewer with the capability of synchronizing multiple instances
6 
7  Copyright (C) 2011-2013 Markus Diem <markus@nomacs.org>
8  Copyright (C) 2011-2013 Stefan Fiel <stefan@nomacs.org>
9  Copyright (C) 2011-2013 Florian Kleber <florian@nomacs.org>
10 
11  This file is part of nomacs.
12 
13  nomacs is free software: you can redistribute it and/or modify
14  it under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  nomacs is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  GNU General Public License for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with this program.  If not, see <http://www.gnu.org/licenses/>..
25 
26  *******************************************************************************************************/
27 
28 #pragma  once
29 
30 #define local_tcp_port_start 45454
31 #define local_tcp_port_end 45484
32 
33 #pragma warning(push, 0)	// no warnings from includes - begin
34 #include <QTcpServer>
35 #include <QThread>
36 #include <QMutex>
37 #include <QSharedPointer>
38 #pragma warning(pop)		// no warnings from includes - end
39 
40 #include "DkConnection.h"
41 
42 class QMimeData;
43 
44 namespace nmc {
45 
46 // nomacs defines
47 class DkLocalTcpServer;
48 class DkLANTcpServer;
49 class DkLANUdpSocket;
50 
51 class DkPeer : public QObject{
52 	Q_OBJECT
53 
54 public:
55 	DkPeer(
56 		quint16 port,
57 		quint16 peerId,
58 		const QHostAddress& hostAddress,
59 		quint16 peerServerPort,
60 		const QString& title,
61 		DkConnection* connection,
62 		bool sychronized = false,
63 		const QString& clientName="",
64 		bool showInMenu = false,
65 		QObject* parent = NULL);
66 
67 	~DkPeer();
68 
69 	bool operator==(const DkPeer& peer) const;
70 
isActive()71 	bool isActive() const { return mHasChangedRecently; };
72 	void setSynchronized(bool flag);
isSynchronized()73 	bool isSynchronized() const {return sychronized;};
isLocal()74 	bool isLocal() const {
75 		return hostAddress == QHostAddress::LocalHost;
76 	};
77 
78 	quint16 peerId;
79 	quint16 localServerPort;
80 	quint16 peerServerPort;
81 	QHostAddress hostAddress;
82 	QString clientName;
83 	QString title;
84 	DkConnection* connection;
85 	QTimer* timer;
86 	bool showInMenu;
87 
88 signals:
89 	void sendGoodByeMessage();
90 private slots:
91 	void timerTimeout();
92 
93 private:
94 	bool mHasChangedRecently = false;
95 	bool sychronized;
96 };
97 
98 class DkPeerList {
99 
100 public:
101 	DkPeerList();
102 	bool addPeer(DkPeer* peer);
103 	bool removePeer(quint16 peerId);
104 	bool setSynchronized(quint16 peerId, bool synchronized);
105 	bool setTitle(quint16 peerId, const QString& title);
106 	bool setShowInMenu(quint16 peerId, bool showInMenu);
107 	QList<DkPeer*> getPeerList();
108 	DkPeer* getPeerById(quint16 id);
109 	DkPeer* getPeerByAddress(const QHostAddress& address, quint16 port) const;
110 
111 	QList<DkPeer*> getSynchronizedPeers() const;
112 	QList<quint16> getSynchronizedPeerServerPorts() const;
113 	QList<DkPeer*> getActivePeers() const;
114 
115 	DkPeer* getPeerByServerport(quint16 port) const;
116 	bool alreadyConnectedTo(const QHostAddress& address, quint16 port) const;
117 	void print() const;
118 
119 private:
120 	QMultiHash<quint16, DkPeer*> peerList;
121 };
122 
123 class DkClientManager : public QObject {
124 	Q_OBJECT
125 	public:
126 		DkClientManager(const QString& title, QObject* parent = 0);
127 		~DkClientManager();
128 		virtual	QList<DkPeer*> getPeerList() = 0;
129 
130 	signals:
131 		void receivedTransformation(QTransform transform, QTransform imgTransform, QPointF canvasSize);
132 		void receivedPosition(QRect position, bool opacity, bool overlaid);
133 		void receivedNewFile(qint16 op, const QString& filename);
134 		void receivedImage(const QImage& image);
135 		void receivedImageTitle(const QString& title);
136 		void sendInfoSignal(const QString& msg, int time = 3000);
137 		void sendGreetingMessage(const QString& title);
138 		void sendSynchronizeMessage();
139 		void sendDisableSynchronizeMessage();
140 		void sendNewTitleMessage(const QString& newtitle);
141 		void sendNewPositionMessage(QRect position, bool opacity, bool overlaid);
142 		void sendNewTransformMessage(QTransform transform, QTransform imgTransform, QPointF canvasSize);
143 		void sendNewFileMessage(qint16 op, const QString& filename);
144 		void sendNewImageMessage(QImage image, const QString& title);
145 		void sendNewUpcomingImageMessage(const QString& imageTitle);
146 		void sendGoodByeMessage();
147 		void synchronizedPeersListChanged(QList<quint16> newList);
148 		void updateConnectionSignal(const QString&);
149 		void clientConnectedSignal(bool);
150 
151 		void receivedQuit();
152 
153 	public slots:
154 		virtual void synchronizeWith(quint16 peerId) = 0;
155 		virtual void synchronizeWithServerPort(quint16 port) = 0;
156 		virtual void stopSynchronizeWith(quint16 peerId) = 0;
157 		virtual void sendTitle(const QString& newTitle);
158 		void sendTransform(QTransform transform, QTransform imgTransform, QPointF canvasSize);
159 		void sendPosition(QRect newRect, bool overlaid);
160 
161 		void sendNewFile(qint16 op, const QString& filename);
sendNewImage(QImage,const QString &)162 		virtual void sendNewImage(QImage, const QString&) {}; // dummy
163 		void sendGoodByeToAll();
164 
165 	protected slots:
166 		void newConnection( int socketDescriptor );
167 		virtual void connectionReadyForUse(quint16 peerId, const QString& title, DkConnection* connection);
168 		virtual void connectionSynchronized(QList<quint16> synchronizedPeersOfOtherClient, DkConnection* connection) = 0;
169 		virtual void connectionStopSynchronized(DkConnection* connection) = 0;
170 		virtual void connectionSentNewTitle(DkConnection* connection, const QString& newTitle);
171 		virtual void connectionReceivedTransformation(DkConnection* connection, const QTransform& transform, const QTransform& imgTransform, const QPointF& canvasSize);
172 		virtual void connectionReceivedPosition(DkConnection* connection, const QRect& rect, bool opacity, bool overlaid);
173 		virtual void connectionReceivedNewFile(DkConnection* connection, qint16 op, const QString& filename);
174 		virtual void connectionReceivedGoodBye(DkConnection* connection);
175 		void connectionShowStatusMessage(DkConnection* connection, const QString& msg);
176 		void disconnected();
177 
178 	protected:
179 		void removeConnection(DkConnection* connection);
180 		void connectConnection(DkConnection* connection);
181 		virtual DkConnection* createConnection() = 0;
182 		QString listConnections(QList<DkPeer*> peers, bool connected);
183 
184 		DkPeerList mPeerList;
185 		QString mCurrentTitle;
186 		quint16 mNewPeerId;
187 		QList<DkConnection*> mStartUpConnections;
188 
189 };
190 
191 class DkLocalClientManager : public DkClientManager {
192 	Q_OBJECT
193 
194 public:
195 	DkLocalClientManager(const QString& title, QObject* parent = 0);
196 	QList<DkPeer*> getPeerList();
197 	quint16 getServerPort() const;
198 
199 	QMimeData* mimeData() const;
200 	void startServer();
201 
202 signals:
203 	void receivedQuit();
204 	void sendQuitMessage();
205 
206 public slots:
207 	void stopSynchronizeWith(quint16 peerId);
208 	void synchronizeWithServerPort(quint16 port);
209 	void synchronizeWith(quint16 peerId);
210 	void sendArrangeInstances(bool overlaid);
211 	void sendQuitMessageToPeers();
212 	void connectToNomacs();
213 	void connectAll();
214 
215 private slots:
216 	void connectionSynchronized(QList<quint16> synchronizedPeersOfOtherClient, DkConnection* connection);
217 	virtual void connectionStopSynchronized(DkConnection* connection);
218 	void connectionReceivedQuit();
219 
220 private:
221 	DkLocalConnection* createConnection();
222 	void searchForOtherClients();
223 
224 	DkLocalTcpServer* mServer;
225 };
226 
227 class DkLocalTcpServer : public QTcpServer {
228 	Q_OBJECT
229 
230 public:
231 	DkLocalTcpServer(QObject* parent = 0);
232 
233 signals:
234 	void serverReiceivedNewConnection(int DkDescriptor);
235 
236 protected:
237 	void incomingConnection(qintptr socketDescriptor) override;
238 };
239 
240 class DllCoreExport DkSyncManager {
241 
242 public:
243 	static DkSyncManager& inst();
244 
245 	// singleton
246 	DkSyncManager(DkSyncManager const&) = delete;
247 	void operator=(DkSyncManager const&) = delete;
248 
249 	DkClientManager* client();
250 
251 private:
252 	DkSyncManager();
253 
254 	DkLocalClientManager* mClient = 0;
255 };
256 
257 
258 }
259 
260