PageRenderTime 67ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/kdegames-3.5.10/libkdegames/kgame/kmessageserver.cpp

#
C++ | 515 lines | 373 code | 90 blank | 52 comment | 49 complexity | d93b42c53672c2bb2af2fc13365540f0 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, 0BSD, GPL-2.0, CC-BY-SA-3.0
  1. /*
  2. This file is part of the KDE games library
  3. Copyright (C) 2001 Burkhard Lehner (Burkhard.Lehner@gmx.de)
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License version 2 as published by the Free Software Foundation.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public License
  12. along with this library; see the file COPYING.LIB. If not, write to
  13. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  14. Boston, MA 02110-1301, USA.
  15. */
  16. #include <qiodevice.h>
  17. #include <qbuffer.h>
  18. #include <qptrlist.h>
  19. #include <qptrqueue.h>
  20. #include <qtimer.h>
  21. #include <qvaluelist.h>
  22. #include <kdebug.h>
  23. #include "kmessageio.h"
  24. #include "kmessageserver.h"
  25. // --------------- internal class KMessageServerSocket
  26. KMessageServerSocket::KMessageServerSocket (Q_UINT16 port, QObject *parent)
  27. : QServerSocket (port, 0, parent)
  28. {
  29. }
  30. KMessageServerSocket::~KMessageServerSocket ()
  31. {
  32. }
  33. void KMessageServerSocket::newConnection (int socket)
  34. {
  35. emit newClientConnected (new KMessageSocket (socket));
  36. }
  37. // ---------------- class for storing an incoming message
  38. class MessageBuffer
  39. {
  40. public:
  41. MessageBuffer (Q_UINT32 clientID, const QByteArray &messageData)
  42. : id (clientID), data (messageData) { }
  43. ~MessageBuffer () {}
  44. Q_UINT32 id;
  45. QByteArray data;
  46. };
  47. // ---------------- KMessageServer's private class
  48. class KMessageServerPrivate
  49. {
  50. public:
  51. KMessageServerPrivate()
  52. : mMaxClients (-1), mGameId (1), mUniqueClientNumber (1), mAdminID (0), mServerSocket (0)
  53. {
  54. mClientList.setAutoDelete (true);
  55. mMessageQueue.setAutoDelete (true);
  56. }
  57. int mMaxClients;
  58. int mGameId;
  59. Q_UINT16 mCookie;
  60. Q_UINT32 mUniqueClientNumber;
  61. Q_UINT32 mAdminID;
  62. KMessageServerSocket* mServerSocket;
  63. QPtrList <KMessageIO> mClientList;
  64. QPtrQueue <MessageBuffer> mMessageQueue;
  65. QTimer mTimer;
  66. bool mIsRecursive;
  67. };
  68. // ------------------ KMessageServer
  69. KMessageServer::KMessageServer (Q_UINT16 cookie,QObject* parent)
  70. : QObject(parent, 0)
  71. {
  72. d = new KMessageServerPrivate;
  73. d->mIsRecursive=false;
  74. d->mCookie=cookie;
  75. connect (&(d->mTimer), SIGNAL (timeout()),
  76. this, SLOT (processOneMessage()));
  77. kdDebug(11001) << "CREATE(KMessageServer="
  78. << this
  79. << ") cookie="
  80. << d->mCookie
  81. << " sizeof(this)="
  82. << sizeof(KMessageServer)
  83. << endl;
  84. }
  85. KMessageServer::~KMessageServer()
  86. {
  87. kdDebug(11001) << k_funcinfo << "this=" << this << endl;
  88. Debug();
  89. stopNetwork();
  90. deleteClients();
  91. delete d;
  92. kdDebug(11001) << k_funcinfo << " done" << endl;
  93. }
  94. //------------------------------------- TCP/IP server stuff
  95. bool KMessageServer::initNetwork (Q_UINT16 port)
  96. {
  97. kdDebug(11001) << k_funcinfo << endl;
  98. if (d->mServerSocket)
  99. {
  100. kdDebug (11001) << k_funcinfo << ": We were already offering connections!" << endl;
  101. delete d->mServerSocket;
  102. }
  103. d->mServerSocket = new KMessageServerSocket (port);
  104. d->mIsRecursive = false;
  105. if (!d->mServerSocket || !d->mServerSocket->ok())
  106. {
  107. kdError(11001) << k_funcinfo << ": Serversocket::ok() == false" << endl;
  108. delete d->mServerSocket;
  109. d->mServerSocket=0;
  110. return false;
  111. }
  112. kdDebug (11001) << k_funcinfo << ": Now listening to port "
  113. << d->mServerSocket->port() << endl;
  114. connect (d->mServerSocket, SIGNAL (newClientConnected (KMessageIO*)),
  115. this, SLOT (addClient (KMessageIO*)));
  116. return true;
  117. }
  118. Q_UINT16 KMessageServer::serverPort () const
  119. {
  120. if (d->mServerSocket)
  121. return d->mServerSocket->port();
  122. else
  123. return 0;
  124. }
  125. void KMessageServer::stopNetwork()
  126. {
  127. if (d->mServerSocket)
  128. {
  129. delete d->mServerSocket;
  130. d->mServerSocket = 0;
  131. }
  132. }
  133. bool KMessageServer::isOfferingConnections() const
  134. {
  135. return d->mServerSocket != 0;
  136. }
  137. //----------------------------------------------- adding / removing clients
  138. void KMessageServer::addClient (KMessageIO* client)
  139. {
  140. QByteArray msg;
  141. // maximum number of clients reached?
  142. if (d->mMaxClients >= 0 && d->mMaxClients <= clientCount())
  143. {
  144. kdError (11001) << k_funcinfo << ": Maximum number of clients reached!" << endl;
  145. return;
  146. }
  147. // give it a unique ID
  148. client->setId (uniqueClientNumber());
  149. kdDebug (11001) << k_funcinfo << ": " << client->id() << endl;
  150. // connect its signals
  151. connect (client, SIGNAL (connectionBroken()),
  152. this, SLOT (removeBrokenClient()));
  153. connect (client, SIGNAL (received (const QByteArray &)),
  154. this, SLOT (getReceivedMessage (const QByteArray &)));
  155. // Tell everyone about the new guest
  156. // Note: The new client doesn't get this message!
  157. QDataStream (msg, IO_WriteOnly) << Q_UINT32 (EVNT_CLIENT_CONNECTED) << client->id();
  158. broadcastMessage (msg);
  159. // add to our list
  160. d->mClientList.append (client);
  161. // tell it its ID
  162. QDataStream (msg, IO_WriteOnly) << Q_UINT32 (ANS_CLIENT_ID) << client->id();
  163. client->send (msg);
  164. // Give it the complete list of client IDs
  165. QDataStream (msg, IO_WriteOnly) << Q_UINT32 (ANS_CLIENT_LIST) << clientIDs();
  166. client->send (msg);
  167. if (clientCount() == 1)
  168. {
  169. // if it is the first client, it becomes the admin
  170. setAdmin (client->id());
  171. }
  172. else
  173. {
  174. // otherwise tell it who is the admin
  175. QDataStream (msg, IO_WriteOnly) << Q_UINT32 (ANS_ADMIN_ID) << adminID();
  176. client->send (msg);
  177. }
  178. emit clientConnected (client);
  179. }
  180. void KMessageServer::removeClient (KMessageIO* client, bool broken)
  181. {
  182. Q_UINT32 clientID = client->id();
  183. if (!d->mClientList.removeRef (client))
  184. {
  185. kdError(11001) << k_funcinfo << ": Deleting client that wasn't added before!" << endl;
  186. return;
  187. }
  188. // tell everyone about the removed client
  189. QByteArray msg;
  190. QDataStream (msg, IO_WriteOnly) << Q_UINT32 (EVNT_CLIENT_DISCONNECTED) << client->id() << (Q_INT8)broken;
  191. broadcastMessage (msg);
  192. // If it was the admin, select a new admin.
  193. if (clientID == adminID())
  194. {
  195. if (!d->mClientList.isEmpty())
  196. setAdmin (d->mClientList.first()->id());
  197. else
  198. setAdmin (0);
  199. }
  200. }
  201. void KMessageServer::deleteClients()
  202. {
  203. d->mClientList.clear();
  204. d->mAdminID = 0;
  205. }
  206. void KMessageServer::removeBrokenClient ()
  207. {
  208. if (!sender()->inherits ("KMessageIO"))
  209. {
  210. kdError (11001) << k_funcinfo << ": sender of the signal was not a KMessageIO object!" << endl;
  211. return;
  212. }
  213. KMessageIO *client = (KMessageIO *) sender();
  214. emit connectionLost (client);
  215. removeClient (client, true);
  216. }
  217. void KMessageServer::setMaxClients(int c)
  218. {
  219. d->mMaxClients = c;
  220. }
  221. int KMessageServer::maxClients() const
  222. {
  223. return d->mMaxClients;
  224. }
  225. int KMessageServer::clientCount() const
  226. {
  227. return d->mClientList.count();
  228. }
  229. QValueList <Q_UINT32> KMessageServer::clientIDs () const
  230. {
  231. QValueList <Q_UINT32> list;
  232. for (QPtrListIterator <KMessageIO> iter (d->mClientList); *iter; ++iter)
  233. list.append ((*iter)->id());
  234. return list;
  235. }
  236. KMessageIO* KMessageServer::findClient (Q_UINT32 no) const
  237. {
  238. if (no == 0)
  239. no = d->mAdminID;
  240. QPtrListIterator <KMessageIO> iter (d->mClientList);
  241. while (*iter)
  242. {
  243. if ((*iter)->id() == no)
  244. return (*iter);
  245. ++iter;
  246. }
  247. return 0;
  248. }
  249. Q_UINT32 KMessageServer::adminID () const
  250. {
  251. return d->mAdminID;
  252. }
  253. void KMessageServer::setAdmin (Q_UINT32 adminID)
  254. {
  255. // Trying to set the the client that is already admin => nothing to do
  256. if (adminID == d->mAdminID)
  257. return;
  258. if (adminID > 0 && findClient (adminID) == 0)
  259. {
  260. kdWarning (11001) << "Trying to set a new admin that doesn't exist!" << endl;
  261. return;
  262. }
  263. d->mAdminID = adminID;
  264. QByteArray msg;
  265. QDataStream (msg, IO_WriteOnly) << Q_UINT32 (ANS_ADMIN_ID) << adminID;
  266. // Tell everyone about the new master
  267. broadcastMessage (msg);
  268. }
  269. //------------------------------------------- ID stuff
  270. Q_UINT32 KMessageServer::uniqueClientNumber() const
  271. {
  272. return d->mUniqueClientNumber++;
  273. }
  274. // --------------------- Messages ---------------------------
  275. void KMessageServer::broadcastMessage (const QByteArray &msg)
  276. {
  277. for (QPtrListIterator <KMessageIO> iter (d->mClientList); *iter; ++iter)
  278. (*iter)->send (msg);
  279. }
  280. void KMessageServer::sendMessage (Q_UINT32 id, const QByteArray &msg)
  281. {
  282. KMessageIO *client = findClient (id);
  283. if (client)
  284. client->send (msg);
  285. }
  286. void KMessageServer::sendMessage (const QValueList <Q_UINT32> &ids, const QByteArray &msg)
  287. {
  288. for (QValueListConstIterator <Q_UINT32> iter = ids.begin(); iter != ids.end(); ++iter)
  289. sendMessage (*iter, msg);
  290. }
  291. void KMessageServer::getReceivedMessage (const QByteArray &msg)
  292. {
  293. if (!sender() || !sender()->inherits("KMessageIO"))
  294. {
  295. kdError (11001) << k_funcinfo << ": slot was not called from KMessageIO!" << endl;
  296. return;
  297. }
  298. //kdDebug(11001) << k_funcinfo << ": size=" << msg.size() << endl;
  299. KMessageIO *client = (KMessageIO *) sender();
  300. Q_UINT32 clientID = client->id();
  301. //QByteArray *ta=new QByteArray;
  302. //ta->duplicate(msg);
  303. //d->mMessageQueue.enqueue (new MessageBuffer (clientID, *ta));
  304. d->mMessageQueue.enqueue (new MessageBuffer (clientID, msg));
  305. if (!d->mTimer.isActive())
  306. d->mTimer.start(0); // AB: should be , TRUE i guess
  307. }
  308. void KMessageServer::processOneMessage ()
  309. {
  310. // This shouldn't happen, since the timer should be stopped before. But only to be sure!
  311. if (d->mMessageQueue.isEmpty())
  312. {
  313. d->mTimer.stop();
  314. return;
  315. }
  316. if (d->mIsRecursive)
  317. {
  318. return;
  319. }
  320. d->mIsRecursive = true;
  321. MessageBuffer *msg_buf = d->mMessageQueue.head();
  322. Q_UINT32 clientID = msg_buf->id;
  323. QBuffer in_buffer (msg_buf->data);
  324. in_buffer.open (IO_ReadOnly);
  325. QDataStream in_stream (&in_buffer);
  326. QByteArray out_msg;
  327. QBuffer out_buffer (out_msg);
  328. out_buffer.open (IO_WriteOnly);
  329. QDataStream out_stream (&out_buffer);
  330. bool unknown = false;
  331. QByteArray ttt=in_buffer.buffer();
  332. Q_UINT32 messageID;
  333. in_stream >> messageID;
  334. //kdDebug(11001) << k_funcinfo << ": got message with messageID=" << messageID << endl;
  335. switch (messageID)
  336. {
  337. case REQ_BROADCAST:
  338. out_stream << Q_UINT32 (MSG_BROADCAST) << clientID;
  339. // FIXME, compiler bug?
  340. // this should be okay, since QBuffer is subclass of QIODevice! :
  341. // out_buffer.writeBlock (in_buffer.readAll());
  342. out_buffer.QIODevice::writeBlock (in_buffer.readAll());
  343. broadcastMessage (out_msg);
  344. break;
  345. case REQ_FORWARD:
  346. {
  347. QValueList <Q_UINT32> clients;
  348. in_stream >> clients;
  349. out_stream << Q_UINT32 (MSG_FORWARD) << clientID << clients;
  350. // see above!
  351. out_buffer.QIODevice::writeBlock (in_buffer.readAll());
  352. sendMessage (clients, out_msg);
  353. }
  354. break;
  355. case REQ_CLIENT_ID:
  356. out_stream << Q_UINT32 (ANS_CLIENT_ID) << clientID;
  357. sendMessage (clientID, out_msg);
  358. break;
  359. case REQ_ADMIN_ID:
  360. out_stream << Q_UINT32 (ANS_ADMIN_ID) << d->mAdminID;
  361. sendMessage (clientID, out_msg);
  362. break;
  363. case REQ_ADMIN_CHANGE:
  364. if (clientID == d->mAdminID)
  365. {
  366. Q_UINT32 newAdmin;
  367. in_stream >> newAdmin;
  368. setAdmin (newAdmin);
  369. }
  370. break;
  371. case REQ_REMOVE_CLIENT:
  372. if (clientID == d->mAdminID)
  373. {
  374. QValueList <Q_UINT32> client_list;
  375. in_stream >> client_list;
  376. for (QValueListIterator <Q_UINT32> iter = client_list.begin(); iter != client_list.end(); ++iter)
  377. {
  378. KMessageIO *client = findClient (*iter);
  379. if (client)
  380. removeClient (client, false);
  381. else
  382. kdWarning (11001) << k_funcinfo << ": removing non-existing clientID" << endl;
  383. }
  384. }
  385. break;
  386. case REQ_MAX_NUM_CLIENTS:
  387. if (clientID == d->mAdminID)
  388. {
  389. Q_INT32 maximum_clients;
  390. in_stream >> maximum_clients;
  391. setMaxClients (maximum_clients);
  392. }
  393. break;
  394. case REQ_CLIENT_LIST:
  395. {
  396. out_stream << Q_UINT32 (ANS_CLIENT_LIST) << clientIDs();
  397. sendMessage (clientID, out_msg);
  398. }
  399. break;
  400. default:
  401. unknown = true;
  402. }
  403. // check if all the data has been used
  404. if (!unknown && !in_buffer.atEnd())
  405. kdWarning (11001) << k_funcinfo << ": Extra data received for message ID " << messageID << endl;
  406. emit messageReceived (msg_buf->data, clientID, unknown);
  407. if (unknown)
  408. kdWarning (11001) << k_funcinfo << ": received unknown message ID " << messageID << endl;
  409. // remove the message, since we are ready with it
  410. d->mMessageQueue.remove();
  411. if (d->mMessageQueue.isEmpty())
  412. d->mTimer.stop();
  413. d->mIsRecursive = false;
  414. }
  415. void KMessageServer::Debug()
  416. {
  417. kdDebug(11001) << "------------------ KMESSAGESERVER -----------------------" << endl;
  418. kdDebug(11001) << "MaxClients : " << maxClients() << endl;
  419. kdDebug(11001) << "NoOfClients : " << clientCount() << endl;
  420. kdDebug(11001) << "---------------------------------------------------" << endl;
  421. }
  422. #include "kmessageserver.moc"