• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

libkdegames/kgame

kmessageclient.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of the KDE games library
00003     Copyright (C) 2001 Burkhard Lehner (Burkhard.Lehner@gmx.de)
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License version 2 as published by the Free Software Foundation.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to
00016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017     Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "kmessageclient.h"
00021 
00022 #include <kdebug.h>
00023 #include <stdio.h>
00024 
00025 #include <qbuffer.h>
00026 #include <QTimer>
00027 #include <QList>
00028 #include <QDataStream>
00029 #include "kmessageio.h"
00030 #include "kmessageserver.h"
00031 
00032 class KMessageClientPrivate
00033 {
00034 public:
00035   KMessageClientPrivate ()
00036     : adminID (0), connection (0)
00037   {}
00038 
00039   ~KMessageClientPrivate ()
00040   {
00041     delete connection;
00042   }
00043 
00044   quint32 adminID;
00045   QList <quint32> clientList;
00046   KMessageIO *connection;
00047 
00048   bool isLocked;
00049   QList <QByteArray> delayedMessages;
00050 };
00051 
00052 KMessageClient::KMessageClient (QObject *parent)
00053     : QObject (parent),
00054       d( new KMessageClientPrivate )
00055 {
00056   d->isLocked = false;
00057 }
00058 
00059 KMessageClient::~KMessageClient ()
00060 {
00061   d->delayedMessages.clear();
00062   delete d;
00063 }
00064 
00065 // -- setServer stuff
00066 
00067 void KMessageClient::setServer (const QString &host, quint16 port)
00068 {
00069   setServer (new KMessageSocket (host, port));
00070 }
00071 
00072 void KMessageClient::setServer (KMessageServer *server)
00073 {
00074   KMessageDirect *serverIO = new KMessageDirect ();
00075   setServer (new KMessageDirect (serverIO));
00076   server->addClient (serverIO);
00077 }
00078 
00079 void KMessageClient::setServer (KMessageIO *connection)
00080 {
00081   if (d->connection)
00082   {
00083     delete d->connection;
00084     kDebug (11001) << ": We are changing the server!";
00085   }
00086 
00087   d->connection = connection;
00088   if (connection )
00089   {
00090     connect (connection, SIGNAL (received(const QByteArray &)),
00091              this, SLOT (processIncomingMessage(const QByteArray &)));
00092     connect (connection, SIGNAL (connectionBroken()),
00093              this, SLOT (removeBrokenConnection ()));
00094   }
00095 }
00096 
00097 // -- id stuff
00098 
00099 quint32 KMessageClient::id () const
00100 {
00101   return (d->connection) ? d->connection->id () : 0;
00102 }
00103 
00104 bool KMessageClient::isAdmin () const
00105 {
00106   return id() != 0 && id() == adminId();
00107 }
00108 
00109 quint32 KMessageClient::adminId () const
00110 {
00111   return d->adminID;
00112 }
00113 
00114 QList <quint32> KMessageClient::clientList() const
00115 {
00116   return d->clientList;
00117 }
00118 
00119 bool KMessageClient::isConnected () const
00120 {
00121   return d->connection && d->connection->isConnected();
00122 }
00123 
00124 bool KMessageClient::isNetwork () const
00125 {
00126   return isConnected() ? d->connection->isNetwork() : false;
00127 }
00128 
00129 quint16 KMessageClient::peerPort () const
00130 {
00131  return d->connection ? d->connection->peerPort() : 0;
00132 }
00133 
00134 QString KMessageClient::peerName () const
00135 {
00136  return d->connection ? d->connection->peerName() : QString::fromLatin1("localhost");
00137 }
00138 
00139 // --------------------- Sending messages
00140 
00141 void KMessageClient::sendServerMessage (const QByteArray &msg)
00142 {
00143   if (!d->connection)
00144   {
00145     kWarning (11001) << ": We have no connection yet!";
00146     return;
00147   }
00148   d->connection->send (msg);
00149 }
00150 
00151 void KMessageClient::sendBroadcast (const QByteArray &msg)
00152 {
00153   QByteArray sendBuffer;
00154   QBuffer buffer (&sendBuffer);
00155   buffer.open (QIODevice::WriteOnly);
00156   QDataStream stream (&buffer);
00157 
00158   stream << static_cast<quint32> ( KMessageServer::REQ_BROADCAST );
00159   buffer.QIODevice::write (msg);
00160   sendServerMessage (sendBuffer);
00161 }
00162 
00163 void KMessageClient::sendForward (const QByteArray &msg, const QList <quint32> &clients)
00164 {
00165   QByteArray sendBuffer;
00166   QBuffer buffer (&sendBuffer);
00167   buffer.open (QIODevice::WriteOnly);
00168   QDataStream stream (&buffer);
00169 
00170   stream << static_cast<quint32>( KMessageServer::REQ_FORWARD ) << clients;
00171   buffer.QIODevice::write (msg);
00172   sendServerMessage (sendBuffer);
00173 }
00174 
00175 void KMessageClient::sendForward (const QByteArray &msg, quint32 client)
00176 {
00177   sendForward (msg, QList <quint32> () << client);
00178 }
00179 
00180 
00181 // --------------------- Receiving and processing messages
00182 
00183 void KMessageClient::processIncomingMessage (const QByteArray &msg)
00184 {
00185   if (d->isLocked)
00186   {
00187     d->delayedMessages.append(msg);
00188     return;
00189   }
00190   if (d->delayedMessages.count() > 0)
00191   {
00192     d->delayedMessages.append (msg);
00193     QByteArray first = d->delayedMessages.front();
00194     d->delayedMessages.pop_front();
00195     processMessage (first);
00196   }
00197   else
00198   {
00199     processMessage(msg);
00200   }
00201 }
00202 
00203 void KMessageClient::processMessage (const QByteArray &msg)
00204 {
00205   if (d->isLocked)
00206   { // must NOT happen, since we check in processIncomingMessage as well as in processFirstMessage
00207     d->delayedMessages.append(msg);
00208     return;
00209   }
00210   QBuffer in_buffer;
00211   in_buffer.setData(msg);
00212   in_buffer.open (QIODevice::ReadOnly);
00213   QDataStream in_stream (&in_buffer);
00214 
00215 
00216   bool unknown = false;
00217 
00218   quint32 messageID;
00219   in_stream >> messageID;
00220   switch (messageID)
00221   {
00222     case KMessageServer::MSG_BROADCAST:
00223       {
00224         quint32 clientID;
00225         in_stream >> clientID;
00226         emit broadcastReceived (in_buffer.readAll(), clientID);
00227       }
00228       break;
00229 
00230     case KMessageServer::MSG_FORWARD:
00231       {
00232         quint32 clientID;
00233         QList <quint32> receivers;
00234         in_stream >> clientID >> receivers;
00235         emit forwardReceived (in_buffer.readAll(), clientID, receivers);
00236       }
00237       break;
00238 
00239     case KMessageServer::ANS_CLIENT_ID:
00240       {
00241         bool old_admin = isAdmin();
00242         quint32 clientID;
00243         in_stream >> clientID;
00244         d->connection->setId (clientID);
00245         if (old_admin != isAdmin())
00246           emit adminStatusChanged (isAdmin());
00247       }
00248       break;
00249 
00250     case KMessageServer::ANS_ADMIN_ID:
00251       {
00252         bool old_admin = isAdmin();
00253         in_stream >> d->adminID;
00254         if (old_admin != isAdmin())
00255           emit adminStatusChanged (isAdmin());
00256       }
00257       break;
00258 
00259     case KMessageServer::ANS_CLIENT_LIST:
00260       {
00261         in_stream >> d->clientList;
00262       }
00263       break;
00264 
00265     case KMessageServer::EVNT_CLIENT_CONNECTED:
00266       {
00267         quint32 id;
00268         in_stream >> id;
00269 
00270         if (d->clientList.contains (id))
00271           kWarning (11001) << ": Adding a client that already existed!";
00272         else
00273           d->clientList.append (id);
00274 
00275         emit eventClientConnected (id);
00276       }
00277       break;
00278 
00279     case KMessageServer::EVNT_CLIENT_DISCONNECTED:
00280       {
00281         quint32 id;
00282         qint8 broken;
00283         in_stream >> id >> broken;
00284 
00285         if (!d->clientList.contains (id))
00286           kWarning (11001) << ": Removing a client that doesn't exist!";
00287         else
00288           d->clientList.removeAll (id);
00289 
00290         emit eventClientDisconnected (id, bool (broken));
00291       }
00292       break;
00293 
00294     default:
00295       unknown = true;
00296   }
00297 
00298   if (!unknown && !in_buffer.atEnd())
00299     kWarning (11001) << ": Extra data received for message ID" << messageID;
00300 
00301   emit serverMessageReceived (msg, unknown);
00302 
00303   if (unknown)
00304     kWarning (11001) << ": received unknown message ID" << messageID;
00305 }
00306 
00307 void KMessageClient::processFirstMessage()
00308 {
00309   if (d->isLocked)
00310   {
00311     return;
00312   }
00313   if (d->delayedMessages.count() == 0)
00314   {
00315     kDebug(11001) << ": no messages delayed";
00316     return;
00317   }
00318   QByteArray first = d->delayedMessages.front();
00319   d->delayedMessages.pop_front();
00320   processMessage (first);
00321 }
00322 
00323 void KMessageClient::removeBrokenConnection ()
00324 {
00325   kDebug (11001) << ": timer single shot for removeBrokenConnection"<<this;
00326   // MH We cannot directly delete the socket. otherwise QSocket crashes
00327   QTimer::singleShot( 0, this, SLOT(removeBrokenConnection2()) );
00328   return;
00329 }
00330 
00331 
00332 void KMessageClient::removeBrokenConnection2 ()
00333 {
00334   kDebug (11001) << ": Broken:Deleting the connection object"<<this;
00335 
00336   emit aboutToDisconnect(id());
00337   delete d->connection;
00338   d->connection = 0;
00339   d->adminID = 0;
00340   emit connectionBroken();
00341   kDebug (11001) << ": Broken:Deleting the connection object DONE";
00342 }
00343 
00344 void KMessageClient::disconnect ()
00345 {
00346   kDebug (11001) << ": Disconnect:Deleting the connection object";
00347 
00348   emit aboutToDisconnect(id());
00349   delete d->connection;
00350   d->connection = 0;
00351   d->adminID = 0;
00352   emit connectionBroken();
00353   kDebug (11001) << ": Disconnect:Deleting the connection object DONE";
00354 }
00355 
00356 void KMessageClient::lock ()
00357 {
00358   d->isLocked = true;
00359 }
00360 
00361 void KMessageClient::unlock ()
00362 {
00363   d->isLocked = false;
00364   for (int i = 0; i < d->delayedMessages.count(); i++)
00365   {
00366     QTimer::singleShot(0, this, SLOT(processFirstMessage()));
00367   }
00368 }
00369 
00370 unsigned int KMessageClient::delayedMessageCount() const
00371 {
00372   return d->delayedMessages.count();
00373 }
00374 
00375 #include "kmessageclient.moc"

libkdegames/kgame

Skip menu "libkdegames/kgame"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • kblackbox
  • kgoldrunner
  • kmahjongg
  • ksquares
  • libkdegames
  •   highscore
  •   kgame
  •   kggzgames
  •   kggzmod
  •   kggznet
  • libkmahjongg
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal