Stellarium 0.15.2
SyncProtocol.hpp
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 SYNCPROTOCOL_HPP_
21 #define SYNCPROTOCOL_HPP_
22 
23 #include <QByteArray>
24 #include <QDataStream>
25 #include <QAbstractSocket>
26 #include <QUuid>
27 
29 namespace SyncProtocol
30 {
31 
32 //Important: All data should use the sized typedefs provided by Qt (i.e. qint32 instead of 4 byte int on x86)
33 
35 const quint8 SYNC_PROTOCOL_VERSION = 1;
36 const QDataStream::Version SYNC_DATASTREAM_VERSION = QDataStream::Qt_5_0;
38 const QByteArray SYNC_MAGIC_VALUE = "StellariumSyncPluginProtocol";
39 
40 typedef quint16 tPayloadSize;
41 
43 struct SyncHeader
44 {
45  quint8 msgType; //The SyncMessageType of the data
46  SyncProtocol::tPayloadSize dataSize; //The size of the data part
47  //TODO maybe add checksum?
48 };
49 
51 QDataStream& operator<<(QDataStream& out, const SyncHeader& header);
53 QDataStream& operator>>(QDataStream& in, SyncHeader& header);
54 
55 const qint64 SYNC_HEADER_SIZE = sizeof(quint8) + sizeof(tPayloadSize); //3 byte
56 const qint64 SYNC_MAX_PAYLOAD_SIZE = (2<<15) - 1; // 65535
57 const qint64 SYNC_MAX_MESSAGE_SIZE = SYNC_HEADER_SIZE + SYNC_MAX_PAYLOAD_SIZE;
58 
62 {
63  ERROR, //sent to the other party on protocol/auth error with a message, connection will be dropped afterwards
64  SERVER_CHALLENGE, //sent as a challenge to the client on establishment of connection
65  CLIENT_CHALLENGE_RESPONSE, //sent as a reply to the challenge
66  SERVER_CHALLENGERESPONSEVALID, //sent from the server to the client after valid client hello was received.
67 
68  //all messages below here can only be sent from authenticated peers
69  TIME, //time jumps + time scale updates
70  LOCATION, //location changes
71  SELECTION,
72 
73  ALIVE, //sent from a peer after no data was sent for about 5 seconds to indicate it is still alive
74  MSGTYPE_MAX = ALIVE,
75  MSGTYPE_SIZE = MSGTYPE_MAX+1
76 };
77 
78 inline QDebug& operator<<(QDebug& deb, SyncMessageType msg)
79 {
80  switch (msg) {
81  case SyncProtocol::ERROR:
82  deb<<"ERROR";
83  break;
84  case SyncProtocol::SERVER_CHALLENGE:
85  deb<<"SERVER_CHALLENGE";
86  break;
87  case SyncProtocol::CLIENT_CHALLENGE_RESPONSE:
88  deb<<"CLIENT_CHALLENGE_RESPONSE";
89  break;
90  case SyncProtocol::SERVER_CHALLENGERESPONSEVALID:
91  deb<<"SERVER_CHALLENGERESPONSEVALID";
92  break;
93  case SyncProtocol::TIME:
94  deb<<"TIME";
95  break;
96  case SyncProtocol::LOCATION:
97  deb<<"LOCATION";
98  break;
99  case SyncProtocol::SELECTION:
100  deb<<"SELECTION";
101  break;
102  case SyncProtocol::ALIVE:
103  deb<<"ALIVE";
104  break;
105  default:
106  deb<<"UNKNOWN("<<int(msg)<<')';
107  break;
108  }
109  return deb;
110 }
111 
112 }
113 
116 {
117 public:
118  virtual ~SyncMessage() {}
119 
121  virtual SyncProtocol::SyncMessageType getMessageType() const = 0;
122 
125  qint64 createFullMessage(QByteArray& target) const;
126 
129  virtual void serialize(QDataStream& stream) const;
132  virtual bool deserialize(QDataStream& stream, SyncProtocol::tPayloadSize dataSize);
133 
134 protected:
135  static void writeString(QDataStream& stream, const QString& str);
136  static QString readString(QDataStream& stream);
137 };
138 
139 class SyncMessageHandler;
140 
143 {
144 public:
145  SyncRemotePeer();
146  SyncRemotePeer(QAbstractSocket* socket, bool isServer, const QVector<SyncMessageHandler*>& handlerList);
147 
150  void receiveMessage();
151 
153  void writeMessage(const SyncMessage& msg);
155  void writeData(const QByteArray& data, int size=-1);
157  void writeError(const QString& err);
158 
160  void peerLog(const QString& msg);
161 
162  bool isValid;
163  QAbstractSocket* sock; // The socket for communication with this peer
164  bool isPeerAServer; // True if this identifies a server
165  QUuid id; // An ID value, currently not used for anything else than auth. The server always has a NULL UUID.
166  bool isAuthenticated; // True if the peer ran through the HELLO process and can receive/send all message types
167  bool authResponseSent; //only for client use, tracks if the client has sent a resonse to the server challenge
168  bool waitingForBody; //True if waiting for full message body (after header was received)
169  SyncProtocol::SyncHeader msgHeader; //the last message header read/currently being processed
170  qint64 lastReceiveTime; // The time the last data of this peer was received
171  qint64 lastSendTime; //The time the last data was written to this peer
172  QVector<SyncMessageHandler*> handlerList;
173  QByteArray msgWriteBuffer; //Byte array used to construct messages before writing them
174 };
175 
178 {
179 public:
180  virtual ~SyncMessageHandler() {}
181 
185  virtual bool handleMessage(QDataStream& stream, SyncRemotePeer& peer) = 0;
186 };
187 
188 Q_DECLARE_INTERFACE(SyncMessageHandler,"Stellarium/RemoteSync/SyncMessageHandler/1.0")
189 
190 
191 #endif
All messages are preceded by this.
Base interface for message handlers, i.e. reacting to messages.
Contains sync protocol data definitions shared between client and server.
Handling the connection to a remote peer (i.e. all clients on the server, and the server on the clien...
QDataStream & operator>>(QDataStream &in, SyncHeader &header)
Read a SyncHeader from a DataStream.
SyncMessageType
Contains the possible message types.
const QByteArray SYNC_MAGIC_VALUE
Magic value for protocol used during connection. Should NEVER change.
const quint8 SYNC_PROTOCOL_VERSION
Should be changed with every breaking change.
Base interface for the messages themselves, allowing to serialize/deserialize them.
QDataStream & operator<<(QDataStream &out, const SyncHeader &header)
Write a SyncHeader to a DataStream.