| 1 | /* | 
|---|
| 2 |    orxonox - the future of 3D-vertical-scrollers | 
|---|
| 3 |  | 
|---|
| 4 |    Copyright (C) 2004 orx | 
|---|
| 5 |  | 
|---|
| 6 |    This program is free software; you can redistribute it and/or modify | 
|---|
| 7 |    it under the terms of the GNU General Public License as published by | 
|---|
| 8 |    the Free Software Foundation; either version 2, or (at your option) | 
|---|
| 9 |    any later version. | 
|---|
| 10 |  | 
|---|
| 11 | ### File Specific: | 
|---|
| 12 |    main-programmer: claudio | 
|---|
| 13 |    co-programmer: | 
|---|
| 14 | */ | 
|---|
| 15 |  | 
|---|
| 16 |  | 
|---|
| 17 | /* this is for debug output. It just says, that all calls to PRINT() belong to the DEBUG_MODULE_NETWORK module | 
|---|
| 18 |    For more information refere to https://www.orxonox.net/cgi-bin/trac.cgi/wiki/DebugOutput | 
|---|
| 19 | */ | 
|---|
| 20 | #define DEBUG_MODULE_NETWORK | 
|---|
| 21 |  | 
|---|
| 22 |  | 
|---|
| 23 | #include "base_object.h" | 
|---|
| 24 | #include "network_protocol.h" | 
|---|
| 25 | #include "udp_socket.h" | 
|---|
| 26 | #include "udp_server_socket.h" | 
|---|
| 27 | #include "connection_monitor.h" | 
|---|
| 28 | #include "synchronizeable.h" | 
|---|
| 29 | #include "network_game_manager.h" | 
|---|
| 30 | #include "shared_network_data.h" | 
|---|
| 31 | #include "message_manager.h" | 
|---|
| 32 | #include "preferences.h" | 
|---|
| 33 | #include "zip.h" | 
|---|
| 34 |  | 
|---|
| 35 | #include "src/lib/util/loading/resource_manager.h" | 
|---|
| 36 |  | 
|---|
| 37 | #include "network_log.h" | 
|---|
| 38 |  | 
|---|
| 39 |  | 
|---|
| 40 | #include "lib/util/loading/factory.h" | 
|---|
| 41 |  | 
|---|
| 42 | #include "debug.h" | 
|---|
| 43 | #include "class_list.h" | 
|---|
| 44 | #include <algorithm> | 
|---|
| 45 |  | 
|---|
| 46 | /* include your own header */ | 
|---|
| 47 | #include "network_stream.h" | 
|---|
| 48 |  | 
|---|
| 49 | /* probably unnecessary */ | 
|---|
| 50 | using namespace std; | 
|---|
| 51 |  | 
|---|
| 52 |  | 
|---|
| 53 | #define PACKAGE_SIZE  256 | 
|---|
| 54 |  | 
|---|
| 55 |  | 
|---|
| 56 | NetworkStream::NetworkStream() | 
|---|
| 57 |     : DataStream() | 
|---|
| 58 | { | 
|---|
| 59 |   this->init(); | 
|---|
| 60 |   /* initialize the references */ | 
|---|
| 61 |   this->type = NET_CLIENT; | 
|---|
| 62 | } | 
|---|
| 63 |  | 
|---|
| 64 |  | 
|---|
| 65 | NetworkStream::NetworkStream( std::string host, int port ) | 
|---|
| 66 | { | 
|---|
| 67 |   this->type = NET_CLIENT; | 
|---|
| 68 |   this->init(); | 
|---|
| 69 |   this->peers[0].socket = new UdpSocket( host, port ); | 
|---|
| 70 |   this->peers[0].userId = 0; | 
|---|
| 71 |   this->peers[0].isServer = true; | 
|---|
| 72 |   this->peers[0].connectionMonitor = new ConnectionMonitor( 0 ); | 
|---|
| 73 | } | 
|---|
| 74 |  | 
|---|
| 75 |  | 
|---|
| 76 | NetworkStream::NetworkStream( int port ) | 
|---|
| 77 | { | 
|---|
| 78 |   this->type = NET_SERVER; | 
|---|
| 79 |   this->init(); | 
|---|
| 80 |   this->serverSocket = new UdpServerSocket(port); | 
|---|
| 81 |   this->bActive = true; | 
|---|
| 82 | } | 
|---|
| 83 |  | 
|---|
| 84 |  | 
|---|
| 85 | void NetworkStream::init() | 
|---|
| 86 | { | 
|---|
| 87 |   /* set the class id for the base object */ | 
|---|
| 88 |   this->setClassID(CL_NETWORK_STREAM, "NetworkStream"); | 
|---|
| 89 |   this->bActive = false; | 
|---|
| 90 |   this->serverSocket = NULL; | 
|---|
| 91 |   this->networkGameManager = NULL; | 
|---|
| 92 |   myHostId = 0; | 
|---|
| 93 |   currentState = 0; | 
|---|
| 94 |    | 
|---|
| 95 |   remainingBytesToWriteToDict = Preferences::getInstance()->getInt( "compression", "writedict", 0 ); | 
|---|
| 96 |    | 
|---|
| 97 |   assert( Zip::getInstance()->loadDictionary( "testdict" ) >= 0 ); | 
|---|
| 98 |   this->dictClient = Zip::getInstance()->loadDictionary( "dict2pl_client" ); | 
|---|
| 99 |   assert( this->dictClient >= 0 ); | 
|---|
| 100 |   this->dictServer = Zip::getInstance()->loadDictionary( "dict2p_server" ); | 
|---|
| 101 |   assert( this->dictServer >= 0 ); | 
|---|
| 102 | } | 
|---|
| 103 |  | 
|---|
| 104 |  | 
|---|
| 105 | NetworkStream::~NetworkStream() | 
|---|
| 106 | { | 
|---|
| 107 |   if ( this->serverSocket ) | 
|---|
| 108 |   { | 
|---|
| 109 |     serverSocket->close(); | 
|---|
| 110 |     delete serverSocket; | 
|---|
| 111 |     serverSocket = NULL; | 
|---|
| 112 |   } | 
|---|
| 113 |  | 
|---|
| 114 |   for ( PeerList::iterator i = peers.begin(); i!=peers.end(); i++) | 
|---|
| 115 |   { | 
|---|
| 116 |     if ( i->second.socket ) | 
|---|
| 117 |     { | 
|---|
| 118 |       i->second.socket->disconnectServer(); | 
|---|
| 119 |       delete i->second.socket; | 
|---|
| 120 |       i->second.socket = NULL; | 
|---|
| 121 |     } | 
|---|
| 122 |      | 
|---|
| 123 |     if ( i->second.handshake ) | 
|---|
| 124 |     { | 
|---|
| 125 |       delete i->second.handshake; | 
|---|
| 126 |       i->second.handshake = NULL; | 
|---|
| 127 |     } | 
|---|
| 128 |      | 
|---|
| 129 |     if ( i->second.connectionMonitor ) | 
|---|
| 130 |     { | 
|---|
| 131 |       delete i->second.connectionMonitor; | 
|---|
| 132 |       i->second.connectionMonitor = NULL; | 
|---|
| 133 |     } | 
|---|
| 134 |   } | 
|---|
| 135 |    | 
|---|
| 136 |   for ( SynchronizeableList::const_iterator it = getSyncBegin(); it != getSyncEnd(); it ++ ) | 
|---|
| 137 |     (*it)->setNetworkStream( NULL ); | 
|---|
| 138 | } | 
|---|
| 139 |  | 
|---|
| 140 |  | 
|---|
| 141 | void NetworkStream::createNetworkGameManager() | 
|---|
| 142 | { | 
|---|
| 143 |   this->networkGameManager = NetworkGameManager::getInstance(); | 
|---|
| 144 |   // setUniqueID( maxCon+2 ) because we need one id for every handshake | 
|---|
| 145 |   // and one for handshake to reject client maxCon+1 | 
|---|
| 146 |   this->networkGameManager->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() ); | 
|---|
| 147 |   MessageManager::getInstance()->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() ); | 
|---|
| 148 | } | 
|---|
| 149 |  | 
|---|
| 150 |  | 
|---|
| 151 | void NetworkStream::startHandshake() | 
|---|
| 152 | { | 
|---|
| 153 |   Handshake* hs = new Handshake(false); | 
|---|
| 154 |   hs->setUniqueID( 0 ); | 
|---|
| 155 |   assert( peers[0].handshake == NULL ); | 
|---|
| 156 |   peers[0].handshake = hs; | 
|---|
| 157 | //   peers[0].handshake->setSynchronized( true ); | 
|---|
| 158 |   //this->connectSynchronizeable(*hs); | 
|---|
| 159 |   //this->connectSynchronizeable(*hs); | 
|---|
| 160 |   PRINTF(0)("NetworkStream: Handshake created: %s\n", hs->getName()); | 
|---|
| 161 | } | 
|---|
| 162 |  | 
|---|
| 163 |  | 
|---|
| 164 | void NetworkStream::connectSynchronizeable(Synchronizeable& sync) | 
|---|
| 165 | { | 
|---|
| 166 |   this->synchronizeables.push_back(&sync); | 
|---|
| 167 |   sync.setNetworkStream( this ); | 
|---|
| 168 |  | 
|---|
| 169 |   this->bActive = true; | 
|---|
| 170 | } | 
|---|
| 171 |  | 
|---|
| 172 |  | 
|---|
| 173 | void NetworkStream::disconnectSynchronizeable(Synchronizeable& sync) | 
|---|
| 174 | { | 
|---|
| 175 |   // removing the Synchronizeable from the List. | 
|---|
| 176 |   std::list<Synchronizeable*>::iterator disconnectSynchro = std::find(this->synchronizeables.begin(), this->synchronizeables.end(), &sync); | 
|---|
| 177 |   if (disconnectSynchro != this->synchronizeables.end()) | 
|---|
| 178 |     this->synchronizeables.erase(disconnectSynchro); | 
|---|
| 179 |    | 
|---|
| 180 |   oldSynchronizeables[sync.getUniqueID()] = SDL_GetTicks(); | 
|---|
| 181 | } | 
|---|
| 182 |  | 
|---|
| 183 |  | 
|---|
| 184 | void NetworkStream::processData() | 
|---|
| 185 | { | 
|---|
| 186 |   int tick = SDL_GetTicks(); | 
|---|
| 187 |    | 
|---|
| 188 |   currentState++; | 
|---|
| 189 |    | 
|---|
| 190 |   if ( this->type == NET_SERVER ) | 
|---|
| 191 |   { | 
|---|
| 192 |     if ( serverSocket ) | 
|---|
| 193 |       serverSocket->update(); | 
|---|
| 194 |      | 
|---|
| 195 |     this->updateConnectionList(); | 
|---|
| 196 |   } | 
|---|
| 197 |   else | 
|---|
| 198 |   { | 
|---|
| 199 |     if ( peers[0].socket && ( !peers[0].socket->isOk() || peers[0].connectionMonitor->hasTimedOut() ) ) | 
|---|
| 200 |     { | 
|---|
| 201 |       PRINTF(1)("lost connection to server\n"); | 
|---|
| 202 |  | 
|---|
| 203 |       peers[0].socket->disconnectServer(); | 
|---|
| 204 |       delete peers[0].socket; | 
|---|
| 205 |       peers[0].socket = NULL; | 
|---|
| 206 |  | 
|---|
| 207 |       if ( peers[0].handshake ) | 
|---|
| 208 |         delete peers[0].handshake; | 
|---|
| 209 |       peers[0].handshake = NULL; | 
|---|
| 210 |        | 
|---|
| 211 |       if ( peers[0].connectionMonitor ) | 
|---|
| 212 |         delete peers[0].connectionMonitor; | 
|---|
| 213 |       peers[0].connectionMonitor = NULL; | 
|---|
| 214 |     } | 
|---|
| 215 |   } | 
|---|
| 216 |  | 
|---|
| 217 |   cleanUpOldSyncList(); | 
|---|
| 218 |   handleHandshakes(); | 
|---|
| 219 |    | 
|---|
| 220 |   // order of up/downstream is important!!!! | 
|---|
| 221 |   // don't change it | 
|---|
| 222 |   handleDownstream( tick ); | 
|---|
| 223 |   handleUpstream( tick ); | 
|---|
| 224 |  | 
|---|
| 225 | } | 
|---|
| 226 |  | 
|---|
| 227 | void NetworkStream::updateConnectionList( ) | 
|---|
| 228 | { | 
|---|
| 229 |   //check for new connections | 
|---|
| 230 |  | 
|---|
| 231 |   NetworkSocket* tempNetworkSocket = serverSocket->getNewSocket(); | 
|---|
| 232 |  | 
|---|
| 233 |   if ( tempNetworkSocket ) | 
|---|
| 234 |   { | 
|---|
| 235 |     int clientId; | 
|---|
| 236 |     if ( freeSocketSlots.size() >0 ) | 
|---|
| 237 |     { | 
|---|
| 238 |       clientId = freeSocketSlots.back(); | 
|---|
| 239 |       freeSocketSlots.pop_back(); | 
|---|
| 240 |       peers[clientId].socket = tempNetworkSocket; | 
|---|
| 241 |       peers[clientId].handshake = new Handshake(true, clientId, this->networkGameManager->getUniqueID(), MessageManager::getInstance()->getUniqueID() ); | 
|---|
| 242 |       peers[clientId].connectionMonitor = new ConnectionMonitor( clientId ); | 
|---|
| 243 |       peers[clientId].handshake->setUniqueID(clientId); | 
|---|
| 244 |       peers[clientId].userId = clientId; | 
|---|
| 245 |       peers[clientId].isServer = false; | 
|---|
| 246 |     } else | 
|---|
| 247 |     { | 
|---|
| 248 |       clientId = 1; | 
|---|
| 249 |        | 
|---|
| 250 |       for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ ) | 
|---|
| 251 |         if ( it->first >= clientId ) | 
|---|
| 252 |           clientId = it->first + 1; | 
|---|
| 253 |        | 
|---|
| 254 |       peers[clientId].socket = tempNetworkSocket; | 
|---|
| 255 |       peers[clientId].handshake = new Handshake(true, clientId, this->networkGameManager->getUniqueID(), MessageManager::getInstance()->getUniqueID()); | 
|---|
| 256 |       peers[clientId].handshake->setUniqueID(clientId); | 
|---|
| 257 |       peers[clientId].connectionMonitor = new ConnectionMonitor( clientId ); | 
|---|
| 258 |       peers[clientId].userId = clientId; | 
|---|
| 259 |       peers[clientId].isServer = false; | 
|---|
| 260 |        | 
|---|
| 261 |       PRINTF(0)("num sync: %d\n", synchronizeables.size()); | 
|---|
| 262 |     } | 
|---|
| 263 |  | 
|---|
| 264 |     if ( clientId > MAX_CONNECTIONS ) | 
|---|
| 265 |     { | 
|---|
| 266 |       peers[clientId].handshake->doReject( "too many connections" ); | 
|---|
| 267 |       PRINTF(0)("Will reject client %d because there are to many connections!\n", clientId); | 
|---|
| 268 |     } | 
|---|
| 269 |     else | 
|---|
| 270 |  | 
|---|
| 271 |     PRINTF(0)("New Client: %d\n", clientId); | 
|---|
| 272 |  | 
|---|
| 273 |     //this->connectSynchronizeable(*handshakes[clientId]); | 
|---|
| 274 |   } | 
|---|
| 275 |  | 
|---|
| 276 |   //check if connections are ok else remove them | 
|---|
| 277 |   for ( PeerList::iterator it = peers.begin(); it != peers.end(); ) | 
|---|
| 278 |   { | 
|---|
| 279 |     if (   | 
|---|
| 280 |           it->second.socket && | 
|---|
| 281 |           (  | 
|---|
| 282 |             !it->second.socket->isOk()  || | 
|---|
| 283 |             it->second.connectionMonitor->hasTimedOut() | 
|---|
| 284 |           ) | 
|---|
| 285 |        ) | 
|---|
| 286 |     { | 
|---|
| 287 |       std::string reason = "disconnected"; | 
|---|
| 288 |       if ( it->second.connectionMonitor->hasTimedOut() ) | 
|---|
| 289 |         reason = "timeout"; | 
|---|
| 290 |       PRINTF(0)("Client is gone: %d (%s)\n", it->second.userId, reason.c_str()); | 
|---|
| 291 |        | 
|---|
| 292 |       //assert(false); | 
|---|
| 293 |  | 
|---|
| 294 |       it->second.socket->disconnectServer(); | 
|---|
| 295 |       delete it->second.socket; | 
|---|
| 296 |       it->second.socket = NULL; | 
|---|
| 297 |  | 
|---|
| 298 |       if ( it->second.connectionMonitor ) | 
|---|
| 299 |         delete it->second.connectionMonitor; | 
|---|
| 300 |       it->second.connectionMonitor = NULL; | 
|---|
| 301 |        | 
|---|
| 302 |       if ( it->second.handshake ) | 
|---|
| 303 |         delete it->second.handshake; | 
|---|
| 304 |       it->second.handshake = NULL; | 
|---|
| 305 |        | 
|---|
| 306 |       for ( SynchronizeableList::iterator it2 = synchronizeables.begin(); it2 != synchronizeables.end(); it2++ ) | 
|---|
| 307 |       { | 
|---|
| 308 |         (*it2)->cleanUpUser( it->second.userId ); | 
|---|
| 309 |       } | 
|---|
| 310 |  | 
|---|
| 311 |       NetworkGameManager::getInstance()->signalLeftPlayer(it->second.userId); | 
|---|
| 312 |  | 
|---|
| 313 |       freeSocketSlots.push_back( it->second.userId ); | 
|---|
| 314 |        | 
|---|
| 315 |       PeerList::iterator delit = it; | 
|---|
| 316 |       it++; | 
|---|
| 317 |        | 
|---|
| 318 |       peers.erase( delit ); | 
|---|
| 319 |        | 
|---|
| 320 |       continue; | 
|---|
| 321 |     } | 
|---|
| 322 |      | 
|---|
| 323 |     it++; | 
|---|
| 324 |   } | 
|---|
| 325 |  | 
|---|
| 326 |  | 
|---|
| 327 | } | 
|---|
| 328 |  | 
|---|
| 329 | void NetworkStream::debug() | 
|---|
| 330 | { | 
|---|
| 331 |   if( this->isServer()) | 
|---|
| 332 |     PRINT(0)(" Host ist Server with ID: %i\n", this->myHostId); | 
|---|
| 333 |   else | 
|---|
| 334 |     PRINT(0)(" Host ist Client with ID: %i\n", this->myHostId); | 
|---|
| 335 |  | 
|---|
| 336 |   PRINT(0)(" Got %i connected Synchronizeables, showing active Syncs:\n", this->synchronizeables.size()); | 
|---|
| 337 |   for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++) | 
|---|
| 338 |   { | 
|---|
| 339 |     if( (*it)->beSynchronized() == true) | 
|---|
| 340 |       PRINT(0)("  Synchronizeable of class: %s::%s, with unique ID: %i, Synchronize: %i\n", (*it)->getClassName(), (*it)->getName(), | 
|---|
| 341 |                (*it)->getUniqueID(), (*it)->beSynchronized()); | 
|---|
| 342 |   } | 
|---|
| 343 |   PRINT(0)(" Maximal Connections: %i\n", MAX_CONNECTIONS ); | 
|---|
| 344 |  | 
|---|
| 345 | } | 
|---|
| 346 |  | 
|---|
| 347 |  | 
|---|
| 348 | int NetworkStream::getSyncCount() | 
|---|
| 349 | { | 
|---|
| 350 |   int n = 0; | 
|---|
| 351 |   for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++) | 
|---|
| 352 |     if( (*it)->beSynchronized() == true) | 
|---|
| 353 |       ++n; | 
|---|
| 354 |  | 
|---|
| 355 |   //return synchronizeables.size(); | 
|---|
| 356 |   return n; | 
|---|
| 357 | } | 
|---|
| 358 |  | 
|---|
| 359 | /** | 
|---|
| 360 |  * check if handshakes completed | 
|---|
| 361 |  */ | 
|---|
| 362 | void NetworkStream::handleHandshakes( ) | 
|---|
| 363 | { | 
|---|
| 364 |   for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ ) | 
|---|
| 365 |   { | 
|---|
| 366 |     if ( it->second.handshake ) | 
|---|
| 367 |     { | 
|---|
| 368 |       if ( it->second.handshake->completed() ) | 
|---|
| 369 |       { | 
|---|
| 370 |         if ( it->second.handshake->ok() ) | 
|---|
| 371 |         { | 
|---|
| 372 |           if ( !it->second.handshake->allowDel() ) | 
|---|
| 373 |           { | 
|---|
| 374 |             if ( type != NET_SERVER ) | 
|---|
| 375 |             { | 
|---|
| 376 |               SharedNetworkData::getInstance()->setHostID( it->second.handshake->getHostId() ); | 
|---|
| 377 |               myHostId = SharedNetworkData::getInstance()->getHostID(); | 
|---|
| 378 |  | 
|---|
| 379 |               this->networkGameManager = NetworkGameManager::getInstance(); | 
|---|
| 380 |               this->networkGameManager->setUniqueID( it->second.handshake->getNetworkGameManagerId() ); | 
|---|
| 381 |               MessageManager::getInstance()->setUniqueID( it->second.handshake->getMessageManagerId() ); | 
|---|
| 382 |             } | 
|---|
| 383 |                | 
|---|
| 384 |  | 
|---|
| 385 |             PRINT(0)("handshake finished id=%d\n", it->second.handshake->getNetworkGameManagerId()); | 
|---|
| 386 |  | 
|---|
| 387 |             it->second.handshake->del(); | 
|---|
| 388 |           } | 
|---|
| 389 |           else | 
|---|
| 390 |           { | 
|---|
| 391 |             if ( it->second.handshake->canDel() ) | 
|---|
| 392 |             { | 
|---|
| 393 |               if ( type == NET_SERVER ) | 
|---|
| 394 |               { | 
|---|
| 395 |                 handleNewClient( it->second.userId ); | 
|---|
| 396 |               } | 
|---|
| 397 |                | 
|---|
| 398 |               PRINT(0)("handshake finished delete it\n"); | 
|---|
| 399 |               delete it->second.handshake; | 
|---|
| 400 |               it->second.handshake = NULL; | 
|---|
| 401 |             } | 
|---|
| 402 |           } | 
|---|
| 403 |  | 
|---|
| 404 |         } | 
|---|
| 405 |         else | 
|---|
| 406 |         { | 
|---|
| 407 |           PRINT(1)("handshake failed!\n"); | 
|---|
| 408 |           it->second.socket->disconnectServer(); | 
|---|
| 409 |         } | 
|---|
| 410 |       } | 
|---|
| 411 |     } | 
|---|
| 412 |   } | 
|---|
| 413 | } | 
|---|
| 414 |  | 
|---|
| 415 | /** | 
|---|
| 416 |  * handle upstream network traffic | 
|---|
| 417 |  */ | 
|---|
| 418 | void NetworkStream::handleUpstream( int tick ) | 
|---|
| 419 | { | 
|---|
| 420 |   int offset; | 
|---|
| 421 |   int n; | 
|---|
| 422 |    | 
|---|
| 423 |   for ( PeerList::reverse_iterator peer = peers.rbegin(); peer != peers.rend(); peer++ ) | 
|---|
| 424 |   { | 
|---|
| 425 |     offset = INTSIZE; //make already space for length  | 
|---|
| 426 |      | 
|---|
| 427 |     if ( !peer->second.socket ) | 
|---|
| 428 |       continue; | 
|---|
| 429 |      | 
|---|
| 430 |     n = Converter::intToByteArray( currentState, buf + offset, UDP_PACKET_SIZE - offset ); | 
|---|
| 431 |     assert( n == INTSIZE ); | 
|---|
| 432 |     offset += n; | 
|---|
| 433 |      | 
|---|
| 434 |     n = Converter::intToByteArray( peer->second.lastAckedState, buf + offset, UDP_PACKET_SIZE - offset ); | 
|---|
| 435 |     assert( n == INTSIZE ); | 
|---|
| 436 |     offset += n; | 
|---|
| 437 |      | 
|---|
| 438 |     n = Converter::intToByteArray( peer->second.lastRecvedState, buf + offset, UDP_PACKET_SIZE - offset ); | 
|---|
| 439 |     assert( n == INTSIZE ); | 
|---|
| 440 |     offset += n; | 
|---|
| 441 |      | 
|---|
| 442 |     for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ ) | 
|---|
| 443 |     { | 
|---|
| 444 |       int oldOffset = offset; | 
|---|
| 445 |       Synchronizeable & sync = **it; | 
|---|
| 446 |        | 
|---|
| 447 |       if ( !sync.beSynchronized() || sync.getUniqueID() < 0 ) | 
|---|
| 448 |         continue; | 
|---|
| 449 |  | 
|---|
| 450 |       //if handshake not finished only sync handshake | 
|---|
| 451 |       if ( peer->second.handshake && sync.getLeafClassID() != CL_HANDSHAKE ) | 
|---|
| 452 |         continue; | 
|---|
| 453 |        | 
|---|
| 454 |       if ( isServer() && sync.getLeafClassID() == CL_HANDSHAKE && sync.getUniqueID() != peer->second.userId ) | 
|---|
| 455 |         continue; | 
|---|
| 456 |        | 
|---|
| 457 |       //do not sync null parent | 
|---|
| 458 |       if ( sync.getLeafClassID() == CL_NULL_PARENT ) | 
|---|
| 459 |         continue; | 
|---|
| 460 |  | 
|---|
| 461 |       assert( offset + INTSIZE <= UDP_PACKET_SIZE ); | 
|---|
| 462 |        | 
|---|
| 463 |       //server fakes uniqueid=0 for handshake | 
|---|
| 464 |       if ( this->isServer() && sync.getUniqueID() < MAX_CONNECTIONS - 1 ) | 
|---|
| 465 |         n = Converter::intToByteArray( 0, buf + offset, UDP_PACKET_SIZE - offset ); | 
|---|
| 466 |       else | 
|---|
| 467 |         n = Converter::intToByteArray( sync.getUniqueID(), buf + offset, UDP_PACKET_SIZE - offset ); | 
|---|
| 468 |       assert( n == INTSIZE ); | 
|---|
| 469 |       offset += n; | 
|---|
| 470 |        | 
|---|
| 471 |       //make space for size | 
|---|
| 472 |       offset += INTSIZE; | 
|---|
| 473 |  | 
|---|
| 474 |       n = sync.getStateDiff( peer->second.userId, buf + offset, UDP_PACKET_SIZE-offset, currentState, peer->second.lastAckedState, -1000 ); | 
|---|
| 475 |       offset += n; | 
|---|
| 476 |       //NETPRINTF(0)("GGGGGEEEEETTTTT: %s (%d) %d\n",sync.getClassName(), sync.getUniqueID(), n); | 
|---|
| 477 |        | 
|---|
| 478 |       assert( Converter::intToByteArray( n, buf + offset - n - INTSIZE, INTSIZE ) == INTSIZE ); | 
|---|
| 479 |        | 
|---|
| 480 |       //check if all bytes == 0 -> remove data  | 
|---|
| 481 |       //TODO not all synchronizeables like this maybe add Synchronizeable::canRemoveZeroDiff() | 
|---|
| 482 |       bool allZero = true;  | 
|---|
| 483 |       for ( int i = 0; i < n; i++ )  | 
|---|
| 484 |       {  | 
|---|
| 485 |          if ( buf[i+oldOffset+2*INTSIZE] != 0 )  | 
|---|
| 486 |            allZero = false;  | 
|---|
| 487 |       }  | 
|---|
| 488 |  | 
|---|
| 489 |       if ( allZero )  | 
|---|
| 490 |       {  | 
|---|
| 491 |         //NETPRINTF(n)("REMOVE ZERO DIFF: %s (%d)\n", sync.getClassName(), sync.getUniqueID());  | 
|---|
| 492 |         offset = oldOffset;  | 
|---|
| 493 |       }  | 
|---|
| 494 |  | 
|---|
| 495 |        | 
|---|
| 496 |     } | 
|---|
| 497 |      | 
|---|
| 498 |     for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ ) | 
|---|
| 499 |     { | 
|---|
| 500 |       Synchronizeable & sync = **it; | 
|---|
| 501 |        | 
|---|
| 502 |       if ( !sync.beSynchronized() || sync.getUniqueID() < 0 ) | 
|---|
| 503 |         continue; | 
|---|
| 504 |        | 
|---|
| 505 |       sync.handleSentState( peer->second.userId, currentState, peer->second.lastAckedState ); | 
|---|
| 506 |     } | 
|---|
| 507 |      | 
|---|
| 508 |     assert( Converter::intToByteArray( offset, buf, INTSIZE ) == INTSIZE ); | 
|---|
| 509 |      | 
|---|
| 510 |     int compLength = 0; | 
|---|
| 511 |     if ( this->isServer() ) | 
|---|
| 512 |       compLength = Zip::getInstance()->zip( buf, offset, compBuf, UDP_PACKET_SIZE, dictServer ); | 
|---|
| 513 |     else | 
|---|
| 514 |       compLength = Zip::getInstance()->zip( buf, offset, compBuf, UDP_PACKET_SIZE, dictClient ); | 
|---|
| 515 |      | 
|---|
| 516 |     if ( compLength <= 0 ) | 
|---|
| 517 |     { | 
|---|
| 518 |       PRINTF(1)("compression failed!\n"); | 
|---|
| 519 |       continue; | 
|---|
| 520 |     } | 
|---|
| 521 |      | 
|---|
| 522 |     assert( peer->second.socket->writePacket( compBuf, compLength ) ); | 
|---|
| 523 |      | 
|---|
| 524 |     if ( this->remainingBytesToWriteToDict > 0 ) | 
|---|
| 525 |       writeToNewDict( buf, offset, true ); | 
|---|
| 526 |      | 
|---|
| 527 |     peer->second.connectionMonitor->processUnzippedOutgoingPacket( tick, buf, offset, currentState ); | 
|---|
| 528 |     peer->second.connectionMonitor->processZippedOutgoingPacket( tick, compBuf, compLength, currentState ); | 
|---|
| 529 |      | 
|---|
| 530 |     //NETPRINTF(n)("send packet: %d userId = %d\n", offset, peer->second.userId); | 
|---|
| 531 |   } | 
|---|
| 532 | } | 
|---|
| 533 |  | 
|---|
| 534 | /** | 
|---|
| 535 |  * handle downstream network traffic | 
|---|
| 536 |  */ | 
|---|
| 537 | void NetworkStream::handleDownstream( int tick ) | 
|---|
| 538 | { | 
|---|
| 539 |   int offset = 0; | 
|---|
| 540 |    | 
|---|
| 541 |   int length = 0; | 
|---|
| 542 |   int packetLength = 0; | 
|---|
| 543 |   int compLength = 0; | 
|---|
| 544 |   int uniqueId = 0; | 
|---|
| 545 |   int state = 0; | 
|---|
| 546 |   int ackedState = 0; | 
|---|
| 547 |   int fromState = 0; | 
|---|
| 548 |   int syncDataLength = 0; | 
|---|
| 549 |    | 
|---|
| 550 |   for ( PeerList::iterator peer = peers.begin(); peer != peers.end(); peer++ ) | 
|---|
| 551 |   { | 
|---|
| 552 |      | 
|---|
| 553 |     if ( !peer->second.socket ) | 
|---|
| 554 |       continue; | 
|---|
| 555 |  | 
|---|
| 556 |     while ( 0 < (compLength = peer->second.socket->readPacket( compBuf, UDP_PACKET_SIZE )) ) | 
|---|
| 557 |     { | 
|---|
| 558 |       peer->second.connectionMonitor->processZippedIncomingPacket( tick, compBuf, compLength ); | 
|---|
| 559 |        | 
|---|
| 560 |       //PRINTF(0)("GGGGGOOOOOOOOOOTTTTTTTT: %d\n", compLength); | 
|---|
| 561 |       packetLength = Zip::getInstance()->unZip( compBuf, compLength, buf, UDP_PACKET_SIZE ); | 
|---|
| 562 |  | 
|---|
| 563 |       if ( packetLength < 4*INTSIZE ) | 
|---|
| 564 |       { | 
|---|
| 565 |         if ( packetLength != 0 ) | 
|---|
| 566 |           PRINTF(1)("got too small packet: %d\n", packetLength); | 
|---|
| 567 |         continue; | 
|---|
| 568 |       } | 
|---|
| 569 |        | 
|---|
| 570 |       if ( this->remainingBytesToWriteToDict > 0 ) | 
|---|
| 571 |         writeToNewDict( buf, packetLength, false ); | 
|---|
| 572 |      | 
|---|
| 573 |       assert( Converter::byteArrayToInt( buf, &length ) == INTSIZE ); | 
|---|
| 574 |       assert( Converter::byteArrayToInt( buf + INTSIZE, &state ) == INTSIZE ); | 
|---|
| 575 |       assert( Converter::byteArrayToInt( buf + 2*INTSIZE, &fromState ) == INTSIZE ); | 
|---|
| 576 |       assert( Converter::byteArrayToInt( buf + 3*INTSIZE, &ackedState ) == INTSIZE ); | 
|---|
| 577 |       //NETPRINTF(n)("ackedstate: %d\n", ackedState); | 
|---|
| 578 |       offset = 4*INTSIZE; | 
|---|
| 579 |        | 
|---|
| 580 |       peer->second.connectionMonitor->processUnzippedIncomingPacket( tick, buf, packetLength, state, ackedState ); | 
|---|
| 581 |  | 
|---|
| 582 |       //NETPRINTF(n)("got packet: %d, %d\n", length, packetLength); | 
|---|
| 583 |      | 
|---|
| 584 |     //if this is an old state drop it | 
|---|
| 585 |       if ( state <= peer->second.lastRecvedState ) | 
|---|
| 586 |         continue; | 
|---|
| 587 |      | 
|---|
| 588 |       if ( packetLength != length ) | 
|---|
| 589 |       { | 
|---|
| 590 |         PRINTF(1)("real packet length (%d) and transmitted packet length (%d) do not match!\n", packetLength, length); | 
|---|
| 591 |         peer->second.socket->disconnectServer(); | 
|---|
| 592 |         continue; | 
|---|
| 593 |       } | 
|---|
| 594 |        | 
|---|
| 595 |       while ( offset + 2*INTSIZE < length ) | 
|---|
| 596 |       { | 
|---|
| 597 |         assert( offset > 0 ); | 
|---|
| 598 |         assert( Converter::byteArrayToInt( buf + offset, &uniqueId ) == INTSIZE ); | 
|---|
| 599 |         offset += INTSIZE; | 
|---|
| 600 |        | 
|---|
| 601 |         assert( Converter::byteArrayToInt( buf + offset, &syncDataLength ) == INTSIZE ); | 
|---|
| 602 |         offset += INTSIZE; | 
|---|
| 603 |          | 
|---|
| 604 |         assert( syncDataLength > 0 ); | 
|---|
| 605 |         assert( syncDataLength < 10000 ); | 
|---|
| 606 |        | 
|---|
| 607 |         Synchronizeable * sync = NULL; | 
|---|
| 608 |          | 
|---|
| 609 |         for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ ) | 
|---|
| 610 |         {  | 
|---|
| 611 |         //                                        client thinks his handshake has id 0!!!!! | 
|---|
| 612 |           if ( (*it)->getUniqueID() == uniqueId || ( uniqueId == 0 && (*it)->getUniqueID() == peer->second.userId ) ) | 
|---|
| 613 |           { | 
|---|
| 614 |             sync = *it; | 
|---|
| 615 |             break; | 
|---|
| 616 |           } | 
|---|
| 617 |         } | 
|---|
| 618 |          | 
|---|
| 619 |         if ( sync == NULL ) | 
|---|
| 620 |         { | 
|---|
| 621 |           PRINTF(0)("could not find sync with id %d. try to create it\n", uniqueId); | 
|---|
| 622 |           if ( oldSynchronizeables.find( uniqueId ) != oldSynchronizeables.end() ) | 
|---|
| 623 |           { | 
|---|
| 624 |             offset += syncDataLength; | 
|---|
| 625 |             continue; | 
|---|
| 626 |           } | 
|---|
| 627 |            | 
|---|
| 628 |           if ( !peers[peer->second.userId].isServer ) | 
|---|
| 629 |           { | 
|---|
| 630 |             offset += syncDataLength; | 
|---|
| 631 |             continue; | 
|---|
| 632 |           } | 
|---|
| 633 |            | 
|---|
| 634 |           int leafClassId; | 
|---|
| 635 |           if ( INTSIZE > length - offset ) | 
|---|
| 636 |           { | 
|---|
| 637 |             offset += syncDataLength; | 
|---|
| 638 |             continue; | 
|---|
| 639 |           } | 
|---|
| 640 |  | 
|---|
| 641 |           Converter::byteArrayToInt( buf + offset, &leafClassId ); | 
|---|
| 642 |            | 
|---|
| 643 |           assert( leafClassId != 0 ); | 
|---|
| 644 |          | 
|---|
| 645 |           BaseObject * b = NULL; | 
|---|
| 646 |           /* These are some small exeptions in creation: Not all objects can/should be created via Factory */ | 
|---|
| 647 |           /* Exception 1: NullParent */ | 
|---|
| 648 |           if( leafClassId == CL_NULL_PARENT || leafClassId == CL_SYNCHRONIZEABLE || leafClassId == CL_NETWORK_GAME_MANAGER ) | 
|---|
| 649 |           { | 
|---|
| 650 |             PRINTF(1)("Can not create Class with ID %x!\n", (int)leafClassId); | 
|---|
| 651 |             offset += syncDataLength; | 
|---|
| 652 |             continue; | 
|---|
| 653 |           } | 
|---|
| 654 |           else | 
|---|
| 655 |             b = Factory::fabricate( (ClassID)leafClassId ); | 
|---|
| 656 |  | 
|---|
| 657 |           if ( !b ) | 
|---|
| 658 |           { | 
|---|
| 659 |             PRINTF(1)("Could not fabricate Object with classID %x\n", leafClassId); | 
|---|
| 660 |             offset += syncDataLength; | 
|---|
| 661 |             continue; | 
|---|
| 662 |           } | 
|---|
| 663 |  | 
|---|
| 664 |           if ( b->isA(CL_SYNCHRONIZEABLE) ) | 
|---|
| 665 |           { | 
|---|
| 666 |             sync = dynamic_cast<Synchronizeable*>(b); | 
|---|
| 667 |             sync->setUniqueID( uniqueId ); | 
|---|
| 668 |             sync->setSynchronized(true); | 
|---|
| 669 |    | 
|---|
| 670 |             PRINTF(0)("Fabricated %s with id %d\n", sync->getClassName(), sync->getUniqueID()); | 
|---|
| 671 |           } | 
|---|
| 672 |           else | 
|---|
| 673 |           { | 
|---|
| 674 |             PRINTF(1)("Class with ID %x is not a synchronizeable!\n", (int)leafClassId); | 
|---|
| 675 |             delete b; | 
|---|
| 676 |             offset += syncDataLength; | 
|---|
| 677 |             continue; | 
|---|
| 678 |           } | 
|---|
| 679 |         } | 
|---|
| 680 |          | 
|---|
| 681 |  | 
|---|
| 682 |         int n = sync->setStateDiff( peer->second.userId, buf+offset, syncDataLength, state, fromState );  | 
|---|
| 683 |         offset += n; | 
|---|
| 684 |         //NETPRINTF(0)("SSSSSEEEEETTTTT: %s %d\n",sync->getClassName(), n); | 
|---|
| 685 |  | 
|---|
| 686 |       } | 
|---|
| 687 |        | 
|---|
| 688 |       if ( offset != length ) | 
|---|
| 689 |       { | 
|---|
| 690 |         PRINTF(0)("offset (%d) != length (%d)\n", offset, length); | 
|---|
| 691 |         peer->second.socket->disconnectServer(); | 
|---|
| 692 |       } | 
|---|
| 693 |        | 
|---|
| 694 |        | 
|---|
| 695 |       for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ ) | 
|---|
| 696 |       { | 
|---|
| 697 |         Synchronizeable & sync = **it; | 
|---|
| 698 |        | 
|---|
| 699 |         if ( !sync.beSynchronized() || sync.getUniqueID() < 0 ) | 
|---|
| 700 |           continue; | 
|---|
| 701 |        | 
|---|
| 702 |         sync.handleRecvState( peer->second.userId, state, fromState ); | 
|---|
| 703 |       } | 
|---|
| 704 |        | 
|---|
| 705 |       assert( peer->second.lastAckedState <= ackedState ); | 
|---|
| 706 |       peer->second.lastAckedState = ackedState; | 
|---|
| 707 |        | 
|---|
| 708 |       assert( peer->second.lastRecvedState < state ); | 
|---|
| 709 |       peer->second.lastRecvedState = state; | 
|---|
| 710 |  | 
|---|
| 711 |     } | 
|---|
| 712 |    | 
|---|
| 713 |   } | 
|---|
| 714 |    | 
|---|
| 715 | } | 
|---|
| 716 |  | 
|---|
| 717 | /** | 
|---|
| 718 |  * is executed when a handshake has finished | 
|---|
| 719 |  * @todo create playable for new user | 
|---|
| 720 |  */ | 
|---|
| 721 | void NetworkStream::handleNewClient( int userId ) | 
|---|
| 722 | { | 
|---|
| 723 |   MessageManager::getInstance()->initUser( userId ); | 
|---|
| 724 |    | 
|---|
| 725 |   networkGameManager->signalNewPlayer( userId ); | 
|---|
| 726 | } | 
|---|
| 727 |  | 
|---|
| 728 | /** | 
|---|
| 729 |  * removes old items from oldSynchronizeables | 
|---|
| 730 |  */ | 
|---|
| 731 | void NetworkStream::cleanUpOldSyncList( ) | 
|---|
| 732 | { | 
|---|
| 733 |   int now = SDL_GetTicks(); | 
|---|
| 734 |    | 
|---|
| 735 |   for ( std::map<int,int>::iterator it = oldSynchronizeables.begin(); it != oldSynchronizeables.end();  ) | 
|---|
| 736 |   { | 
|---|
| 737 |     if ( it->second < now - 10*1000 ) | 
|---|
| 738 |     { | 
|---|
| 739 |       std::map<int,int>::iterator delIt = it; | 
|---|
| 740 |       it++; | 
|---|
| 741 |       oldSynchronizeables.erase( delIt ); | 
|---|
| 742 |       continue; | 
|---|
| 743 |     } | 
|---|
| 744 |     it++; | 
|---|
| 745 |   } | 
|---|
| 746 | } | 
|---|
| 747 |  | 
|---|
| 748 | /** | 
|---|
| 749 |  * writes data to DATA/dicts/newdict | 
|---|
| 750 |  * @param data pointer to data | 
|---|
| 751 |  * @param length length | 
|---|
| 752 |  */ | 
|---|
| 753 | void NetworkStream::writeToNewDict( byte * data, int length, bool upstream ) | 
|---|
| 754 | { | 
|---|
| 755 |   if ( remainingBytesToWriteToDict <= 0 ) | 
|---|
| 756 |     return; | 
|---|
| 757 |    | 
|---|
| 758 |   if ( length > remainingBytesToWriteToDict ) | 
|---|
| 759 |     length = remainingBytesToWriteToDict; | 
|---|
| 760 |    | 
|---|
| 761 |   std::string fileName = ResourceManager::getInstance()->getDataDir(); | 
|---|
| 762 |   fileName += "/dicts/newdict"; | 
|---|
| 763 |    | 
|---|
| 764 |   if ( upstream ) | 
|---|
| 765 |     fileName += "_upstream"; | 
|---|
| 766 |   else | 
|---|
| 767 |     fileName += "_downstream"; | 
|---|
| 768 |    | 
|---|
| 769 |   FILE * f = fopen( fileName.c_str(), "a" ); | 
|---|
| 770 |    | 
|---|
| 771 |   if ( !f ) | 
|---|
| 772 |   { | 
|---|
| 773 |     PRINTF(2)("could not open %s\n", fileName.c_str()); | 
|---|
| 774 |     remainingBytesToWriteToDict = 0; | 
|---|
| 775 |     return; | 
|---|
| 776 |   } | 
|---|
| 777 |    | 
|---|
| 778 |   if ( fwrite( data, 1, length, f ) != length ) | 
|---|
| 779 |   { | 
|---|
| 780 |     PRINTF(2)("could not write to file\n"); | 
|---|
| 781 |     fclose( f ); | 
|---|
| 782 |     return; | 
|---|
| 783 |   } | 
|---|
| 784 |    | 
|---|
| 785 |   fclose( f ); | 
|---|
| 786 |    | 
|---|
| 787 |   remainingBytesToWriteToDict -= length;   | 
|---|
| 788 | } | 
|---|
| 789 |  | 
|---|
| 790 |  | 
|---|
| 791 |  | 
|---|
| 792 |  | 
|---|
| 793 |  | 
|---|
| 794 |  | 
|---|