1 /*
2  * Stellarium Remote Sync plugin
3  * Copyright (C) 2015 Florian Schaukowitsch
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
18  */
19 
20 #ifndef SYNCSERVER_HPP
21 #define SYNCSERVER_HPP
22 
23 #include "SyncProtocol.hpp"
24 #include <QObject>
25 #include <QAbstractSocket>
26 #include <QDateTime>
27 #include <QLoggingCategory>
28 #include <QUuid>
29 
30 class QTcpServer;
31 class SyncServerEventSender;
32 
33 Q_DECLARE_LOGGING_CATEGORY(syncServer)
34 
35 //! Implements a server to which SyncClients can connect and receive state changes
36 class SyncServer : public QObject
37 {
38 	Q_OBJECT
39 
40 public:
41 	SyncServer(QObject* parent = Q_NULLPTR, bool allowVersionMismatch=false);
42 	virtual ~SyncServer() Q_DECL_OVERRIDE;
43 
44 	//! This should be called in the StelModule::update function
45 	void update();
46 
47 	//! Broadcasts this message to all connected and authenticated clients
48 	void broadcastMessage(const SyncProtocol::SyncMessage& msg);
49 public slots:
50 	//! Starts the SyncServer on the specified port. If the server is already running, stops it first.
51 	//! Returns true if successful (false usually means port was in use, use getErrorString)
52 	bool start(quint16 port);
53 	//! Disconnects all clients, and stops listening
54 	void stop();
55 	//! Returns a string of the last server error.
56 	QString errorString() const;
57 signals:
58 	//! Emitted when the server is completely stopped, and all clients have disconnected
59 	void serverStopped();
60 
61 protected:
62 	void timerEvent(QTimerEvent* evt) Q_DECL_OVERRIDE;
63 private slots:
64 	void handleNewConnection();
65 	void connectionError(QAbstractSocket::SocketError err);
66 
67 	void clientAuthenticated(SyncRemotePeer& peer);
68 	void clientDisconnected(bool clean);
69 
70 private:
71 	void addSender(SyncServerEventSender* snd);
72 	void checkTimeouts();
73 	void checkStopState();
74 	//use composition instead of inheritance, cleaner interfaace this way
75 	//for now, we use TCP, but will test multicast UDP later if the basic setup is working
76 	QTcpServer* qserver;
77 	QVector<SyncMessageHandler*> handlerList;
78 	QVector<SyncServerEventSender*> senderList;
79 
80 	bool stopping;
81 
82 	// client list
83 	typedef QVector<SyncRemotePeer*> tClientList;
84 	tClientList clients;
85 
86 	QByteArray broadcastBuffer;
87 	int timeoutTimerId;
88 	friend class ServerAuthHandler;
89 };
90 
91 #endif
92