KDEGames

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

KDE's Doxygen guidelines are available online.