KDEGames

kmessageio.h
1 /*
2  This file is part of the KDE games library
3  SPDX-FileCopyrightText: 2001 Burkhard Lehner <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.0-only
6 */
7 
8 /*
9  KMessageIO class and subclasses KMessageSocket and KMessageDirect
10 */
11 
12 #ifndef _KMESSAGEIO_H_
13 #define _KMESSAGEIO_H_
14 
15 // own
16 #include "libkdegamesprivate_export.h"
17 // Qt
18 #include <QHostAddress>
19 #include <QLoggingCategory>
20 #include <QObject>
21 #include <QProcess>
22 #include <QString>
23 
24 /*
25  This macro shouldn't be here ideally. Already declared in kgame.h, but throws error if not placed here.
26 */
27 Q_DECLARE_LOGGING_CATEGORY(GAMES_PRIVATE_KGAME)
28 
29 class QTcpSocket;
30 class KProcess;
31 
32 /**
33  \class KMessageIO kmessageio.h <KGame/KMessageIO>
34 
35  This abstract base class represents one end of a message connections
36  between two clients. Each client has one object of a subclass of
37  KMessageIO. Calling /e send() on one object will emit the signal
38  /e received() on the other object, and vice versa.
39 
40  For each type of connection (TCP/IP socket, COM port, direct connection
41  within the same class) a subclass of KMessageIO must be defined that
42  implements the pure virtual methods /e send() and /e isConnected(),
43  and sends the signals. (See /e KMessageSocket for an example implementation.)
44 
45  Two subclasses are already included: /e KMessageSocket (connection using
46  TCP/IP sockets) and /e KMessageDirect (connection using method calls, both
47  sides must be within the same process).
48 */
49 class KDEGAMESPRIVATE_EXPORT KMessageIO : public QObject
50 {
51  Q_OBJECT
52 
53 public:
54  /**
55  * The usual QObject constructor, does nothing else.
56  */
57  explicit KMessageIO(QObject *parent = nullptr);
58 
59  /**
60  * The usual destructor, does nothing special.
61  */
62  ~KMessageIO() override;
63 
64  /**
65  * The runtime identification
66  */
67  virtual int rtti() const
68  {
69  return 0;
70  }
71 
72  /**
73  * @return Whether this KMessageIO is a network IO or not.
74  */
75  // virtual bool isNetwork () const = 0;
76  virtual bool isNetwork() const
77  {
78  qCCritical(GAMES_PRIVATE_KGAME) << "Calling PURE virtual isNetwork...BAD";
79  return false;
80  }
81 
82  /**
83  This method returns the status of the object, whether it is already
84  (or still) connected to another KMessageIO object or not.
85 
86  This is a pure virtual method, so it has to be implemented in a subclass
87  of KMessageIO.
88  */
89  // virtual bool isConnected () const = 0;
90  virtual bool isConnected() const
91  {
92  qCCritical(GAMES_PRIVATE_KGAME) << "Calling PURE virtual isConnected...BAD";
93  return false;
94  }
95 
96  /**
97  Sets the ID number of this object. This number can for example be used to
98  distinguish several objects in a server.
99 
100  NOTE: Sometimes it is useful to let two connected KMessageIO objects
101  have the same ID number. You have to do so yourself, KMessageIO doesn't
102  change this value on its own!
103  */
104  void setId(quint32 id);
105 
106  /**
107  Queries the ID of this object.
108  */
109  quint32 id();
110 
111  /**
112  @return 0 in the default implementation. Reimplemented in @ref KMessageSocket.
113  */
114  virtual quint16 peerPort() const
115  {
116  return 0;
117  }
118 
119  /**
120  @return "localhost" in the default implementation. Reimplemented in @ref KMessageSocket
121  */
122  virtual QString peerName() const
123  {
124  return QStringLiteral("localhost");
125  }
126 
127 Q_SIGNALS:
128  /**
129  This signal is emitted when /e send() on the connected KMessageIO
130  object is called. The parameter contains the same data array in /e msg
131  as was used in /e send().
132  */
133  void received(const QByteArray &msg);
134 
135  /**
136  This signal is emitted when the connection is closed. This can be caused
137  by a hardware error (e.g. broken internet connection) or because the other
138  object was killed.
139 
140  Note: Sometimes a broken connection can be undetected for a long time,
141  or may never be detected at all. So don't rely on this signal!
142  */
143  void connectionBroken();
144 
145 public Q_SLOTS:
146 
147  /**
148  This slot sends the data block in /e msg to the connected object, that will
149  emit /e received().
150 
151  For a concrete class, you have to subclass /e KMessageIO and overwrite this
152  method. In the subclass, implement this method as an ordinary method, not
153  as a slot! (Otherwise another slot would be defined. It would work, but uses
154  more memory and time.) See /e KMessageSocket for an example implementation.
155  */
156  virtual void send(const QByteArray &msg) = 0;
157 
158 protected:
159  quint32 m_id;
160 };
161 
162 /**
163  \class KMessageSocket kmessageio.h <KGame/KMessageIO>
164 
165  This class implements the message communication using a TCP/IP socket. The
166  object can connect to a server socket, or can use an already connected socket.
167 */
168 
170 {
171  Q_OBJECT
172 
173 public:
174  /**
175  Connects to a server socket on /e host with /e port. host can be an
176  numerical (e.g. "192.168.0.212") or symbolic (e.g. "wave.peter.org")
177  IP address. You can immediately use the /e sendSystem() and
178  /e sendBroadcast() methods. The messages are stored and sent to the
179  receiver after the connection is established.
180 
181  If the connection could not be established (e.g. unknown host or no server
182  socket at this port), the signal /e connectionBroken is emitted.
183  */
184  KMessageSocket(const QString &host, quint16 port, QObject *parent = nullptr);
185 
186  /**
187  Connects to a server socket on /e host with /e port. You can immediately
188  use the /e sendSystem() and /e sendBroadcast() methods. The messages are
189  stored and sent to the receiver after the connection is established.
190 
191  If the connection could not be established (e.g. unknown host or no server
192  socket at this port), the signal /e connectionBroken is emitted.
193  */
194  KMessageSocket(const QHostAddress &host, quint16 port, QObject *parent = nullptr);
195 
196  /**
197  Uses /e socket to do the communication.
198 
199  The socket should already be connected, or at least be in /e connecting
200  state.
201 
202  Note: The /e socket object is then owned by the /e KMessageSocket object.
203  So don't use it otherwise any more and don't delete it. It is deleted
204  together with this KMessageSocket object. (Use 0 as parent for the QSocket
205  object t ensure it is not deleted.)
206  */
207  explicit KMessageSocket(QTcpSocket *socket, QObject *parent = nullptr);
208 
209  /**
210  Uses the socket specified by the socket descriptor socketFD to do the
211  communication. The socket must already be connected.
212 
213  This constructor can be used with a QServerSocket within the (pure
214  virtual) method /e newConnection.
215 
216  Note: The socket is then owned by the /e KMessageSocket object. So don't
217  manipulate the socket afterwards, especially don't close it. The socket is
218  automatically closed when KMessageSocket is deleted.
219  */
220  explicit KMessageSocket(int socketFD, QObject *parent = nullptr);
221 
222  /**
223  Destructor, closes the socket.
224  */
225  ~KMessageSocket() override;
226 
227  /**
228  * The runtime identification
229  */
230  int rtti() const override
231  {
232  return 1;
233  }
234 
235  /**
236  @return The port that this object is connected to. See QSocket::peerPort
237  */
238  quint16 peerPort() const override;
239 
240  /**
241  @return The hostname this object is connected to. See QSocket::peerName.
242  */
243  QString peerName() const override;
244 
245  /**
246  @return TRUE as this is a network IO.
247  */
248  bool isNetwork() const override
249  {
250  return true;
251  }
252 
253  /**
254  Returns true if the socket is in state /e connected.
255  */
256  bool isConnected() const override;
257 
258  /**
259  Overwritten slot method from KMessageIO.
260 
261  Note: It is not declared as a slot method, since the slot is already
262  defined in KMessageIO as a virtual method.
263  */
264  void send(const QByteArray &msg) override;
265 
266 protected Q_SLOTS:
267  virtual void processNewData();
268 
269 protected:
270  void initSocket();
271  QTcpSocket *mSocket;
272  bool mAwaitingHeader;
273  quint32 mNextBlockLength;
274 
275  bool isRecursive; // workaround for "bug" in QSocket, Qt 2.2.3 or older
276 };
277 
278 /**
279  \class KMessageDirect kmessageio.h <KGame/KMessageIO>
280 
281  This class implements the message communication using function calls
282  directly. It can only be used when both sides of the message pipe are
283  within the same process. The communication is very fast.
284 
285  To establish a communication, you have to create two instances of
286  KMessageDirect, the first one with no parameters in the constructor,
287  the second one with the first as parameter:
288 
289  /code
290  KMessageDirect *peer1, *peer2;
291  peer1 = new KMessageDirect (); // unconnected
292  peer2 = new KMessageDirect (peer1); // connect with peer1
293  /endcode
294 
295  The connection is only closed when one of the instances is deleted.
296 */
297 
299 {
300  Q_OBJECT
301 
302 public:
303  /**
304  Creates an object and connects it to the object given in the first
305  parameter. Use 0 as first parameter to create an unconnected object,
306  that is later connected.
307 
308  If that object is already connected, the object remains unconnected.
309  */
310  explicit KMessageDirect(KMessageDirect *partner = nullptr, QObject *parent = nullptr);
311 
312  /**
313  Destructor, closes the connection.
314  */
315  ~KMessageDirect() override;
316 
317  /**
318  * The runtime identification
319  */
320  int rtti() const override
321  {
322  return 2;
323  }
324 
325  /**
326  @return FALSE as this is no network IO.
327  */
328  bool isNetwork() const override
329  {
330  return false;
331  }
332 
333  /**
334  Returns true, if the object is connected to another instance.
335 
336  If you use the first constructor, the object is unconnected unless another
337  object is created with this one as parameter.
338 
339  The connection can only be closed by deleting one of the objects.
340  */
341  bool isConnected() const override;
342 
343  /**
344  Overwritten slot method from KMessageIO.
345 
346  Note: It is not declared as a slot method, since the slot is already
347  defined in KMessageIO as a virtual method.
348  */
349  void send(const QByteArray &msg) override;
350 
351 protected:
352  KMessageDirect *mPartner;
353 };
354 
355 /**
356  * \class KMessageProcess kmessageio.h <KGame/KMessageIO>
357  */
358 class KMessageProcess : public KMessageIO
359 {
360  Q_OBJECT
361 
362 public:
363  KMessageProcess(QObject *parent, const QString &file);
364  ~KMessageProcess() override;
365  bool isConnected() const override;
366  void send(const QByteArray &msg) override;
367 
368  /**
369  @return FALSE as this is no network IO.
370  */
371  bool isNetwork() const override
372  {
373  return false;
374  }
375 
376  /**
377  * The runtime identification
378  */
379  int rtti() const override
380  {
381  return 3;
382  }
383 
384 public Q_SLOTS:
385  void slotReceivedStdout();
386  void slotReceivedStderr();
387  void slotProcessExited(int, QProcess::ExitStatus);
388 
389 Q_SIGNALS:
390  void signalReceivedStderr(const QString &msg);
391 
392 private:
393  QString mProcessName;
394  KProcess *mProcess;
395  QByteArray *mSendBuffer;
396  QByteArray mReceiveBuffer;
397  int mReceiveCount;
398 };
399 
400 #endif
Q_OBJECTQ_OBJECT
~KMessageSocket() override
Destructor, closes the socket.
Definition: kmessageio.cpp:74
Q_SLOTSQ_SLOTS
bool isNetwork() const override
Definition: kmessageio.h:248
virtual quint16 peerPort() const
Definition: kmessageio.h:114
int rtti() const override
The runtime identification.
Definition: kmessageio.h:230
virtual bool isNetwork() const
Definition: kmessageio.h:76
void send(const QByteArray &msg) override
Overwritten slot method from KMessageIO.
Definition: kmessageio.cpp:84
~KMessageDirect() override
Destructor, closes the connection.
Definition: kmessageio.cpp:182
KMessageDirect(KMessageDirect *partner=nullptr, QObject *parent=nullptr)
Creates an object and connects it to the object given in the first parameter.
Definition: kmessageio.cpp:161
bool isNetwork() const override
Definition: kmessageio.h:328
virtual int rtti() const
The runtime identification.
Definition: kmessageio.h:67
virtual void send(const QByteArray &msg)=0
This slot sends the data block in /e msg to the connected object, that will emit /e received().
QString peerName() const override
Definition: kmessageio.cpp:154
virtual bool isConnected() const
This method returns the status of the object, whether it is already (or still) connected to another K...
Definition: kmessageio.h:90
bool isConnected() const override
Returns true if the socket is in state /e connected.
Definition: kmessageio.cpp:79
Q_SIGNALSQ_SIGNALS
int rtti() const override
The runtime identification.
Definition: kmessageio.h:320
ScriptableExtension * host() const
void send(const QByteArray &msg) override
Overwritten slot method from KMessageIO.
Definition: kmessageio.cpp:195
KMessageSocket(const QString &host, quint16 port, QObject *parent=nullptr)
Connects to a server socket on /e host with /e port.
Definition: kmessageio.cpp:43
bool isConnected() const override
Returns true, if the object is connected to another instance.
Definition: kmessageio.cpp:190
quint16 peerPort() const override
Definition: kmessageio.cpp:149
virtual QString peerName() const
Definition: kmessageio.h:122
QObject * parent() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon May 8 2023 03:49:44 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.