kmessageclient.cpp

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 <kdebug.h>
00021 #include <stdio.h>
00022 
00023 #include <qbuffer.h>
00024 #include <qtimer.h>
00025 
00026 #include "kmessageio.h"
00027 #include "kmessageserver.h"
00028 
00029 #include "kmessageclient.h"
00030 
00031 class KMessageClientPrivate
00032 {
00033 public:
00034   KMessageClientPrivate ()
00035     : adminID (0), connection (0)
00036   {}
00037 
00038   ~KMessageClientPrivate ()
00039   {
00040     delete connection;
00041   }
00042 
00043   Q_UINT32 adminID;
00044   QValueList <Q_UINT32> clientList;
00045   KMessageIO *connection;
00046 
00047   bool isLocked;
00048   QValueList <QByteArray> delayedMessages;
00049 };
00050 
00051 KMessageClient::KMessageClient (QObject *parent, const char *name)
00052   : QObject (parent, name)
00053 {
00054   d = new KMessageClientPrivate ();
00055   d->isLocked = false;
00056 }
00057 
00058 KMessageClient::~KMessageClient ()
00059 {
00060   d->delayedMessages.clear();
00061   delete d;
00062 }
00063 
00064 // -- setServer stuff
00065 
00066 void KMessageClient::setServer (const QString &host, Q_UINT16 port)
00067 {
00068   setServer (new KMessageSocket (host, port));
00069 }
00070 
00071 void KMessageClient::setServer (KMessageServer *server)
00072 {
00073   KMessageDirect *serverIO = new KMessageDirect ();
00074   setServer (new KMessageDirect (serverIO));
00075   server->addClient (serverIO);
00076 }
00077 
00078 void KMessageClient::setServer (KMessageIO *connection)
00079 {
00080   if (d->connection)
00081   {
00082     delete d->connection;
00083     kdDebug (11001) << k_funcinfo << ": We are changing the server!" << endl;
00084   }
00085 
00086   d->connection = connection;
00087   if (connection )
00088   {
00089     connect (connection, SIGNAL (received(const QByteArray &)),
00090              this, SLOT (processIncomingMessage(const QByteArray &)));
00091     connect (connection, SIGNAL (connectionBroken()),
00092              this, SLOT (removeBrokenConnection ()));
00093   }
00094 }
00095 
00096 // -- id stuff
00097 
00098 Q_UINT32 KMessageClient::id () const
00099 {
00100   return (d->connection) ? d->connection->id () : 0;
00101 }
00102 
00103 bool KMessageClient::isAdmin () const
00104 {
00105   return id() != 0 && id() == adminId();
00106 }
00107 
00108 Q_UINT32 KMessageClient::adminId () const
00109 {
00110   return d->adminID;
00111 }
00112 
00113 const QValueList <Q_UINT32> &KMessageClient::clientList() const
00114 {
00115   return d->clientList;
00116 }
00117 
00118 bool KMessageClient::isConnected () const
00119 {
00120   return d->connection && d->connection->isConnected();
00121 }
00122 
00123 bool KMessageClient::isNetwork () const
00124 {
00125   return isConnected() ? d->connection->isNetwork() : false;
00126 }
00127 
00128 Q_UINT16 KMessageClient::peerPort () const
00129 {
00130  return d->connection ? d->connection->peerPort() : 0;
00131 }
00132 
00133 QString KMessageClient::peerName () const
00134 {
00135  return d->connection ? d->connection->peerName() : QString::fromLatin1("localhost");
00136 }
00137 
00138 // --------------------- Sending messages
00139 
00140 void KMessageClient::sendServerMessage (const QByteArray &msg)
00141 {
00142   if (!d->connection)
00143   {
00144     kdWarning (11001) << k_funcinfo << ": We have no connection yet!" << endl;
00145     return;
00146   }
00147   d->connection->send (msg);
00148 }
00149 
00150 void KMessageClient::sendBroadcast (const QByteArray &msg)
00151 {
00152   QByteArray sendBuffer;
00153   QBuffer buffer (sendBuffer);
00154   buffer.open (IO_WriteOnly);
00155   QDataStream stream (&buffer);
00156 
00157   stream << static_cast<Q_UINT32> ( KMessageServer::REQ_BROADCAST );
00158   buffer.QIODevice::writeBlock (msg);
00159   sendServerMessage (sendBuffer);
00160 }
00161 
00162 void KMessageClient::sendForward (const QByteArray &msg, const QValueList <Q_UINT32> &clients)
00163 {
00164   QByteArray sendBuffer;
00165   QBuffer buffer (sendBuffer);
00166   buffer.open (IO_WriteOnly);
00167   QDataStream stream (&buffer);
00168 
00169   stream << static_cast<Q_UINT32>( KMessageServer::REQ_FORWARD ) << clients;
00170   buffer.QIODevice::writeBlock (msg);
00171   sendServerMessage (sendBuffer);
00172 }
00173 
00174 void KMessageClient::sendForward (const QByteArray &msg, Q_UINT32 client)
00175 {
00176   sendForward (msg, QValueList <Q_UINT32> () << client);
00177 }
00178 
00179 
00180 // --------------------- Receiving and processing messages
00181 
00182 void KMessageClient::processIncomingMessage (const QByteArray &msg)
00183 {
00184   if (d->isLocked)
00185   {
00186     d->delayedMessages.append(msg);
00187     return;
00188   }
00189   if (d->delayedMessages.count() > 0)
00190   {
00191     d->delayedMessages.append (msg);
00192     QByteArray first = d->delayedMessages.front();
00193     d->delayedMessages.pop_front();
00194     processMessage (first);
00195   }
00196   else
00197   {
00198     processMessage(msg);
00199   }
00200 }
00201 
00202 void KMessageClient::processMessage (const QByteArray &msg)
00203 {
00204   if (d->isLocked)
00205   { // must NOT happen, since we check in processIncomingMessage as well as in processFirstMessage
00206     d->delayedMessages.append(msg);
00207     return;
00208   }
00209   QBuffer in_buffer (msg);
00210   in_buffer.open (IO_ReadOnly);
00211   QDataStream in_stream (&in_buffer);
00212 
00213 
00214   bool unknown = false;
00215 
00216   Q_UINT32 messageID;
00217   in_stream >> messageID;
00218   switch (messageID)
00219   {
00220     case KMessageServer::MSG_BROADCAST:
00221       {
00222         Q_UINT32 clientID;
00223         in_stream >> clientID;
00224         emit broadcastReceived (in_buffer.readAll(), clientID);
00225       }
00226       break;
00227 
00228     case KMessageServer::MSG_FORWARD:
00229       {
00230         Q_UINT32 clientID;
00231         QValueList <Q_UINT32> receivers;
00232         in_stream >> clientID >> receivers;
00233         emit forwardReceived (in_buffer.readAll(), clientID, receivers);
00234       }
00235       break;
00236 
00237     case KMessageServer::ANS_CLIENT_ID:
00238       {
00239         bool old_admin = isAdmin();
00240         Q_UINT32 clientID;
00241         in_stream >> clientID;
00242         d->connection->setId (clientID);
00243         if (old_admin != isAdmin())
00244           emit adminStatusChanged (isAdmin());
00245       }
00246       break;
00247 
00248     case KMessageServer::ANS_ADMIN_ID:
00249       {
00250         bool old_admin = isAdmin();
00251         in_stream >> d->adminID;
00252         if (old_admin != isAdmin())
00253           emit adminStatusChanged (isAdmin());
00254       }
00255       break;
00256 
00257     case KMessageServer::ANS_CLIENT_LIST:
00258       {
00259         in_stream >> d->clientList;
00260       }
00261       break;
00262 
00263     case KMessageServer::EVNT_CLIENT_CONNECTED:
00264       {
00265         Q_UINT32 id;
00266         in_stream >> id;
00267 
00268         if (d->clientList.contains (id))
00269           kdWarning (11001) << k_funcinfo << ": Adding a client that already existed!" << endl;
00270         else
00271           d->clientList.append (id);
00272 
00273         emit eventClientConnected (id);
00274       }
00275       break;
00276 
00277     case KMessageServer::EVNT_CLIENT_DISCONNECTED:
00278       {
00279         Q_UINT32 id;
00280         Q_INT8 broken;
00281         in_stream >> id >> broken;
00282 
00283         if (!d->clientList.contains (id))
00284           kdWarning (11001) << k_funcinfo << ": Removing a client that doesn't exist!" << endl;
00285         else
00286           d->clientList.remove (id);
00287 
00288         emit eventClientDisconnected (id, bool (broken));
00289       }
00290       break;
00291 
00292     default:
00293       unknown = true;
00294   }
00295 
00296   if (!unknown && !in_buffer.atEnd())
00297     kdWarning (11001) << k_funcinfo << ": Extra data received for message ID " << messageID << endl;
00298 
00299   emit serverMessageReceived (msg, unknown);
00300 
00301   if (unknown)
00302     kdWarning (11001) << k_funcinfo << ": received unknown message ID " << messageID << endl;
00303 }
00304 
00305 void KMessageClient::processFirstMessage()
00306 {
00307   if (d->isLocked)
00308   {
00309     return;
00310   }
00311   if (d->delayedMessages.count() == 0)
00312   {
00313     kdDebug(11001) << k_funcinfo << ": no messages delayed" << endl;
00314     return;
00315   }
00316   QByteArray first = d->delayedMessages.front();
00317   d->delayedMessages.pop_front();
00318   processMessage (first);
00319 }
00320 
00321 void KMessageClient::removeBrokenConnection ()
00322 {
00323   kdDebug (11001) << k_funcinfo << ": timer single shot for removeBrokenConnection"<<this << endl;
00324   // MH We cannot directly delete the socket. otherwise QSocket crashes
00325   QTimer::singleShot( 0, this, SLOT(removeBrokenConnection2()) );
00326   return;
00327 }
00328 
00329 
00330 void KMessageClient::removeBrokenConnection2 ()
00331 {
00332   kdDebug (11001) << k_funcinfo << ": Broken:Deleting the connection object"<<this << endl;
00333 
00334   emit aboutToDisconnect(id());
00335   delete d->connection;
00336   d->connection = 0;
00337   d->adminID = 0;
00338   emit connectionBroken();
00339   kdDebug (11001) << k_funcinfo << ": Broken:Deleting the connection object DONE" << endl;
00340 }
00341 
00342 void KMessageClient::disconnect ()
00343 {
00344   kdDebug (11001) << k_funcinfo << ": Disconnect:Deleting the connection object" << endl;
00345 
00346   emit aboutToDisconnect(id());
00347   delete d->connection;
00348   d->connection = 0;
00349   d->adminID = 0;
00350   emit connectionBroken();
00351   kdDebug (11001) << k_funcinfo << ": Disconnect:Deleting the connection object DONE" << endl;
00352 }
00353 
00354 void KMessageClient::lock ()
00355 {
00356   d->isLocked = true;
00357 }
00358 
00359 void KMessageClient::unlock ()
00360 {
00361   d->isLocked = false;
00362   for (unsigned int i = 0; i < d->delayedMessages.count(); i++)
00363   {
00364     QTimer::singleShot(0, this, SLOT(processFirstMessage()));
00365   }
00366 }
00367 
00368 unsigned int KMessageClient::delayedMessageCount() const
00369 {
00370   return d->delayedMessages.count();
00371 }
00372 
00373 #include "kmessageclient.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys