libkdegames/kgame
kmessageclient.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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
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
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 {
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
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"