• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • libtdegames
 

libtdegames

  • libtdegames
  • kgame
kmessageserver.cpp
1/*
2 This file is part of the TDE games library
3 Copyright (C) 2001 Burkhard Lehner (Burkhard.Lehner@gmx.de)
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#include <tqiodevice.h>
21#include <tqbuffer.h>
22#include <tqptrlist.h>
23#include <tqptrqueue.h>
24#include <tqtimer.h>
25#include <tqvaluelist.h>
26
27#include <kdebug.h>
28
29#include "kmessageio.h"
30#include "kmessageserver.h"
31
32// --------------- internal class KMessageServerSocket
33
34KMessageServerSocket::KMessageServerSocket (TQ_UINT16 port, TQObject *parent)
35 : TQServerSocket (port, 0, parent)
36{
37}
38
39KMessageServerSocket::~KMessageServerSocket ()
40{
41}
42
43void KMessageServerSocket::newConnection (int socket)
44{
45 emit newClientConnected (new KMessageSocket (socket));
46}
47
48// ---------------- class for storing an incoming message
49
50class MessageBuffer
51{
52 public:
53 MessageBuffer (TQ_UINT32 clientID, const TQByteArray &messageData)
54 : id (clientID), data (messageData) { }
55 ~MessageBuffer () {}
56 TQ_UINT32 id;
57 TQByteArray data;
58};
59
60// ---------------- KMessageServer's private class
61
62class KMessageServerPrivate
63{
64public:
65 KMessageServerPrivate()
66 : mMaxClients (-1), mGameId (1), mUniqueClientNumber (1), mAdminID (0), mServerSocket (0)
67 {
68 mClientList.setAutoDelete (true);
69 mMessageQueue.setAutoDelete (true);
70 }
71
72 int mMaxClients;
73 int mGameId;
74 TQ_UINT16 mCookie;
75 TQ_UINT32 mUniqueClientNumber;
76 TQ_UINT32 mAdminID;
77
78 KMessageServerSocket* mServerSocket;
79
80 TQPtrList <KMessageIO> mClientList;
81 TQPtrQueue <MessageBuffer> mMessageQueue;
82 TQTimer mTimer;
83 bool mIsRecursive;
84};
85
86
87// ------------------ KMessageServer
88
89KMessageServer::KMessageServer (TQ_UINT16 cookie,TQObject* parent)
90 : TQObject(parent, 0)
91{
92 d = new KMessageServerPrivate;
93 d->mIsRecursive=false;
94 d->mCookie=cookie;
95 connect (&(d->mTimer), TQ_SIGNAL (timeout()),
96 this, TQ_SLOT (processOneMessage()));
97 kdDebug(11001) << "CREATE(KMessageServer="
98 << this
99 << ") cookie="
100 << d->mCookie
101 << " sizeof(this)="
102 << sizeof(KMessageServer)
103 << endl;
104}
105
106KMessageServer::~KMessageServer()
107{
108 kdDebug(11001) << k_funcinfo << "this=" << this << endl;
109 Debug();
110 stopNetwork();
111 deleteClients();
112 delete d;
113 kdDebug(11001) << k_funcinfo << " done" << endl;
114}
115
116//------------------------------------- TCP/IP server stuff
117
118bool KMessageServer::initNetwork (TQ_UINT16 port)
119{
120 kdDebug(11001) << k_funcinfo << endl;
121
122 if (d->mServerSocket)
123 {
124 kdDebug (11001) << k_funcinfo << ": We were already offering connections!" << endl;
125 delete d->mServerSocket;
126 }
127
128 d->mServerSocket = new KMessageServerSocket (port);
129 d->mIsRecursive = false;
130
131 if (!d->mServerSocket || !d->mServerSocket->ok())
132 {
133 kdError(11001) << k_funcinfo << ": Serversocket::ok() == false" << endl;
134 delete d->mServerSocket;
135 d->mServerSocket=0;
136 return false;
137 }
138
139 kdDebug (11001) << k_funcinfo << ": Now listening to port "
140 << d->mServerSocket->port() << endl;
141 connect (d->mServerSocket, TQ_SIGNAL (newClientConnected (KMessageIO*)),
142 this, TQ_SLOT (addClient (KMessageIO*)));
143 return true;
144}
145
146TQ_UINT16 KMessageServer::serverPort () const
147{
148 if (d->mServerSocket)
149 return d->mServerSocket->port();
150 else
151 return 0;
152}
153
154void KMessageServer::stopNetwork()
155{
156 if (d->mServerSocket)
157 {
158 delete d->mServerSocket;
159 d->mServerSocket = 0;
160 }
161}
162
163bool KMessageServer::isOfferingConnections() const
164{
165 return d->mServerSocket != 0;
166}
167
168//----------------------------------------------- adding / removing clients
169
170void KMessageServer::addClient (KMessageIO* client)
171{
172 TQByteArray msg;
173
174 // maximum number of clients reached?
175 if (d->mMaxClients >= 0 && d->mMaxClients <= clientCount())
176 {
177 kdError (11001) << k_funcinfo << ": Maximum number of clients reached!" << endl;
178 return;
179 }
180
181 // give it a unique ID
182 client->setId (uniqueClientNumber());
183 kdDebug (11001) << k_funcinfo << ": " << client->id() << endl;
184
185 // connect its signals
186 connect (client, TQ_SIGNAL (connectionBroken()),
187 this, TQ_SLOT (removeBrokenClient()));
188 connect (client, TQ_SIGNAL (received (const TQByteArray &)),
189 this, TQ_SLOT (getReceivedMessage (const TQByteArray &)));
190
191 // Tell everyone about the new guest
192 // Note: The new client doesn't get this message!
193 TQDataStream (msg, IO_WriteOnly) << TQ_UINT32 (EVNT_CLIENT_CONNECTED) << client->id();
194 broadcastMessage (msg);
195
196 // add to our list
197 d->mClientList.append (client);
198
199 // tell it its ID
200 TQDataStream (msg, IO_WriteOnly) << TQ_UINT32 (ANS_CLIENT_ID) << client->id();
201 client->send (msg);
202
203 // Give it the complete list of client IDs
204 TQDataStream (msg, IO_WriteOnly) << TQ_UINT32 (ANS_CLIENT_LIST) << clientIDs();
205 client->send (msg);
206
207
208 if (clientCount() == 1)
209 {
210 // if it is the first client, it becomes the admin
211 setAdmin (client->id());
212 }
213 else
214 {
215 // otherwise tell it who is the admin
216 TQDataStream (msg, IO_WriteOnly) << TQ_UINT32 (ANS_ADMIN_ID) << adminID();
217 client->send (msg);
218 }
219
220 emit clientConnected (client);
221}
222
223void KMessageServer::removeClient (KMessageIO* client, bool broken)
224{
225 TQ_UINT32 clientID = client->id();
226 if (!d->mClientList.removeRef (client))
227 {
228 kdError(11001) << k_funcinfo << ": Deleting client that wasn't added before!" << endl;
229 return;
230 }
231
232 // tell everyone about the removed client
233 TQByteArray msg;
234 TQDataStream (msg, IO_WriteOnly) << TQ_UINT32 (EVNT_CLIENT_DISCONNECTED) << client->id() << (TQ_INT8)broken;
235 broadcastMessage (msg);
236
237 // If it was the admin, select a new admin.
238 if (clientID == adminID())
239 {
240 if (!d->mClientList.isEmpty())
241 setAdmin (d->mClientList.first()->id());
242 else
243 setAdmin (0);
244 }
245}
246
247void KMessageServer::deleteClients()
248{
249 d->mClientList.clear();
250 d->mAdminID = 0;
251}
252
253void KMessageServer::removeBrokenClient ()
254{
255 if (!sender()->inherits ("KMessageIO"))
256 {
257 kdError (11001) << k_funcinfo << ": sender of the signal was not a KMessageIO object!" << endl;
258 return;
259 }
260
261 KMessageIO *client = (KMessageIO *) sender();
262
263 emit connectionLost (client);
264 removeClient (client, true);
265}
266
267
268void KMessageServer::setMaxClients(int c)
269{
270 d->mMaxClients = c;
271}
272
273int KMessageServer::maxClients() const
274{
275 return d->mMaxClients;
276}
277
278int KMessageServer::clientCount() const
279{
280 return d->mClientList.count();
281}
282
283TQValueList <TQ_UINT32> KMessageServer::clientIDs () const
284{
285 TQValueList <TQ_UINT32> list;
286 for (TQPtrListIterator <KMessageIO> iter (d->mClientList); *iter; ++iter)
287 list.append ((*iter)->id());
288 return list;
289}
290
291KMessageIO* KMessageServer::findClient (TQ_UINT32 no) const
292{
293 if (no == 0)
294 no = d->mAdminID;
295
296 TQPtrListIterator <KMessageIO> iter (d->mClientList);
297 while (*iter)
298 {
299 if ((*iter)->id() == no)
300 return (*iter);
301 ++iter;
302 }
303 return 0;
304}
305
306TQ_UINT32 KMessageServer::adminID () const
307{
308 return d->mAdminID;
309}
310
311void KMessageServer::setAdmin (TQ_UINT32 adminID)
312{
313 // Trying to set the the client that is already admin => nothing to do
314 if (adminID == d->mAdminID)
315 return;
316
317 if (adminID > 0 && findClient (adminID) == 0)
318 {
319 kdWarning (11001) << "Trying to set a new admin that doesn't exist!" << endl;
320 return;
321 }
322
323 d->mAdminID = adminID;
324
325 TQByteArray msg;
326 TQDataStream (msg, IO_WriteOnly) << TQ_UINT32 (ANS_ADMIN_ID) << adminID;
327
328 // Tell everyone about the new master
329 broadcastMessage (msg);
330}
331
332
333//------------------------------------------- ID stuff
334
335TQ_UINT32 KMessageServer::uniqueClientNumber() const
336{
337 return d->mUniqueClientNumber++;
338}
339
340// --------------------- Messages ---------------------------
341
342void KMessageServer::broadcastMessage (const TQByteArray &msg)
343{
344 for (TQPtrListIterator <KMessageIO> iter (d->mClientList); *iter; ++iter)
345 (*iter)->send (msg);
346}
347
348void KMessageServer::sendMessage (TQ_UINT32 id, const TQByteArray &msg)
349{
350 KMessageIO *client = findClient (id);
351 if (client)
352 client->send (msg);
353}
354
355void KMessageServer::sendMessage (const TQValueList <TQ_UINT32> &ids, const TQByteArray &msg)
356{
357 for (TQValueListConstIterator <TQ_UINT32> iter = ids.begin(); iter != ids.end(); ++iter)
358 sendMessage (*iter, msg);
359}
360
361void KMessageServer::getReceivedMessage (const TQByteArray &msg)
362{
363 if (!sender() || !sender()->inherits("KMessageIO"))
364 {
365 kdError (11001) << k_funcinfo << ": slot was not called from KMessageIO!" << endl;
366 return;
367 }
368 //kdDebug(11001) << k_funcinfo << ": size=" << msg.size() << endl;
369 KMessageIO *client = (KMessageIO *) sender();
370 TQ_UINT32 clientID = client->id();
371
372 //TQByteArray *ta=new TQByteArray;
373 //ta->duplicate(msg);
374 //d->mMessageQueue.enqueue (new MessageBuffer (clientID, *ta));
375
376
377 d->mMessageQueue.enqueue (new MessageBuffer (clientID, msg));
378 if (!d->mTimer.isActive())
379 d->mTimer.start(0); // AB: should be , true i guess
380}
381
382void KMessageServer::processOneMessage ()
383{
384 // This shouldn't happen, since the timer should be stopped before. But only to be sure!
385 if (d->mMessageQueue.isEmpty())
386 {
387 d->mTimer.stop();
388 return;
389 }
390 if (d->mIsRecursive)
391 {
392 return;
393 }
394 d->mIsRecursive = true;
395
396 MessageBuffer *msg_buf = d->mMessageQueue.head();
397
398 TQ_UINT32 clientID = msg_buf->id;
399 TQBuffer in_buffer (msg_buf->data);
400 in_buffer.open (IO_ReadOnly);
401 TQDataStream in_stream (&in_buffer);
402
403 TQByteArray out_msg;
404 TQBuffer out_buffer (out_msg);
405 out_buffer.open (IO_WriteOnly);
406 TQDataStream out_stream (&out_buffer);
407
408 bool unknown = false;
409
410 TQByteArray ttt=in_buffer.buffer();
411 TQ_UINT32 messageID;
412 in_stream >> messageID;
413 //kdDebug(11001) << k_funcinfo << ": got message with messageID=" << messageID << endl;
414 switch (messageID)
415 {
416 case REQ_BROADCAST:
417 out_stream << TQ_UINT32 (MSG_BROADCAST) << clientID;
418 out_buffer.writeBlock (in_buffer.readAll());
419 broadcastMessage (out_msg);
420 break;
421
422 case REQ_FORWARD:
423 {
424 TQValueList <TQ_UINT32> clients;
425 in_stream >> clients;
426 out_stream << TQ_UINT32 (MSG_FORWARD) << clientID << clients;
427 out_buffer.writeBlock (in_buffer.readAll());
428 sendMessage (clients, out_msg);
429 }
430 break;
431
432 case REQ_CLIENT_ID:
433 out_stream << TQ_UINT32 (ANS_CLIENT_ID) << clientID;
434 sendMessage (clientID, out_msg);
435 break;
436
437 case REQ_ADMIN_ID:
438 out_stream << TQ_UINT32 (ANS_ADMIN_ID) << d->mAdminID;
439 sendMessage (clientID, out_msg);
440 break;
441
442 case REQ_ADMIN_CHANGE:
443 if (clientID == d->mAdminID)
444 {
445 TQ_UINT32 newAdmin;
446 in_stream >> newAdmin;
447 setAdmin (newAdmin);
448 }
449 break;
450
451 case REQ_REMOVE_CLIENT:
452 if (clientID == d->mAdminID)
453 {
454 TQValueList <TQ_UINT32> client_list;
455 in_stream >> client_list;
456 for (TQValueListIterator <TQ_UINT32> iter = client_list.begin(); iter != client_list.end(); ++iter)
457 {
458 KMessageIO *client = findClient (*iter);
459 if (client)
460 removeClient (client, false);
461 else
462 kdWarning (11001) << k_funcinfo << ": removing non-existing clientID" << endl;
463 }
464 }
465 break;
466
467 case REQ_MAX_NUM_CLIENTS:
468 if (clientID == d->mAdminID)
469 {
470 TQ_INT32 maximum_clients;
471 in_stream >> maximum_clients;
472 setMaxClients (maximum_clients);
473 }
474 break;
475
476 case REQ_CLIENT_LIST:
477 {
478 out_stream << TQ_UINT32 (ANS_CLIENT_LIST) << clientIDs();
479 sendMessage (clientID, out_msg);
480 }
481 break;
482
483 default:
484 unknown = true;
485 }
486
487 // check if all the data has been used
488 if (!unknown && !in_buffer.atEnd())
489 kdWarning (11001) << k_funcinfo << ": Extra data received for message ID " << messageID << endl;
490
491 emit messageReceived (msg_buf->data, clientID, unknown);
492
493 if (unknown)
494 kdWarning (11001) << k_funcinfo << ": received unknown message ID " << messageID << endl;
495
496 // remove the message, since we are ready with it
497 d->mMessageQueue.remove();
498 if (d->mMessageQueue.isEmpty())
499 d->mTimer.stop();
500 d->mIsRecursive = false;
501}
502
503void KMessageServer::Debug()
504{
505 kdDebug(11001) << "------------------ KMESSAGESERVER -----------------------" << endl;
506 kdDebug(11001) << "MaxClients : " << maxClients() << endl;
507 kdDebug(11001) << "NoOfClients : " << clientCount() << endl;
508 kdDebug(11001) << "---------------------------------------------------" << endl;
509}
510
511#include "kmessageserver.moc"
KMessageIO
This abstract base class represents one end of a message connections between two clients.
Definition: kmessageio.h:57
KMessageIO::send
virtual void send(const TQByteArray &msg)=0
This slot sends the data block in /e msg to the connected object, that will emit /e received().
KMessageIO::id
TQ_UINT32 id()
Queries the ID of this object.
Definition: kmessageio.cpp:44
KMessageIO::setId
void setId(TQ_UINT32 id)
Sets the ID number of this object.
Definition: kmessageio.cpp:39
KMessageServerSocket
Internal class of KMessageServer.
Definition: kmessageserver.h:478
KMessageServer::removeClient
void removeClient(KMessageIO *io, bool broken)
Removes the KMessageIO object from the client list and deletes it.
Definition: kmessageserver.cpp:223
KMessageServer::getReceivedMessage
virtual void getReceivedMessage(const TQByteArray &msg)
This slot receives all the messages from the KMessageIO::received signals.
Definition: kmessageserver.cpp:361
KMessageServer::initNetwork
bool initNetwork(TQ_UINT16 port=0)
Starts the Communication server to listen for incoming TCP/IP connections.
Definition: kmessageserver.cpp:118
KMessageServer::clientConnected
void clientConnected(KMessageIO *client)
A new client connected to the game.
KMessageServer::broadcastMessage
virtual void broadcastMessage(const TQByteArray &msg)
Sends a message to all connected clients.
Definition: kmessageserver.cpp:342
KMessageServer::setMaxClients
void setMaxClients(int maxnumber)
sets the maximum number of clients which can connect.
Definition: kmessageserver.cpp:268
KMessageServer::Debug
virtual void Debug()
Gives debug output of the game status.
Definition: kmessageserver.cpp:503
KMessageServer::addClient
void addClient(KMessageIO *)
Adds a new KMessageIO object to the communication server.
Definition: kmessageserver.cpp:170
KMessageServer::KMessageServer
KMessageServer(TQ_UINT16 cookie=42, TQObject *parent=0)
Create a KGameNetwork object.
Definition: kmessageserver.cpp:89
KMessageServer::maxClients
int maxClients() const
returns the maximum number of clients
Definition: kmessageserver.cpp:273
KMessageServer::processOneMessage
virtual void processOneMessage()
This slot is called whenever there are elements in the message queue.
Definition: kmessageserver.cpp:382
KMessageServer::uniqueClientNumber
TQ_UINT32 uniqueClientNumber() const
Definition: kmessageserver.cpp:335
KMessageServer::clientIDs
TQValueList< TQ_UINT32 > clientIDs() const
returns a list of the unique IDs of all clients.
Definition: kmessageserver.cpp:283
KMessageServer::serverPort
TQ_UINT16 serverPort() const
Returns the TCP/IP port number we are listening to for incoming connections.
Definition: kmessageserver.cpp:146
KMessageServer::connectionLost
void connectionLost(KMessageIO *client)
A network connection got broken.
KMessageServer::adminID
TQ_UINT32 adminID() const
Returns the clientID of the admin, if there is a admin, 0 otherwise.
Definition: kmessageserver.cpp:306
KMessageServer::deleteClients
void deleteClients()
Deletes all connections to the clients.
Definition: kmessageserver.cpp:247
KMessageServer::stopNetwork
void stopNetwork()
Stops listening for connections.
Definition: kmessageserver.cpp:154
KMessageServer::setAdmin
void setAdmin(TQ_UINT32 adminID)
Sets the admin to a new client with the given ID.
Definition: kmessageserver.cpp:311
KMessageServer::sendMessage
virtual void sendMessage(TQ_UINT32 id, const TQByteArray &msg)
Sends a message to a single client with the given ID.
Definition: kmessageserver.cpp:348
KMessageServer::messageReceived
void messageReceived(const TQByteArray &data, TQ_UINT32 clientID, bool &unknown)
This signal is always emitted when a message from a client is received.
KMessageServer::findClient
KMessageIO * findClient(TQ_UINT32 no) const
Find the KMessageIO object to the given client number.
Definition: kmessageserver.cpp:291
KMessageServer::isOfferingConnections
bool isOfferingConnections() const
Are we still offer offering server connections?
Definition: kmessageserver.cpp:163
KMessageServer::clientCount
int clientCount() const
returns the current number of connected clients.
Definition: kmessageserver.cpp:278
KMessageSocket
This class implements the message communication using a TCP/IP socket.
Definition: kmessageio.h:171

libtdegames

Skip menu "libtdegames"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

libtdegames

Skip menu "libtdegames"
  • libtdegames
Generated for libtdegames by doxygen 1.9.4
This website is maintained by Timothy Pearson.