libkdegames Library API Documentation

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., 59 Temple Place - Suite 330, 00017 Boston, MA 02111-1307, 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 Logo
This file is part of the documentation for libkdegames Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Sep 21 12:08:03 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003