KDEGames

kmessageclient.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 #ifndef __KMESSAGECLIENT_H__
9 #define __KMESSAGECLIENT_H__
10 
11 // own
12 #include "libkdegamesprivate_export.h"
13 // Qt
14 #include <QObject>
15 #include <QString>
16 // Std
17 #include <memory>
18 
19 class KMessageIO;
20 class KMessageServer;
21 class KMessageClientPrivate;
22 
23 /**
24  \class KMessageClient kmessageclient.h <KGame/KMessageClient>
25 
26  @short A client to connect to a KMessageServer
27 
28  This class implements a client that can connect to a KMessageServer object.
29  It can be used to exchange messages between clients.
30 
31  Usually you will connect the signals broadcastReceived and forwardReceived to
32  some specific slots. In these slot methods you can analyze the messages that are
33  sent to you from other clients.
34 
35  To send messages to other clients, use the methods sendBroadcast() (to send to all
36  clients) or sendForward() (to send to a list of selected clients).
37 
38  If you want to communicate with the KMessageServer object directly (on a more low
39  level base), use the method sendServerMessage to send a command to the server and
40  connect to the signal serverMessageReceived to see all the incoming messages.
41  In that case the messages must be of the format specified in KMessageServer.
42  @author Burkhard Lehner <[email protected]>
43 */
44 class KDEGAMESPRIVATE_EXPORT KMessageClient : public QObject
45 {
46  Q_OBJECT
47 
48 public:
49 
50  /**
51  Constructor.
52  Creates an unconnected KMessageClient object. Use setServer() later to connect to a
53  KMessageServer object.
54  */
55  explicit KMessageClient (QObject *parent = nullptr);
56 
57  /**
58  Destructor.
59  Disconnects from the server, if any connection was established.
60  */
61  ~KMessageClient () override;
62 
63  /**
64  @return The client ID of this client. Every client that is connected to a KMessageServer
65  has a unique ID number.
66 
67  NOTE: As long as the object is not yet connected to the server, and as long as the server
68  hasn't sent the client ID, this method returns 0.
69  */
70  quint32 id () const;
71 
72  /**
73  @return Whether or not this client is the server admin.
74  One of the clients connected to the server is the admin and can administrate the server
75  (set maximum number of clients, remove clients, ...).
76 
77  If you use admin commands without being the admin, these commands are simply ignored by
78  the server.
79 
80  NOTE: As long as you are not connected to a server, this method returns false.
81  */
82  bool isAdmin () const;
83 
84  /**
85  @return The ID of the admin client on the message server.
86  */
87  quint32 adminId() const;
88 
89  /**
90  @return The list of the IDs of all the message clients connected to the message server.
91  */
92  QList <quint32> clientList() const;
93 
94  /**
95  Connects the client to (another) server.
96 
97  Tries to connect via a TCP/IP socket to a KMessageServer object
98  on the given host, listening on the specified port.
99 
100  If we were already connected, the old connection is closed.
101  @param host The name of the host to connect to. Must be either a hostname which can
102  be resolved to an IP or just an IP
103  @param port The port to connect to
104  */
105  void setServer (const QString &host, quint16 port);
106 
107  /**
108  Connects the client to (another) server.
109 
110  Connects to the given server, using KMessageDirect.
111  (The server object has to be in the same process.)
112 
113  If we were already connected, the old connection is closed.
114  @param server The KMessageServer to connect to
115  */
116  void setServer (KMessageServer *server);
117 
118  /**
119  * Corresponds to setServer(0); but also emits the connectionBroken signal
120  **/
121  void disconnect();
122 
123  /**
124  Connects the client to (another) server.
125 
126  To use this method, you have to create a KMessageIO object with new (indeed you must
127  create an instance of a subclass of KMessageIO, e.g. KMessageSocket or KMessageDirect).
128  This object must already be connected to the new server.
129 
130  Calling this method disconnects any earlier connection, and uses the new KMessageIO
131  object instead. This object gets owned by the KMessageClient object, so don't delete
132  or manipulate it afterwards.
133 
134  With this method it is possible to change the server on the fly. But be careful that
135  there are no important messages from the old server not yet delivered.
136 
137  NOTE: It is very likely that we will have another client ID on the new server. The
138  value returned by clientID may be a little outdated until the new server tells us
139  our new ID.
140 
141  NOTE: The two other setServer methods are for convenience. If you use them, you don't
142  have to create a KMessageIO object yourself.
143  */
144  virtual void setServer (KMessageIO *connection);
145 
146  /**
147  @return True, if a connection to a KMessageServer has been started, and if the
148  connection is ready for transferring data. (It will return false e.g. as long as
149  a socket connection hasn't been established, and it will also return false after
150  a socket connection is broken.)
151  */
152  bool isConnected () const;
153 
154  /**
155  @return TRUE if isConnected() is true AND this is not a local (like
156  KMessageDirect) connection.
157  */
158  bool isNetwork () const;
159 
160  /**
161  @return 0 if isConnected() is FALSE, otherwise the port number this client is
162  connected to. See also KMessageIO::peerPort and QSocket::peerPort.
163  */
164  quint16 peerPort () const;
165 
166  /**
167  @return "localhost" if isConnected() is FALSE, otherwise the hostname this client is
168  connected to. See also KMessageIO::peerName() and QSocket::peerName().
169  */
170  QString peerName() const;
171 
172  /**
173  Sends a message to the KMessageServer. If we are not yet connected to one, nothing
174  happens.
175 
176  Use this method to send a low level command to the server. It has to be in the
177  format specified in KMessageServer.
178 
179  If you want to send messages to other clients, you should use sendBroadcast()
180  and sendForward().
181  @param msg The message to be sent to the server. Must be in the format specified in KMessageServer.
182  */
183  void sendServerMessage (const QByteArray &msg);
184 
185  /**
186  Sends a message to all the clients connected to the server, including ourself.
187  The message consists of an arbitrary block of data with arbitrary length.
188 
189  All the clients will receive an exact copy of this block of data, which will be
190  processed in their processBroadcast() method.
191  @param msg The message to be sent to the clients
192  */
193  //AB: processBroadcast doesn't exist!! is processIncomingMessage meant?
194  void sendBroadcast (const QByteArray &msg);
195 
196  /**
197  Sends a message to all the clients in a list.
198  The message consists of an arbitrary block of data with arbitrary length.
199 
200  All clients will receive an exact copy of this block of data, which will be
201  processed in their processForward() method.
202 
203  If the list contains client IDs that are not defined, they are ignored. If
204  it contains an ID several times, that client will receive the message several
205  times.
206 
207  To send a message to the admin of the KMessageServer, you can use 0 as clientID,
208  instead of using the real client ID.
209  @param msg The message to be sent to the clients
210  @param clients A list of clients the message should be sent to
211  */
212  //AB: processForward doesn't exist!! is processIncomingMessage meant?
213  void sendForward (const QByteArray &msg, const QList <quint32> &clients);
214 
215  /**
216  Sends a message to a single client. This is a convenience method. It calls
217  sendForward (const QByteArray &msg, const QValueList &ltquint32> &clients)
218  with a list containing only one client ID.
219 
220  To send a message to the admin of the KMessageServer, you can use 0 as clientID,
221  instead of using the real client ID.
222  @param msg The message to be sent to the client
223  @param client The id of the client the message shall be sent to
224  */
225  void sendForward (const QByteArray &msg, quint32 client);
226 
227  /**
228  Once this function is called no message will be received anymore.
229  processIncomingMessage() gets delayed until unlock() is called.
230 
231  Note that all messages are still received, but their delivery (like
232  broadcastReceived()) get delayed only.
233  */
234  void lock();
235 
236  /**
237  Deliver every message that was delayed by lock() and actually deliver
238  all messages that get received from now on.
239  */
240  void unlock();
241 
242  /**
243  @return The number of messages that got delayed since lock() was called
244  */
245  unsigned int delayedMessageCount() const;
246 
247 Q_SIGNALS:
248  /**
249  This signal is emitted when the client receives a broadcast message from the
250  KMessageServer, sent by another client. Connect to this signal to analyze the
251  received message and do the right reaction.
252 
253  senderID contains the ID of the client that sent the broadcast message. You can
254  use this e.g. to send a reply message to only that client. Or you can use it
255  to ignore broadcast messages that were sent by yourself:
256 
257  \code
258  void myObject::myBroadcastSlot (const QByteArray &msg, quint32 senderID)
259  {
260  if (senderID == ((KMessageClient *)sender())->id())
261  return;
262  ...
263  }
264  \endcode
265  @param msg The message that has been sent to us
266  @param senderID The ID of the client which sent the message
267  */
268  void broadcastReceived (const QByteArray &msg, quint32 senderID);
269 
270  /**
271  This signal is emitted when the client receives a forward message from the
272  KMessageServer, sent by another client. Connect to this signal to analyze the
273  received message and do the right reaction.
274 
275  senderID contains the ID of the client that sent the broadcast message. You can
276  use this e.g. to send a reply message to only that client.
277 
278  receivers contains the list of the clients that got the message. (If this list
279  only contains one number, this will be your client ID, and it was exclusively
280  sent to you.)
281 
282  If you don't want to distinguish between broadcast and forward messages and
283  treat them the same, you can connect forwardReceived signal to the
284  broadcastReceived signal. (Yes, that's possible! You can connect a Qt signal to
285  a Qt signal, and the second one can have less parameters.)
286 
287  \code
288  KMessageClient *client = new KMessageClient ();
289  connect (client, SIGNAL (forwardReceived (const QByteArray &, quint32, const QValueList <quint32>&)),
290  client, SIGNAL (broadcastReceived (const QByteArray &, quint32)));
291  \endcode
292 
293  Then connect the broadcast signal to your slot that analyzes the message.
294  @param msg The message that has been sent to us
295  @param senderID The ID of the client which sent the message
296  @param receivers All clients which receive this message
297  */
298  void forwardReceived (const QByteArray &msg, quint32 senderID, const QList <quint32> &receivers);
299 
300  /**
301  This signal is emitted when the connection to the KMessageServer is broken.
302  Reasons for this can be: a network error, a server breakdown, or you were just kicked
303  from the server.
304 
305  When this signal is sent, the connection is already lost and the client is unconnected.
306  You can connect to another server by calling setServer() afterwards. But keep in mind that
307  some important messages might have vanished.
308  */
309  void connectionBroken ();
310 
311  /**
312  This signal is emitted right before the client disconnects. It can be used
313  to this store the id of the client which is about to be lost.
314  */
315  void aboutToDisconnect(quint32 id);
316 
317  /**
318  This signal is emitted when this client becomes the admin client or when it loses
319  the admin client status. Connect to this signal if you have to do any initialization
320  or cleanup.
321  @param isAdmin Whether we are now admin or not
322  */
323  void adminStatusChanged (bool isAdmin);
324 
325  /**
326  This signal is emitted when another client has connected
327  to the server. Connect to this method if that clients needs initialization.
328  This should usually only be done in one client, e.g. the admin client.
329  @param clientID The ID of the client that has newly connected.
330  */
331  void eventClientConnected (quint32 clientID);
332 
333  /**
334  This signal is emitted when the server has lost the
335  connection to one of the clients (This could be because of a bad internet connection
336  or because the client disconnected on purpose).
337  @param clientID The ID of the client that has disconnected
338  @param broken true if it was disconnected because of a network error
339  */
340  void eventClientDisconnected (quint32 clientID, bool broken);
341 
342  /**
343  This signal is emitted on every message that came from the server. You can connect to this
344  signal to see the messages directly. They are in the format specified in KMessageServer.
345 
346  @param msg The message that has been sent to us
347  @param unknown True when KMessageClient didn't recognize the message, i.e. it contained an unknown
348  message ID. If you want to add additional message types to the client, connect to this signal,
349  and if unknown is true, analyze the message by yourself. If you recognized the message,
350  set unknown to false (Otherwise a debug message will be printed).
351  */
352  //AB: maybe add a setNoEmit() so that the other signals can be deactivated?
353  //Could be a performance benefit (note: KMessageClient is a time critical
354  //class!!!)
355  void serverMessageReceived (const QByteArray &msg, bool &unknown);
356 
357 protected:
358  /**
359  This slot is called from processIncomingMessage or
360  processFirstMessage, depending on whether the client is locked or a delayed
361  message is still here (see lock)
362 
363  It processes the message and analyzes it. If it is a broadcast or a forward message from
364  another client, it emits the signal processBroadcast or processForward accordingly.
365 
366  If you want to treat additional server messages, you can overwrite this method. Don't
367  forget to call processIncomingMessage of your superclass!
368 
369  At the moment, the following server messages are interpreted:
370 
371  MSG_BROADCAST, MSG_FORWARD, ANS_CLIENT_ID, ANS_ADMIN_ID, ANS_CLIENT_LIST
372  @param msg The incoming message
373  */
374 
375  virtual void processMessage (const QByteArray& msg);
376 
377 protected Q_SLOTS:
378  /**
379  This slot is called from the signal KMessageIO::received whenever a message from the
380  KMessageServer arrives.
381 
382  It processes the message and analyzes it. If it is a broadcast or a forward message from
383  another client, it emits the signal processBroadcast or processForward accordingly.
384 
385  If you want to treat additional server messages, you can overwrite this method. Don't
386  forget to call processIncomingMessage() of your superclass!
387 
388  At the moment, the following server messages are interpreted:
389 
390  MSG_BROADCAST, MSG_FORWARD, ANS_CLIENT_ID, ANS_ADMIN_ID, ANS_CLIENT_LIST
391  @param msg The incoming message
392  */
393  virtual void processIncomingMessage (const QByteArray &msg);
394 
395  /**
396  Called from unlock() (using QTimer::singleShot) until all delayed
397  messages are delivered.
398  */
399  void processFirstMessage();
400 
401  /**
402  This slot is called from the signal KMessageIO::connectionBroken.
403 
404  It deletes the internal KMessageIO object, and resets the client to default
405  values. To connect again to another server, use setServer.
406  */
407  virtual void removeBrokenConnection ();
408  void removeBrokenConnection2 ();
409 
410 private:
411  std::unique_ptr<KMessageClientPrivate> const d;
412 };
413 
414 #endif
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
A client to connect to a KMessageServer.
This abstract base class represents one end of a message connections between two clients.
Definition: kmessageio.h:51
A server for message sending and broadcasting, using TCP/IP connections.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Dec 7 2021 22:34:15 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.