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