Changeset 7954 in orxonox.OLD for trunk/src/lib/network
- Timestamp:
- May 29, 2006, 3:28:41 PM (19 years ago)
- Location:
- trunk/src/lib/network
- Files:
-
- 20 edited
- 31 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/lib/network/Makefile.am
r7026 r7954 13 13 network_protocol.cc \ 14 14 server_socket.cc \ 15 tcp_server_socket.cc \ 16 tcp_socket.cc \ 17 udp_server_socket.cc \ 18 udp_socket.cc \ 15 19 handshake.cc \ 16 20 network_game_manager.cc \ 17 converter.cc 21 converter.cc \ 22 message_manager.cc \ 23 network_log.cc \ 24 zip.cc \ 25 \ 26 synchronizeable_var/synchronizeable_var.cc \ 27 synchronizeable_var/synchronizeable_vector.cc \ 28 synchronizeable_var/synchronizeable_int.cc \ 29 synchronizeable_var/synchronizeable_quaternion.cc \ 30 synchronizeable_var/synchronizeable_string.cc \ 31 synchronizeable_var/synchronizeable_float.cc \ 32 synchronizeable_var/synchronizeable_bool.cc \ 33 synchronizeable_var/synchronizeable_uint.cc 18 34 19 35 … … 29 45 network_protocol.h \ 30 46 server_socket.h \ 47 tcp_server_socket.h \ 48 tcp_socket.h \ 49 udp_server_socket.h \ 50 udp_socket.h \ 31 51 handshake.h \ 32 52 network_game_manager.h \ 33 53 converter.h \ 34 netdefs.h 54 netdefs.h \ 55 message_manager.h \ 56 network_log.h \ 57 zip.h \ 58 \ 59 synchronizeable_var/synchronizeable_var.h \ 60 synchronizeable_var/synchronizeable_vector.h \ 61 synchronizeable_var/synchronizeable_int.h \ 62 synchronizeable_var/synchronizeable_quaternion.h \ 63 synchronizeable_var/synchronizeable_string.h \ 64 synchronizeable_var/synchronizeable_float.h \ 65 synchronizeable_var/synchronizeable_bool.h \ 66 synchronizeable_var/synchronizeable_uint.h 35 67 36 68 -
trunk/src/lib/network/connection_monitor.cc
r5822 r7954 10 10 11 11 ### File Specific: 12 main-programmer: Silvan Nellen12 main-programmer: Christoph Renner 13 13 co-programmer: ... 14 14 */ 15 15 16 16 #include "connection_monitor.h" 17 #include "network_log.h" 18 17 19 #include <debug.h> 18 20 #include <SDL/SDL.h> … … 22 24 using namespace std; 23 25 24 ConnectionMonitor::ConnectionMonitor() 25 { 26 26 /** 27 * constructor 28 * @param userId user's id 29 */ 30 ConnectionMonitor::ConnectionMonitor( int userId ) 31 { 27 32 /* set the class id for the base object and add ist to class list*/ 28 33 this->setClassID(CL_CONNECTION_MONITOR, "ConnectionMonitor"); 29 30 /*initialize variables*/ 31 32 /*Data of the lifetime of the ConnectionMonitor Object*/ 33 packetToAverage = 100; 34 protocollType = "default(TCP)"; 35 36 startTime= SDL_GetTicks(); 37 totalReceivedPackets=0; 38 averageDatarate=0; 39 totalLostPackets=0; 40 totalPacketloss=0; 41 42 /*Data of the current packet*/ 43 currentPacketID=0; 44 currentPacketTick=0; 45 lastPacketID=0; 46 lastPacketTick=0; 47 currentDelay=0; 48 49 /*Data of the last n packets (n is specified by paxketsToAverage)*/ 50 sizeOfLastFewPackets=0; 51 currentDatarate=0; 52 lastFewDelays = new unsigned int [packetToAverage]; 53 lastFewPackets = new byte* [packetToAverage]; 54 packetCounter=0; 55 56 57 } 58 59 60 ConnectionMonitor::~ConnectionMonitor() 61 { 62 63 64 } 65 66 67 68 void ConnectionMonitor::processPacket(byte* currentPacket, unsigned int packetLength) 69 { 70 /*Process the current Packet*/ 71 currentPacketTick = SDL_GetTicks(); 72 currentDelay = currentPacketTick - lastPacketTick; 73 74 /*Do whats needed for Averaging*/ 75 76 if(packetCounter == packetToAverage) 77 { 78 computeCurrentDatarate(); 79 displayStatistic(); 80 packetCounter = 0; 81 sizeOfLastFewPackets = 0; 82 } 83 84 lastFewDelays[packetCounter] = currentDelay; 85 lastFewPackets[packetCounter] = currentPacket; 86 sizeOfLastFewPackets += packetLength; 87 88 /*Update the lifetime Variables*/ 89 totalReceivedPackets ++; 90 float timeDiff = this->currentPacketTick - this->startTime; 91 if( timeDiff != 0.0f ) 92 averageDatarate = totalReceivedPackets/timeDiff; 93 94 /*Preparefor the next Packet*/ 95 lastPacketTick = currentPacketTick; 96 packetCounter++; 97 } 98 99 100 /* Compute the value of current Datarate*/ 101 void ConnectionMonitor::computeCurrentDatarate() 102 { 103 int timeForLastFewPackets=0; 104 for(int i=0;i < packetToAverage;i++) 105 timeForLastFewPackets += lastFewDelays[i]; 106 107 if( timeForLastFewPackets != 0) 108 currentDatarate = sizeOfLastFewPackets/timeForLastFewPackets; 109 } 110 111 void doUDPRelatedStuff() 112 { 113 /* Do protocol related stuff 114 115 Only for Udp: 116 "currentPacketID = getID from package"; 117 118 if(currentPacketID - lastPacketID > 1) 34 35 this->userId = userId; 36 this->ping = 0; 37 this->incomingUnzippedBandWidth = 0; 38 this->outgoingUnzippedBandWidth = 0; 39 this->incomingZippedBandWidth = 0; 40 this->outgoingZippedBandWidth = 0; 41 this->nIncomingPackets = 0; 42 this->nOutgoingPackets = 0; 43 this->nZIncomingPackets = 0; 44 this->nZOutgoingPackets = 0; 45 46 this->lastPacketTick = 0; 47 this->lastPrintTick = 0; 48 } 49 50 /** 51 * deconstructor 52 */ 53 ConnectionMonitor::~ConnectionMonitor( ) 54 { 55 } 56 57 /** 58 * process unzipped outgoing packet 59 * @param data pointer to packet data 60 * @param length length of packet 61 * @param stateId packet's state id 62 */ 63 void ConnectionMonitor::processUnzippedOutgoingPacket( byte * data, int length, int stateId ) 64 { 65 int tick = SDL_GetTicks(); 66 67 nOutgoingPackets++; 68 69 // for ping calculation 70 sentStateTicks[stateId] = tick; 71 72 // calculate bandwidth 73 outgoingUnzippedPacketHistory[tick] = length; 74 outgoingUnzippedBandWidth = calculateBandWidth( outgoingUnzippedPacketHistory, tick ); 75 76 //NETPRINTF(n)("UNZIPPED UPSTREAM: user: %d bandwidth %f\n", userId, outgoingUnzippedBandWidth ); 77 78 // count zero bytes 79 int nZeroBytes = 0; 80 81 for ( int i = 0; i < length; i++ ) 82 if ( data[i] == '\0' ) 83 nZeroBytes++; 84 85 //NETPRINTF(n)( "ZEROBYTES: %d (%f%%)\n", nZeroBytes, ((float)100)*nZeroBytes/length ); 86 } 87 88 /** 89 * process unzipped incoming packet 90 * @param data pointer to packet data 91 * @param length length of packet 92 * @param stateId packet's state id 93 * @param ackedState state which was acked by this packet 94 */ 95 void ConnectionMonitor::processUnzippedIncomingPacket( byte * data, int length, int stateId, int ackedState ) 96 { 97 int tick = SDL_GetTicks(); 98 99 nIncomingPackets++; 100 101 lastPacketTick = tick; 102 103 // calculate ping 104 if ( sentStateTicks.find( ackedState ) != sentStateTicks.end() ) 119 105 { 120 totalLostPackets += currentPacketID - lastPacketID; 121 } 122 123 totalPacketloss = (totalLostPackets/totalReceivedPackets)*100 ; 124 */ 125 } 126 127 128 129 /* Display connectoin statistic*/ 130 void ConnectionMonitor::displayStatistic() 131 { 132 // PRINT(0)("============================================\n"); 133 // PRINT(0)("Connection Monitor Network Statistics:\n"); 134 // PRINT(0)("Total received packets:",totalReceivedPackets); 135 // PRINT(0)("Average datarate :\n",averageDatarate); 136 // PRINT(0)("Total lost packets:",totalLostPackets); 137 // PRINT(0)("Packetloss [%] :\n",totalPacketloss); 138 // 139 // PRINT(0)("Current datarate :\n",currentDatarate); 140 // PRINT(0)("Delays of the last few packets :\n"); 141 // for(int i=1 ;i <= packetToAverage-1;i++) 142 // PRINT(0)("%i ",lastFewDelays[i]); 143 // 144 // PRINT(0)("============================================\n"); 145 146 } 147 106 ackDelay.push_back( tick - sentStateTicks[ackedState] ); 107 } 108 109 while ( sentStateTicks.begin() != sentStateTicks.end() && sentStateTicks.begin()->first <= ackedState ) 110 sentStateTicks.erase( sentStateTicks.begin() ); 111 112 while ( ackDelay.size() > N_PACKETS_FOR_PING ) 113 ackDelay.erase( ackDelay.begin() ); 114 115 ping = 0; 116 117 for ( std::list<int>::iterator it = ackDelay.begin(); it != ackDelay.end(); it++ ) 118 ping += *it; 119 120 if ( ackDelay.size() == 0 ) 121 ping = -1; 122 else 123 ping /= ackDelay.size(); 124 125 //NETPRINTF(n)("PING: user: %d ping: %d\n", userId, ping ); 126 127 // calculate bandwidth 128 incomingUnzippedPacketHistory[tick] = length; 129 incomingUnzippedBandWidth = calculateBandWidth( incomingUnzippedPacketHistory, tick ); 130 131 //NETPRINTF(n)("UNZIPPED DOWNSTREAM: user: %d bandwidth %f\n", userId, incomingUnzippedBandWidth ); 132 133 } 134 135 /** 136 * calculate bandwidth out of packethistory 137 * @param packetHistory packet history 138 * @param tick current tick from SDL_GetTicks 139 * @return bandwidth in bytes/sec 140 */ 141 float ConnectionMonitor::calculateBandWidth( std::map< int, int > packetHistory, int tick ) 142 { 143 // delete old packets 144 while ( packetHistory.begin()->first < tick - MSECS_TO_CALC_BWIDTH ) 145 packetHistory.erase( packetHistory.begin() ); 146 147 float res = 0.0f; 148 149 for ( std::map<int,int>::iterator it = packetHistory.begin(); it != packetHistory.end(); it++ ) 150 { 151 res += it->second; 152 } 153 154 if ( packetHistory.size() <= 1 || tick - packetHistory.begin()->first == 0 ) 155 res = 0.0f; 156 else 157 res /= (float)((tick - packetHistory.begin()->first)*( 1 + 1/((float)(packetHistory.size()-1)) )); 158 159 res *= 1000.0f; 160 161 return res; 162 } 163 164 165 /** 166 * process zipped outgoing packet 167 * @param data pointer to packet data 168 * @param length length of packet 169 * @param stateId packet's state id 170 */ 171 void ConnectionMonitor::processZippedOutgoingPacket( byte * data, int length, int stateId ) 172 { 173 int tick = SDL_GetTicks(); 174 175 nZOutgoingPackets++; 176 177 // calculate bandwidth 178 outgoingZippedPacketHistory[tick] = length; 179 outgoingZippedBandWidth = calculateBandWidth( outgoingZippedPacketHistory, tick ); 180 181 //NETPRINTF(n)("UPSTREAM: user: %d bandwidth %f nOutgoingPackets %d\n", userId, outgoingZippedBandWidth, nOutgoingPackets ); 182 183 if ( lastPrintTick < tick-1000 ) 184 { 185 printStatis(); 186 lastPrintTick = tick; 187 } 188 } 189 190 191 /** 192 * process zipped incoming packet 193 * @param data pointer to packet data 194 * @param length length of packet 195 * @param stateId packet's state id 196 * @param ackedState state which was acked by this packet 197 */ 198 void ConnectionMonitor::processZippedIncomingPacket( byte * data, int length, int stateId, int ackedState ) 199 { 200 int tick = SDL_GetTicks(); 201 202 nZIncomingPackets++; 203 204 // calculate bandwidth 205 incomingZippedPacketHistory[tick] = length; 206 incomingZippedBandWidth = calculateBandWidth( incomingZippedPacketHistory, tick ); 207 208 //NETPRINTF(n)("DOWNSTREAM: user: %d bandwidth %f nIncomingPackets %d\n", userId, incomingZippedBandWidth, nIncomingPackets ); 209 210 } 211 212 213 /** 214 * check if client sent no packets for SECS_TO_TIMEOUT 215 * @return true if last packet recieved \< NOW() - SECS_TO_TIMEOUT 216 */ 217 bool ConnectionMonitor::hasTimedOut( ) 218 { 219 if ( lastPacketTick + SECS_TO_TIMEOUT*1000 < SDL_GetTicks() && nIncomingPackets > 0 ) 220 return true; 221 222 if ( nIncomingPackets == 0 && nOutgoingPackets >= NETWORK_FREQUENCY*SECS_TO_TIMEOUT ) 223 return true; 224 225 return false; 226 } 227 228 229 230 /** 231 * prints bandwith usage, ping and other important things to telnet-console 232 */ 233 void ConnectionMonitor::printStatis( ) 234 { 235 NETPRINT(n)("=========NETWORKSTATS FOR USER %d=========\n", userId); 236 NETPRINT(n)("PING = %d\n", ping); 237 NETPRINT(n)("BANDWIDTH: UP: %f (%f) DOWN %f (%f)\n", outgoingZippedBandWidth, outgoingUnzippedBandWidth, incomingZippedBandWidth, incomingUnzippedBandWidth); 238 NETPRINT(n)("=========================================="); 239 } 240 241 -
trunk/src/lib/network/connection_monitor.h
r6981 r7954 10 10 #include "netdefs.h" 11 11 12 #include <map> 13 14 #define N_PACKETS_FOR_PING 20 15 #define MSECS_TO_CALC_BWIDTH 1000 16 #define SECS_TO_TIMEOUT 10 17 12 18 class ConnectionMonitor : virtual public BaseObject 13 19 { 14 20 public: 15 ConnectionMonitor( );21 ConnectionMonitor( int userId ); 16 22 virtual ~ConnectionMonitor(); 17 23 18 void processPacket(byte* packet, unsigned int packetLength); 24 void processUnzippedOutgoingPacket( byte * data, int length, int stateId ); 25 void processUnzippedIncomingPacket( byte * data, int length, int stateId, int ackedState ); 26 27 void processZippedOutgoingPacket( byte * data, int length, int stateId ); 28 void processZippedIncomingPacket( byte * data, int length, int stateId, int ackedState ); 29 30 void calculatePing(); 31 32 bool hasTimedOut(); 33 34 void printStatis(); 35 36 private: 37 float calculateBandWidth( std::map<int,int> packetHistory, int tick ); 38 39 int userId; //!< user's id 19 40 41 std::map<int,int> sentStateTicks; 42 43 std::map<int,int> incomingUnzippedPacketHistory; 44 std::map<int,int> outgoingUnzippedPacketHistory; 45 46 std::map<int,int> incomingZippedPacketHistory; 47 std::map<int,int> outgoingZippedPacketHistory; 48 49 std::list<int> ackDelay; 50 int ping; 20 51 21 private: 22 23 24 void displayStatistic(); 25 void computeCurrentDatarate(); 26 void doUDPRelatedStuff(); 27 28 /*Data of the lifetime of the ConnectionMonitor Object*/ 29 unsigned int packetToAverage; 30 char* protocollType; 31 32 unsigned int totalReceivedPackets; 33 float averageDatarate; 34 unsigned int totalLostPackets; 35 float totalPacketloss; 36 unsigned int startTime; 37 38 /*Data of the current packet*/ 39 unsigned int currentPacketID; 40 unsigned int currentPacketTick; 41 unsigned int lastPacketID; 42 unsigned int lastPacketTick; 43 unsigned int currentDelay; 44 45 /*Data of the last n packets (n is specified by paxketsToAverage)*/ 46 unsigned int sizeOfLastFewPackets; 47 unsigned int currentDatarate; 48 byte** lastFewPackets; 49 unsigned int* lastFewDelays; 50 unsigned int packetCounter; 51 52 float incomingUnzippedBandWidth; 53 float outgoingUnzippedBandWidth; 54 55 float incomingZippedBandWidth; 56 float outgoingZippedBandWidth; 57 58 int nIncomingPackets; 59 int nOutgoingPackets; 60 61 int nZIncomingPackets; 62 int nZOutgoingPackets; 63 64 int lastPacketTick; 65 66 int lastPrintTick; 52 67 }; 53 68 -
trunk/src/lib/network/converter.cc
r7230 r7954 489 489 { 490 490 PRINTF(1)("something went wrong length > remaining bytes in buffer\n" ); 491 492 //TODO remove this 493 for ( int i = -1000; i < 1001; i++ ) 494 { 495 if ( ( a[i] > 'a' && a[i] < 'z' ) || ( a[i] > 'A' && a[i] < 'Z' ) ) 496 printf("%c", a[i]); 497 else 498 printf("."); 499 } 500 printf("\n"); 501 491 502 s = ""; 492 503 return -1; 493 504 } 494 505 495 s [0] = '\0';506 s = ""; 496 507 s.append( (char*)a+n, length ); 497 508 -
trunk/src/lib/network/data_stream.cc
r5822 r7954 16 16 /* include Data_stream Header */ 17 17 #include "data_stream.h" 18 19 20 18 21 19 -
trunk/src/lib/network/handshake.cc
r6815 r7954 24 24 #include <cassert> 25 25 26 Handshake::Handshake( bool server, int clientId, int networkGameManagerId )26 Handshake::Handshake( bool server, int clientId, int networkGameManagerId, int messageManagerId ) 27 27 : Synchronizeable() 28 28 { … … 31 31 32 32 this->setIsServer(server); 33 this->clientId = clientId; 34 this->networkGameManagerId = networkGameManagerId; 35 this->state = 0; 36 this->isOk = false; 37 this->setOwner(0); 33 34 orxId_handler = registerVarId( new SynchronizeableInt( &localState.orxId, &remoteState.orxId, "orxonoxId", PERMISSION_ALL ) ); 35 version_handler = registerVarId( new SynchronizeableInt( &localState.version, &remoteState.version, "version", PERMISSION_ALL ) ); 36 netManId_handler = registerVarId( new SynchronizeableInt( &localState.networkManagerId, &remoteState.networkManagerId, "networkManagerId", PERMISSION_ALL ) ); 37 msgManId_handler = registerVarId( new SynchronizeableInt( &localState.messageManagerId, &remoteState.messageManagerId, "messageManagerId", PERMISSION_ALL ) ); 38 hostId_handler = registerVarId( new SynchronizeableInt( &localState.hostId, &remoteState.hostId, "hostId", PERMISSION_ALL ) ); 39 completed_handler = registerVarId( new SynchronizeableInt( &localState.completed, &remoteState.completed, "completed", PERMISSION_ALL ) ); 40 error_handler = registerVarId( new SynchronizeableInt( &localState.error, &remoteState.error, "error", PERMISSION_ALL ) ); 41 errorString_handler = registerVarId( new SynchronizeableString( &localState.errorString, &remoteState.errorString, "errorString", PERMISSION_ALL ) ); 42 43 candel_id = registerVarId( new SynchronizeableInt( &localState.canDel, &remoteState.canDel, "canDel", PERMISSION_ALL ) ); 44 45 localState.completed = 0; 46 localState.error = 0; 47 localState.errorString = ""; 48 localState.hostId = clientId; 49 localState.networkManagerId = networkGameManagerId; 50 this->localState.messageManagerId = messageManagerId; 51 localState.orxId = _ORXONOX_ID; 52 localState.version = _ORXONOX_VERSION; 53 localState.canDel = 0; 54 55 remoteState.completed = 0; 56 remoteState.error = 0; 57 remoteState.errorString = ""; 58 remoteState.hostId = -1; 59 remoteState.networkManagerId = -1; 60 remoteState.messageManagerId = -1; 61 remoteState.orxId = 0; 62 remoteState.version = 0; 63 remoteState.canDel = 0; 38 64 39 65 this->setSynchronized(true); 40 PRINTF( 5)("Handshake created clientId = %d\n", clientId);66 PRINTF(0)("Handshake created clientId = %d\n", clientId); 41 67 } 42 68 43 int Handshake::writeBytes( const byte * data, int length, int sender) 69 /** 70 * handler for changes in synced vars 71 * @param id id's which have changed 72 */ 73 void Handshake::varChangeHandler( std::list< int > & id ) 44 74 { 45 PRINTF(5)("Handshake::writeBytes states = %d %d %d %d (%d)\n", hasState( HS_RECVD_INIT ), hasState( HS_RECVD_VER ), hasState( HS_RECVD_HID ), hasState( HS_COMPLETED ), state); 75 for ( std::list<int>::iterator it = id.begin(); it != id.end(); it++ ) 76 { 77 if ( *it == orxId_handler ) 78 { 79 if ( remoteState.orxId != _ORXONOX_ID ) 80 { 81 localState.error = 1; 82 localState.completed = 1; 83 localState.errorString = "Seems not to be orxonox!"; 84 continue; 85 } 46 86 47 SYNCHELP_READ_BEGIN(); 87 } 88 89 if ( *it == version_handler ) 90 { 91 if ( remoteState.version != _ORXONOX_VERSION ) 92 { 93 localState.error = 2; 94 localState.completed = 1; 95 localState.errorString = "Versions of server and client do not match!"; 96 continue; 97 } 48 98 49 if ( hasState( HS_COMPLETED ) ) 50 return 0; 51 52 if ( !hasState( HS_RECVD_INIT ) ) 53 { 54 if ( length != _INITIAL_DATA_LENGTH ) 99 } 100 101 if ( *it == candel_id ) 55 102 { 56 PRINTF(0)("initial packet has wrong size %d instead of %d\n", length, _INITIAL_DATA_LENGTH); 57 setState( HS_COMPLETED ); 58 return 0; 103 PRINTF(0)("handshake finished candel changed\n"); 59 104 } 60 61 if ( strncmp((char*)data, _INITIAL_DATA, length) ) 62 { 63 PRINTF(0)("initial packed does not match\n"); 64 setState( HS_COMPLETED ); 65 return length; 66 } 67 68 setState( HS_RECVD_INIT ); 69 PRINTF(0)("got valid initial packet from client %d\n", clientId); 70 return length; 105 71 106 } 72 73 if ( hasState( HS_RECVD_INIT ) && !hasState( HS_RECVD_VER ) ) 74 { 75 if ( length != _ORXONOX_VERSION_LENGTH ) 76 { 77 PRINTF(0)("version number packet has wrong size %d instead of %d\n", length, _ORXONOX_VERSION_LENGTH); 78 setState( HS_COMPLETED ); 79 return 0; 80 } 81 82 if ( strncmp((char*)data, _ORXONOX_VERSION, length) ) 83 { 84 PRINTF(0)("versions do not match\n"); 85 setState( HS_COMPLETED ); 86 return length; 87 } 88 89 setState( HS_RECVD_VER ); 90 91 PRINTF(0)("client %d's version does match\n", clientId); 92 return length; 93 } 94 95 if ( !isServer() && hasState( HS_RECVD_VER ) && !hasState( HS_RECVD_HID ) ) 96 { 97 /*if ( length != INTSIZE+INTSIZE ) 98 { 99 PRINTF(0)("hostID packet has wrong size %d instead of %d\n", length, INTSIZE+INTSIZE); 100 setState( HS_COMPLETED ); 101 return 0; 102 }*/ 103 104 setState( HS_COMPLETED ); 105 setState( HS_RECVD_HID ); 106 this->isOk = true; 107 SYNCHELP_READ_INT( this->newHostId, NWT_HS_HOST_ID ); 108 SYNCHELP_READ_INT( this->newNetworkGameManagerId, NWT_HS_NGM_ID ); 109 110 if ( newHostId == 0 ) 111 { 112 setState( HS_WAS_REJECT ); 113 isOk = false; 114 PRINTF(0)("Server did not accept handshake!\n"); 115 } 116 else 117 { 118 PRINTF(0)("got my hostID: %d and networkGameManagerId: %d\n", newHostId, newNetworkGameManagerId); 119 } 120 return SYNCHELP_READ_N; 121 } 122 107 108 if ( 109 remoteState.orxId == _ORXONOX_ID && 110 remoteState.version == _ORXONOX_VERSION 111 ) 112 localState.completed = 1; 123 113 } 124 114 125 int Handshake::readBytes( byte * data, int maxLength, int * reciever )126 {127 PRINTF(5)("Handshake::readBytes states = %d %d %d %d (%d)\n", hasState( HS_SENT_INIT ), hasState( HS_SENT_VER ), hasState( HS_SENT_HID ), hasState( HS_COMPLETED ), state);128 129 SYNCHELP_WRITE_BEGIN();130 131 if ( hasState( HS_COMPLETED ) )132 return 0;133 134 if ( !hasState( HS_SENT_INIT ) )135 {136 if ( maxLength < _INITIAL_DATA_LENGTH )137 {138 PRINTF(0)("buffer too small for _INITIAL_DATA");139 setState( HS_COMPLETED );140 return 0;141 }142 143 setState( HS_SENT_INIT );144 memcpy(data, _INITIAL_DATA, _INITIAL_DATA_LENGTH);145 if ( this->isServer() )146 *reciever = clientId;147 return _INITIAL_DATA_LENGTH;148 }149 150 if ( hasState( HS_RECVD_INIT ) && hasState( HS_SENT_INIT ) && !hasState( HS_SENT_VER ) )151 {152 if ( maxLength < _ORXONOX_VERSION_LENGTH )153 {154 PRINTF(0)("buffer too small for version number");155 setState( HS_COMPLETED );156 return 0;157 }158 159 setState( HS_SENT_VER );160 memcpy(data, _ORXONOX_VERSION, _ORXONOX_VERSION_LENGTH);161 if ( this->isServer() )162 *reciever = clientId;163 return _ORXONOX_VERSION_LENGTH;164 }165 166 if ( isServer() && hasState( HS_RECVD_VER) && hasState( HS_SENT_VER ) && !hasState( HS_SENT_HID ) )167 {168 if ( maxLength < 2 )169 {170 PRINTF(0)("buffer too small for ID");171 setState( HS_COMPLETED );172 return 0;173 }174 175 setState( HS_SENT_HID );176 setState( HS_COMPLETED );177 178 if ( hasState( HS_DO_REJECT ) )179 {180 isOk = false;181 //memcpy(data, (byte*)0, 4);182 SYNCHELP_WRITE_INT( 0, NWT_HS_HOST_ID);183 SYNCHELP_WRITE_INT( 0, NWT_HS_NGM_ID);184 }185 else186 {187 isOk = true;188 //memcpy(data, &clientId, 4);189 SYNCHELP_WRITE_INT( clientId, NWT_HS_HOST_ID );190 SYNCHELP_WRITE_INT( networkGameManagerId, NWT_HS_NGM_ID );191 }192 *reciever = clientId;193 return SYNCHELP_WRITE_N;194 }195 196 return 0;197 }198 199 void Handshake::writeDebug( ) const200 {201 }202 203 void Handshake::readDebug( ) const204 {205 } -
trunk/src/lib/network/handshake.h
r6341 r7954 10 10 #include "synchronizeable.h" 11 11 12 #define _INITIAL_DATA "orxonox" 13 #define _INITIAL_DATA_LENGTH 7 12 #define _ORXONOX_ID 0xF91337A0 14 13 15 #define _ORXONOX_VERSION "\x00\x00\x00\x01" 16 #define _ORXONOX_VERSION_LENGTH 4 14 #define _ORXONOX_VERSION 1 17 15 18 typedef enum HandshakeState { 19 HS_SENT_INIT = 0x00000001, 20 HS_RECVD_INIT = 0x00000002, 21 HS_SENT_VER = 0x00000004, 22 HS_RECVD_VER = 0x00000008, 23 HS_SENT_HID = 0x00000010, 24 HS_RECVD_HID = 0x00000020, 25 HS_COMPLETED = 0x00000040, 26 27 HS_DO_REJECT = 0x00010000, 28 HS_WAS_REJECT = 0x00020000, 29 30 NUM_STATES 16 struct HandshakeState { 17 int orxId; 18 int version; 19 20 int networkManagerId; 21 int messageManagerId; 22 int hostId; 23 24 int completed; 25 int canDel; 26 27 int error; 28 29 std::string errorString; 31 30 }; 32 31 … … 34 33 { 35 34 public: 36 Handshake( bool server, int clientId = 0, int networkGameManagerId = 0);37 inline bool completed(){ return hasState( HS_COMPLETED ); }38 inline bool ok(){ return isOk; }39 inline int getHostId(){ return newHostId; }40 inline int getNetworkGameManagerId(){ return newNetworkGameManagerId; }41 42 inline void doReject( ){ setState(HS_DO_REJECT); }43 44 virtual int writeBytes(const byte* data, int length, int sender);45 virtual int readBytes(byte* data, int maxLength, int * reciever);46 virtual void writeDebug() const;47 virtual void readDebug() const;35 Handshake( bool server, int clientId = 0, int networkGameManagerId = 0, int messageManagerId = 0 ); 36 inline bool completed(){ return localState.completed != 0 && remoteState.completed != 0; } 37 inline bool ok(){ return localState.error == 0 && remoteState.error == 0; } 38 inline int getHostId(){ return remoteState.hostId; } 39 inline int getNetworkGameManagerId(){ return remoteState.networkManagerId; } 40 inline int getMessageManagerId(){ return remoteState.messageManagerId; } 41 inline void doReject( std::string reason ){ localState.error = 1; localState.errorString = "the server rejected your connection ["+ reason +"]"; } 42 inline bool canDel(){ return localState.canDel == 1 && remoteState.canDel == 1; } 43 inline bool allowDel(){ return localState.canDel == 1; } 44 inline void del(){ localState.canDel = 1; } 45 46 virtual void varChangeHandler( std::list<int> & id ); 48 47 49 48 private: 50 int state; 51 int clientId; 52 int networkGameManagerId; 53 int newHostId; 54 int newNetworkGameManagerId; 55 bool isOk; 56 57 inline bool hasState( int a ){ return (state & a) == a; } 58 inline void setState( int a ){ state = state | a; } 59 inline void unsetState( int a ){ state = state & (~a); } 49 HandshakeState localState; 50 HandshakeState remoteState; 51 52 int netManId_handler; 53 int msgManId_handler; 54 int hostId_handler; 55 int completed_handler; 56 int error_handler; 57 int errorString_handler; 58 int orxId_handler; 59 int version_handler; 60 int candel_id; 60 61 61 62 }; -
trunk/src/lib/network/netdefs.h
r6695 r7954 19 19 #define MAX_CONNECTIONS 1000 20 20 21 #define NETWORK_FREQUENCY 33 22 21 23 22 24 typedef unsigned char byte; … … 28 30 } NodeType; 29 31 32 typedef enum ConnectionType { 33 NET_UDP = 0, 34 NET_TCP 35 }; 36 30 37 31 38 typedef enum { -
trunk/src/lib/network/network_game_manager.cc
r7354 r7954 27 27 #include "shared_network_data.h" 28 28 #include "converter.h" 29 #include "message_manager.h" 29 30 30 31 #include "playable.h" … … 52 53 this->setClassID(CL_NETWORK_GAME_MANAGER, "NetworkGameManager"); 53 54 54 hasRequestedWorld = false;55 55 this->setSynchronized(true); 56 57 MessageManager::getInstance()->registerMessageHandler( MSGID_YOU_ARE, youAreHandler, NULL ); 56 58 } 57 59 … … 61 63 NetworkGameManager::~NetworkGameManager() 62 64 { 65 #if 0 63 66 for ( int i = 0; i<outBuffer.size(); i++) 64 67 { … … 66 69 delete outBuffer[i].buffer; 67 70 } 68 69 } 70 71 71 #endif 72 73 } 74 75 #if 0 72 76 int NetworkGameManager::writeBytes(const byte* data, int length, int sender) 73 77 { … … 141 145 { 142 146 sendEntityList( sender ); 143 continue;144 }145 else if ( b == NET_REQUEST_SYNC )146 {147 if ( !handleRequestSync( i, data, length, sender ) )148 return i;149 147 continue; 150 148 } … … 160 158 return i; 161 159 } 162 160 #endif 161 162 #if 0 163 163 int NetworkGameManager::readBytes(byte* data, int maxLength, int * reciever) 164 164 { … … 192 192 return 0; 193 193 } 194 194 #endif 195 196 #if 0 195 197 void NetworkGameManager::writeDebug() const 196 198 { … … 200 202 { 201 203 } 204 #endif 202 205 203 206 … … 211 214 if ( this->isServer()) 212 215 { 213 if ( SharedNetworkData::getInstance()->getNewUniqueID() < 0 ) 216 int res = this->executeCreateEntity( classID, SharedNetworkData::getInstance()->getNewUniqueID(), owner ); 217 218 if ( res < 0 ) 214 219 { 215 220 PRINTF(1)("Cannot create entity! There are no more uniqueIDs left!\n"); 216 221 return -1; 217 222 } 218 return this->executeCreateEntity( classID, SharedNetworkData::getInstance()->getNewUniqueID(), owner ); 223 224 return res; 219 225 } 220 226 else 221 227 { 228 #if 0 222 229 this->requestCreateEntity( classID ); 230 #endif 223 231 return -1; 224 232 } … … 288 296 else 289 297 { 298 #if 0 290 299 this->requestRemoveEntity( uniqueID ); 291 } 292 } 293 294 295 300 #endif 301 } 302 } 303 304 305 #if 0 296 306 /*! 297 307 * Creates the needed entity on the server if possible … … 311 321 } 312 322 } 313 323 #endif 324 325 #if 0 314 326 /*! 315 327 * Removes the specified entity on the server … … 329 341 } 330 342 } 343 #endif 331 344 332 345 /*! … … 337 350 int NetworkGameManager::executeCreateEntity(ClassID classID, int uniqueID, int owner) 338 351 { 352 #if 0 339 353 for ( int i = 0; i<outBuffer.size(); i++) 340 354 { … … 351 365 return -1; 352 366 } 353 367 #endif 354 368 PRINTF(0)("ExecuteCreateEntity: server side: classID: %x, uniqueID: %i, owner: %i\n", classID, uniqueID, owner); 355 369 doCreateEntity( classID, uniqueID, owner ); … … 365 379 void NetworkGameManager::executeRemoveEntity(int uniqueID) 366 380 { 381 #if 0 367 382 for ( int i = 0; i<outBuffer.size(); i++) 368 383 { … … 375 390 return; 376 391 } 392 #endif 377 393 378 394 doRemoveEntity(uniqueID); … … 388 404 } 389 405 406 #if 0 390 407 /*! 391 408 * Sends the Entities to the new connected client … … 443 460 signalNewPlayer( userID ); 444 461 } 462 #endif 445 463 446 464 … … 448 466 bool NetworkGameManager::signalNewPlayer(int userId) 449 467 { 450 if ( userId >= outBuffer.size() )451 resizeBufferVector( userId );452 453 468 /* create new playable for Player*/ 454 469 PRINTF(0)("Request for creation: %i\n", userId); … … 456 471 PRINTF(0)("Request for creation: userid: %i, uniqueid: %i\n", userId, uniqueId); 457 472 this->sendYouAre(uniqueId, userId); 458 459 473 } 460 474 … … 464 478 { 465 479 const std::list<BaseObject*>* playableList = ClassList::getList(CL_PLAYABLE); 480 481 if ( !playableList ) 482 return false; 483 466 484 std::list<BaseObject*>::const_iterator it = playableList->begin(); 467 485 … … 478 496 } 479 497 480 498 #if 0 481 499 /** 482 500 * Creates a buffer for user n … … 498 516 } 499 517 } 518 #endif 500 519 501 520 /** … … 532 551 s->setSynchronized(true); 533 552 //this->networkStream->connectSynchronizeable( *s ); 534 if ( !isServer() ) 535 s->setIsOutOfSync( true ); 553 536 554 PRINTF(0)("Fabricated %s with id %d\n", s->getClassName(), s->getUniqueID()); 537 555 … … 601 619 } 602 620 603 /** 604 * Tell the synchronizeable that a user's synchronizeable is out of sync 605 * @param uniqueID: unique ID assigned with the entity which is out of sync 606 * @param userID: user ID who's synchronizeable is out of sync 607 */ 608 void NetworkGameManager::doRequestSync( int uniqueID, int userID ) 609 { 610 SynchronizeableList::const_iterator it,e; 611 it = this->networkStream->getSyncBegin(); 612 e = this->networkStream->getSyncEnd(); 613 614 while ( it != e ) 615 { 616 if ( (*it)->getUniqueID() == uniqueID ) 617 { 618 (*it)->requestSync( userID ); 619 break; 620 } 621 it++; 622 } 623 } 624 621 #if 0 625 622 /** 626 623 * Copies length bytes to the clientBuffer with error checking … … 641 638 return true; 642 639 } 643 640 #endif 641 642 #if 0 644 643 /** 645 644 * Reads data from clientBuffer with error checking … … 660 659 return true; 661 660 } 661 #endif 662 662 663 663 /** … … 687 687 } else 688 688 { 689 PRINTF(1)("UniqueID is not a Playable\n");689 PRINTF(1)("UniqueID %d is not a Playable\n", uniqueID); 690 690 } 691 691 } … … 697 697 assert(player != NULL); 698 698 699 s->setIsOutOfSync( true );700 701 699 PRINTF(0)("uniqueID = %d\n", s->getUniqueID()); 702 700 … … 715 713 if ( !isServer() ) 716 714 return; 717 718 if ( userID != 0 ) 719 { 720 if ( !writeToClientBuffer( outBuffer[userID], (byte)NET_YOU_ARE_ENTITY ) ) 721 return; 722 723 if ( !writeToClientBuffer( outBuffer[userID], uniqueID ) ) 724 return; 725 } 726 else 727 { 728 doYouAre(uniqueID); 729 } 715 716 byte buf[INTSIZE]; 717 718 Converter::intToByteArray( uniqueID, buf, INTSIZE ); 719 720 MessageManager::getInstance()->sendMessage( MSGID_YOU_ARE, buf, INTSIZE, RT_USER, userID, MP_HIGHBANDWIDTH); 730 721 } 731 722 … … 902 893 return true; 903 894 } 904 905 bool NetworkGameManager::handleRequestSync( int & i, const byte * data, int length, int sender )906 {907 if ( INTSIZE > length-i )908 {909 PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");910 return false;911 }912 int uniqueID;913 i += Converter::byteArrayToInt( &data[i], &uniqueID );914 915 PRINTF(0)("handleRequestSync %d %d\n", uniqueID, sender);916 doRequestSync( uniqueID, sender );917 918 return true;919 }920 921 895 922 896 /** … … 958 932 } 959 933 960 934 bool NetworkGameManager::youAreHandler( MessageId messageId, byte * data, int dataLength, void * someData, int userId ) 935 { 936 assert( dataLength == INTSIZE ); 937 int uniqueId; 938 939 Converter::byteArrayToInt( data, &uniqueId ); 940 941 SynchronizeableList::const_iterator it = NetworkGameManager::getInstance()->networkStream->getSyncBegin(); 942 943 Playable *p = NULL; 944 Synchronizeable *s = NULL; 945 946 for ( ; it !=NetworkGameManager::getInstance()->networkStream->getSyncEnd(); it++ ) 947 { 948 if ( (*it)->getUniqueID()==uniqueId ) 949 { 950 break; 951 } 952 } 953 954 if ( it == NetworkGameManager::getInstance()->networkStream->getSyncEnd() ) 955 return false; 956 957 NetworkGameManager::getInstance()->doYouAre( uniqueId ); 958 959 return true; 960 } 961 962 #if 0 961 963 bool NetworkGameManager::writeToClientBuffer( clientBuffer & cb, byte b ) 962 964 { … … 971 973 return true; 972 974 } 975 973 976 974 977 bool NetworkGameManager::writeToClientBuffer( clientBuffer & cb, int i ) … … 985 988 return true; 986 989 } 987 988 void NetworkGameManager::sync( int uniqueID, int owner ) 989 { 990 /*if ( owner==this->getHostID() ) 991 return;*/ 992 993 if ( !isServer() ) 994 executeRequestSync( uniqueID, 0 ); 995 else 996 executeRequestSync( uniqueID, owner ); 997 } 998 999 void NetworkGameManager::executeRequestSync( int uniqueID, int user ) 1000 { 1001 PRINTF(0)("executeRequestSync %d %d\n", uniqueID, user); 1002 if ( user >= outBuffer.size() ) 1003 resizeBufferVector( user ); 1004 1005 if ( !writeToClientBuffer( outBuffer[user], (byte)NET_REQUEST_SYNC ) ) 1006 return; 1007 if ( !writeToClientBuffer( outBuffer[user], uniqueID ) ) 1008 return; 1009 } 1010 990 #endif 991 992 -
trunk/src/lib/network/network_game_manager.h
r6981 r7954 12 12 /* include base_object.h since all classes are derived from this one */ 13 13 #include "synchronizeable.h" 14 #include "message_manager.h" 14 15 15 16 16 17 class TiXmlElement; 17 18 class PNode; 18 19 /**20 * protocol definition21 *22 * CREATE_ENTITY: >> CLASS_ID, UNIQUE_ID, OWNER23 * REMOVE_ENTITY: >> UNIQUE_ID24 *25 * CREATE_ENTITY_LIST: >> NUMBER, [CLASS_ID, UNIQUE_ID, OWNER][0..NUMBER]26 * REMOVE_ENTITY_LIST: >> NUMBER, [UNIQUE_ID][0..NUMBER]27 *28 * REQUEST_CREATE: >> CLASS_ID29 * << [Sync Info]30 * REQUEST_REMOVE: >> UNIQUE_ID31 * << [Sync Info]32 *33 * //REQUEST_CREATE_LIST: NUMBER, [CLASS_ID][0..NUMBER]34 * //REQUEST_CREATE_LIST: NUMBER, [UNIQUE_ID][0..NUMBER]35 *36 * REQUEST_ENTITY_LIST: //request the whole world :D37 * REQUEST_SYNC: >> UNIQUE_ID38 * << [Sync Info]39 * //REQUEST_SYNC_LIST: NUMBER, [UNIQUE_ID][0..NUMBER]40 *41 * YOU_ARE_ENTITY: >> UNIQUE_ID42 *43 * REQUEST_PNODE_PATH >> UNIQUE_ID_START UNIQUE_ID_STOP44 * << UNIQUE_ID_1 UNIQUE_ID_2 UNIQUE_ID_3 ... UNIQUE_ID_N45 *46 * SEND_PNODE_PATH >> UNIQUE_ID_START UNIQUE_ID_STOP NUMBER [UNIQUE_ID][0..NUMBER]47 */48 19 49 20 typedef enum NetworkGameManagerProtocol { … … 54 25 NET_REQUEST_CREATE, 55 26 NET_REQUEST_REMOVE, 56 NET_REQUEST_SYNC,57 27 NET_YOU_ARE_ENTITY, 58 28 NET_REQUEST_ENTITY_LIST, … … 81 51 { if (!NetworkGameManager::singletonRef) NetworkGameManager::singletonRef = new NetworkGameManager(); return NetworkGameManager::singletonRef; } 82 52 53 #if 0 83 54 virtual int writeBytes(const byte* data, int length, int sender); 84 55 virtual int readBytes(byte* data, int maxLength, int * reciever); 85 56 virtual void writeDebug() const; 86 57 virtual void readDebug() const; 58 #endif 87 59 88 60 int createEntity( ClassID classID, int owner = 0 ); … … 91 63 void sendYouAre( int uniqueID, int userID ); 92 64 93 void sync(int uniqueID, int owner); 94 65 #if 0 95 66 void sendEntityList(int userID); 67 #endif 96 68 97 69 bool signalNewPlayer(int userId); … … 101 73 private: 102 74 NetworkGameManager(); 75 76 static bool youAreHandler(MessageId messageId, byte * data, int dataLength, void * someData, int userId ); 103 77 104 78 … … 111 85 bool handleRemoveEntityList( int& i, const byte* data, int length, int sender ); 112 86 bool handleYouAreEntity( int& i, const byte* data, int length, int sender ); 113 bool handleRequestSync( int& i, const byte* data, int length, int sender );114 87 bool handleRequestPNodePath(int& i, const byte* data, int length, int sender); 115 88 bool handleSendPNodePath(int& i, const byte* data, int length, int sender); … … 117 90 118 91 /* some network handlers helper functions */ 119 void requestCreateEntity(ClassID classID);92 // void requestCreateEntity(ClassID classID); 120 93 int executeCreateEntity(ClassID classID, int uniqueID = 0, int owner = 0); 121 94 BaseObject* doCreateEntity(ClassID classID, int uniqueID, int owner); 122 95 123 void requestRemoveEntity(int uniqueID);96 // void requestRemoveEntity(int uniqueID); 124 97 void executeRemoveEntity(int uniqueID); 125 98 void doRemoveEntity(int uniqueID); 126 99 127 void executeRequestSync( int uniqueID, int user );128 void doRequestSync(int uniqueID, int userID);129 130 100 void doYouAre( int uniqueID ); 131 101 132 void requestPNodePath(const PNode* node1, const PNode* node2);102 // void requestPNodePath(const PNode* node1, const PNode* node2); 133 103 void executeRequestPNodePath(const PNode* node2, const PNode* node2); 134 104 void doRequestPNodePath(const PNode* node1, const PNode* node2); 135 105 136 106 bool canCreateEntity(ClassID classID); 107 #if 0 108 void resizeBufferVector(int n); 137 109 138 void resizeBufferVector(int n);139 110 140 111 bool writeToClientBuffer( clientBuffer &cb, byte*data, int length ); … … 142 113 bool writeToClientBuffer( clientBuffer &cb, int i ); 143 114 bool readFromClientBuffer( clientBuffer &cb, byte*data, int length ); 144 115 #endif 145 116 146 117 private: 118 #if 0 147 119 std::vector<clientBuffer> outBuffer; 148 120 //clientBuffer allOutBuffer; 121 #endif 149 122 static NetworkGameManager* singletonRef; 150 bool hasRequestedWorld;151 123 }; 152 124 -
trunk/src/lib/network/network_manager.cc
r7256 r7954 28 28 #include "shared_network_data.h" 29 29 #include "network_stream.h" 30 #include "preferences.h" 31 #include "network_log.h" 30 32 31 33 … … 52 54 this->defaultSyncStream = NULL; 53 55 this->sharedNetworkData = SharedNetworkData::getInstance(); 56 this->elapsedTime = 0.0f; 57 58 59 int port = Preferences::getInstance()->getInt( "network", "telnetport", 0 ); 60 61 if ( port > 0 ) 62 NetworkLog::getInstance()->listen( port ); 54 63 55 64 PRINTF(0)("NetworkManager created\n"); … … 72 81 this->netStreamList = ClassList::getList(CL_SYNCHRONIZEABLE); 73 82 PRINTF(0)("NetworkManager initzalized\n"); 83 74 84 } 75 85 … … 90 100 int NetworkManager::establishConnection(const std::string & name, unsigned int port) 91 101 { 92 IPaddress ipAddress; 93 int error = SDLNet_ResolveHost(&ipAddress, name.c_str(), port); 94 if( error == -1) { 95 printf("\n\nerror on address resolution, program inconsistency\n\n"); 96 return -1; 97 } 98 99 this->defaultSyncStream = new NetworkStream(ipAddress); 102 this->defaultSyncStream = new NetworkStream( name, port ); 100 103 this->sharedNetworkData->setDefaultSyncStream(this->defaultSyncStream); 101 104 this->defaultSyncStream->startHandshake(); … … 130 133 /** 131 134 * sync the network 135 * @param dtS: the seceonds elapsed since the last synchronize call 132 136 */ 133 void NetworkManager::synchronize( )137 void NetworkManager::synchronize( float dtS) 134 138 { 139 this->elapsedTime += dtS; 140 if( likely(this->elapsedTime < 1.0f / NETWORK_FREQUENCY)) 141 return; 142 this->elapsedTime = 0.0f; 143 135 144 if (this->netStreamList != NULL || (this->netStreamList = ClassList::getList(CL_NETWORK_STREAM)) != NULL) 136 145 { -
trunk/src/lib/network/network_manager.h
r7256 r7954 45 45 46 46 void connectSynchronizeable(Synchronizeable& sync); 47 void synchronize( );47 void synchronize(float dtS); 48 48 49 49 void debug(); … … 61 61 62 62 SharedNetworkData* sharedNetworkData; //!< reference to the shared data 63 float elapsedTime; //!< elapsed time since the last network update 63 64 }; 64 65 -
trunk/src/lib/network/network_socket.cc
r7440 r7954 21 21 #define DEBUG_MODULE_NETWORK 22 22 23 #include "converter.h"24 25 23 /* include your own header */ 26 24 #include "network_socket.h" … … 34 32 NetworkSocket::NetworkSocket() 35 33 { 36 this->init();34 bOk = true; 37 35 } 38 36 39 /** 40 * Constructor to connect directly 41 */ 42 NetworkSocket::NetworkSocket(IPaddress ip) 37 NetworkSocket::~ NetworkSocket( ) 43 38 { 44 this->init();45 connectToServer(ip);46 }47 48 49 NetworkSocket::NetworkSocket( TCPsocket sock )50 {51 this->init();52 this->tcpSocket = sock;53 54 readThread = SDL_CreateThread(thread_read, (void*)this);55 writeThread = SDL_CreateThread(thread_write, (void*)this);56 }57 58 void NetworkSocket::init()59 {60 /* set the class id for the base object */61 this->setClassID(CL_NETWORK_SOCKET, "NetworkSocket");62 63 tcpSocket = NULL;64 incomingBufferLength = 0;65 outgoingBufferLength = 0;66 67 readThread = NULL;68 writeThread = NULL;69 70 71 thread_write_running = false;72 thread_read_running = false;73 74 incomingBufferMutex = SDL_CreateMutex();75 outgoingBufferMutex = SDL_CreateMutex();76 77 78 socketMutex = SDL_CreateMutex();79 terminateThread = false;80 81 /* Init SDL_net */82 //NOTE: do we need to call SDLNet_Init for all instances?83 if(SDLNet_Init()==-1)84 {85 PRINTF(1)("SDLNet_Init: %s\n", SDLNet_GetError());86 return;87 }88 else89 PRINTF(5)("SDL_net initialized\n");90 91 PRINTF(0)("NetworkSocket created\n");92 93 39 } 94 40 95 41 96 42 97 /**98 * Default destructor99 * dont use this from outside: use destroy() instead!!100 */101 NetworkSocket::~NetworkSocket( )102 {103 this->terminateThread = true;104 /* Quit SDL_net */105 // NOTE: what if other instances of NetworkSocket running?106 SDLNet_Quit();107 PRINTF(5)("SDL_net shutdown\n");108 109 SDL_DestroyMutex(incomingBufferMutex);110 SDL_DestroyMutex(outgoingBufferMutex);111 SDL_DestroyMutex(socketMutex);112 SDL_DestroyMutex(threadTerminationMutex);113 }114 115 /**116 * This function establishes a TCP/UDP connection to a given server (function argument).117 * It is called by the NetworkStream. It creates a TCP/UDP socket for the connection.118 * @param ip119 */120 void NetworkSocket::connectToServer(IPaddress ip)121 {122 //HACK this will cause segfault123 #warning remove this124 int * a;125 *a = 99;126 //check if not already connected or listening127 if (tcpSocket)128 {129 PRINTF(1)("NetworkSocket::listen: tcpSocket!=NULL! maybe you already called listen or connectToServer or did not call disconnectServer()!");130 }131 132 /* Connect to the host and port contained in ip using a TCP connection. */133 tcpSocket = SDLNet_TCP_Open(&ip);134 if(!tcpSocket)135 {136 PRINTF(1)("SDLNet_TCP_Open: %s\n", SDLNet_GetError());137 return;138 }139 140 readThread = SDL_CreateThread(thread_read, (void*)this);141 writeThread = SDL_CreateThread(thread_write, (void*)this);142 }143 144 145 /**146 * DTears down a TCP/UDP connection.147 */148 void NetworkSocket::disconnectServer( )149 {150 terminateThread = true;151 /* Close the connection */152 153 SDL_mutexP(socketMutex);154 SDLNet_TCP_Close(tcpSocket);155 tcpSocket = NULL;156 SDL_mutexV(socketMutex);157 }158 159 160 /**161 * This function writes some bytes (data) to the network connection (if the connection is already162 * estabilhed) otherwise it just does nothing (silently discarding the data). And writes some163 * warnings164 * @param data: pointer to the data to send165 * @param length: n bytes to send166 * @return the number successfully written bytes167 */168 int NetworkSocket::writeBytes(byte * data, int length)169 {170 PRINTF(5)("NetworkSocket::writeBytes()\n");171 #ifdef _USE_OUTGOING_BUFFER172 173 #define min(a,b) (a<b)?a:b174 int nbytes = min(_OUTGOING_BUFFER_SIZE - outgoingBufferLength, length);175 #undef min176 177 if (!tcpSocket || data==NULL || nbytes<=0)178 {179 assert(_OUTGOING_BUFFER_SIZE - outgoingBufferLength > 0);180 return 0;181 }182 183 SDL_mutexP(outgoingBufferMutex);184 185 memcpy(outgoingBuffer + outgoingBufferLength, data, nbytes);186 outgoingBufferLength += nbytes;187 188 SDL_mutexV(outgoingBufferMutex);189 190 191 return nbytes;192 #else193 SDL_mutexP(socketMutex);194 195 if (!tcpSocket || data==NULL)196 return 0;197 198 int res = SDLNet_TCP_Send(tcpSocket, data, length);199 200 SDL_mutexV(socketMutex);201 202 if (res<length)203 PRINTF(1)("SDLNet_TCP_Send: %s\n", SDLNet_GetError());204 205 return res;206 #endif207 }208 209 /**210 * Reads in the bytes from the network interface and passes it to the NetworkStream.211 * This function must internaly be implemented/connected as a thread, since the read212 * functions of many network libraries are blocking an would therefore block the whole213 * program.214 * From outside, the thread shouldn't be accessible at all.215 * @param data: pointer to memory, big enough to store length bytes216 * @param length: n bytes to read217 * @return the number successfully read bytes. -1 on error. may be less than length!218 */219 int NetworkSocket::readBytes(byte * data, int length)220 {221 PRINTF(5)("NetworkSocket::readBytes()\n");222 if (data==NULL)223 return 0;224 225 int nbytes = (length<incomingBufferLength) ? length : incomingBufferLength;226 227 228 //printf("readBytes: nbytes = %d; length=%d; incomingBufferLength=%d\n", nbytes, length, incomingBufferLength);229 230 // just in case ...231 if (nbytes<0)232 return -1;233 234 if (nbytes==0)235 return 0;236 237 SDL_mutexP(incomingBufferMutex);238 239 memcpy(data, incomingBuffer, nbytes);240 241 //important: use memmove because the memory areas may overlap242 memmove(incomingBuffer, incomingBuffer+nbytes, incomingBufferLength-nbytes);243 incomingBufferLength -= nbytes;244 245 SDL_mutexV(incomingBufferMutex);246 247 return nbytes;248 }249 250 /**251 * Reads in the bytes form the network interface and passes it to the NetworkStream.252 * It only reads the bytes if there are enough bytes in our buffer.253 * @param data: pointer to memory, big enough to store length bytes254 * @param length: n bytes to read255 * @return the number successfully read bytes. -1 on error. 0 if there are not enough bytes in our buffer.256 */257 int NetworkSocket::readBlock(byte * data, int length)258 {259 printf("NetworkSocket: got %i bytes, NetworkStream requested %i bytes\n", this->incomingBufferLength, length);260 if (incomingBufferLength >= length)261 return readBytes(data, length);262 else return 0;263 }264 265 266 /**267 * used to create a thread to read from socket268 * @param data: pointer to NetworkSocket269 */270 int NetworkSocket::thread_read( void * data )271 {272 int nbytesread = 0;273 int nbytestoread = 0;274 char buffer[_LOCAL_BUFFER_SIZE];275 NetworkSocket * self = (NetworkSocket*)data;276 277 self->thread_read_running = true;278 279 while (!self->terminateThread)280 {281 #define min(a,b) (a<b)?a:b282 nbytestoread = min(_INCOMING_BUFFER_SIZE - self->incomingBufferLength, _LOCAL_BUFFER_SIZE);283 #undef min284 285 //if buffer is full286 if (nbytestoread<=0 || !self->tcpSocket)287 {288 SDL_Delay(_MSECONDS_SLEEP_FULL_BUFFER);289 continue;290 }291 292 nbytesread = SDLNet_TCP_Recv(self->tcpSocket, buffer, nbytestoread);293 294 SDL_mutexP(self->incomingBufferMutex);295 296 if (nbytesread<=0)297 {298 if (nbytesread<0)299 printf("SDLNet_TCP_Recv: %s\n", SDLNet_GetError());300 301 SDL_mutexP(self->socketMutex);302 303 SDLNet_TCP_Close(self->tcpSocket);304 self->tcpSocket = NULL;305 306 SDL_mutexV(self->socketMutex);307 SDL_mutexV(self->incomingBufferMutex);308 continue;309 }310 311 //printf("thread_read: nbytesread=%d\n", nbytesread);312 313 memcpy(self->incomingBuffer+self->incomingBufferLength, buffer, nbytesread);314 self->incomingBufferLength += nbytesread;315 316 SDL_mutexV(self->incomingBufferMutex);317 }318 319 SDL_mutexP(self->threadTerminationMutex);320 self->thread_read_running = false;321 322 if ( !self->thread_write_running )323 {324 //delete self;325 SDL_mutexV(self->threadTerminationMutex);326 }327 else328 {329 SDL_mutexV(self->threadTerminationMutex);330 }331 332 333 #ifdef DONTEXITTHREADS334 while ( true )335 {336 SDL_Delay(1000);337 }338 #endif339 340 PRINTF(0)("QUIT READ THREAD\n");341 342 return 0;343 }344 345 int NetworkSocket::thread_write( void * data )346 {347 int nbyteswrite = 0;348 int nbytestowrite = 0;349 char buffer[_LOCAL_BUFFER_SIZE];350 NetworkSocket * self = (NetworkSocket*)data;351 352 self->thread_write_running = true;353 354 while (!self->terminateThread)355 {356 #define min(a,b) (a<b)?a:b357 nbytestowrite = min(self->outgoingBufferLength, _LOCAL_BUFFER_SIZE);358 #undef min359 360 // printf("thread_write nbytes=%d listening=%d\n", nbytestowrite, (int)self->_isListening);361 362 //if buffer is full363 if (nbytestowrite<=0 || !self->tcpSocket)364 {365 SDL_Delay(_MSECONDS_SLEEP_EMPTY_BUFFER);366 continue;367 }368 369 SDL_mutexP(self->outgoingBufferMutex);370 371 //printf("a\n");372 373 memcpy(buffer, self->outgoingBuffer, nbytestowrite);374 self->outgoingBufferLength -= nbytestowrite;375 memmove(self->outgoingBuffer, self->outgoingBuffer+nbytestowrite, self->outgoingBufferLength);376 377 SDL_mutexV(self->outgoingBufferMutex);378 379 nbyteswrite = SDLNet_TCP_Send(self->tcpSocket, buffer, nbytestowrite);380 381 if (nbyteswrite<=0)382 {383 printf("SDLNet_TCP_Recv: %s\n", SDLNet_GetError());384 385 SDL_mutexP(self->socketMutex);386 387 SDLNet_TCP_Close(self->tcpSocket);388 self->tcpSocket = NULL;389 390 SDL_mutexV(self->socketMutex);391 continue;392 }393 394 }395 396 SDL_mutexP(self->threadTerminationMutex);397 self->thread_write_running = false;398 399 if ( !self->thread_read_running )400 {401 //delete self;402 SDL_mutexV(self->threadTerminationMutex);403 }404 else405 {406 SDL_mutexV(self->threadTerminationMutex);407 }408 409 #ifdef DONTEXITTHREADS410 while ( true )411 {412 SDL_Delay(1000);413 }414 #endif415 416 PRINTF(0)("QUIT WRITE THREAD\n");417 418 return 0;419 420 }421 422 bool NetworkSocket::writePacket( byte * data, int length )423 {424 PRINTF(5)("NetworkSocket::writePacket() size=%d\n", length);425 426 if ( length > 1024 )427 PRINTF(2)("WARNING SENDING BIG PACKET SIZE = %d\n", length);428 429 byte blen[INTSIZE];430 431 Converter::intToByteArray( length, blen, INTSIZE );432 433 writeBytes(blen, INTSIZE);434 writeBytes(data, length);435 }436 437 int NetworkSocket::readPacket( byte * data, int maxLength )438 {439 PRINTF(5)("NetworkSocket::readPacket()\n");440 if (incomingBufferLength<INTSIZE)441 {442 return 0;443 }444 445 int blen;446 Converter::byteArrayToInt( incomingBuffer, &blen );447 448 if (blen>maxLength)449 {450 PRINTF(1)("Buffersize is too small (%d) for packet (%d).\n", maxLength, blen);451 assert(false);452 return 0;453 }454 455 if (blen>incomingBufferLength)456 {457 return 0;458 }459 460 byte t[INTSIZE];461 readBytes(t, INTSIZE);462 int res = readBytes(data, blen);463 464 if (res!=blen)465 return -1;466 else467 return blen;468 469 }470 471 -
trunk/src/lib/network/network_socket.h
r6994 r7954 8 8 #define _NETWORK_SOCKET 9 9 10 //TODO HACK else gdb will not work on server11 #define DONTEXITTHREADS12 13 //if you want to use outgoing buffer define _USE_OUTGOING_BUFFER14 #define _USE_OUTGOING_BUFFER15 16 #define _INCOMING_BUFFER_SIZE 202400017 #define _OUTGOING_BUFFER_SIZE 202400018 #define _LOCAL_BUFFER_SIZE 102419 //sleep if incoming buffer is full20 #define _MSECONDS_SLEEP_FULL_BUFFER 1021 //sleep if outgoing buffer is empty22 #define _MSECONDS_SLEEP_EMPTY_BUFFER 1023 24 25 /* contains memmove and memcpy */26 #include <string.h>27 28 #ifdef HAVE_SDL_H29 #include <SDL_thread.h>30 #else31 #include <SDL/SDL_thread.h>32 #endif33 10 /* include this file, it contains some default definitions */ 34 11 #include "netdefs.h" … … 38 15 #include "base_object.h" 39 16 40 /* using namespace std is default, this needs to be here */41 using namespace std;42 43 17 class NetworkSocket : public BaseObject 44 18 { 19 public: 20 NetworkSocket(); 21 virtual ~NetworkSocket(); 45 22 46 private: 47 // IPaddress serverAddress; 48 // unsigned int port; 49 TCPsocket tcpSocket; 50 // UDPsocket udpSocket; 23 /** 24 * connect to server on host with port port 25 * @param host hostname might be xxx.xxx.xxx.xxx or localhost ... 26 * @param port port to connect to 27 */ 28 virtual void connectToServer( std::string host, int port ) = 0; 29 30 /** 31 * disconnect from server 32 */ 33 virtual void disconnectServer() = 0; 51 34 52 byte incomingBuffer[_INCOMING_BUFFER_SIZE]; 53 #ifdef _USE_OUTGOING_BUFFER 54 byte outgoingBuffer[_OUTGOING_BUFFER_SIZE]; 55 #endif 56 int incomingBufferLength; 57 #ifdef _USE_OUTGOING_BUFFER 58 int outgoingBufferLength; 59 #endif 35 /** 36 * send packet to connected socket. will be recieved as whole packet 37 * @param data pointer to data to send 38 * @param length lengt of packet to send 39 * @return true on success 40 */ 41 virtual bool writePacket(byte * data, int length) = 0; 42 43 /** 44 * read a packet sent by another NetworkSocket 45 * @param data data will be copied here 46 * @param maxLength readPacket will not read more than maxLength 47 * @return bytes read. on error less than zero 48 */ 49 virtual int readPacket(byte * data, int maxLength) = 0; 60 50 61 SDL_mutex * incomingBufferMutex; 62 #ifdef _USE_OUTGOING_BUFFER 63 SDL_mutex * outgoingBufferMutex; 64 #endif 65 SDL_mutex * socketMutex; 66 bool terminateThread; 67 68 SDL_mutex* threadTerminationMutex; 69 static int thread_read(void * data); 70 bool thread_read_running; 71 bool thread_write_running; 72 73 SDL_Thread* readThread; 74 SDL_Thread* writeThread; 75 76 #ifdef _USE_OUTGOING_BUFFER 77 static int thread_write(void * data); 78 #endif 79 80 int writeBytes(byte * data, int length); 81 int readBytes(byte * data, int length); 82 int readBlock(byte * data, int length); 83 84 void init(); 85 86 public: 87 88 NetworkSocket(); 89 virtual ~NetworkSocket(); 90 NetworkSocket(IPaddress ip); 91 NetworkSocket(TCPsocket sock); 92 void destroy() { terminateThread = true; }; 93 94 95 void connectToServer(IPaddress ip); 96 void disconnectServer(); 97 98 bool writePacket(byte * data, int length); 99 int readPacket(byte * data, int maxLength); 100 101 inline bool isOk() { return tcpSocket!=NULL; } 51 /** 52 * check if socket is ok 53 * @return true if socket is ok 54 */ 55 inline bool isOk() { return this->bOk; } 56 57 protected: 58 bool bOk; //!< check for socket status 102 59 103 60 }; -
trunk/src/lib/network/network_stream.cc
r6959 r7954 23 23 #include "base_object.h" 24 24 #include "network_protocol.h" 25 #include "network_socket.h" 25 #include "udp_socket.h" 26 #include "udp_server_socket.h" 26 27 #include "connection_monitor.h" 27 28 #include "synchronizeable.h" 28 29 #include "network_game_manager.h" 29 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" 30 41 31 42 #include "debug.h" … … 49 60 /* initialize the references */ 50 61 this->type = NET_CLIENT; 51 this->networkProtocol = new NetworkProtocol(); 52 this->connectionMonitor = new ConnectionMonitor(); 53 } 54 55 56 NetworkStream::NetworkStream(IPaddress& address) 62 } 63 64 65 NetworkStream::NetworkStream( std::string host, int port ) 57 66 { 58 67 this->type = NET_CLIENT; 59 68 this->init(); 60 this-> networkSockets.push_back(new NetworkSocket(address));61 this-> networkProtocol = new NetworkProtocol();62 this-> connectionMonitor = new ConnectionMonitor();63 this-> maxConnections = 1;64 } 65 66 67 NetworkStream::NetworkStream( unsigned int port)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 ) 68 77 { 69 78 this->type = NET_SERVER; 70 79 this->init(); 71 this->serverSocket = new ServerSocket(port); 72 this->networkProtocol = new NetworkProtocol(); 73 this->connectionMonitor = new ConnectionMonitor(); 74 this->networkSockets.push_back( NULL ); 75 this->networkSockets[0] = NULL; //TODO: remove this 76 this->handshakes.push_back( NULL ); 80 this->serverSocket = new UdpServerSocket(port); 77 81 this->bActive = true; 78 82 } … … 87 91 this->networkGameManager = NULL; 88 92 myHostId = 0; 93 currentState = 0; 94 95 remainingBytesToWriteToDict = Preferences::getInstance()->getInt( "compression", "writedict", 0 ); 96 97 assert( Zip::getInstance()->loadDictionary( "testdict" ) ); 89 98 } 90 99 … … 98 107 } 99 108 100 for (NetworkSocketVector::iterator i = networkSockets.begin(); i!=networkSockets.end(); i++) 101 { 102 if ( *i ) 103 { 104 (*i)->disconnectServer(); 105 (*i)->destroy(); 106 } 107 } 108 109 for (HandshakeVector::iterator i = handshakes.begin(); i!=handshakes.end(); i++) 110 { 111 if ( *i ) 112 { 113 delete (*i); 114 } 115 } 116 117 delete connectionMonitor; 118 delete networkProtocol; 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 119 131 } 120 132 … … 125 137 // setUniqueID( maxCon+2 ) because we need one id for every handshake 126 138 // and one for handshake to reject client maxCon+1 127 this->networkGameManager->setUniqueID( this->maxConnections + 2 ); 128 //this->connectSynchronizeable( *(this->networkGameManager) ); 129 this->setMaxConnections( 10 ); 139 this->networkGameManager->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() ); 140 MessageManager::getInstance()->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() ); 130 141 } 131 142 … … 135 146 Handshake* hs = new Handshake(false); 136 147 hs->setUniqueID( 0 ); 137 this->handshakes.push_back(hs); 148 assert( peers[0].handshake == NULL ); 149 peers[0].handshake = hs; 150 // peers[0].handshake->setSynchronized( true ); 138 151 //this->connectSynchronizeable(*hs); 139 PRINTF(0)("NetworkStream: %s\n", hs->getName()); 152 //this->connectSynchronizeable(*hs); 153 PRINTF(0)("NetworkStream: Handshake created: %s\n", hs->getName()); 140 154 } 141 155 … … 146 160 sync.setNetworkStream( this ); 147 161 148 if( this->networkSockets.size()>0 ) 149 this->bActive = true; 162 this->bActive = true; 150 163 } 151 164 … … 157 170 if (disconnectSynchro != this->synchronizeables.end()) 158 171 this->synchronizeables.erase(disconnectSynchro); 159 160 if( this->networkSockets.size()<=0 ) 161 this->bActive = false; 172 173 oldSynchronizeables[sync.getUniqueID()] = SDL_GetTicks(); 162 174 } 163 175 … … 165 177 void NetworkStream::processData() 166 178 { 179 currentState++; 180 167 181 if ( this->type == NET_SERVER ) 182 { 183 if ( serverSocket ) 184 serverSocket->update(); 185 168 186 this->updateConnectionList(); 187 } 169 188 else 170 189 { 171 if ( networkSockets[0] && !networkSockets[0]->isOk() )190 if ( peers[0].socket && ( !peers[0].socket->isOk() || peers[0].connectionMonitor->hasTimedOut() ) ) 172 191 { 173 192 PRINTF(1)("lost connection to server\n"); 174 193 175 //delete networkSockets[i]; 176 networkSockets[0]->disconnectServer(); 177 networkSockets[0]->destroy(); 178 networkSockets[0] = NULL; 179 180 if ( handshakes[0] ) 181 delete handshakes[0]; 182 handshakes[0] = NULL; 183 } 184 } 185 186 for (int i = 0; i<handshakes.size(); i++) 187 { 188 if ( handshakes[i] ) 189 { 190 if ( handshakes[i]->completed() ) 194 peers[0].socket->disconnectServer(); 195 delete peers[0].socket; 196 peers[0].socket = NULL; 197 198 if ( peers[0].handshake ) 199 delete peers[0].handshake; 200 peers[0].handshake = NULL; 201 } 202 } 203 204 cleanUpOldSyncList(); 205 handleHandshakes(); 206 207 // order of up/downstream is important!!!! 208 // don't change it 209 handleDownstream(); 210 handleUpstream(); 211 212 } 213 214 void NetworkStream::updateConnectionList( ) 215 { 216 //check for new connections 217 218 NetworkSocket* tempNetworkSocket = serverSocket->getNewSocket(); 219 220 if ( tempNetworkSocket ) 221 { 222 int clientId; 223 if ( freeSocketSlots.size() >0 ) 224 { 225 clientId = freeSocketSlots.back(); 226 freeSocketSlots.pop_back(); 227 peers[clientId].socket = tempNetworkSocket; 228 peers[clientId].handshake = new Handshake(true, clientId, this->networkGameManager->getUniqueID(), MessageManager::getInstance()->getUniqueID() ); 229 peers[clientId].connectionMonitor = new ConnectionMonitor( clientId ); 230 peers[clientId].handshake->setUniqueID(clientId); 231 peers[clientId].userId = clientId; 232 peers[clientId].isServer = false; 233 } else 234 { 235 clientId = 1; 236 237 for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ ) 238 if ( it->first >= clientId ) 239 clientId = it->first + 1; 240 241 peers[clientId].socket = tempNetworkSocket; 242 peers[clientId].handshake = new Handshake(true, clientId, this->networkGameManager->getUniqueID(), MessageManager::getInstance()->getUniqueID()); 243 peers[clientId].handshake->setUniqueID(clientId); 244 peers[clientId].connectionMonitor = new ConnectionMonitor( clientId ); 245 peers[clientId].userId = clientId; 246 peers[clientId].isServer = false; 247 248 PRINTF(0)("num sync: %d\n", synchronizeables.size()); 249 } 250 251 if ( clientId > MAX_CONNECTIONS ) 252 { 253 peers[clientId].handshake->doReject( "too many connections" ); 254 PRINTF(0)("Will reject client %d because there are to many connections!\n", clientId); 255 } 256 else 257 258 PRINTF(0)("New Client: %d\n", clientId); 259 260 //this->connectSynchronizeable(*handshakes[clientId]); 261 } 262 263 //check if connections are ok else remove them 264 for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ ) 265 { 266 if ( 267 it->second.socket && 268 ( 269 !it->second.socket->isOk() || 270 it->second.connectionMonitor->hasTimedOut() 271 ) 272 ) 273 { 274 std::string reason = "disconnected"; 275 if ( it->second.connectionMonitor->hasTimedOut() ) 276 reason = "timeout"; 277 PRINTF(0)("Client is gone: %d (%s)\n", it->second.userId, reason.c_str()); 278 279 assert(false); 280 281 it->second.socket->disconnectServer(); 282 delete it->second.socket; 283 it->second.socket = NULL; 284 285 if ( it->second.handshake ) 286 delete it->second.handshake; 287 it->second.handshake = NULL; 288 289 for ( SynchronizeableList::iterator it2 = synchronizeables.begin(); it2 != synchronizeables.end(); it2++ ) 191 290 { 192 if ( handshakes[i]->ok() ) 291 (*it2)->cleanUpUser( it->second.userId ); 292 } 293 294 NetworkGameManager::getInstance()->signalLeftPlayer(it->second.userId); 295 296 freeSocketSlots.push_back( it->second.userId ); 297 298 } 299 } 300 301 302 } 303 304 void NetworkStream::debug() 305 { 306 if( this->isServer()) 307 PRINT(0)(" Host ist Server with ID: %i\n", this->myHostId); 308 else 309 PRINT(0)(" Host ist Client with ID: %i\n", this->myHostId); 310 311 PRINT(0)(" Got %i connected Synchronizeables, showing active Syncs:\n", this->synchronizeables.size()); 312 for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++) 313 { 314 if( (*it)->beSynchronized() == true) 315 PRINT(0)(" Synchronizeable of class: %s::%s, with unique ID: %i, Synchronize: %i\n", (*it)->getClassName(), (*it)->getName(), 316 (*it)->getUniqueID(), (*it)->beSynchronized()); 317 } 318 PRINT(0)(" Maximal Connections: %i\n", MAX_CONNECTIONS ); 319 320 } 321 322 323 int NetworkStream::getSyncCount() 324 { 325 int n = 0; 326 for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++) 327 if( (*it)->beSynchronized() == true) 328 ++n; 329 330 //return synchronizeables.size(); 331 return n; 332 } 333 334 /** 335 * check if handshakes completed 336 */ 337 void NetworkStream::handleHandshakes( ) 338 { 339 for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ ) 340 { 341 if ( it->second.handshake ) 342 { 343 if ( it->second.handshake->completed() ) 344 { 345 if ( it->second.handshake->ok() ) 193 346 { 194 if ( type != NET_SERVER ) 195 { 196 SharedNetworkData::getInstance()->setHostID( handshakes[i]->getHostId() ); 197 myHostId = SharedNetworkData::getInstance()->getHostID(); 198 199 this->networkGameManager = NetworkGameManager::getInstance(); 200 this->networkGameManager->setUniqueID( handshakes[i]->getNetworkGameManagerId() ); 201 //this->connectSynchronizeable( *(this->networkGameManager) ); 347 if ( !it->second.handshake->allowDel() ) 348 { 349 if ( type != NET_SERVER ) 350 { 351 SharedNetworkData::getInstance()->setHostID( it->second.handshake->getHostId() ); 352 myHostId = SharedNetworkData::getInstance()->getHostID(); 353 354 this->networkGameManager = NetworkGameManager::getInstance(); 355 this->networkGameManager->setUniqueID( it->second.handshake->getNetworkGameManagerId() ); 356 MessageManager::getInstance()->setUniqueID( it->second.handshake->getMessageManagerId() ); 357 } 358 359 360 PRINT(0)("handshake finished id=%d\n", it->second.handshake->getNetworkGameManagerId()); 361 362 it->second.handshake->del(); 202 363 } 203 364 else 204 365 { 205 206 } 207 PRINT(0)("handshake finished id=%d\n", handshakes[i]->getNetworkGameManagerId()); 208 209 210 delete handshakes[i]; 211 handshakes[i] = NULL; 366 if ( it->second.handshake->canDel() ) 367 { 368 if ( type == NET_SERVER ) 369 { 370 handleNewClient( it->second.userId ); 371 } 372 373 PRINT(0)("handshake finished delete it\n"); 374 delete it->second.handshake; 375 it->second.handshake = NULL; 376 } 377 } 378 212 379 } 213 380 else 214 381 { 215 382 PRINT(1)("handshake failed!\n"); 216 networkSockets[i]->disconnectServer(); 217 delete handshakes[i]; 218 handshakes[i] = NULL; 219 //TODO: handle error 383 it->second.socket->disconnectServer(); 220 384 } 221 385 } 222 386 } 223 387 } 224 225 226 /* DOWNSTREAM */ 227 228 229 230 int dataLength; 231 int reciever; 232 Header header; 233 int counter; 234 235 for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++) 236 { 237 counter = 0; 238 239 if ( (*it)!=NULL && (*it)->beSynchronized() /*&& (*it)->getOwner() == myHostId*/ ) 240 { 241 do { 242 counter++; 243 244 //check for endless loop 245 if ( counter > 50 ) 388 } 389 390 /** 391 * handle upstream network traffic 392 */ 393 void NetworkStream::handleUpstream( ) 394 { 395 int offset; 396 int n; 397 398 for ( PeerList::iterator peer = peers.begin(); peer != peers.end(); peer++ ) 399 { 400 offset = INTSIZE; //make already space for length 401 402 if ( !peer->second.socket ) 403 continue; 404 405 n = Converter::intToByteArray( currentState, buf + offset, UDP_PACKET_SIZE - offset ); 406 assert( n == INTSIZE ); 407 offset += n; 408 409 n = Converter::intToByteArray( peer->second.lastAckedState, buf + offset, UDP_PACKET_SIZE - offset ); 410 assert( n == INTSIZE ); 411 offset += n; 412 413 n = Converter::intToByteArray( peer->second.lastRecvedState, buf + offset, UDP_PACKET_SIZE - offset ); 414 assert( n == INTSIZE ); 415 offset += n; 416 417 for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ ) 418 { 419 int oldOffset = offset; 420 Synchronizeable & sync = **it; 421 422 if ( !sync.beSynchronized() || sync.getUniqueID() < 0 ) 423 continue; 424 425 //if handshake not finished only sync handshake 426 if ( peer->second.handshake && sync.getLeafClassID() != CL_HANDSHAKE ) 427 continue; 428 429 if ( isServer() && sync.getLeafClassID() == CL_HANDSHAKE && sync.getUniqueID() != peer->second.userId ) 430 continue; 431 432 //do not sync null parent 433 if ( sync.getLeafClassID() == CL_NULL_PARENT ) 434 continue; 435 436 assert( offset + INTSIZE <= UDP_PACKET_SIZE ); 437 438 //server fakes uniqueid=0 for handshake 439 if ( this->isServer() && sync.getUniqueID() < MAX_CONNECTIONS - 1 ) 440 n = Converter::intToByteArray( 0, buf + offset, UDP_PACKET_SIZE - offset ); 441 else 442 n = Converter::intToByteArray( sync.getUniqueID(), buf + offset, UDP_PACKET_SIZE - offset ); 443 assert( n == INTSIZE ); 444 offset += n; 445 446 //make space for size 447 offset += INTSIZE; 448 449 n = sync.getStateDiff( peer->second.userId, buf + offset, UDP_PACKET_SIZE-offset, currentState, peer->second.lastAckedState, -1000 ); 450 offset += n; 451 //NETPRINTF(0)("GGGGGEEEEETTTTT: %s (%d) %d\n",sync.getClassName(), sync.getUniqueID(), n); 452 453 assert( Converter::intToByteArray( n, buf + offset - n - INTSIZE, INTSIZE ) == INTSIZE ); 454 455 //check if all bytes == 0 -> remove data 456 //TODO not all synchronizeables like this maybe add Synchronizeable::canRemoveZeroDiff() 457 bool allZero = true; 458 for ( int i = 0; i < n; i++ ) 459 { 460 if ( buf[i+oldOffset+2*INTSIZE] != 0 ) 461 allZero = false; 462 } 463 464 if ( allZero ) 465 { 466 //NETPRINTF(n)("REMOVE ZERO DIFF: %s (%d)\n", sync.getClassName(), sync.getUniqueID()); 467 offset = oldOffset; 468 } 469 470 471 } 472 473 for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ ) 474 { 475 Synchronizeable & sync = **it; 476 477 if ( !sync.beSynchronized() || sync.getUniqueID() < 0 ) 478 continue; 479 480 sync.handleSentState( peer->second.userId, currentState, peer->second.lastAckedState ); 481 } 482 483 assert( Converter::intToByteArray( offset, buf, INTSIZE ) == INTSIZE ); 484 485 int compLength = Zip::getInstance()->zip( buf, offset, compBuf, UDP_PACKET_SIZE ); 486 487 if ( compLength < 0 ) 488 { 489 PRINTF(1)("compression failed!\n"); 490 continue; 491 } 492 493 assert( peer->second.socket->writePacket( compBuf, compLength ) ); 494 495 if ( this->remainingBytesToWriteToDict > 0 ) 496 writeToNewDict( buf, offset ); 497 498 peer->second.connectionMonitor->processUnzippedOutgoingPacket( buf, offset, currentState ); 499 peer->second.connectionMonitor->processZippedOutgoingPacket( compBuf, compLength, currentState ); 500 501 //NETPRINTF(n)("send packet: %d userId = %d\n", offset, peer->second.userId); 502 } 503 } 504 505 /** 506 * handle downstream network traffic 507 */ 508 void NetworkStream::handleDownstream( ) 509 { 510 int offset = 0; 511 512 int length = 0; 513 int packetLength = 0; 514 int compLength = 0; 515 int uniqueId = 0; 516 int state = 0; 517 int ackedState = 0; 518 int fromState = 0; 519 int syncDataLength = 0; 520 521 for ( PeerList::iterator peer = peers.begin(); peer != peers.end(); peer++ ) 522 { 523 524 if ( !peer->second.socket ) 525 continue; 526 527 while ( 0 < (compLength = peer->second.socket->readPacket( compBuf, UDP_PACKET_SIZE )) ) 528 { 529 //TODO tell monitor about zipped packet. because dropped packets dont count to bandwidth 530 //PRINTF(0)("GGGGGOOOOOOOOOOTTTTTTTT: %d\n", compLength); 531 packetLength = Zip::getInstance()->unZip( compBuf, compLength, buf, UDP_PACKET_SIZE ); 532 533 if ( packetLength < 4*INTSIZE ) 534 { 535 if ( packetLength != 0 ) 536 PRINTF(1)("got too small packet: %d\n", packetLength); 537 continue; 538 } 539 540 if ( this->remainingBytesToWriteToDict > 0 ) 541 writeToNewDict( buf, packetLength ); 542 543 assert( Converter::byteArrayToInt( buf, &length ) == INTSIZE ); 544 assert( Converter::byteArrayToInt( buf + INTSIZE, &state ) == INTSIZE ); 545 assert( Converter::byteArrayToInt( buf + 2*INTSIZE, &fromState ) == INTSIZE ); 546 assert( Converter::byteArrayToInt( buf + 3*INTSIZE, &ackedState ) == INTSIZE ); 547 //NETPRINTF(n)("ackedstate: %d\n", ackedState); 548 offset = 4*INTSIZE; 549 550 //NETPRINTF(n)("got packet: %d, %d\n", length, packetLength); 551 552 //if this is an old state drop it 553 if ( state <= peer->second.lastRecvedState ) 554 continue; 555 556 if ( packetLength != length ) 557 { 558 PRINTF(1)("real packet length (%d) and transmitted packet length (%d) do not match!\n", packetLength, length); 559 peer->second.socket->disconnectServer(); 560 continue; 561 } 562 563 while ( offset + 2*INTSIZE < length ) 564 { 565 assert( offset > 0 ); 566 assert( Converter::byteArrayToInt( buf + offset, &uniqueId ) == INTSIZE ); 567 offset += INTSIZE; 568 569 assert( Converter::byteArrayToInt( buf + offset, &syncDataLength ) == INTSIZE ); 570 offset += INTSIZE; 571 572 assert( syncDataLength > 0 ); 573 assert( syncDataLength < 10000 ); 574 575 Synchronizeable * sync = NULL; 576 577 for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ ) 578 { 579 // client thinks his handshake has id 0!!!!! 580 if ( (*it)->getUniqueID() == uniqueId || ( uniqueId == 0 && (*it)->getUniqueID() == peer->second.userId ) ) 581 { 582 sync = *it; 583 break; 584 } 585 } 586 587 if ( sync == NULL ) 246 588 { 247 PRINTF(1)("there seems to be an error in readBytes of %s\n", (*it)->getClassName()); 248 assert(false); 589 PRINTF(0)("could not find sync with id %d. try to create it\n", uniqueId); 590 if ( oldSynchronizeables.find( uniqueId ) != oldSynchronizeables.end() ) 591 { 592 offset += syncDataLength; 593 continue; 594 } 595 596 if ( !peers[peer->second.userId].isServer ) 597 { 598 offset += syncDataLength; 599 continue; 600 } 601 602 int leafClassId; 603 if ( INTSIZE > length - offset ) 604 { 605 offset += syncDataLength; 606 continue; 607 } 608 609 Converter::byteArrayToInt( buf + offset, &leafClassId ); 610 611 assert( leafClassId != 0 ); 612 613 BaseObject * b = NULL; 614 /* These are some small exeptions in creation: Not all objects can/should be created via Factory */ 615 /* Exception 1: NullParent */ 616 if( leafClassId == CL_NULL_PARENT || leafClassId == CL_SYNCHRONIZEABLE || leafClassId == CL_NETWORK_GAME_MANAGER ) 617 { 618 PRINTF(1)("Can not create Class with ID %x!\n", (int)leafClassId); 619 offset += syncDataLength; 620 continue; 621 } 622 else 623 b = Factory::fabricate( (ClassID)leafClassId ); 624 625 if ( !b ) 626 { 627 PRINTF(1)("Could not fabricate Object with classID %x\n", leafClassId); 628 offset += syncDataLength; 629 continue; 630 } 631 632 if ( b->isA(CL_SYNCHRONIZEABLE) ) 633 { 634 sync = dynamic_cast<Synchronizeable*>(b); 635 sync->setUniqueID( uniqueId ); 636 sync->setSynchronized(true); 637 638 PRINTF(0)("Fabricated %s with id %d\n", sync->getClassName(), sync->getUniqueID()); 639 } 640 else 641 { 642 PRINTF(1)("Class with ID %x is not a synchronizeable!\n", (int)leafClassId); 643 delete b; 644 offset += syncDataLength; 645 continue; 646 } 249 647 } 250 648 251 reciever = 0; 252 dataLength = (*it)->readBytes(downBuffer, DATA_STREAM_BUFFER_SIZE, &reciever); 253 254 if ( dataLength<=0 ){ 255 reciever = 0; 649 int n = sync->setStateDiff( peer->second.userId, buf+offset, syncDataLength, state, fromState ); 650 offset += n; 651 //NETPRINTF(0)("SSSSSEEEEETTTTT: %s %d\n",sync->getClassName(), n); 652 653 } 654 655 if ( offset != length ) 656 { 657 PRINTF(0)("offset (%d) != length (%d)\n", offset, length); 658 peer->second.socket->disconnectServer(); 659 } 660 661 //TODO REMOVE THIS 662 int saveOffset = offset; 663 664 for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ ) 665 { 666 Synchronizeable & sync = **it; 667 668 if ( !sync.beSynchronized() || sync.getUniqueID() < 0 ) 256 669 continue; 257 } 258 259 dataLength = networkProtocol->createHeader((byte*)downBuffer, dataLength, DATA_STREAM_BUFFER_SIZE, static_cast<const Synchronizeable&>(*(*it))); 260 261 Header* header = (Header*)downBuffer; 262 if ( header->synchronizeableID < this->maxConnections+2 ) 263 { 264 //if ( !isServer() ) PRINTF(0)("RESET UNIQUEID FROM %d TO 0 maxCon=%d\n", header->synchronizeableID, this->maxConnections); 265 header->synchronizeableID = 0; 266 } 267 else 268 { 269 //if ( !isServer() ) PRINTF(0)("UNIQUEID=%d\n", header->synchronizeableID); 270 } 271 272 if ( dataLength<=0 ) 273 continue; 274 275 if ( reciever!=0 ) 276 { 277 if ( reciever < 0) 278 { 279 for ( int i = 0; i<networkSockets.size(); i++) 280 { 281 if ( i!=abs(reciever) && networkSockets[i] != NULL ) 282 { 283 PRINTF(0)("write %d bytes to socket %d uniqueid %d reciever %d\n", dataLength, i, (*it)->getUniqueID(), reciever); 284 networkSockets[i]->writePacket(downBuffer, dataLength); 285 } 286 } 287 } 288 else 289 { 290 if ( networkSockets[reciever] != NULL ) 291 { 292 PRINTF(5)("write %d bytes to socket %d\n", dataLength, reciever); 293 networkSockets[reciever]->writePacket(downBuffer, dataLength); 294 } 295 else 296 { 297 PRINTF(1)("networkSockets[reciever] == NULL\n"); 298 } 299 } 300 } 301 else 302 { 303 for ( int i = 0; i<networkSockets.size(); i++) 304 { 305 if ( networkSockets[i] != NULL ) 306 { 307 PRINTF(5)("write %d bytes to socket %d\n", dataLength, i); 308 networkSockets[i]->writePacket(downBuffer, dataLength); 309 } 310 } 311 } 312 313 } while( reciever!=0 ); 314 } 315 } 316 317 /* UPSTREAM */ 318 319 for ( int i = 0; i<networkSockets.size(); i++) 320 { 321 if ( networkSockets[i] ) 322 { 323 do { 324 dataLength = networkSockets[i]->readPacket(upBuffer, DATA_STREAM_BUFFER_SIZE); 325 326 if ( dataLength<=0 ) 327 continue; 328 329 header = networkProtocol->extractHeader(upBuffer, dataLength); 330 dataLength -= sizeof(header); 331 332 PRINTF(5)("read %d bytes from socket uniqueID = %d\n", dataLength, header.synchronizeableID); 333 334 if ( dataLength != header.length ) 335 { 336 PRINTF(1)("packetsize in header and real packetsize do not match! %d:%d\n", dataLength, header.length); 337 continue; 338 } 339 340 if ( header.synchronizeableID == 0 ) 341 { 342 header.synchronizeableID = i; 343 } 344 345 for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++) 346 { 347 if ( *it && (*it)->getUniqueID()==header.synchronizeableID ) 348 { 349 if ( (*it)->writeBytes(upBuffer+sizeof(header), dataLength, i) != header.length ) 350 { 351 PRINTF(1)("%s did not read all the data id = %d!\n", (*it)->getClassName(), (*it)->getUniqueID()); 352 break; 353 } 354 continue; 355 } 356 } 357 358 } while ( dataLength>0 ); 359 } 360 } 361 } 362 363 void NetworkStream::updateConnectionList( ) 364 { 365 //check for new connections 366 367 NetworkSocket* tempNetworkSocket = serverSocket->getNewSocket(); 368 369 if ( tempNetworkSocket ) 370 { 371 int clientId; 372 if ( freeSocketSlots.size() >0 ) 373 { 374 clientId = freeSocketSlots.back(); 375 freeSocketSlots.pop_back(); 376 networkSockets[clientId] = tempNetworkSocket; 377 handshakes[clientId] = new Handshake(true, clientId, this->networkGameManager->getUniqueID()); 378 handshakes[clientId]->setUniqueID(clientId); 379 } else 380 { 381 clientId = networkSockets.size(); 382 networkSockets.push_back(tempNetworkSocket); 383 Handshake* tHs = new Handshake(true, clientId, this->networkGameManager->getUniqueID()); 384 tHs->setUniqueID(clientId); 385 handshakes.push_back(tHs); 386 } 387 388 if ( clientId > this->maxConnections ) 389 { 390 handshakes[clientId]->doReject(); 391 PRINTF(0)("Will reject client %d because there are to many connections!\n", clientId); 392 } 393 else 394 395 PRINTF(0)("New Client: %d\n", clientId); 396 397 //this->connectSynchronizeable(*handshakes[clientId]); 398 } 399 400 401 //check if connections are ok else remove them 402 for ( int i = 1; i<networkSockets.size(); i++) 403 { 404 if ( networkSockets[i] && !networkSockets[i]->isOk() ) 405 { 406 //TODO: tell EntityManager that this player left the game 407 PRINTF(0)("Client is gone: %d\n", i); 408 409 //delete networkSockets[i]; 410 networkSockets[i]->disconnectServer(); 411 networkSockets[i]->destroy(); 412 networkSockets[i] = NULL; 413 414 if ( handshakes[i] ) 415 delete handshakes[i]; 416 handshakes[i] = NULL; 417 418 419 NetworkGameManager::getInstance()->signalLeftPlayer(i); 420 421 if ( i == networkSockets.size()-1 ) 422 { 423 networkSockets.pop_back(); 424 handshakes.pop_back(); 670 671 sync.handleRecvState( peer->second.userId, state, fromState ); 425 672 } 426 else 427 { 428 freeSocketSlots.push_back(i); 429 } 430 } 431 } 432 433 434 } 435 436 void NetworkStream::setMaxConnections( int n ) 437 { 438 if ( !this->isServer() ) 439 { 440 PRINTF(1)("Cannot set maxConnections because I am no server.\n"); 441 } 442 if ( this->networkSockets.size() > 1 ) 443 { 444 PRINTF(1)("Cannot set maxConnections because there are already %d connections.\n", this->networkSockets.size()); 673 674 peer->second.connectionMonitor->processZippedIncomingPacket( compBuf, compLength, state, ackedState ); 675 peer->second.connectionMonitor->processUnzippedIncomingPacket( buf, offset, state, ackedState ); 676 677 assert( peer->second.lastAckedState <= ackedState ); 678 peer->second.lastAckedState = ackedState; 679 680 assert( peer->second.lastRecvedState < state ); 681 peer->second.lastRecvedState = state; 682 683 assert( saveOffset == offset ); 684 685 } 686 687 } 688 689 } 690 691 /** 692 * is executed when a handshake has finished 693 * @todo create playable for new user 694 */ 695 void NetworkStream::handleNewClient( int userId ) 696 { 697 MessageManager::getInstance()->initUser( userId ); 698 699 networkGameManager->signalNewPlayer( userId ); 700 } 701 702 /** 703 * removes old items from oldSynchronizeables 704 */ 705 void NetworkStream::cleanUpOldSyncList( ) 706 { 707 int now = SDL_GetTicks(); 708 709 for ( std::map<int,int>::iterator it = oldSynchronizeables.begin(); it != oldSynchronizeables.end(); ) 710 { 711 if ( it->second < now - 10*1000 ) 712 { 713 std::map<int,int>::iterator delIt = it; 714 it++; 715 oldSynchronizeables.erase( delIt ); 716 continue; 717 } 718 it++; 719 } 720 } 721 722 /** 723 * writes data to DATA/dicts/newdict 724 * @param data pointer to data 725 * @param length length 726 */ 727 void NetworkStream::writeToNewDict( byte * data, int length ) 728 { 729 if ( remainingBytesToWriteToDict <= 0 ) 445 730 return; 446 } 447 448 if ( n > MAX_CONNECTIONS ) 449 { 450 PRINTF(1)("Cannot set maxConnectiosn to %d because of hardcoded limit %d\n", n, MAX_CONNECTIONS); 731 732 if ( length > remainingBytesToWriteToDict ) 733 length = remainingBytesToWriteToDict; 734 735 std::string fileName = ResourceManager::getInstance()->getDataDir(); 736 fileName += "/dicts/newdict"; 737 738 FILE * f = fopen( fileName.c_str(), "a" ); 739 740 if ( !f ) 741 { 742 PRINTF(2)("could not open %s\n", fileName.c_str()); 743 remainingBytesToWriteToDict = 0; 451 744 return; 452 745 } 453 454 this->maxConnections = n; 455 this->networkGameManager->setUniqueID( n+2 ); 456 } 457 458 459 460 void NetworkStream::debug() 461 { 462 if( this->isServer()) 463 PRINT(0)(" Host ist Server with ID: %i\n", this->myHostId); 464 else 465 PRINT(0)(" Host ist Client with ID: %i\n", this->myHostId); 466 467 PRINT(0)(" Got %i connected Synchronizeables, showing active Syncs:\n", this->synchronizeables.size()); 468 for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++) 469 { 470 if( (*it)->beSynchronized() == true) 471 PRINT(0)(" Synchronizeable of class: %s::%s, with unique ID: %i, Synchronize: %i\n", (*it)->getClassName(), (*it)->getName(), 472 (*it)->getUniqueID(), (*it)->beSynchronized()); 473 } 474 PRINT(0)(" Maximal Connections: %i\n", this->maxConnections); 475 476 } 477 478 479 int NetworkStream::getSyncCount() 480 { 481 int n = 0; 482 for (SynchronizeableList::iterator it = synchronizeables.begin(); it!=synchronizeables.end(); it++) 483 if( (*it)->beSynchronized() == true) 484 ++n; 485 486 //return synchronizeables.size(); 487 return n; 488 } 489 490 491 492 493 494 746 747 if ( fwrite( data, 1, length, f ) != length ) 748 { 749 PRINTF(2)("could not write to file\n"); 750 fclose( f ); 751 return; 752 } 753 754 fclose( f ); 755 756 remainingBytesToWriteToDict -= length; 757 } 758 759 760 761 762 763 -
trunk/src/lib/network/network_stream.h
r6981 r7954 9 9 #include <vector> 10 10 #include <list> 11 #include <map> 11 12 12 13 #include "data_stream.h" 13 #include "network_protocol.h"14 14 #include "server_socket.h" 15 15 #include "handshake.h" 16 #include "connection_monitor.h" 17 #include "udp_server_socket.h" 16 18 17 19 class Synchronizeable; 18 20 class NetworkSocket; 19 21 class ServerSocket; 20 class ConnectionMonitor;21 class NetworkProtocol;22 22 class NetworkGameManager; 23 23 24 class PeerInfo 25 { 26 public: 27 PeerInfo() { clear(); } 28 void clear() { userId = 0; isServer = false; socket = NULL; handshake = NULL; lastAckedState = 0; lastRecvedState = 0; connectionMonitor = NULL; } 29 int userId; 30 bool isServer; 31 NetworkSocket * socket; 32 Handshake * handshake; 33 ConnectionMonitor * connectionMonitor; 34 int lastAckedState; 35 int lastRecvedState; 36 }; 37 24 38 typedef std::list<Synchronizeable*> SynchronizeableList; 25 typedef std::vector<NetworkSocket*> NetworkSocketVector; 26 typedef std::vector<Handshake*> HandshakeVector; 39 typedef std::map<int,PeerInfo> PeerList; 27 40 28 41 … … 32 45 public: 33 46 NetworkStream(); 34 NetworkStream( IPaddress& address);35 NetworkStream( unsigned int port);47 NetworkStream( std::string host, int port); 48 NetworkStream( int port ); 36 49 37 50 virtual ~NetworkStream(); … … 47 60 inline bool isActive() const { return this->bActive; } 48 61 49 inline int getMaxConnections(){ return maxConnections; } 50 void setMaxConnections( int n ); 62 inline int getMaxConnections(){ return MAX_CONNECTIONS; } 51 63 52 64 virtual void processData(); … … 56 68 int getSyncCount(); 57 69 58 inline bool isUserIdActive( int userID ) { if (userID>=networkSockets.size()) return false; else return networkSockets[userID]!=NULL; } 70 inline bool isUserIdActive( int userID ) { return (peers.find(userID) != peers.end()); } 71 inline bool isUserServer( int userID ){ if ( !isUserIdActive(userID) ) return false; return peers[userID].isServer; } 59 72 60 73 void debug(); 74 75 inline PeerInfo & getPeerInfo( int userId ) { return peers[userId]; } 61 76 62 77 63 78 private: 64 79 void updateConnectionList(); 80 void handleHandshakes(); 81 void handleUpstream(); 82 void handleDownstream(); 83 void handleNewClient( int userId ); 84 void cleanUpOldSyncList(); 85 86 void writeToNewDict( byte * data, int length ); 65 87 66 88 67 89 private: 68 NetworkProtocol* networkProtocol;69 ConnectionMonitor* connectionMonitor;70 90 SynchronizeableList synchronizeables; 71 NetworkSocketVector networkSockets; 72 HandshakeVector handshakes; 91 PeerList peers; 73 92 ServerSocket* serverSocket; 74 93 int type; 75 Header packetHeader;76 94 bool bActive; 77 95 std::list<int> freeSocketSlots; 78 96 79 97 int myHostId; 80 int maxConnections; 98 99 int currentState; //!< current state id 81 100 82 101 NetworkGameManager* networkGameManager; 102 103 std::map<int,int> oldSynchronizeables; //!< used to save recently deleted sync ids to not recreate them 104 105 byte buf[UDP_PACKET_SIZE]; //!< used by handleUp/Downstream 106 byte compBuf[UDP_PACKET_SIZE]; //!< used by handleUp/Downstream 107 108 int remainingBytesToWriteToDict; //!< if > 0 NetworkStream will write packets to DATA/dicts/newdict 83 109 }; 84 110 #endif /* _NETWORK_STREAM */ -
trunk/src/lib/network/server_socket.cc
r6139 r7954 26 26 #include "debug.h" 27 27 28 ServerSocket::ServerSocket( ) 28 29 /** 30 * constructor 31 * @param port port to assign to socket 32 */ 33 ServerSocket::ServerSocket( int port ) 29 34 { 30 init();35 bOk = true; 31 36 } 32 37 33 ServerSocket:: ServerSocket( unsigned int port)38 ServerSocket::~ ServerSocket( ) 34 39 { 35 init();36 listen(port);37 40 } 38 39 /**40 * Default destructor41 */42 ServerSocket::~ServerSocket( )43 {44 /* Quit SDL_net */45 // NOTE: what if other instances of NetworkSocket running?46 SDLNet_Quit();47 PRINTF(5)("SDL_net shutdown\n");48 49 _isListening = false;50 }51 52 void ServerSocket::init( )53 {54 /* set the class id for the base object */55 this->setClassID(CL_SERVER_SOCKET, "ServerSocket");56 57 terminateThread = false;58 listenSocket = NULL;59 _isListening = false;60 61 if(SDLNet_Init()==-1)62 {63 PRINTF(1)("SDLNet_Init: %s\n", SDLNet_GetError());64 return;65 }66 else67 PRINTF(5)("SDL_net initialized\n");68 69 PRINTF(0)("ServerSocket created\n");70 }71 72 73 /**74 * Tells the NetworkSocket to listen on a specific port for incoming connections.75 * NetworkSocket::writeBytes(...) will have no effect until there is a valuable connection.76 * @param port77 */78 bool ServerSocket::listen(unsigned int port)79 {80 PRINTF(0)("ServerSocket::listen()\n");81 _isListening = true;82 //check if not already connected or listening83 if (listenSocket)84 {85 PRINTF(1)("ServerSocket::listen: tcpSocket!=NULL! maybe you already called listen or did not call close()!\n");86 _isListening = false;87 return false;88 }89 90 IPaddress ip;91 92 if (SDLNet_ResolveHost(&ip, NULL, port)==-1)93 {94 PRINTF(1)("SDLNet_ResolveHost: %s\n", SDLNet_GetError());95 _isListening = false;96 return false;97 }98 99 listenSocket = SDLNet_TCP_Open(&ip);100 101 if (!listenSocket)102 {103 PRINTF(1)("SDLNet_TCP_Open: %s\n", SDLNet_GetError());104 _isListening = false;105 return false;106 }107 108 return true;109 }110 111 112 NetworkSocket* ServerSocket::getNewSocket( )113 {114 if ( !listenSocket )115 {116 PRINTF(1)("listenSocket == NULL! Maybe you forgot to call listen()\n");117 close();118 return NULL;119 }120 121 TCPsocket sock = SDLNet_TCP_Accept(listenSocket);122 123 if ( !sock )124 {125 return NULL;126 }127 else128 {129 return new NetworkSocket(sock);130 }131 }132 133 void ServerSocket::close( )134 {135 if ( listenSocket )136 {137 SDLNet_TCP_Close( listenSocket );138 listenSocket = NULL;139 }140 141 _isListening = false;142 }143 -
trunk/src/lib/network/server_socket.h
r6981 r7954 8 8 #define _SERVER_SOCKET 9 9 10 #ifdef HAVE_SDL_H11 #include <SDL_thread.h>12 #else13 #include <SDL/SDL_thread.h>14 #endif15 10 /* include this file, it contains some default definitions */ 16 11 #include "netdefs.h" … … 21 16 #include "network_socket.h" 22 17 23 //sleep when waiting for connections24 #define _MSECONDS_SLEEP_LISTEN 10025 18 26 19 class ServerSocket : public BaseObject 27 20 { 28 private: 29 TCPsocket listenSocket; 30 bool terminateThread; 21 public: 22 ServerSocket( int port); 31 23 32 bool _isListening;24 virtual ~ServerSocket(); 33 25 34 void init(); 26 virtual bool listen( unsigned int port ) = 0; 27 virtual NetworkSocket* getNewSocket( void ) = 0; 28 virtual void close() = 0; 29 virtual void update() = 0; 30 virtual bool isOk() { return this->bOk; }; 35 31 36 public: 37 ServerSocket(); 38 ServerSocket( unsigned int port ); 39 virtual ~ServerSocket(); 40 bool listen( unsigned int port ); 41 NetworkSocket* getNewSocket( void ); 42 void close(); 43 inline bool isOk(){ return listenSocket!=NULL; } 32 protected: 33 bool bOk; 34 44 35 }; 45 36 -
trunk/src/lib/network/synchronizeable.cc
r6753 r7954 20 20 #include "network_stream.h" 21 21 #include "netdefs.h" 22 #include "network_log.h" 22 23 23 24 #include "state.h" … … 36 37 this->setClassID(CL_SYNCHRONIZEABLE, "Synchronizeable"); 37 38 this->owner = -1; 38 this->state = 0;39 39 this->hostID = SharedNetworkData::getInstance()->getHostID(); 40 40 this->setIsServer(this->hostID == 0); 41 41 this->uniqueID = NET_UID_UNASSIGNED; 42 42 this->networkStream = NULL; 43 this->setRequestedSync( false );44 this->setIsOutOfSync( !(this->isServer()) );45 43 this->bSynchronize = false; 46 44 47 45 if( State::isOnline()) 48 46 { … … 52 50 this->setUniqueID(SharedNetworkData::getInstance()->getNewUniqueID()); 53 51 } 52 53 /* make sure loadClassId is first synced var because this is read by networkStream */ 54 assert( syncVarList.size() == 0 ); 55 mLeafClassId = this->registerVarId( new SynchronizeableInt( (int*)&this->getLeafClassID(), (int*)&this->getLeafClassID(), "leafClassId" ) ); 56 57 this->registerVar( new SynchronizeableInt( &this->owner, &this->owner, "owner" ) ); 58 this->registerVar( new SynchronizeableString( &this->objectName, &this->objectName, "objectName" ) ); 54 59 } 55 60 … … 64 69 this->networkStream->disconnectSynchronizeable(*this); 65 70 } 66 67 68 /**69 * write data to NetworkStream70 */71 int Synchronizeable::writeBytes(const byte* data, int length, int sender)72 {73 PRINTF(5)("Synchronizeable::writeBytes was called\n");74 }75 76 77 /**78 * read data from NetworkStream79 */80 int Synchronizeable::readBytes(byte* data, int maxLength, int * reciever)81 {82 PRINTF(5)("Synchronizeable::readBytes was called\n");83 }84 85 86 void Synchronizeable::writeDebug() const87 {}88 89 90 void Synchronizeable::readDebug() const91 {}92 93 71 94 72 /** … … 106 84 107 85 /** 108 * Sets the outofsync flag to a given value109 * @param outOfSync: the boolean value which the outofsync flag is to set to110 */111 void Synchronizeable::setIsOutOfSync(bool outOfSync)112 {113 if( outOfSync )114 this->state = this->state | STATE_OUTOFSYNC;115 else116 this->state = this->state & (~STATE_OUTOFSYNC);117 //PRINTF(0)("isoutofsync %s %d\n", this->getClassName(), state);118 }119 120 121 /**122 86 * Determines if the server flag is set 123 87 * @return true, if the server flag is true, false else … … 129 93 130 94 131 /** 132 * Determines if the outofsync flag is set 133 * @return true, if the outofsync flag is true, false else 134 */ 135 bool Synchronizeable::isOutOfSync() 136 { 137 return (this->state & STATE_OUTOFSYNC) >0; 138 } 139 140 141 /** 142 * Determines if the requestedSync flag is set 143 * @return true, if the requestedSync flag is true, false else 144 */ 145 bool Synchronizeable::requestedSync() 146 { 147 return (this->state & STATE_REQUESTEDSYNC) >0; 148 } 149 150 151 /** 152 * Sets the requestedsync flag to a given value 153 * @param requestedSync: the boolean value which the requestedsync flag is to set to 154 */ 155 void Synchronizeable::setRequestedSync( bool requestedSync ) 156 { 157 if( requestedSync ) 158 this->state = this->state | STATE_REQUESTEDSYNC; 95 96 int Synchronizeable::getStateDiff( int userId, byte* data, int maxLength, int stateId, int fromStateId, int priorityTH ) 97 { 98 //make sure this user has his history 99 if ( sentStates.size() <= userId ) 100 sentStates.resize( userId+1 ); 101 102 //calculate needed memory 103 int neededSize = 0; 104 105 for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ ) 106 neededSize += (*it)->getSize(); 107 108 if ( !( neededSize <= maxLength ) ) 109 { 110 PRINTF(0)( "%d > %d\n", neededSize, maxLength ); 111 assert(false); 112 } 113 114 //remove older states from history than fromStateId 115 StateHistory::iterator it = sentStates[userId].begin(); 116 117 while ( it != sentStates[userId].end() && (*it)->stateId < fromStateId ) 118 it++; 119 120 if ( it != sentStates[userId].begin() ) 121 { 122 for ( StateHistory::iterator it2 = sentStates[userId].begin(); it2 != it; it2++ ) 123 { 124 if ( (*it2)->data != NULL ) 125 { 126 delete [] (*it2)->data; 127 (*it2)->data = NULL; 128 } 129 } 130 sentStates[userId].erase( sentStates[userId].begin(), it ); 131 } 132 133 //find state to create diff from 134 StateHistoryEntry * stateFrom = NULL; 135 136 it = sentStates[userId].begin(); 137 while ( it != sentStates[userId].end() && (*it)->stateId != fromStateId ) 138 it++; 139 140 // if ( getLeafClassID() == CL_SPACE_SHIP ) 141 // { 142 // PRINTF(0)("getStateDiff:SpaceShip from: %d stateId: %d\n", (it == sentStates[userId].end())?-1:fromStateId, stateId); 143 // } 144 145 if ( it == sentStates[userId].end() ) 146 { 147 StateHistoryEntry * initialEntry = new StateHistoryEntry(); 148 149 initialEntry->stateId = fromStateId; 150 initialEntry->dataLength = 0; 151 initialEntry->data = NULL; 152 153 stateFrom = initialEntry; 154 } 159 155 else 160 this->state = this->state & (~STATE_REQUESTEDSYNC); 161 } 162 163 164 156 stateFrom = (*it); 157 158 StateHistoryEntry * stateTo = new StateHistoryEntry(); 159 160 stateTo->stateId = stateId; 161 stateTo->dataLength = neededSize; 162 stateTo->data = new byte[ neededSize ]; 163 164 std::list<int>::iterator sizeIter = stateFrom->sizeList.begin(); 165 166 int i = 0; 167 int n; 168 169 bool hasPermission; 170 171 // now do the actual synchronization: kick all variables to write into a common buffer 172 for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ ) 173 { 174 hasPermission = ( 175 this->isServer() && (*it)->checkPermission( PERMISSION_SERVER ) || 176 this->owner == this->hostID && (*it)->checkPermission( PERMISSION_OWNER ) || 177 (*it)->checkPermission( PERMISSION_ALL ) 178 ); 179 180 if ( ( hasPermission && (*it)->getPriority() >= priorityTH ) || sizeIter == stateFrom->sizeList.end() ) 181 { 182 n = (*it)->writeToBuf( stateTo->data+i, stateTo->dataLength - i ); 183 //NETPRINTF(0)("getvar %s %d\n", (*it)->getName().c_str(), n); 184 stateTo->sizeList.push_back( n ); 185 //(*it)->debug(); 186 i += n; 187 } 188 else 189 { 190 for ( int j = 0; j<(*sizeIter); j++ ) 191 { 192 assert( i < stateFrom->dataLength ); 193 stateTo->data[i] = stateFrom->data[i]; 194 i++; 195 } 196 //NETPRINTF(0)("getvar %s %d\n", (*it)->getName().c_str(), *sizeIter); 197 stateTo->sizeList.push_back( (*sizeIter) ); 198 } 199 200 if ( sizeIter != stateFrom->sizeList.end() ) 201 sizeIter++; 202 } 203 204 sentStates[userId].push_back( stateTo ); 205 206 assert( i == neededSize ); 207 208 //write diff to data 209 for ( i = 0; i<neededSize; i++ ) 210 { 211 if ( i < stateFrom->dataLength ) 212 data[i] = stateTo->data[i] - stateFrom->data[i]; 213 else 214 data[i] = stateTo->data[i]; 215 } 216 217 return neededSize; 218 } 219 220 /** 221 * sets a new state out of a diff created on another host 222 * @param userId hostId of user who send me that diff 223 * @param data pointer to diff 224 * @param length length of diff 225 * @param stateId id of current state 226 * @param fromStateId id of the base state id 227 * @return number bytes read 228 * @todo check for permissions 229 */ 230 int Synchronizeable::setStateDiff( int userId, byte* data, int length, int stateId, int fromStateId ) 231 { 232 //make sure this user has his history 233 if ( recvStates.size() <= userId ) 234 recvStates.resize( userId+1 ); 235 236 //create new state 237 StateHistoryEntry * stateTo = new StateHistoryEntry(); 238 stateTo->stateId = stateId; 239 stateTo->dataLength = length; 240 stateTo->data = new byte[ length ]; 241 242 243 //find state to apply diff to 244 StateHistoryEntry * stateFrom = NULL; 245 246 StateHistory::iterator it = recvStates[userId].begin(); 247 while ( it != recvStates[userId].end() && (*it)->stateId != fromStateId ) 248 it++; 249 250 251 // if ( getLeafClassID() == CL_SPACE_SHIP ) 252 // { 253 // PRINTF(0)("setStateDiff:SpaceShip from: %d stateId: %d\n", (it == recvStates[userId].end())?-1:fromStateId, stateId); 254 // } 255 256 if ( it == recvStates[userId].end() ) 257 { 258 StateHistoryEntry * initialEntry = new StateHistoryEntry(); 259 260 initialEntry->stateId = fromStateId; 261 initialEntry->dataLength = 0; 262 initialEntry->data = NULL; 263 264 stateFrom = initialEntry; 265 } 266 else 267 stateFrom = (*it); 268 269 //apply diff 270 for ( int i = 0; i<length; i++ ) 271 { 272 if ( i < stateFrom->dataLength ) 273 stateTo->data[i] = stateFrom->data[i] + data[i]; 274 else 275 stateTo->data[i] = data[i]; 276 277 } 278 279 //add state to state history 280 recvStates[userId].push_back( stateTo ); 281 282 int i = 0; 283 int n = 0; 284 std::list<int> changes; 285 286 for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ ) 287 { 288 if ( 289 (*it)->checkPermission( PERMISSION_SERVER ) && networkStream->isUserServer( userId ) || 290 (*it)->checkPermission( PERMISSION_OWNER ) && this->owner == userId || 291 (*it)->checkPermission( PERMISSION_ALL ) 292 ) 293 { 294 n = (*it)->readFromBuf( stateTo->data + i, stateTo->dataLength - i ); 295 i += n; 296 //NETPRINTF(0)("%s::setvar %s %d\n", getClassName(), (*it)->getName().c_str(), n); 297 //(*it)->debug(); 298 if ( (*it)->getHasChanged() ) 299 { 300 changes.push_back( (*it)->getVarId() ); 301 } 302 } 303 else 304 { 305 // PRINTF(0)("DONT SET VAR BECAUSE OF PERMISSION: %s %d %d %d %d %d %d\n", (*it)->getName().c_str(), (*it)->checkPermission( PERMISSION_SERVER ), (*it)->checkPermission( PERMISSION_OWNER ), (*it)->checkPermission( PERMISSION_ALL ), networkStream->isUserServer( userId ), this->owner, userId ); 306 n = (*it)->getSizeFromBuf( stateTo->data + i, stateTo->dataLength - i ); 307 //NETPRINTF(0)("%s::setvar %s %d\n", getClassName(), (*it)->getName().c_str(), n); 308 //(*it)->debug(); 309 i += n; 310 } 311 } 312 313 this->varChangeHandler( changes ); 314 315 return i; 316 } 317 318 /** 319 * override this function to be notified on change 320 * of your registred variables. 321 * @param id id's which have changed 322 */ 323 void Synchronizeable::varChangeHandler( std::list<int> & id ) 324 { 325 } 326 327 /** 328 * registers a varable to be synchronized over network 329 * @param var see src/lib/network/synchronizeable_var/ for available classes 330 */ 331 void Synchronizeable::registerVar( SynchronizeableVar * var ) 332 { 333 PRINTF(0)("ADDING VAR: %s\n", var->getName().c_str()); 334 syncVarList.push_back( var ); 335 } 336 337 /** 338 * registers a varable to be synchronized over network 339 * return value is passed to varChangeHandler on change 340 * @param var see src/lib/network/synchronizeable_var/ for available classes 341 * @return handle passed to varChangeHandler on changes 342 */ 343 int Synchronizeable::registerVarId( SynchronizeableVar * var ) 344 { 345 PRINTF(0)("ADDING VAR: %s\n", var->getName().c_str()); 346 syncVarList.push_back( var ); 347 var->setWatched( true ); 348 var->setVarId( syncVarList.size()-1 ); 349 return syncVarList.size()-1; 350 } 351 352 /** 353 * removed user's states from memory 354 * @param userId user to clean 355 */ 356 void Synchronizeable::cleanUpUser( int userId ) 357 { 358 for ( UserStateHistory::iterator it = sentStates.begin(); it != sentStates.end(); it++ ) 359 { 360 for ( StateHistory::iterator it2 = it->begin(); it2 != it->end(); it2++ ) 361 { 362 if ( (*it2)->data ) 363 delete [] (*it2)->data; 364 (*it2)->data = NULL; 365 366 delete *it2; 367 } 368 } 369 370 sentStates.clear(); 371 372 for ( UserStateHistory::iterator it = recvStates.begin(); it != recvStates.end(); it++ ) 373 { 374 for ( StateHistory::iterator it2 = it->begin(); it2 != it->end(); it2++ ) 375 { 376 if ( (*it2)->data ) 377 delete [] (*it2)->data; 378 (*it2)->data = NULL; 379 380 delete *it2; 381 } 382 } 383 384 recvStates.clear(); 385 } 386 387 /** 388 * this function is called after recieving a state. 389 * @param userId 390 * @param stateId 391 * @param fromStateId 392 */ 393 void Synchronizeable::handleRecvState( int userId, int stateId, int fromStateId ) 394 { 395 //make sure this user has his history 396 if ( recvStates.size() <= userId ) 397 recvStates.resize( userId+1 ); 398 399 //remove old states 400 StateHistory::iterator it = recvStates[userId].begin(); 401 402 #if 0 403 while ( it != recvStates[userId].end() && (*it)->stateId < fromStateId ) 404 it++; 405 406 if ( it != recvStates[userId].begin() ) 407 { 408 for ( StateHistory::iterator it2 = recvStates[userId].begin(); it2 != it; it2++ ) 409 { 410 if ( (*it2)->data != NULL ) 411 { 412 delete [] (*it2)->data; 413 (*it2)->data = NULL; 414 } 415 } 416 recvStates[userId].erase( recvStates[userId].begin(), it ); 417 } 418 #endif 419 420 for ( it = recvStates[userId].begin(); it != recvStates[userId].end(); ) 421 { 422 if ( (*it)->stateId < fromStateId ) 423 { 424 StateHistory::iterator delIt = it; 425 it ++; 426 427 if ( (*delIt)->data ) 428 delete [] (*delIt)->data; 429 recvStates[userId].erase( delIt ); 430 431 continue; 432 } 433 it++; 434 } 435 436 StateHistory::iterator fromState = recvStates[userId].end(); 437 StateHistory::iterator toState = recvStates[userId].end(); 438 439 for ( it = recvStates[userId].begin(); it != recvStates[userId].end(); it++ ) 440 { 441 if ( (*it)->stateId == stateId ) 442 toState = it; 443 if ( (*it)->stateId == fromStateId ) 444 fromState = it; 445 446 if ( fromState != recvStates[userId].end() && toState != recvStates[userId].end() ) 447 break; 448 } 449 450 // setStateDiff was not called and i know fromStateId 451 if ( fromState != recvStates[userId].end() && toState == recvStates[userId].end() ) 452 { 453 StateHistoryEntry * entry = new StateHistoryEntry; 454 455 entry->dataLength = (*fromState)->dataLength; 456 if ( entry->dataLength > 0 ) 457 { 458 entry->data = new byte[entry->dataLength]; 459 460 assert( (*fromState)->data ); 461 memcpy( entry->data, (*fromState)->data, entry->dataLength ); 462 } 463 else 464 entry->data = NULL; 465 466 entry->sizeList = (*fromState)->sizeList; 467 entry->stateId = stateId; 468 469 recvStates[userId].push_back(entry); 470 } 471 } 472 473 /** 474 * this function is called after sending a state 475 * @param userId 476 * @param stateId 477 * @param fromStateId 478 */ 479 void Synchronizeable::handleSentState( int userId, int stateId, int fromStateId ) 480 { 481 //make sure this user has his history 482 if ( sentStates.size() <= userId ) 483 sentStates.resize( userId+1 ); 484 485 //remove old states 486 StateHistory::iterator it = sentStates[userId].begin(); 487 488 for ( it = sentStates[userId].begin(); it != sentStates[userId].end(); ) 489 { 490 if ( (*it)->stateId < fromStateId ) 491 { 492 StateHistory::iterator delIt = it; 493 it ++; 494 495 if ( (*delIt)->data ) 496 delete [] (*delIt)->data; 497 sentStates[userId].erase( delIt ); 498 499 continue; 500 } 501 it++; 502 } 503 504 505 StateHistory::iterator fromState = sentStates[userId].end(); 506 StateHistory::iterator toState = sentStates[userId].end(); 507 508 for ( it = sentStates[userId].begin(); it != sentStates[userId].end(); it++ ) 509 { 510 if ( (*it)->stateId == stateId ) 511 toState = it; 512 if ( (*it)->stateId == fromStateId ) 513 fromState = it; 514 515 if ( fromState != sentStates[userId].end() && toState != sentStates[userId].end() ) 516 break; 517 } 518 519 520 // getStateDiff was not called and i know fromStateId 521 if ( fromState != sentStates[userId].end() && toState == sentStates[userId].end() ) 522 { 523 StateHistoryEntry * entry = new StateHistoryEntry; 524 525 entry->dataLength = (*fromState)->dataLength; 526 if ( entry->dataLength > 0 ) 527 { 528 entry->data = new byte[entry->dataLength]; 529 530 assert( (*fromState)->data ); 531 memcpy( entry->data, (*fromState)->data, entry->dataLength ); 532 } 533 else 534 entry->data = NULL; 535 536 entry->sizeList = (*fromState)->sizeList; 537 entry->stateId = stateId; 538 539 sentStates[userId].push_back(entry); 540 } 541 542 } 543 544 545 -
trunk/src/lib/network/synchronizeable.h
r7230 r7954 1 1 /*! 2 * @file connection_monitor.h2 * @file synchronizeable.h 3 3 \brief interface for all classes that have to be synchronized 4 4 */ … … 10 10 #include "netdefs.h" 11 11 #include "converter.h" 12 12 #include "vector.h" 13 #include "quaternion.h" 14 #include "synchronizeable_var/synchronizeable_var.h" 15 #include "synchronizeable_var/synchronizeable_vector.h" 16 #include "synchronizeable_var/synchronizeable_quaternion.h" 17 #include "synchronizeable_var/synchronizeable_string.h" 18 #include "synchronizeable_var/synchronizeable_int.h" 19 #include "synchronizeable_var/synchronizeable_float.h" 20 #include "synchronizeable_var/synchronizeable_bool.h" 21 #include "synchronizeable_var/synchronizeable_uint.h" 13 22 14 23 … … 18 27 //State constants: They have to be of the form 2^n 19 28 #define STATE_SERVER 1 20 #define STATE_OUTOFSYNC 221 #define STATE_REQUESTEDSYNC 422 29 23 enum { 24 NWT_SS_WE_STATE = 1000000, 25 NWT_SS_B, 26 NWT_SS_FLAGS, 27 NWT_SS_MOUSEDIRX, 28 NWT_SS_MOUSEDIRY, 29 NWT_SS_MOUSEDIRZ, 30 NWT_SS_MOUSEDIRW, 31 NWT_SS_PN_SYNC, 32 NWT_SS_VELX, 33 NWT_SS_VELY, 34 NWT_SS_VELZ, 35 NWT_SS_PL_SYNC, 36 NWT_SS_CO_N, 37 NWT_SS_CO_CLID, 38 39 NWT_HS_HOST_ID, 40 NWT_HS_NGM_ID, 41 42 NWT_PL_B, 43 NWT_PL_FLAGS, 44 NWT_PL_SCORE, 45 46 NWT_PN_BO_WRITESTATE, 47 NWT_PN_PARENTMODE, 48 NWT_PN_COORX, 49 NWT_PN_COORY, 50 NWT_PN_COORZ, 51 NWT_PN_ROTX, 52 NWT_PN_ROTY, 53 NWT_PN_ROTZ, 54 NWT_PN_ROTV, 55 56 NWT_PN_FLAGS, 57 NWT_PN_SCOORX, 58 NWT_PN_SCOORY, 59 NWT_PN_SCOORZ, 60 NWT_PN_SROTX, 61 NWT_PN_SROTY, 62 NWT_PN_SROTZ, 63 NWT_PN_SROTV, 64 65 NWT_BO_NAME, 66 67 NWT_WE_PN_WRITESTATE, 68 NWT_WE_PN_MODELFILENAME, 69 NWT_WE_PN_SCALING, 70 71 NWT_GT_WE_STATE, 72 73 NWT_SB_WE_STATE, 74 NWT_SB_SIZE, 75 NWT_SB_TEXTURENAME, 76 77 NWT_TER_WE_STATE, 78 79 NWT_PU_WE_STATE, 80 81 NWT_TPU_WE_STATE, 82 83 NWT_LPU_WE_STATE, 84 85 NWT_WPU_WE_STATE, 86 87 NWT_PPU_WE_STATE, 88 NWT_PPU_TYPE, 89 NWT_PPU_VALUE, 90 NWT_PPU_MINVALUE, 91 NWT_PPU_MAXVALUE, 92 93 NWT_WAT_STATE, 94 NWT_WAT_WE_STATE, 95 NWT_WAT_SIZEX, 96 NWT_WAT_SIZEY, 97 NWT_WAT_RESX, 98 NWT_WAT_RESY, 99 NWT_WAT_HEIGHT 30 struct StateHistoryEntry 31 { 32 int stateId; 33 byte * data; 34 int dataLength; 35 std::list<int> sizeList; 100 36 }; 101 37 38 typedef std::list<StateHistoryEntry*> StateHistory; 102 39 103 //macros to help writing data in byte buffer 104 /* 105 * Important: these macros must be used in 106 * SYNCHELP_READ_*: virtual void writeBytes(const byte* data, int length, int sender); 107 * SYNCHELP_WRITE_*: virtual int readBytes(byte* data, int maxLength, int * reciever); 108 * with the same argument names! 109 * 110 * id is one int out of that enum on top of this comment it is used to identify 111 * read/write. when you read a value you have to use exactly the same as you used 112 * to write or you will see an assertion failing. 113 * 114 * SYNCHELP_WRITE_BEGIN() 115 * SYNCHELP_WRITE_INT(i,id) 116 * SYNCHELP_WRITE_FLOAT(f,id) 117 * SYNCHELP_WRITE_BYTE(b,id) 118 * SYNCHELP_WRITE_STRING(s,id) 119 * SYNCHELP_WRITE_N 120 * 121 * SYNCHELP_READ_BEGIN() 122 * SYNCHELP_READ_INT(i,id) 123 * SYNCHELP_READ_FLOAT(f,id) 124 * SYNCHELP_READ_STRING(s,l,id) l = size of buffer s 125 * SYNCHELP_READ_STRINGM(s,id) allocates memory for string! you have to delete this later 126 * SYNCHELP_READ_BYTE(b,id) 127 * SYNCHELP_READ_REMAINING() returns the remaining buffer size 128 * SYNCHELP_READ_NEXTBYTE() reads the next byte but it is not removed from the buffer 129 * SYNCHELP_READ_N 130 * 131 * 132 * 133 * Example 1: 134 * SYNCHELP_READ_BEGIN(); 135 * SYNCHELP_READ_FLOAT(size); 136 * SYNCHELP_READ_STRING( textureName, 1024 ); //1024 is the length of textureName 137 * delete[] textureName; 138 * textureName = NULL; 139 * SYNCHELP_READ_STRINGM( texturename ); //this will call new char[strlen()+1] 140 * 141 * Example 2: 142 * SYNCHELP_WRITE_BEGIN(); 143 * SYNCHELP_WRITE_FLOAT(this->size); 144 * SYNCHELP_WRITE_STRING(this->textureName); 145 * return SYNCHELP_WRITE_N; 146 * 147 */ 40 typedef std::vector<StateHistory> UserStateHistory; 148 41 149 #define SYNCHELP_WRITE_DEBUG(n) {\ 150 __synchelp_write_n = Converter::intToByteArray( n, data+__synchelp_write_i, maxLength-__synchelp_write_i ); \ 151 assert( __synchelp_write_n == INTSIZE ); \ 152 __synchelp_write_i += __synchelp_write_n; \ 153 } 154 155 #define SYNCHELP_READ_DEBUG(n) { \ 156 int nn; \ 157 __synchelp_read_n = Converter::byteArrayToInt( data+__synchelp_read_i, &nn ); \ 158 assert( __synchelp_read_n == INTSIZE ); \ 159 if ( n != nn ) { \ 160 PRINTF(1)("Check your code! read/writes not in right order! read %d instead of %d\n", nn, n); \ 161 assert( false ); \ 162 } \ 163 __synchelp_read_i += __synchelp_read_n; \ 164 } 165 166 #define SYNCHELP_WRITE_BEGIN() int __synchelp_write_i = 0; \ 167 int __synchelp_write_n 168 #define SYNCHELP_WRITE_INT(i,n) { SYNCHELP_WRITE_DEBUG(n); \ 169 __synchelp_write_n = \ 170 Converter::intToByteArray( i, data+__synchelp_write_i, maxLength-__synchelp_write_i ); \ 171 assert( __synchelp_write_n == INTSIZE ); \ 172 if ( __synchelp_write_n <= 0) \ 173 { \ 174 PRINTF(1)("Buffer is too small to store a int\n"); \ 175 return 0; \ 176 } \ 177 __synchelp_write_i += __synchelp_write_n; \ 178 } 179 #define SYNCHELP_WRITE_FLOAT(f,n) { SYNCHELP_WRITE_DEBUG(n); \ 180 __synchelp_write_n = \ 181 Converter::floatToByteArray( f, data+__synchelp_write_i, maxLength-__synchelp_write_i ); \ 182 assert( __synchelp_write_n == FLOATSIZE ); \ 183 if ( __synchelp_write_n <= 0) \ 184 { \ 185 PRINTF(1)("Buffer is too small to store a float\n"); \ 186 return 0; \ 187 } \ 188 __synchelp_write_i += __synchelp_write_n; \ 189 } 190 #define SYNCHELP_WRITE_BYTE(b,n) { SYNCHELP_WRITE_DEBUG(n); \ 191 \ 192 if (maxLength - __synchelp_write_i < 1) \ 193 { \ 194 PRINTF(1)("Buffer is too small to store string\n"); \ 195 return 0; \ 196 } \ 197 data[__synchelp_write_i] = b; \ 198 __synchelp_write_i++; \ 199 } 200 #define SYNCHELP_WRITE_STRING(s,n) { SYNCHELP_WRITE_DEBUG(n); \ 201 __synchelp_write_n = \ 202 Converter::stringToByteArray( s, data+__synchelp_write_i, maxLength-__synchelp_write_i ); \ 203 assert( __synchelp_write_n == ((std::string)s).length()+INTSIZE ); \ 204 if ( __synchelp_write_n <= 0) \ 205 { \ 206 PRINTF(1)("Buffer is too small to store string\n"); \ 207 return 0; \ 208 } \ 209 __synchelp_write_i += __synchelp_write_n; \ 210 } 211 #define SYNCHELP_WRITE_N __synchelp_write_i 212 #define SYNCHELP_WRITE_FKT(f,n) { SYNCHELP_WRITE_DEBUG(n); \ 213 PRINTF(0)("calling %s with %d left\n", #f, maxLength - __synchelp_write_i); \ 214 byte * spos = data+__synchelp_write_i; \ 215 if (maxLength - __synchelp_write_i < INTSIZE) \ 216 { \ 217 PRINTF(1)("Buffer is too small to store more data\n"); \ 218 return 0; \ 219 } \ 220 __synchelp_write_i += INTSIZE; \ 221 __synchelp_write_n = \ 222 f( data+__synchelp_write_i, maxLength-__synchelp_write_i ); \ 223 __synchelp_write_i += __synchelp_write_n; \ 224 Converter::intToByteArray( __synchelp_write_n, spos, INTSIZE ); \ 225 } 226 227 228 #define SYNCHELP_READ_BEGIN() int __synchelp_read_i = 0; \ 229 int __synchelp_read_n 230 231 #define SYNCHELP_READ_INT(i,n) { SYNCHELP_READ_DEBUG(n); \ 232 if ( length-__synchelp_read_i < INTSIZE ) \ 233 { \ 234 PRINTF(1)("There is not enough data to read an int\n"); \ 235 return 0; \ 236 } \ 237 __synchelp_read_n = Converter::byteArrayToInt( data+__synchelp_read_i, &i ); \ 238 assert( __synchelp_read_n == INTSIZE ); \ 239 __synchelp_read_i += __synchelp_read_n; \ 240 } 241 #define SYNCHELP_READ_FLOAT(f,n) { SYNCHELP_READ_DEBUG(n); \ 242 if ( length-__synchelp_read_i < FLOATSIZE ) \ 243 { \ 244 PRINTF(1)("There is not enough data to read a flaot\n"); \ 245 return 0; \ 246 } \ 247 __synchelp_read_n = Converter::byteArrayToFloat( data+__synchelp_read_i, &f ); \ 248 assert( __synchelp_read_n == FLOATSIZE ) ;\ 249 __synchelp_read_i += __synchelp_read_n; \ 250 } 251 #define SYNCHELP_READ_STRING(s,n) {SYNCHELP_READ_DEBUG(n); \ 252 __synchelp_read_n = Converter::byteArrayToString( data+__synchelp_read_i, s, length-__synchelp_read_i ); \ 253 assert( __synchelp_read_n == s.length()+INTSIZE ) ;\ 254 if ( __synchelp_read_n <0 ) \ 255 { \ 256 PRINTF(1)("There is not enough data to read string\n"); \ 257 return 0; \ 258 } \ 259 __synchelp_read_i += __synchelp_read_n; \ 260 } 261 #if 0 //not needed any more 262 #define SYNCHELP_READ_STRINGM(s,n) { SYNCHELP_READ_DEBUG(n); \ 263 __synchelp_read_n = Converter::byteArrayToStringM( data+__synchelp_read_i, s ); \ 264 assert( __synchelp_read_n == strlen(s)+INTSIZE ) ;\ 265 if ( __synchelp_read_n <0 ) \ 266 { \ 267 PRINTF(1)("There is not enough data to read string\n"); \ 268 return 0; \ 269 } \ 270 __synchelp_read_i += __synchelp_read_n; \ 271 } 272 #endif 273 #define SYNCHELP_READ_BYTE(b,n) { SYNCHELP_READ_DEBUG(n); \ 274 if ( length-__synchelp_read_i < 1 ) \ 275 { \ 276 PRINTF(1)("There is not enough data to read a byte\n"); \ 277 return 0; \ 278 } \ 279 b = data[__synchelp_read_i]; \ 280 __synchelp_read_i ++; \ 281 } 282 #define SYNCHELP_READ_FKT(f,n) { SYNCHELP_READ_DEBUG(n); \ 283 int s; \ 284 if ( length-__synchelp_read_i < INTSIZE ) \ 285 { \ 286 PRINTF(1)("There is not enough data to read an int\n"); \ 287 return 0; \ 288 } \ 289 __synchelp_read_n = Converter::byteArrayToInt( data+__synchelp_read_i, &s ); \ 290 assert( __synchelp_read_n == INTSIZE ); \ 291 __synchelp_read_i += __synchelp_read_n; \ 292 __synchelp_read_i += \ 293 f( data+__synchelp_read_i, s, sender); \ 294 } 295 #define SYNCHELP_READ_REMAINING() ( length-__synchelp_read_i ) 296 #define SYNCHELP_READ_NEXTBYTE() ( data[__synchelp_read_i] ) 297 #define SYNCHELP_READ_N __synchelp_read_i 42 typedef std::vector<SynchronizeableVar*> SyncVarList; 298 43 299 44 class NetworkStream; 300 301 45 302 46 class Synchronizeable : virtual public BaseObject … … 307 51 virtual ~Synchronizeable(); 308 52 309 virtual int writeBytes(const byte* data, int length, int sender); 310 virtual int readBytes(byte* data, int maxLength, int * reciever); 311 virtual void writeDebug() const; 312 virtual void readDebug() const; 53 void setIsServer( bool isServer ); 54 bool isServer(); 313 55 314 void setIsServer( bool isServer ); 315 void setIsOutOfSync( bool outOfSync ); 316 void setRequestedSync( bool requestedSync ); 317 bool isServer(); 318 bool isOutOfSync(); 319 bool requestedSync(); 56 virtual void varChangeHandler( std::list<int> & id ); 57 58 virtual int getStateDiff( int userId, byte* data, int maxLength, int stateId, int fromStateId, int priorityTH ); 59 virtual int setStateDiff( int userId, byte* data, int length, int stateId, int fromStateId ); 60 virtual void cleanUpUser( int userId ); 61 virtual void handleSentState( int userId, int stateId, int fromStateId ); 62 virtual void handleRecvState( int userId, int stateId, int fromStateId ); 63 64 void registerVar( SynchronizeableVar * var ); 65 int registerVarId( SynchronizeableVar * var ); 320 66 321 67 inline void setUniqueID( int id ){ uniqueID = id; } … … 326 72 inline void setOwner(int owner){ this->owner = owner; } 327 73 328 /** @returns true if this Synchronizeable has to be synchronized over network */74 /** @returns true if this Synchronizeable wants to be synchronized over network */ 329 75 inline bool beSynchronized() { return this->bSynchronize; } 330 76 /** @param bSynchronize sets the Synchronizeable to be sunchronized or not */ 331 77 inline void setSynchronized(bool bSynchronize) { this->bSynchronize = bSynchronize; } 332 333 inline void requestSync( int hostID ){ this->synchronizeRequests.push_back( hostID ); }334 inline int getRequestSync( void ){ if ( this->synchronizeRequests.size()>0 ){ int n = *(synchronizeRequests.begin()); synchronizeRequests.pop_front(); return n; } else { return -1; } };335 78 336 79 inline void setNetworkStream(NetworkStream* stream) { this->networkStream = stream; } … … 339 82 340 83 protected: 341 NetworkStream* networkStream; 84 NetworkStream* networkStream; //!< reference network stream we are connected to 342 85 int state; 343 86 87 private: 88 int uniqueID; //!< unique id assigned to synchronizeable 89 int mLeafClassId; //!< store leafClassId to send via states 90 int owner; //!< hostId of owner ( 0 if none / server ) 91 int hostID; //!< my own host id 92 bool bSynchronize; //!< do we need beeing synchronized? 344 93 345 private: 346 int uniqueID; 347 int owner; 348 int hostID; 349 bool bSynchronize; 94 SyncVarList syncVarList; //!< list containing variables to synchronize 350 95 351 std::list<int> synchronizeRequests; 96 UserStateHistory sentStates; //!< store already sent states to create diffs from, offset corresponds to the user id 97 UserStateHistory recvStates; //!< store recieved states to apply diffs, offset corresponds to the user id 352 98 353 99 };
Note: See TracChangeset
for help on using the changeset viewer.