00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "kgamenetwork.h"
00025 #include "kgamenetwork.moc"
00026 #include "kgamemessage.h"
00027 #include "kgameerror.h"
00028
00029 #include "kmessageserver.h"
00030 #include "kmessageclient.h"
00031 #include "kmessageio.h"
00032 #include <dnssd/publicservice.h>
00033
00034 #include <kdebug.h>
00035
00036 #include <qbuffer.h>
00037
00038
00039 class KGameNetworkPrivate
00040 {
00041 public:
00042 KGameNetworkPrivate()
00043 {
00044 mMessageClient = 0;
00045 mMessageServer = 0;
00046 mDisconnectId = 0;
00047 mService = 0;
00048 }
00049
00050 public:
00051 KMessageClient* mMessageClient;
00052 KMessageServer* mMessageServer;
00053 Q_UINT32 mDisconnectId;
00054 DNSSD::PublicService* mService;
00055 QString mType;
00056 QString mName;
00057
00058 int mCookie;
00059 };
00060
00061
00062 KGameNetwork::KGameNetwork(int c, QObject* parent) : QObject(parent, 0)
00063 {
00064 d = new KGameNetworkPrivate;
00065 d->mCookie = (Q_INT16)c;
00066
00067
00068
00069 setMaster();
00070
00071 kdDebug(11001) << k_funcinfo << "this=" << this <<", cookie=" << cookie() << " sizeof(this)="<<sizeof(KGameNetwork) << endl;
00072 }
00073
00074 KGameNetwork::~KGameNetwork()
00075 {
00076 kdDebug(11001) << k_funcinfo << "this=" << this << endl;
00077
00078 delete d->mService;
00079 delete d;
00080 }
00081
00082
00083 bool KGameNetwork::isNetwork() const
00084 { return isOfferingConnections() || d->mMessageClient->isNetwork();}
00085
00086 Q_UINT32 KGameNetwork::gameId() const
00087 {
00088
00089
00090
00091 if (d->mMessageClient->id()!=0 ) {
00092 return d->mMessageClient->id() ;
00093 } else {
00094 return d->mDisconnectId;
00095 }
00096 }
00097
00098 int KGameNetwork::cookie() const
00099 { return d->mCookie; }
00100
00101 bool KGameNetwork::isMaster() const
00102 { return (d->mMessageServer != 0); }
00103
00104 bool KGameNetwork::isAdmin() const
00105 { return (d->mMessageClient->isAdmin()); }
00106
00107 KMessageClient* KGameNetwork::messageClient() const
00108 { return d->mMessageClient; }
00109
00110 KMessageServer* KGameNetwork::messageServer() const
00111 { return d->mMessageServer; }
00112
00113
00114 void KGameNetwork::setMaster()
00115 {
00116 if (!d->mMessageServer) {
00117 d->mMessageServer = new KMessageServer (cookie(), this);
00118 } else {
00119 kdWarning(11001) << k_funcinfo << "Server already running!!" << endl;
00120 }
00121 if (!d->mMessageClient) {
00122 d->mMessageClient = new KMessageClient (this);
00123 connect (d->mMessageClient, SIGNAL(broadcastReceived(const QByteArray&, Q_UINT32)),
00124 this, SLOT(receiveNetworkTransmission(const QByteArray&, Q_UINT32)));
00125 connect (d->mMessageClient, SIGNAL(connectionBroken()),
00126 this, SIGNAL(signalConnectionBroken()));
00127 connect (d->mMessageClient, SIGNAL(aboutToDisconnect(Q_UINT32)),
00128 this, SLOT(aboutToLoseConnection(Q_UINT32)));
00129 connect (d->mMessageClient, SIGNAL(connectionBroken()),
00130 this, SLOT(slotResetConnection()));
00131
00132 connect (d->mMessageClient, SIGNAL(adminStatusChanged(bool)),
00133 this, SLOT(slotAdminStatusChanged(bool)));
00134 connect (d->mMessageClient, SIGNAL(eventClientConnected(Q_UINT32)),
00135 this, SIGNAL(signalClientConnected(Q_UINT32)));
00136 connect (d->mMessageClient, SIGNAL(eventClientDisconnected(Q_UINT32, bool)),
00137 this, SIGNAL(signalClientDisconnected(Q_UINT32, bool)));
00138
00139
00140 connect (d->mMessageClient, SIGNAL(forwardReceived(const QByteArray&, Q_UINT32, const QValueList<Q_UINT32>&)),
00141 d->mMessageClient, SIGNAL(broadcastReceived(const QByteArray&, Q_UINT32)));
00142
00143 } else {
00144
00145 kdDebug(11001) << k_funcinfo << "Client already exists!" << endl;
00146 }
00147 d->mMessageClient->setServer(d->mMessageServer);
00148 }
00149
00150 void KGameNetwork::setDiscoveryInfo(const QString& type, const QString& name)
00151 {
00152 kdDebug() << k_funcinfo << type << ":" << name << endl;
00153 d->mType = type;
00154 d->mName = name;
00155 tryPublish();
00156 }
00157
00158 void KGameNetwork::tryPublish()
00159 {
00160 if (d->mType.isNull() || !isOfferingConnections()) return;
00161 if (!d->mService) d->mService = new DNSSD::PublicService(d->mName,d->mType,port());
00162 else {
00163 if (d->mType!=d->mService->type()) d->mService->setType(d->mType);
00164 if (d->mName!=d->mService->serviceName()) d->mService->setServiceName(d->mName);
00165 }
00166 if (!d->mService->isPublished()) d->mService->publishAsync();
00167 }
00168
00169 void KGameNetwork::tryStopPublishing()
00170 {
00171 if (d->mService) d->mService->stop();
00172 }
00173
00174 bool KGameNetwork::offerConnections(Q_UINT16 port)
00175 {
00176 kdDebug (11001) << k_funcinfo << "on port " << port << endl;
00177 if (!isMaster()) {
00178 setMaster();
00179 }
00180
00181
00182 d->mDisconnectId = 0;
00183
00184
00185 if (d->mMessageServer && d->mMessageServer->isOfferingConnections()) {
00186 kdDebug (11001) << k_funcinfo << "Already running as server! Changing the port now!" << endl;
00187 }
00188
00189 tryStopPublishing();
00190 kdDebug (11001) << k_funcinfo << "before Server->initNetwork" << endl;
00191 if (!d->mMessageServer->initNetwork (port)) {
00192 kdError (11001) << k_funcinfo << "Unable to bind to port " << port << "!" << endl;
00193
00194
00195
00196
00197 return false;
00198 }
00199 kdDebug (11001) << k_funcinfo << "after Server->initNetwork" << endl;
00200 tryPublish();
00201 return true;
00202 }
00203
00204 bool KGameNetwork::connectToServer (const QString& host, Q_UINT16 port)
00205 {
00206 if (host.isEmpty()) {
00207 kdError(11001) << k_funcinfo << "No hostname given" << endl;
00208 return false;
00209 }
00210
00211
00212 d->mDisconnectId = 0;
00213
00214
00215
00216
00218
00219 if (d->mMessageServer) {
00220
00221 kdWarning(11001) << "we are server but we are trying to connect to another server! "
00222 << "make sure that all clients connect to that server! "
00223 << "quitting the local server now..." << endl;
00224 stopServerConnection();
00225 d->mMessageClient->setServer((KMessageIO*)0);
00226 delete d->mMessageServer;
00227 d->mMessageServer = 0;
00228 }
00229
00230 kdDebug(11001) << " about to set server" << endl;
00231 d->mMessageClient->setServer(host, port);
00232 emit signalAdminStatusChanged(false);
00233
00234
00235
00236
00237
00238 kdDebug(11001) << "connected to " << host << ":" << port << endl;
00239 return true;
00240 }
00241
00242 Q_UINT16 KGameNetwork::port() const
00243 {
00244 if (isNetwork()) {
00245 if (isOfferingConnections()) {
00246 return d->mMessageServer->serverPort();
00247 } else {
00248 return d->mMessageClient->peerPort();
00249 }
00250 }
00251 return 0;
00252 }
00253
00254 QString KGameNetwork::hostName() const
00255 {
00256 return d->mMessageClient->peerName();
00257 }
00258
00259 bool KGameNetwork::stopServerConnection()
00260 {
00261
00262 tryStopPublishing();
00263 if (d->mMessageServer) {
00264 d->mMessageServer->stopNetwork();
00265 return true;
00266 }
00267 return false;
00268 }
00269
00270 bool KGameNetwork::isOfferingConnections() const
00271 { return (d->mMessageServer && d->mMessageServer->isOfferingConnections()); }
00272
00273 void KGameNetwork::disconnect()
00274 {
00275
00276 kdDebug(11001) << k_funcinfo << endl;
00277 stopServerConnection();
00278 if (d->mMessageServer) {
00279 QValueList <Q_UINT32> list=d->mMessageServer->clientIDs();
00280 QValueList<Q_UINT32>::Iterator it;
00281 for( it = list.begin(); it != list.end(); ++it )
00282 {
00283 kdDebug(11001) << "Client id=" << (*it) << endl;
00284 KMessageIO *client=d->mMessageServer->findClient(*it);
00285 if (!client)
00286 {
00287 continue;
00288 }
00289 kdDebug(11001) << " rtti=" << client->rtti() << endl;
00290 if (client->rtti()==2)
00291 {
00292 kdDebug(11001) << "DIRECT IO " << endl;
00293 }
00294 else
00295 {
00296 d->mMessageServer->removeClient(client,false);
00297 }
00298 }
00299 }
00300 else
00301 {
00302 kdDebug(11001) << k_funcinfo << "before client->disconnect() id="<<gameId()<< endl;
00303
00304 kdDebug(11001) << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++"<<endl;
00305 d->mMessageClient->disconnect();
00306
00307 kdDebug(11001) << "++++++--------------------------------------------+++++"<<endl;
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 kdDebug(11001) << k_funcinfo << "DONE" << endl;
00321 }
00322
00323 void KGameNetwork::aboutToLoseConnection(Q_UINT32 clientID)
00324 {
00325 kdDebug(11001) << "Storing client id of connection "<<clientID<<endl;
00326 d->mDisconnectId = clientID;
00327 }
00328
00329 void KGameNetwork::slotResetConnection()
00330 {
00331 kdDebug(11001) << "Resseting client disconnect id"<<endl;
00332 d->mDisconnectId = 0;
00333 }
00334
00335 void KGameNetwork::electAdmin(Q_UINT32 clientID)
00336 {
00337 if (!isAdmin()) {
00338 kdWarning(11001) << k_funcinfo << "only ADMIN is allowed to call this!" << endl;
00339 return;
00340 }
00341 QByteArray buffer;
00342 QDataStream stream(buffer,IO_WriteOnly);
00343 stream << static_cast<Q_UINT32>( KMessageServer::REQ_ADMIN_CHANGE );
00344 stream << clientID;
00345 d->mMessageClient->sendServerMessage(buffer);
00346 }
00347
00348 void KGameNetwork::setMaxClients(int max)
00349 {
00350 if (!isAdmin()) {
00351 kdWarning(11001) << k_funcinfo << "only ADMIN is allowed to call this!" << endl;
00352 return;
00353 }
00354 QByteArray buffer;
00355 QDataStream stream(buffer,IO_WriteOnly);
00356 stream << static_cast<Q_UINT32>( KMessageServer::REQ_MAX_NUM_CLIENTS );
00357 stream << (Q_INT32)max;
00358 d->mMessageClient->sendServerMessage(buffer);
00359 }
00360
00361 void KGameNetwork::lock()
00362 {
00363 if (messageClient()) {
00364 messageClient()->lock();
00365 }
00366 }
00367
00368 void KGameNetwork::unlock()
00369 {
00370 if (messageClient()) {
00371 messageClient()->unlock();
00372 }
00373 }
00374
00375
00376
00377 bool KGameNetwork::sendSystemMessage(int data, int msgid, Q_UINT32 receiver, Q_UINT32 sender)
00378 {
00379 QByteArray buffer;
00380 QDataStream stream(buffer,IO_WriteOnly);
00381 stream << data;
00382 return sendSystemMessage(buffer,msgid,receiver,sender);
00383 }
00384
00385 bool KGameNetwork::sendSystemMessage(const QString &msg, int msgid, Q_UINT32 receiver, Q_UINT32 sender)
00386 {
00387 QByteArray buffer;
00388 QDataStream stream(buffer, IO_WriteOnly);
00389 stream << msg;
00390 return sendSystemMessage(buffer, msgid, receiver, sender);
00391 }
00392
00393 bool KGameNetwork::sendSystemMessage(const QDataStream &msg, int msgid, Q_UINT32 receiver, Q_UINT32 sender)
00394 { return sendSystemMessage(((QBuffer*)msg.device())->buffer(), msgid, receiver, sender); }
00395
00396 bool KGameNetwork::sendSystemMessage(const QByteArray& data, int msgid, Q_UINT32 receiver, Q_UINT32 sender)
00397 {
00398 QByteArray buffer;
00399 QDataStream stream(buffer,IO_WriteOnly);
00400 if (!sender) {
00401 sender = gameId();
00402 }
00403
00404 Q_UINT32 receiverClient = KGameMessage::rawGameId(receiver);
00405 int receiverPlayer = KGameMessage::rawPlayerId(receiver);
00406
00407 KGameMessage::createHeader(stream, sender, receiver, msgid);
00408 stream.writeRawBytes(data.data(), data.size());
00409
00410
00411
00412
00413
00414
00415
00416 if (!d->mMessageClient) {
00417
00418
00419
00420 kdWarning (11001) << k_funcinfo << "We don't have a client! Should never happen!" << endl;
00421 return false;
00422 }
00423
00424 if (receiverClient == 0 || receiverPlayer != 0)
00425 {
00426
00427
00428
00429 d->mMessageClient->sendBroadcast(buffer);
00430 }
00431 else
00432 {
00433 d->mMessageClient->sendForward(buffer, receiverClient);
00434 }
00435 return true;
00436 }
00437
00438 bool KGameNetwork::sendMessage(int data, int msgid, Q_UINT32 receiver, Q_UINT32 sender)
00439 { return sendSystemMessage(data,msgid+KGameMessage::IdUser,receiver,sender); }
00440
00441 bool KGameNetwork::sendMessage(const QString &msg, int msgid, Q_UINT32 receiver, Q_UINT32 sender)
00442 { return sendSystemMessage(msg,msgid+KGameMessage::IdUser,receiver,sender); }
00443
00444 bool KGameNetwork::sendMessage(const QDataStream &msg, int msgid, Q_UINT32 receiver, Q_UINT32 sender)
00445 { return sendSystemMessage(msg, msgid+KGameMessage::IdUser, receiver, sender); }
00446
00447 bool KGameNetwork::sendMessage(const QByteArray &msg, int msgid, Q_UINT32 receiver, Q_UINT32 sender)
00448 { return sendSystemMessage(msg, msgid+KGameMessage::IdUser, receiver, sender); }
00449
00450 void KGameNetwork::sendError(int error,const QByteArray& message, Q_UINT32 receiver, Q_UINT32 sender)
00451 {
00452 QByteArray buffer;
00453 QDataStream stream(buffer,IO_WriteOnly);
00454 stream << (Q_INT32) error;
00455 stream.writeRawBytes(message.data(), message.size());
00456 sendSystemMessage(stream,KGameMessage::IdError,receiver,sender);
00457 }
00458
00459
00460
00461 void KGameNetwork::receiveNetworkTransmission(const QByteArray& receiveBuffer, Q_UINT32 clientID)
00462 {
00463 QDataStream stream(receiveBuffer, IO_ReadOnly);
00464 int msgid;
00465 Q_UINT32 sender;
00466 Q_UINT32 receiver;
00467 KGameMessage::extractHeader(stream, sender, receiver, msgid);
00468
00469
00470
00471
00472
00473 if (receiver && receiver!=gameId() && !KGameMessage::isPlayer(receiver) )
00474 {
00475
00476 kdDebug(11001) << k_funcinfo << "Message not meant for us "
00477 << gameId() << "!=" << receiver << " rawid="
00478 << KGameMessage::rawGameId(receiver) << endl;
00479 return;
00480 }
00481 else if (msgid==KGameMessage::IdError)
00482 {
00483 QString text;
00484 Q_INT32 error;
00485 stream >> error;
00486 kdDebug(11001) << k_funcinfo << "Got IdError " << error << endl;
00487 text = KGameError::errorText(error, stream);
00488 kdDebug(11001) << "Error text: " << text.latin1() << endl;
00489 emit signalNetworkErrorMessage((int)error,text);
00490 }
00491 else
00492 {
00493 networkTransmission(stream, msgid, receiver, sender, clientID);
00494 }
00495 }
00496
00497
00498 void KGameNetwork::slotAdminStatusChanged(bool isAdmin)
00499 {
00500 emit signalAdminStatusChanged(isAdmin);
00501
00502
00503 }
00504
00505 void KGameNetwork::Debug()
00506 {
00507 kdDebug(11001) << "------------------- KNETWORKGAME -------------------------" << endl;
00508 kdDebug(11001) << "gameId " << gameId() << endl;
00509 kdDebug(11001) << "gameMaster " << isMaster() << endl;
00510 kdDebug(11001) << "gameAdmin " << isAdmin() << endl;
00511 kdDebug(11001) << "---------------------------------------------------" << endl;
00512 }
00513
00514
00515
00516