• 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 
34 KMessageServerSocket::KMessageServerSocket (TQ_UINT16 port, TQObject *parent)
35  : TQServerSocket (port, 0, parent)
36 {
37 }
38 
39 KMessageServerSocket::~KMessageServerSocket ()
40 {
41 }
42 
43 void KMessageServerSocket::newConnection (int socket)
44 {
45  emit newClientConnected (new KMessageSocket (socket));
46 }
47 
48 // ---------------- class for storing an incoming message
49 
50 class 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 
62 class KMessageServerPrivate
63 {
64 public:
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 
89 KMessageServer::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 
106 KMessageServer::~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 
118 bool 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 
146 TQ_UINT16 KMessageServer::serverPort () const
147 {
148  if (d->mServerSocket)
149  return d->mServerSocket->port();
150  else
151  return 0;
152 }
153 
154 void KMessageServer::stopNetwork()
155 {
156  if (d->mServerSocket)
157  {
158  delete d->mServerSocket;
159  d->mServerSocket = 0;
160  }
161 }
162 
163 bool KMessageServer::isOfferingConnections() const
164 {
165  return d->mServerSocket != 0;
166 }
167 
168 //----------------------------------------------- adding / removing clients
169 
170 void 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 
223 void 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 
247 void KMessageServer::deleteClients()
248 {
249  d->mClientList.clear();
250  d->mAdminID = 0;
251 }
252 
253 void 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 
268 void KMessageServer::setMaxClients(int c)
269 {
270  d->mMaxClients = c;
271 }
272 
273 int KMessageServer::maxClients() const
274 {
275  return d->mMaxClients;
276 }
277 
278 int KMessageServer::clientCount() const
279 {
280  return d->mClientList.count();
281 }
282 
283 TQValueList <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 
291 KMessageIO* 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 
306 TQ_UINT32 KMessageServer::adminID () const
307 {
308  return d->mAdminID;
309 }
310 
311 void 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 
335 TQ_UINT32 KMessageServer::uniqueClientNumber() const
336 {
337  return d->mUniqueClientNumber++;
338 }
339 
340 // --------------------- Messages ---------------------------
341 
342 void KMessageServer::broadcastMessage (const TQByteArray &msg)
343 {
344  for (TQPtrListIterator <KMessageIO> iter (d->mClientList); *iter; ++iter)
345  (*iter)->send (msg);
346 }
347 
348 void KMessageServer::sendMessage (TQ_UINT32 id, const TQByteArray &msg)
349 {
350  KMessageIO *client = findClient (id);
351  if (client)
352  client->send (msg);
353 }
354 
355 void 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 
361 void 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 
382 void 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 
503 void 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"
KMessageServer::uniqueClientNumber
TQ_UINT32 uniqueClientNumber() const
Definition: kmessageserver.cpp:335
KMessageServer::findClient
KMessageIO * findClient(TQ_UINT32 no) const
Find the KMessageIO object to the given client number.
Definition: kmessageserver.cpp:291
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()...
KMessageServer::serverPort
TQ_UINT16 serverPort() const
Returns the TCP/IP port number we are listening to for incoming connections.
Definition: kmessageserver.cpp:146
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:170
KMessageServer::Debug
virtual void Debug()
Gives debug output of the game status.
Definition: kmessageserver.cpp:503
KMessageServer::removeClient
void removeClient(KMessageIO *io, bool broken)
Removes the KMessageIO object from the client list and deletes it.
Definition: kmessageserver.cpp:223
KMessageServerSocket
Internal class of KMessageServer.
Definition: kmessageserver.h:477
KMessageServer::addClient
void addClient(KMessageIO *)
Adds a new KMessageIO object to the communication server.
Definition: kmessageserver.cpp:170
KMessageServer::clientConnected
void clientConnected(KMessageIO *client)
A new client connected to the game.
KMessageServer::deleteClients
void deleteClients()
Deletes all connections to the clients.
Definition: kmessageserver.cpp:247
KMessageServer::adminID
TQ_UINT32 adminID() const
Returns the clientID of the admin, if there is a admin, 0 otherwise.
Definition: kmessageserver.cpp:306
KMessageServer::KMessageServer
KMessageServer(TQ_UINT16 cookie=42, TQObject *parent=0)
Create a KGameNetwork object.
Definition: kmessageserver.cpp:89
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.
KMessageIO
This abstract base class represents one end of a message connections between two clients.
Definition: kmessageio.h:56
KMessageServer::initNetwork
bool initNetwork(TQ_UINT16 port=0)
Starts the Communication server to listen for incoming TCP/IP connections.
Definition: kmessageserver.cpp:118
KMessageIO::setId
void setId(TQ_UINT32 id)
Sets the ID number of this object.
Definition: kmessageio.cpp:39
KMessageServer::setAdmin
void setAdmin(TQ_UINT32 adminID)
Sets the admin to a new client with the given ID.
Definition: kmessageserver.cpp:311
KMessageServer::getReceivedMessage
virtual void getReceivedMessage(const TQByteArray &msg)
This slot receives all the messages from the KMessageIO::received signals.
Definition: kmessageserver.cpp:361
KMessageServer::processOneMessage
virtual void processOneMessage()
This slot is called whenever there are elements in the message queue.
Definition: kmessageserver.cpp:382
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::clientIDs
TQValueList< TQ_UINT32 > clientIDs() const
returns a list of the unique IDs of all clients.
Definition: kmessageserver.cpp:283
KMessageServer::broadcastMessage
virtual void broadcastMessage(const TQByteArray &msg)
Sends a message to all connected clients.
Definition: kmessageserver.cpp:342
KMessageServer::isOfferingConnections
bool isOfferingConnections() const
Are we still offer offering server connections?
Definition: kmessageserver.cpp:163
KMessageServer::maxClients
int maxClients() const
returns the maximum number of clients
Definition: kmessageserver.cpp:273
KMessageIO::id
TQ_UINT32 id()
Queries the ID of this object.
Definition: kmessageio.cpp:44
KMessageServer::connectionLost
void connectionLost(KMessageIO *client)
A network connection got broken.
KMessageServer::setMaxClients
void setMaxClients(int maxnumber)
sets the maximum number of clients which can connect.
Definition: kmessageserver.cpp:268
KMessageServer::stopNetwork
void stopNetwork()
Stops listening for connections.
Definition: kmessageserver.cpp:154

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.8.13
This website is maintained by Timothy Pearson.