void ReplicaManager::Destruct(Replica *replica, PlayerID playerId, bool broadcast) { assert(replica); bool objectExists; unsigned replicatedObjectsIndex; replicatedObjectsIndex = replicatedObjects.GetIndexFromKey(replica, &objectExists); if (objectExists==false) return; // For each existing participant, send a packet telling them of this object destruction RakNet::BitStream outBitstream; unsigned i,tempIndex; bool replicaReferenced; ParticipantStruct *participantStruct; replicaReferenced=false; for (i=0; i < participantList.Size(); i++) { participantStruct=participantList[i]; if ((broadcast==true && playerId!=participantStruct->playerId) || (broadcast==false && playerId==participantStruct->playerId)) { // Send the destruction packet immediately if (replica->GetNetworkID()!=UNASSIGNED_NETWORK_ID && (replicatedObjects[replicatedObjectsIndex].allowedInterfaces & REPLICA_SEND_DESTRUCTION)) { outBitstream.Reset(); outBitstream.Write((unsigned char)ID_REPLICA_MANAGER_DESTRUCTION); outBitstream.Write(replica->GetNetworkID()); replica->SendDestruction(&outBitstream, participantStruct->playerId); if (outBitstream.GetNumberOfBitsUsed()>0) { rakPeer->Send(&outBitstream, HIGH_PRIORITY, RELIABLE_ORDERED, sendChannel, participantStruct->playerId, false); } } // Remove any pending commands that reference this object, for this player tempIndex = participantStruct->commandList.GetIndexFromKey(replica, &objectExists); if (objectExists) participantStruct->commandList.RemoveAtIndex(tempIndex); // Remove any remote object state tracking for this object, for this player tempIndex = participantStruct->remoteObjectList.GetIndexFromKey(replica, &objectExists); if (objectExists) participantStruct->remoteObjectList.RemoveAtIndex(tempIndex); } else if (replicaReferenced==false) { // See if any commands or objects reference replica if (participantStruct->commandList.HasData(replica)) replicaReferenced=true; else if (participantStruct->remoteObjectList.HasData(replica)) replicaReferenced=true; } } // Remove replica from the list if no commands and no remote objects reference it if (replicaReferenced==false) replicatedObjects.RemoveAtIndex(replicatedObjectsIndex); }
void SendPlayerPoolToPlayer(PLAYERID playerID) { // let the player know about all the players in the server for(PLAYERID p = 0; p < MAX_PLAYERS; p++) { if(!playerPool[p].iIsConnected) continue; if(p == playerID) continue; BYTE byteNameLen = (BYTE)strlen(playerPool[p].szPlayerName); RakNet::BitStream bs; bs.Reset(); bs.Write(p); bs.Write((int)1); bs.Write((BYTE)0); bs.Write(byteNameLen); bs.Write(playerPool[p].szPlayerName, byteNameLen); pRakServer->RPC(&RPC_ServerJoin, &bs, HIGH_PRIORITY, RELIABLE, 0, pRakServer->GetPlayerIDFromIndex(playerID), FALSE, FALSE, UNASSIGNED_NETWORK_ID, NULL); Sleep(5); // well, shit. } }
void FileListTransfer::PushReference(SystemAddress systemAddress) { // Was previously using GetStatistics to get outgoing buffer size, but TCP with UnifiedSend doesn't have this unsigned int i=0; unsigned int bytesRead; char *dataBlocks[2]; int lengths[2]; RakNet::BitStream outBitstream; while (i < filesToPush.Size()) { if (filesToPush[i].systemAddress==systemAddress) { outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_REFERENCE_PUSH); outBitstream.Write(filesToPush[i].fileListNode.context); outBitstream.Write(filesToPush[i].setID); stringCompressor->EncodeString(filesToPush[i].fileListNode.filename, 512, &outBitstream); outBitstream.WriteCompressed(filesToPush[i].setIndex); outBitstream.WriteCompressed(filesToPush[i].fileListNode.dataLengthBytes); // Original length in bytes // Read and send chunk. If done, delete at this index void *buff = rakMalloc_Ex(filesToPush[i].chunkSize, __FILE__, __LINE__); if (buff==0) { notifyOutOfMemory(__FILE__, __LINE__); continue; } bytesRead=filesToPush[i].incrementalReadInterface->GetFilePart(filesToPush[i].fileListNode.fullPathToFile, filesToPush[i].currentOffset, filesToPush[i].chunkSize, buff, filesToPush[i].fileListNode.context); outBitstream.WriteCompressed(filesToPush[i].currentOffset); filesToPush[i].currentOffset+=bytesRead; outBitstream.WriteCompressed(bytesRead); bool done = bytesRead!=filesToPush[i].chunkSize; outBitstream.Write(done); if (callback) { callback->OnFilePush(filesToPush[i].fileListNode.filename, filesToPush[i].fileListNode.fileLengthBytes, filesToPush[i].currentOffset-bytesRead, bytesRead, done, filesToPush[i].systemAddress); } dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=(char*) buff; lengths[1]=bytesRead; //rakPeerInterface->SendList(dataBlocks,lengths,2,filesToPush[i].packetPriority, RELIABLE_ORDERED, filesToPush[i].orderingChannel, filesToPush[i].systemAddress, false); SendListUnified(dataBlocks,lengths,2,filesToPush[i].packetPriority, RELIABLE_ORDERED, filesToPush[i].orderingChannel, filesToPush[i].systemAddress, false); if (done) { // Done RakNet::OP_DELETE_ARRAY(filesToPush[i].fileListNode.filename, __FILE__, __LINE__); filesToPush.RemoveAtIndex(i); } rakFree_Ex(buff, __FILE__, __LINE__ ); return; } else i++; } }
void NatPunchthroughServer::OnClosedConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason ) { (void) lostConnectionReason; (void) systemAddress; unsigned int i=0; bool objectExists; i = users.GetIndexFromKey(rakNetGUID, &objectExists); if (objectExists) { RakNet::BitStream outgoingBs; DataStructures::List<User *> freedUpInProgressUsers; User *user = users[i]; User *otherUser; unsigned int connectionAttemptIndex; ConnectionAttempt *connectionAttempt; for (connectionAttemptIndex=0; connectionAttemptIndex < user->connectionAttempts.Size(); connectionAttemptIndex++) { connectionAttempt=user->connectionAttempts[connectionAttemptIndex]; outgoingBs.Reset(); if (connectionAttempt->recipient==user) { otherUser=connectionAttempt->sender; } else { otherUser=connectionAttempt->recipient; } // 05/28/09 Previously only told sender about ID_NAT_CONNECTION_TO_TARGET_LOST // However, recipient may be expecting it due to external code // In that case, recipient would never get any response if the sender dropped outgoingBs.Write((MessageID)ID_NAT_CONNECTION_TO_TARGET_LOST); outgoingBs.Write(rakNetGUID); outgoingBs.Write(connectionAttempt->sessionId); rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,otherUser->systemAddress,false); // 4/22/09 - Bug: was checking inProgress, legacy variable not used elsewhere if (connectionAttempt->attemptPhase==ConnectionAttempt::NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS) { otherUser->isReady=true; freedUpInProgressUsers.Insert(otherUser, _FILE_AND_LINE_ ); } otherUser->DeleteConnectionAttempt(connectionAttempt); } RakNet::OP_DELETE(users[i], _FILE_AND_LINE_); users.RemoveAtIndex(i); for (i=0; i < freedUpInProgressUsers.Size(); i++) { StartPunchthroughForUser(freedUpInProgressUsers[i]); } } }
void CRcon::Packet_NewIncomingConnection(Packet* pPacket) { in_addr in; in.s_addr = pPacket->playerId.binaryAddress; logprintf("[RCON] Admin [%s] has connected.", inet_ntoa(in)); RakNet::BitStream bsSend; char* szHostname = pConsole->GetStringVariable( "hostname" ); BYTE byteHostnameLength = strlen(szHostname); CPlayerPool* pPlayerPool = pNetGame->GetPlayerPool(); bsSend.Write( byteHostnameLength ); bsSend.Write( szHostname, byteHostnameLength ); m_pRakServer->RPC( RPC_RconConnect,&bsSend,HIGH_PRIORITY,RELIABLE,0,UNASSIGNED_PLAYER_ID,true,false); bsSend.Reset(); for( int i = 0; i < MAX_PLAYERS; i++ ) { if( pPlayerPool->GetSlotState(i) == TRUE ) { bsSend.Write((BYTE)i); bsSend.Write(pPlayerPool->GetPlayerName(i),MAX_PLAYER_NAME); pRcon->GetRakServer()->RPC( RPC_ServerJoin, &bsSend, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_PLAYER_ID, true, false ); bsSend.Reset(); PLAYER_DATA playerData = GetPlayerInformation( i ); bsSend.Write( (BYTE)i ); bsSend.Write( (PCHAR)&playerData, sizeof(PLAYER_DATA) ); pRcon->GetRakServer()->RPC( RPC_RconPlayerInfo, &bsSend, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_PLAYER_ID, true, false ); bsSend.Reset(); } } }
void ConnectionGraph2::AddParticipant(const SystemAddress &systemAddress, RakNetGUID rakNetGUID) { // Relay the new connection to other systems. RakNet::BitStream bs; bs.Write((MessageID)ID_REMOTE_NEW_INCOMING_CONNECTION); bs.Write((uint32_t)1); bs.Write(systemAddress); bs.Write(rakNetGUID); bs.WriteCasted<uint16_t>(rakPeerInterface->GetAveragePing(rakNetGUID)); SendUnified(&bs,HIGH_PRIORITY,RELIABLE_ORDERED,0,systemAddress,true); // Send everyone to the new guy DataStructures::List<SystemAddress> addresses; DataStructures::List<RakNetGUID> guids; rakPeerInterface->GetSystemList(addresses, guids); bs.Reset(); bs.Write((MessageID)ID_REMOTE_NEW_INCOMING_CONNECTION); BitSize_t writeOffset = bs.GetWriteOffset(); bs.Write((uint32_t) addresses.Size()); unsigned int i; uint32_t count=0; for (i=0; i < addresses.Size(); i++) { if (addresses[i]==systemAddress) continue; bs.Write(addresses[i]); bs.Write(guids[i]); bs.WriteCasted<uint16_t>(rakPeerInterface->GetAveragePing(guids[i])); count++; } if (count>0) { BitSize_t writeOffset2 = bs.GetWriteOffset(); bs.SetWriteOffset(writeOffset); bs.Write(count); bs.SetWriteOffset(writeOffset2); SendUnified(&bs,HIGH_PRIORITY,RELIABLE_ORDERED,0,systemAddress,false); } bool objectExists; unsigned int ii = remoteSystems.GetIndexFromKey(rakNetGUID, &objectExists); if (objectExists==false) { RemoteSystem* remoteSystem = RakNet::OP_NEW<RemoteSystem>(_FILE_AND_LINE_); remoteSystem->guid=rakNetGUID; remoteSystems.InsertAtIndex(remoteSystem,ii,_FILE_AND_LINE_); } }
void Application::CreateMissile(float x, float y, float w, int id) { #ifdef NETWORKMISSLE // Lab 13 Task 9b : Implement networked version of createmissile RakNet::BitStream bs; unsigned char msgid; unsigned char deleted = 0; if (mymissile) { //sendupdatethroughnetworktodeletethismissile deleted = 1; msgid = ID_UPDATEMISSILE; bs.Write(msgid); bs.Write(id); bs.Write(deleted); bs.Write(x); bs.Write(y); bs.Write(w); rakpeer_->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true); //deleteexistingmissile delete mymissile; mymissile = 0; } //addanewmissilebasedonthefollowingparametercoordinates mymissile = new Missile("missile.png", x, y, w, id); //sendnetworkcommandtoaddnewmissile bs.Reset(); msgid = ID_NEWMISSILE; bs.Write(msgid); bs.Write(id); bs.Write(x); bs.Write(y); bs.Write(w); rakpeer_->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true); #else // Lab 13 Task 3 : Implement local version missile creation if (mymissile) // Delete existing missle { delete mymissile; mymissile = NULL; } // Add missle mymissile = new Missile("missile.png", x, y, w, id); #endif }
void ServerApp::SendWelcomePackage(SystemAddress& addr) { ++newID; unsigned int shipcount = static_cast<unsigned int>(clients_.size()); unsigned char msgid = ID_WELCOME; RakNet::BitStream bs; bs.Write(msgid); bs.Write(newID); bs.Write(shipcount); // Send all existing ships for (ClientMap::iterator itr = clients_.begin(); itr != clients_.end(); ++itr) { std::cout << "Ship " << itr->second.id << " pos" << itr->second.x_ << " " << itr->second.y_ << std::endl; bs.Write( itr->second.id ); bs.Write( itr->second.x_ ); bs.Write( itr->second.y_ ); bs.Write( itr->second.type_ ); } for (vector<ServerEnemy*>::iterator it = enemyList.begin(); it != enemyList.end(); ++it) { ServerEnemy* e = *it; bs.Write(e->id); bs.Write(e->active); bs.Write(e->type_); bs.Write(e->x_); bs.Write(e->y_); bs.Write(e->vel_x); bs.Write(e->vel_y); bs.Write(e->speed); bs.Write(e->hp); } bs.Write(base_hp); rakpeer_->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED,0, addr, false); bs.Reset(); ServerGameObject newobject(newID); newobject.active = true; clients_.insert(std::make_pair(addr, newobject)); clientList.push_back(addr); // Add client to list std::cout << "New guy, assigned id " << newID << std::endl; }
void ConnectionGraph2::OnNewConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, bool isIncoming) { (void) isIncoming; // Send all existing systems to new connection RakNet::BitStream bs; bs.Write((MessageID)ID_REMOTE_NEW_INCOMING_CONNECTION); bs.Write((unsigned int)1); bs.Write(systemAddress); bs.Write(rakNetGUID); SendUnified(&bs,HIGH_PRIORITY,RELIABLE_ORDERED,0,systemAddress,true); // Send everyone to the new guy DataStructures::List<SystemAddress> addresses; DataStructures::List<RakNetGUID> guids; rakPeerInterface->GetSystemList(addresses, guids); bs.Reset(); bs.Write((MessageID)ID_REMOTE_NEW_INCOMING_CONNECTION); BitSize_t writeOffset = bs.GetWriteOffset(); bs.Write((unsigned int) addresses.Size()); unsigned int i; unsigned int count=0; for (i=0; i < addresses.Size(); i++) { if (addresses[i]==systemAddress) continue; bs.Write(addresses[i]); bs.Write(guids[i]); count++; } if (count>0) { BitSize_t writeOffset2 = bs.GetWriteOffset(); bs.SetWriteOffset(writeOffset); bs.Write(count); bs.SetWriteOffset(writeOffset2); SendUnified(&bs,HIGH_PRIORITY,RELIABLE_ORDERED,0,systemAddress,false); } RemoteSystem* remoteSystem = RakNet::OP_NEW<RemoteSystem>(__FILE__,__LINE__); remoteSystem->guid=rakNetGUID; remoteSystems.Insert(rakNetGUID,remoteSystem,true,__FILE__,__LINE__); }
bool CNetwork::update() { Packet *packet = m_peer->Receive(); while(packet) { handlePacket(packet); m_peer->DeallocatePacket(packet); packet = m_peer->Receive(); } if (m_readTimer->elapsed() > m_tick_rate) { RakNet::BitStream bs; typedef std::map<int, CompLocation*> LocationMap; BOOST_FOREACH(LocationMap::value_type value, CKernel::data()->getAllLocation()) { //TODO(#2#) BE SURE ABOUT NETWORK PERFORMANCE if(value.second->getTick() == m_tick) { bs.Reset(); bs.Write((MessageID)ID_ENTITY_POS); bs.Write(value.first); bs.Write(value.second->position()); bs.Write(value.second->direction()); bs.Write(value.second->velocity()); CompInfo* info = CKernel::data()->getGameObjectInfo(value.first); if (info) { sendToAllInMap(info->map(), bs); } } } m_readTimer->restart(); if(m_tick >= m_tick_max) m_tick = 0; else ++m_tick; }
void Router2::SendOOBMessages(Router2::MiniPunchRequest *mpr) { // Mini NAT punch // Send from srcToDestPort to packet->systemAddress (source). If the message arrives, the remote system should reply. SendOOBFromSpecifiedSocket(ID_ROUTER_2_REPLY_TO_SENDER_PORT, mpr->sourceAddress, mpr->forwardingSocket); // Send from destToSourcePort to endpointSystemAddress (destination). If the message arrives, the remote system should reply. SendOOBFromSpecifiedSocket(ID_ROUTER_2_REPLY_TO_SENDER_PORT, mpr->endpointAddress, mpr->forwardingSocket); if (debugInterface) { char buff [512]; char buff2[128]; mpr->sourceAddress .ToString(true,buff2); debugInterface->ShowDiagnostic(FormatStringTS(buff,"call SendOOBFromSpecifiedSocket(...,%s,...)", buff2)); mpr->endpointAddress .ToString(true,buff2); debugInterface->ShowDiagnostic(FormatStringTS(buff,"call SendOOBFromSpecifiedSocket(...,%s,...)", buff2)); } // Tell source to send to forwardingPort RakNet::BitStream extraData; extraData.Write(mpr->forwardingPort); RakAssert(mpr->forwardingPort!=0); SendOOBFromRakNetPort(ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT, &extraData, mpr->sourceAddress); // Tell destination to send to forwardingPort extraData.Reset(); extraData.Write(mpr->forwardingPort); RakAssert(mpr->forwardingPort); SendOOBFromRakNetPort(ID_ROUTER_2_REPLY_TO_SPECIFIED_PORT, &extraData, mpr->endpointAddress); }
/* What is being done here is having 8 peers all connect to eachother and be connected. Then it check if they all connect. If so send data in ordered reliable mode for 100 loops. Possible ideas for changes: Possibly use rakpeerinterfaces GetSystemList() for number of connected peers instead of manually tracking. Would be slower though, shouldn't be significant at this number but the recieve speed it part of the test. Success conditions: Peers connect and receive all packets in order. No disconnections allowed in this version of the test. Failure conditions: If cannot connect to all peers for 20 seconds. All packets are not recieved. All packets are not in order. Disconnection. */ int EightPeerTest::RunTest(DataStructures::List<RakNet::RakString> params,bool isVerbose,bool noPauses) { const int peerNum= 8; RakPeerInterface *peerList[peerNum];//A list of 8 peers int connectionAmount[peerNum];//Counter for me to keep track of connection requests and accepts int recievedFromList[peerNum][peerNum];//Counter for me to keep track of packets received int lastNumberReceivedFromList[peerNum][peerNum];//Counter for me to keep track of last recieved sequence number Packet *packet; RakNet::BitStream bitStream; destroyList.Clear(false,__FILE__,__LINE__); //Initializations of the arrays for (int i=0;i<peerNum;i++) { peerList[i]=RakNetworkFactory::GetRakPeerInterface(); destroyList.Push(peerList[i],__FILE__,__LINE__); connectionAmount[i]=0; for (int j=0;j<peerNum;j++) { recievedFromList[i][j]=0; lastNumberReceivedFromList[i][j]=0; } peerList[i]->Startup(peerNum*2, 30, &SocketDescriptor(60000+i,0), 1); peerList[i]->SetMaximumIncomingConnections(peerNum); } //Connect all the peers together for (int i=0;i<peerNum;i++) { for (int j=i+1;j<peerNum;j++)//Start at i+1 so don't connect two of the same together. { if (!peerList[i]->Connect("127.0.0.1", 60000+j, 0,0)) { if (isVerbose) { DebugTools::ShowError("Problem while calling connect. \n",!noPauses && isVerbose,__LINE__,__FILE__); } return 1;//This fails the test, don't bother going on. } } } RakNetTime entryTime=RakNet::GetTime();//Loop entry time bool initialConnectOver=false;//Our initial connect all has been done. for (int k=0;k<100;)//Quit after we send 100 messages while connected, if not all connected and not failure, otherwise fail after 20 seconds and exit { bool allConnected=true;//Start true, only one failed case makes it all fail for (int i=0;i<peerNum;i++)//Make sure all peers are connected to eachother { if (connectionAmount[i]<peerNum-1) { allConnected=false; } } if (RakNet::GetTime()-entryTime>20000 &&!initialConnectOver &&!allConnected)//failed for 20 seconds { if (isVerbose) DebugTools::ShowError("Failed to connect to all peers after 20 seconds",!noPauses && isVerbose,__LINE__,__FILE__); return 2; break; } if (allConnected) { if(!initialConnectOver) initialConnectOver=true; for (int i=0;i<peerNum;i++)//Have all peers send a message to all peers { bitStream.Reset(); bitStream.Write((unsigned char) (ID_USER_PACKET_ENUM+1)); bitStream.Write(k); bitStream.Write(i); peerList[i]->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED ,0, UNASSIGNED_SYSTEM_ADDRESS, true); } k++; } if (k>=97)//This is our last 3 loops, give it time to send packet and arrive on interface, 2 seconds is more than enough { RakSleep(2000); } for (int i=0;i<peerNum;i++)//Receive for all peers { if (allConnected)//If all connected try to make the data more visually appealing by bunching it in one receive { int waittime=0; do { packet=peerList[i]->Receive(); waittime++; if (!packet) { RakSleep(1); } if (waittime>1000)//Check for packet every millisec and if one second has passed move on, don't block execution { break; } } while(!packet);//For testing purposes wait for packet a little while, go if not recieved } else//Otherwise just keep recieving quickly until connected { packet=peerList[i]->Receive(); } if (isVerbose) printf("For peer %i with %i connected peers.\n",i,connectionAmount[i]); while(packet) { switch (packet->data[0]) { case ID_REMOTE_DISCONNECTION_NOTIFICATION: if (isVerbose) { printf("Another client has disconnected.\n"); DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__); } return 3; break; case ID_REMOTE_CONNECTION_LOST: if (isVerbose) { printf("Another client has lost the connection.\n"); DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__); } return 3; break; case ID_REMOTE_NEW_INCOMING_CONNECTION: if (isVerbose) printf("Another client has connected.\n"); break; case ID_CONNECTION_REQUEST_ACCEPTED: if (isVerbose) printf("Our connection request has been accepted.\n"); connectionAmount[i]++; break; case ID_CONNECTION_ATTEMPT_FAILED: if (isVerbose) DebugTools::ShowError("A connection has failed.\n Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__); return 2; break; case ID_NEW_INCOMING_CONNECTION: if (isVerbose) printf("A connection is incoming.\n"); connectionAmount[i]++;//For this test assume connection. Test will fail if connection fails. break; case ID_NO_FREE_INCOMING_CONNECTIONS://Should not happend if (isVerbose) { printf("The server is full. This shouldn't happen in this test ever.\n"); DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__); } return 2; break; case ID_ALREADY_CONNECTED: if (isVerbose) printf("Already connected\n");//Shouldn't happen break; case ID_DISCONNECTION_NOTIFICATION: if (isVerbose) { printf("We have been disconnected.\n"); DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__); } return 3; break; case ID_CONNECTION_LOST: allConnected=false; connectionAmount[i]--; if (isVerbose) { printf("Connection lost.\n"); DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__); } return 3; break; default: if (packet->data[0]==ID_USER_PACKET_ENUM+1) { int thePeerNum; int sequenceNum; bitStream.Reset(); bitStream.Write((char*)packet->data, packet->length); bitStream.IgnoreBits(8); bitStream.Read(sequenceNum); bitStream.Read(thePeerNum); if (isVerbose) printf("Message %i from %i\n",sequenceNum,thePeerNum ); if (thePeerNum>=0&&thePeerNum<peerNum) { if (lastNumberReceivedFromList[i][thePeerNum]==sequenceNum) { lastNumberReceivedFromList[i][thePeerNum]++; } else { if (isVerbose) { printf("Packets out of order"); DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__); } return 4; } recievedFromList[i][thePeerNum]++;} } break; } peerList[i]->DeallocatePacket(packet); // Stay in the loop as long as there are more packets. packet = peerList[i]->Receive(); } } RakSleep(0);//If needed for testing } for (int i=0;i<peerNum;i++) { for (int j=0;j<peerNum;j++) { if (i!=j) { if (isVerbose) printf("%i recieved %i packets from %i\n",i,recievedFromList[i][j],j); if (recievedFromList[i][j]!=100) { if (isVerbose) { printf("Not all packets recieved. it was in reliable ordered mode so that means test failed or wait time needs increasing\n"); DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__); } return 5; } } } } printf("All packets recieved in order,pass\n"); return 0; }
int main(int argc, char **argv) { RakPeerInterface *rakPeer; char str[256]; char ip[32]; unsigned short remotePort, localPort; RakNet::Packet *packet; printf("This project tests sending a burst of messages to a remote system.\n"); printf("Difficulty: Beginner\n\n"); rakPeer = RakNet::RakPeerInterface::GetInstance(); printf("Enter remote IP (enter to not connect): "); Gets(ip, sizeof(ip)); if (ip[0]) { printf("Enter remote port: "); Gets(str, sizeof(str)); if (str[0]==0) strcpy(str, "60000"); remotePort=atoi(str); printf("Enter local port: "); Gets(str, sizeof(str)); if (str[0]==0) strcpy(str, "0"); localPort=atoi(str); RakNet::SocketDescriptor socketDescriptor(localPort,0); rakPeer->Startup(32, &socketDescriptor, 1); printf("Connecting...\n"); rakPeer->Connect(ip, remotePort, 0, 0); } else { printf("Enter local port: "); Gets(str, sizeof(str)); if (str[0]==0) strcpy(str, "60000"); localPort=atoi(str); RakNet::SocketDescriptor socketDescriptor(localPort,0); rakPeer->Startup(32, &socketDescriptor, 1); } rakPeer->SetMaximumIncomingConnections(32); printf("'s' to send. ' ' for statistics. 'q' to quit.\n"); while (1) { if (kbhit()) { char ch=getch(); if (ch=='q') return 1; else if (ch==' ') { RakNetStatistics *rss; char message[2048]; rss=rakPeer->GetStatistics(rakPeer->GetSystemAddressFromIndex(0)); StatisticsToString(rss, message, 2); printf("%s", message); } else if (ch=='s') { char msgSizeStr[128], msgCountStr[128]; uint32_t msgSize, msgCount,index; printf("Enter message size in bytes: "); Gets(msgSizeStr, sizeof(msgSizeStr)); if (msgSizeStr[0]==0) msgSize=4096; else msgSize=atoi(msgSizeStr); printf("Enter times to repeatedly send message: "); Gets(msgCountStr, sizeof(msgCountStr)); if (msgCountStr[0]==0) msgCount=128; else msgCount=atoi(msgCountStr); RakNet::BitStream bitStream; for (index=0; index < msgCount; index++) { bitStream.Reset(); bitStream.Write((MessageID)ID_USER_PACKET_ENUM); bitStream.Write(msgSize); bitStream.Write(index); bitStream.Write(msgCount); bitStream.PadWithZeroToByteLength(msgSize); rakPeer->Send(&bitStream, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true); } printf("Sent\n"); } } for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive()) { switch(packet->data[0]) { case ID_CONNECTION_REQUEST_ACCEPTED: printf("ID_CONNECTION_REQUEST_ACCEPTED\n"); break; case ID_NEW_INCOMING_CONNECTION: printf("ID_NEW_INCOMING_CONNECTION\n"); break; case ID_NO_FREE_INCOMING_CONNECTIONS: printf("ID_NO_FREE_INCOMING_CONNECTIONS\n"); break; case ID_DISCONNECTION_NOTIFICATION: printf("ID_DISCONNECTION_NOTIFICATION\n"); break; case ID_CONNECTION_LOST: printf("ID_CONNECTION_LOST\n"); break; case ID_CONNECTION_ATTEMPT_FAILED: printf("Connection attempt failed\n"); break; case ID_USER_PACKET_ENUM: { uint32_t msgSize, msgCount, index; RakNet::BitStream bitStream(packet->data, packet->length, false); bitStream.IgnoreBytes(sizeof(MessageID)); bitStream.Read(msgSize); bitStream.Read(index); bitStream.Read(msgCount); printf("%i/%i len=%i", index+1, msgCount, packet->length); if (msgSize > BITS_TO_BYTES(bitStream.GetReadOffset()) && packet->length!=msgSize) printf("UNDERLENGTH!\n"); else printf("\n"); break; } default: printf("Unknown message type %i\n", packet->data[0]); } } RakSleep(30); } rakPeer->Shutdown(100); RakNet::RakPeerInterface::DestroyInstance(rakPeer); return 1; }
void NatTypeDetectionServer::Update(void) { int i=0; RakNet::TimeMS time = RakNet::GetTimeMS(); RakNet::BitStream bs; SystemAddress boundAddress; // Only socket that receives messages is s3p4, to see if the external address is different than that of the connection to rakPeerInterface char data[ MAXIMUM_MTU_SIZE ]; int len; SystemAddress senderAddr; len=NatTypeRecvFrom(data, s3p4, senderAddr); // Client is asking us if this is port restricted. Only client requests of this type come in on s3p4 while (len>0 && data[0]==NAT_TYPE_PORT_RESTRICTED) { RakNet::BitStream bsIn((unsigned char*) data,len,false); RakNetGUID senderGuid; bsIn.IgnoreBytes(sizeof(MessageID)); bool readSuccess = bsIn.Read(senderGuid); RakAssert(readSuccess); if (readSuccess) { unsigned int i = GetDetectionAttemptIndex(senderGuid); if (i!=(unsigned int)-1) { bs.Reset(); bs.Write((unsigned char) ID_NAT_TYPE_DETECTION_RESULT); // If different, then symmetric if (senderAddr!=natDetectionAttempts[i].systemAddress) { printf("Determined client is symmetric\n"); bs.Write((unsigned char) NAT_TYPE_SYMMETRIC); } else { // else port restricted printf("Determined client is port restricted\n"); bs.Write((unsigned char) NAT_TYPE_PORT_RESTRICTED); } rakPeerInterface->Send(&bs,HIGH_PRIORITY,RELIABLE,0,natDetectionAttempts[i].systemAddress,false); // Done natDetectionAttempts.RemoveAtIndexFast(i); } else { // RakAssert("i==0 in Update when looking up GUID in NatTypeDetectionServer.cpp. Either a bug or a late resend" && 0); } } else { // RakAssert("Didn't read GUID in Update in NatTypeDetectionServer.cpp. Message format error" && 0); } len=NatTypeRecvFrom(data, s3p4, senderAddr); } while (i < (int) natDetectionAttempts.Size()) { if (time > natDetectionAttempts[i].nextStateTime) { natDetectionAttempts[i].detectionState=(NATDetectionState)((int)natDetectionAttempts[i].detectionState+1); natDetectionAttempts[i].nextStateTime=time+natDetectionAttempts[i].timeBetweenAttempts; SystemAddress saOut; unsigned char c; bs.Reset(); switch (natDetectionAttempts[i].detectionState) { case STATE_TESTING_NONE_1: case STATE_TESTING_NONE_2: c = NAT_TYPE_NONE; printf("Testing NAT_TYPE_NONE\n"); // S4P5 sends to C2. If arrived, no NAT. Done. (Else S4P5 potentially banned, do not use again). saOut=natDetectionAttempts[i].systemAddress; saOut.SetPort(natDetectionAttempts[i].c2Port); SocketLayer::SendTo_PC( s4p5, (const char*) &c, 1, saOut, __FILE__, __LINE__ ); break; case STATE_TESTING_FULL_CONE_1: case STATE_TESTING_FULL_CONE_2: printf("Testing NAT_TYPE_FULL_CONE\n"); rakPeerInterface->WriteOutOfBandHeader(&bs); bs.Write((unsigned char) ID_NAT_TYPE_DETECT); bs.Write((unsigned char) NAT_TYPE_FULL_CONE); // S2P3 sends to C1 (Different address, different port, to previously used port on client). If received, Full-cone nat. Done. (Else S2P3 potentially banned, do not use again). saOut=natDetectionAttempts[i].systemAddress; saOut.SetPort(natDetectionAttempts[i].systemAddress.GetPort()); SocketLayer::SendTo_PC( s2p3, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), saOut, __FILE__, __LINE__ ); break; case STATE_TESTING_ADDRESS_RESTRICTED_1: case STATE_TESTING_ADDRESS_RESTRICTED_2: printf("Testing NAT_TYPE_ADDRESS_RESTRICTED\n"); rakPeerInterface->WriteOutOfBandHeader(&bs); bs.Write((unsigned char) ID_NAT_TYPE_DETECT); bs.Write((unsigned char) NAT_TYPE_ADDRESS_RESTRICTED); // S1P2 sends to C1 (Same address, different port, to previously used port on client). If received, address-restricted cone nat. Done. saOut=natDetectionAttempts[i].systemAddress; saOut.SetPort(natDetectionAttempts[i].systemAddress.GetPort()); SocketLayer::SendTo_PC( s1p2, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), saOut, __FILE__, __LINE__ ); break; case STATE_TESTING_PORT_RESTRICTED_1: case STATE_TESTING_PORT_RESTRICTED_2: // C1 sends to S3P4. If address of C1 as seen by S3P4 is the same as the address of C1 as seen by S1P1, then port-restricted cone nat. Done printf("Testing NAT_TYPE_PORT_RESTRICTED\n"); bs.Write((unsigned char) ID_NAT_TYPE_DETECTION_REQUEST); bs.Write(RakString::NonVariadic(s3p4Address)); bs.Write(s3p4Port); rakPeerInterface->Send(&bs,HIGH_PRIORITY,RELIABLE,0,natDetectionAttempts[i].systemAddress,false); break; default: printf("Warning, exceeded final check STATE_TESTING_PORT_RESTRICTED_2.\nExpected that client would have sent NAT_TYPE_PORT_RESTRICTED on s3p4.\nDefaulting to Symmetric\n"); bs.Write((unsigned char) ID_NAT_TYPE_DETECTION_RESULT); bs.Write((unsigned char) NAT_TYPE_SYMMETRIC); rakPeerInterface->Send(&bs,HIGH_PRIORITY,RELIABLE,0,natDetectionAttempts[i].systemAddress,false); natDetectionAttempts.RemoveAtIndexFast(i); i--; break; } } i++; } }
int ReliableOrderedConvertedTest::RunTest(DataStructures::List<RakNet::RakString> params,bool isVerbose,bool noPauses) { RakPeerInterface *sender, *receiver; unsigned int packetNumberSender[32],packetNumberReceiver[32], receivedPacketNumberReceiver, receivedTimeReceiver; char str[256]; char ip[32]; RakNetTime sendInterval, nextSend, currentTime, quitTime; unsigned short remotePort, localPort; unsigned char streamNumberSender,streamNumberReceiver; RakNet::BitStream bitStream; Packet *packet; bool doSend=false; for (int i=0; i < 32; i++) { packetNumberSender[i]=0; packetNumberReceiver[i]=0; } /* if (argc==2) { fp = fopen(argv[1],"wt"); SetMalloc_Ex(LoggedMalloc); SetRealloc_Ex(LoggedRealloc); SetFree_Ex(LoggedFree); } else */ fp=0; destroyList.Clear(false,__FILE__,__LINE__); sender =RakNetworkFactory::GetRakPeerInterface(); destroyList.Push( sender ,__FILE__,__LINE__); //sender->ApplyNetworkSimulator(.02, 100, 50); /* if (str[0]==0) sendInterval=30; else sendInterval=atoi(str);*///possible future params sendInterval=30; /* printf("Enter remote IP: "); gets(ip); if (ip[0]==0)*/ strcpy(ip, "127.0.0.1"); /* printf("Enter remote port: "); gets(str); if (str[0]==0)*/ strcpy(str, "60000"); remotePort=atoi(str); /* printf("Enter local port: "); gets(str); if (str[0]==0)*/ strcpy(str, "0"); localPort=atoi(str); if (isVerbose) printf("Connecting...\n"); SocketDescriptor tmp(localPort,0); sender->Startup(1, 30, &tmp, 1); sender->Connect(ip, remotePort, 0, 0); receiver =RakNetworkFactory::GetRakPeerInterface(); destroyList.Push( receiver ,__FILE__,__LINE__); /* printf("Enter local port: "); gets(str); if (str[0]==0)*/ strcpy(str, "60000"); localPort=atoi(str); if (isVerbose) printf("Waiting for connections...\n"); SocketDescriptor tmp2(localPort,0); receiver->Startup(32, 30, &tmp2, 1); receiver->SetMaximumIncomingConnections(32); // if (sender) // sender->ApplyNetworkSimulator(128000, 50, 100); // if (receiver) // receiver->ApplyNetworkSimulator(128000, 50, 100); /*printf("How long to run this test for, in seconds?\n"); gets(str); if (str[0]==0)*/ strcpy(str, "12"); currentTime = RakNet::GetTime(); quitTime = atoi(str) * 1000 + currentTime; nextSend=currentTime; while (currentTime < quitTime) //while (1) { packet = sender->Receive(); while (packet) { // PARSE TYPES switch(packet->data[0]) { case ID_CONNECTION_REQUEST_ACCEPTED: if (isVerbose) printf("ID_CONNECTION_REQUEST_ACCEPTED\n"); doSend=true; nextSend=currentTime; break; case ID_NO_FREE_INCOMING_CONNECTIONS: if (isVerbose) printf("ID_NO_FREE_INCOMING_CONNECTIONS\n"); break; case ID_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("ID_DISCONNECTION_NOTIFICATION\n"); break; case ID_CONNECTION_LOST: if (isVerbose) printf("ID_CONNECTION_LOST\n"); break; case ID_CONNECTION_ATTEMPT_FAILED: if (isVerbose) printf("Connection attempt failed\n"); break; } sender->DeallocatePacket(packet); packet = sender->Receive(); } while (doSend && currentTime > nextSend) { streamNumberSender=0; // streamNumber = randomMT() % 32; // Do the send bitStream.Reset(); bitStream.Write((unsigned char) (ID_USER_PACKET_ENUM+1)); bitStream.Write(packetNumberSender[streamNumberSender]++); bitStream.Write(streamNumberSender); bitStream.Write(currentTime); char *pad; int padLength = (randomMT() % 5000) + 1; pad = new char [padLength]; bitStream.Write(pad, padLength); delete [] pad; // Send on a random priority with a random stream // if (sender->Send(&bitStream, HIGH_PRIORITY, (PacketReliability) (RELIABLE + (randomMT() %2)) ,streamNumber, UNASSIGNED_SYSTEM_ADDRESS, true)==false) if (sender->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED ,streamNumberSender, UNASSIGNED_SYSTEM_ADDRESS, true)==false) packetNumberSender[streamNumberSender]--; // Didn't finish connecting yet? RakNetStatistics *rssSender; rssSender=sender->GetStatistics(sender->GetSystemAddressFromIndex(0)); if (isVerbose) printf("Snd: %i.\n", packetNumberSender[streamNumberSender]); nextSend+=sendInterval; // Test halting // if (rand()%20==0) // nextSend+=1000; } packet = receiver->Receive(); while (packet) { switch(packet->data[0]) { case ID_NEW_INCOMING_CONNECTION: if (isVerbose) printf("ID_NEW_INCOMING_CONNECTION\n"); break; case ID_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("ID_DISCONNECTION_NOTIFICATION\n"); break; case ID_CONNECTION_LOST: if (isVerbose) printf("ID_CONNECTION_LOST\n"); break; case ID_USER_PACKET_ENUM+1: bitStream.Reset(); bitStream.Write((char*)packet->data, packet->length); bitStream.IgnoreBits(8); // Ignore ID_USER_PACKET_ENUM+1 bitStream.Read(receivedPacketNumberReceiver); bitStream.Read(streamNumberReceiver); bitStream.Read(receivedTimeReceiver); if (receivedPacketNumberReceiver!=packetNumberReceiver[streamNumberReceiver]) { //WARNING: If you modify the below code make sure the whole string remains in bounds, sprintf will NOT do it for you. //The error string is 512 in length //Note: Removed buffer checking because chance is insignificant, left code if wanted in future. Needs limits.h ISO C standard. /* int maxIntWorkingCopy= INT_MAX; int maxIntCharLen =0; while (maxIntWorkingCopy>0) {maxIntCharLen++; maxIntWorkingCopy/=10; } if (strlen(lastError)>maxIntCharLen* 3 +27)//512 should be a good len for now {*/ sprintf(lastError,"Expecting %i got %i (channel %i).",packetNumberReceiver[streamNumberReceiver], receivedPacketNumberReceiver, streamNumberReceiver); /* } else { sprintf(lastError,"Did not get what was expected. More details can be given if the error string buffer size is increased."); }*/ if (isVerbose) { RakNetStatistics *rssSender,*rssReceiver; char message[2048]; rssSender=sender->GetStatistics(sender->GetSystemAddressFromIndex(0)); rssReceiver=receiver->GetStatistics(receiver->GetSystemAddressFromIndex(0)); StatisticsToString(rssSender, message, 2); printf("Server stats %s\n", message); StatisticsToString(rssReceiver, message, 2); printf("Client stats%s", message); DebugTools::ShowError(lastError,!noPauses && isVerbose,__LINE__,__FILE__); } return 1; } else if (isVerbose) { printf("Got %i.Channel %i.Len %i.", packetNumberReceiver[streamNumberReceiver], streamNumberReceiver, packet->length); printf("Sent=%u Received=%u Diff=%i.\n", receivedTimeReceiver, currentTime, (int)currentTime - (int) receivedTimeReceiver); } packetNumberReceiver[streamNumberReceiver]++; break; } receiver->DeallocatePacket(packet); packet = receiver->Receive(); } RakSleep(0); currentTime=RakNet::GetTime(); } if (isVerbose) { RakNetStatistics *rssSender,*rssReceiver; char message[2048]; rssSender=sender->GetStatistics(sender->GetSystemAddressFromIndex(0)); rssReceiver=receiver->GetStatistics(receiver->GetSystemAddressFromIndex(0)); StatisticsToString(rssSender, message, 2); printf("Server stats %s\n", message); StatisticsToString(rssReceiver, message, 2); printf("Client stats%s", message); } if (fp) fclose(fp); return 0; }
void UDPProxyCoordinator::OnForwardingReplyFromServerToCoordinator(Packet *packet) { RakNet::BitStream incomingBs(packet->data, packet->length, false); incomingBs.IgnoreBytes(2); SenderAndTargetAddress sata; incomingBs.Read(sata.senderClientAddress); incomingBs.Read(sata.targetClientAddress); DataStructures::DefaultIndexType index = forwardingRequestList.GetIndexOf(sata); if (index==(DataStructures::DefaultIndexType)-1) { // The guy disconnected before the request finished return; } ForwardingRequest *fw = forwardingRequestList[index]; UDPForwarderResult success; unsigned char c; incomingBs.Read(c); success=(UDPForwarderResult)c; RakNet::BitStream outgoingBs; if (success==UDPFORWARDER_SUCCESS) { char serverIP[64]; packet->systemAddress.ToString(false,serverIP); unsigned short srcToDestPort; unsigned short destToSourcePort; incomingBs.Read(srcToDestPort); incomingBs.Read(destToSourcePort); outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL); outgoingBs.Write((MessageID)ID_UDP_PROXY_FORWARDING_SUCCEEDED); outgoingBs.Write(sata.senderClientAddress); outgoingBs.Write(sata.targetClientAddress); outgoingBs.Write(RakNet::RakString(serverIP)); outgoingBs.Write(srcToDestPort); outgoingBs.Write(destToSourcePort); rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, fw->requestingAddress, false); outgoingBs.Reset(); outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL); outgoingBs.Write((MessageID)ID_UDP_PROXY_FORWARDING_NOTIFICATION); outgoingBs.Write(sata.senderClientAddress); outgoingBs.Write(sata.targetClientAddress); outgoingBs.Write(RakNet::RakString(serverIP)); outgoingBs.Write(srcToDestPort); outgoingBs.Write(destToSourcePort); rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, sata.targetClientAddress, false); // 05/18/09 Keep the entry around for some time after success, so duplicates are reported if attempting forwarding from the target system before notification of success fw->timeoutAfterSuccess=RakNet::GetTimeMS()+fw->timeoutOnNoDataMS; // forwardingRequestList.RemoveAtIndex(index); // RakNet::OP_DELETE(fw,_FILE_AND_LINE_); return; } else if (success==UDPFORWARDER_NO_SOCKETS) { // Try next server TryNextServer(sata, fw); } else { RakAssert(success==UDPFORWARDER_FORWARDING_ALREADY_EXISTS); // Return in progress outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL); outgoingBs.Write((MessageID)ID_UDP_PROXY_IN_PROGRESS); outgoingBs.Write(sata.senderClientAddress); outgoingBs.Write(sata.targetClientAddress); rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, fw->requestingAddress, false); forwardingRequestList.RemoveAtIndex(index,_FILE_AND_LINE_); RakNet::OP_DELETE(fw,_FILE_AND_LINE_); } }
void InitialData(RakNet::BitStream * pBitStream, RakNet::Packet * pPacket) { // Get the playerid EntityId playerId = (EntityId) pPacket->guid.systemIndex; // Read the player version DWORD dwVersion; pBitStream->Read(dwVersion); // Read the player name RakNet::RakString _strName; pBitStream->Read(_strName); CString strName(_strName.C_String()); // Read the player serial RakNet::RakString _strSerial; pBitStream->Read(_strSerial); CString strSerial(_strSerial.C_String()); // Is the network version invalid? if (dwVersion != (DWORD)/*NETWORK_VERSION*/0x0) { // TODO } // Is the nickname already in use? // TODO: check is nick in use // Is the player banned? // TODO: check is banned // Add the player to the manager // TODO: add to player manager CPlayerEntity * pPlayer = new CPlayerEntity(); pPlayer->SetName(strName); // Do we need the id; maybe internal for easier sync but definetly not public to the scripting engine pPlayer->SetId(CServer::GetInstance()->GetPlayerManager()->Add(pPlayer)); playerId = pPlayer->GetId(); CLogFile::Printf("[join] %s (%i) has connected to the server. (%s)", strName.Get(), playerId, strSerial.Get()); CScriptArguments args; CScriptPlayer * pScriptPlayer = new CScriptPlayer(); pScriptPlayer->SetEntity(pPlayer); pPlayer->SetScriptPlayer(pScriptPlayer); args.push(pScriptPlayer); CEvents::GetInstance()->Call("playerJoin", &args, CEventHandler::eEventType::GLOBAL_EVENT, 0); // Construct a new bitstream RakNet::BitStream bitStream; // Write the player id bitStream.WriteCompressed(playerId); // Write the player colour bitStream.Write(0xFFFFFF/*CServer::GetInstance()->GetPlayerManager()->GetAt(playerId)->GetColor()*/); // Write the server name bitStream.Write(RakNet::RakString("IV:Network DEV Server")); // Write the max player count bitStream.Write(CVAR_GET_INTEGER("maxplayers")); // Write the port bitStream.Write(CVAR_GET_INTEGER("port")); // Send it back to the player CServer::GetInstance()->GetNetworkModule()->Call(GET_RPC_CODEX(RPC_INITIAL_DATA), &bitStream, HIGH_PRIORITY, RELIABLE, playerId, false); CServer::GetInstance()->GetNetworkModule()->Call(GET_RPC_CODEX(RPC_START_GAME), &bitStream, HIGH_PRIORITY, RELIABLE, playerId, false); for (EntityId i = 0; i < CServer::GetInstance()->GetPlayerManager()->GetMax(); ++i) { if (CServer::GetInstance()->GetPlayerManager()->DoesExists(i) && i != playerId) { bitStream.Reset(); bitStream.WriteCompressed(i); bitStream.Write(CServer::GetInstance()->GetPlayerManager()->GetAt(i)->GetName().Get()); CServer::GetInstance()->GetNetworkModule()->Call(GET_RPC_CODEX(RPC_NEW_PLAYER), &bitStream, HIGH_PRIORITY, RELIABLE, playerId, false); } } for (EntityId i = 0; i < CServer::GetInstance()->GetPlayerManager()->GetMax(); ++i) { if (CServer::GetInstance()->GetPlayerManager()->DoesExists(i) && i != playerId) { bitStream.Reset(); bitStream.WriteCompressed(playerId); bitStream.Write(strName.Get()); CServer::GetInstance()->GetNetworkModule()->Call(GET_RPC_CODEX(RPC_NEW_PLAYER), &bitStream, HIGH_PRIORITY, RELIABLE, i, false); } } for (EntityId i = 0; i < CServer::GetInstance()->GetVehicleManager()->GetMax(); ++i) { if (CServer::GetInstance()->GetVehicleManager()->DoesExists(i)) { bitStream.Reset(); CVehicleEntity * pVehicle = CServer::GetInstance()->GetVehicleManager()->GetAt(i); bitStream.Write(pVehicle->GetId()); bitStream.Write(/*pVehicle->GetModelId()*/90); CVector3 vecPosition; pVehicle->GetPosition(vecPosition); bitStream.Write(vecPosition); CServer::GetInstance()->GetNetworkModule()->Call(GET_RPC_CODEX(RPC_CREATE_VEHICLE), &bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, -1, true); } } bitStream.Reset(); bitStream.WriteCompressed(playerId); bitStream.Write(7); bitStream.Write(3); bitStream.Write(3); bitStream.Write(1); }
void DownloadFinished(RakNet::BitStream * pBitStream, RakNet::Packet * pPacket) { // Read the player name RakNet::RakString _strName; pBitStream->Read(_strName); CString strName(_strName.C_String()); // Read the player serial RakNet::RakString _strSerial; pBitStream->Read(_strSerial); CString strSerial(_strSerial.C_String()); // Is the nickname already in use? // TODO: check is nick in use // Is the player banned? // TODO: check is banned // Add the player to the manager // TODO: add to player manager CPlayerEntity * pPlayer = new CPlayerEntity(); pPlayer->SetName(strName); // Do we need the id; maybe internal for easier sync but definetly not public to the scripting engine pPlayer->SetId(CServer::GetInstance()->GetPlayerManager()->Add(pPlayer)); EntityId playerId = pPlayer->GetId(); srand(time(NULL)); pPlayer->SetColor(CColor(rand() % 256, rand() % 256, rand() % 256).dwHexColor); //generate random color CLogFile::Printf("[join] %s (%i) has connected to the server. (%s)", strName.Get(), playerId, strSerial.Get()); CScriptArguments args; CScriptPlayer * pScriptPlayer = new CScriptPlayer(); pScriptPlayer->SetEntity(pPlayer); pPlayer->SetScriptPlayer(pScriptPlayer); args.push(pScriptPlayer); CEvents::GetInstance()->Call("playerJoin", &args, CEventHandler::eEventType::NATIVE_EVENT, 0); // Construct a new bitstream RakNet::BitStream bitStream; // Write the player id bitStream.Write(playerId); // Write the player colour bitStream.Write(pPlayer->GetColor()); // Write the server name bitStream.Write(RakNet::RakString("IV:Network DEV Server")); // Write the max player count bitStream.Write(CVAR_GET_INTEGER("maxplayers")); // Write the port bitStream.Write(CVAR_GET_INTEGER("port")); // Send it back to the player CServer::GetInstance()->GetNetworkModule()->Call(GET_RPC_CODEX(RPC_INITIAL_DATA), &bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, playerId, false); for (EntityId i = 0; i < CServer::GetInstance()->GetPlayerManager()->GetMax(); ++i) { if (CServer::GetInstance()->GetPlayerManager()->DoesExists(i) && i != playerId) { bitStream.Reset(); bitStream.Write(i); bitStream.Write(CServer::GetInstance()->GetPlayerManager()->GetAt(i)->GetName().Get()); bitStream.Write(CServer::GetInstance()->GetPlayerManager()->GetAt(i)->GetColor()); CServer::GetInstance()->GetNetworkModule()->Call(GET_RPC_CODEX(RPC_NEW_PLAYER), &bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, playerId, false); } } for (EntityId i = 0; i < CServer::GetInstance()->GetPlayerManager()->GetMax(); ++i) { if (CServer::GetInstance()->GetPlayerManager()->DoesExists(i) && i != playerId) { bitStream.Reset(); bitStream.Write(playerId); bitStream.Write(pPlayer->GetName().Get()); bitStream.Write(pPlayer->GetColor()); CServer::GetInstance()->GetNetworkModule()->Call(GET_RPC_CODEX(RPC_NEW_PLAYER), &bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, i, false); } } for (EntityId i = 0; i < CServer::GetInstance()->GetVehicleManager()->GetMax(); ++i) { if (CServer::GetInstance()->GetVehicleManager()->DoesExists(i)) { bitStream.Reset(); CVehicleEntity * pVehicle = CServer::GetInstance()->GetVehicleManager()->GetAt(i); bitStream.Write(pVehicle->GetId()); bitStream.Write(pVehicle->GetModelId()); CVector3 vecPosition; pVehicle->GetPosition(vecPosition); bitStream.Write(vecPosition); CVector3 vecRotation; pVehicle->GetRotation(vecRotation); bitStream.Write(vecRotation.fX); bitStream.Write(pVehicle->GetColor(1)); bitStream.Write(pVehicle->GetColor(2)); bitStream.Write(pVehicle->GetColor(3)); bitStream.Write(pVehicle->GetColor(4)); bitStream.Write(pVehicle->GetColor(5)); CServer::GetInstance()->GetNetworkModule()->Call(GET_RPC_CODEX(RPC_CREATE_VEHICLE), &bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, playerId, false); } } for (EntityId i = 0; i < CServer::GetInstance()->GetCheckpointManager()->GetMax(); ++i) { if (CServer::GetInstance()->GetCheckpointManager()->DoesExists(i)) { bitStream.Reset(); CCheckpointEntity * pCheckpoint = CServer::GetInstance()->GetCheckpointManager()->GetAt(i); bitStream.Write(pCheckpoint->GetId()); bitStream.Write(pCheckpoint->GetType()); CVector3 vecPosition; pCheckpoint->GetPosition(vecPosition); bitStream.Write(vecPosition); CVector3 vecTargetPosition; pCheckpoint->GetTargetPosition(vecTargetPosition); bitStream.Write(vecTargetPosition); bitStream.Write(pCheckpoint->GetRadius()); CServer::GetInstance()->GetNetworkModule()->Call(GET_RPC_CODEX(RPC_CREATE_CHECKPOINT), &bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, playerId, false); // Checkpoint visibility if (!pCheckpoint->GetVisible()) { bitStream.Reset(); bitStream.Write(pCheckpoint->GetId()); CServer::GetInstance()->GetNetworkModule()->Call(GET_RPC_CODEX(RPC_CHECKPOINT_HIDE), &bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, playerId, false); } } } }
// Given a frequency table of 256 elements, all with a frequency of 1 or more, generate the tree void HuffmanEncodingTree::GenerateFromFrequencyTable( unsigned int frequencyTable[ 256 ] ) { int counter; HuffmanEncodingTreeNode * node; HuffmanEncodingTreeNode *leafList[ 256 ]; // Keep a copy of the pointers to all the leaves so we can generate the encryption table bottom-up, which is easier // 1. Make 256 trees each with a weight equal to the frequency of the corresponding character DataStructures::LinkedList<HuffmanEncodingTreeNode *> huffmanEncodingTreeNodeList; FreeMemory(); for ( counter = 0; counter < 256; counter++ ) { node = new HuffmanEncodingTreeNode; node->left = 0; node->right = 0; node->value = (unsigned char) counter; node->weight = frequencyTable[ counter ]; if ( node->weight == 0 ) node->weight = 1; // 0 weights are illegal leafList[ counter ] = node; // Used later to generate the encryption table InsertNodeIntoSortedList( node, &huffmanEncodingTreeNodeList ); // Insert and maintain sort order. } // 2. While there is more than one tree, take the two smallest trees and merge them so that the two trees are the left and right // children of a new node, where the new node has the weight the sum of the weight of the left and right child nodes. #ifdef _MSC_VER #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant #endif while ( 1 ) { huffmanEncodingTreeNodeList.Beginning(); HuffmanEncodingTreeNode *lesser, *greater; lesser = huffmanEncodingTreeNodeList.Pop(); greater = huffmanEncodingTreeNodeList.Pop(); node = new HuffmanEncodingTreeNode; node->left = lesser; node->right = greater; node->weight = lesser->weight + greater->weight; lesser->parent = node; // This is done to make generating the encryption table easier greater->parent = node; // This is done to make generating the encryption table easier if ( huffmanEncodingTreeNodeList.Size() == 0 ) { // 3. Assign the one remaining node in the list to the root node. root = node; root->parent = 0; break; } // Put the new node back into the list at the correct spot to maintain the sort. Linear search time InsertNodeIntoSortedList( node, &huffmanEncodingTreeNodeList ); } bool tempPath[ 256 ]; // Maximum path length is 256 unsigned short tempPathLength; HuffmanEncodingTreeNode *currentNode; RakNet::BitStream bitStream; // Generate the encryption table. From before, we have an array of pointers to all the leaves which contain pointers to their parents. // This can be done more efficiently but this isn't bad and it's way easier to program and debug for ( counter = 0; counter < 256; counter++ ) { // Already done at the end of the loop and before it! tempPathLength = 0; // Set the current node at the leaf currentNode = leafList[ counter ]; do { if ( currentNode->parent->left == currentNode ) // We're storing the paths in reverse order.since we are going from the leaf to the root tempPath[ tempPathLength++ ] = false; else tempPath[ tempPathLength++ ] = true; currentNode = currentNode->parent; } while ( currentNode != root ); // Write to the bitstream in the reverse order that we stored the path, which gives us the correct order from the root to the leaf while ( tempPathLength-- > 0 ) { if ( tempPath[ tempPathLength ] ) // Write 1's and 0's because writing a bool will write the BitStream TYPE_CHECKING validation bits if that is defined along with the actual data bit, which is not what we want bitStream.Write1(); else bitStream.Write0(); } // Read data from the bitstream, which is written to the encoding table in bits and bitlength. Note this function allocates the encodingTable[counter].encoding pointer encodingTable[ counter ].bitLength = ( unsigned char ) bitStream.CopyData( &encodingTable[ counter ].encoding ); // Reset the bitstream for the next iteration bitStream.Reset(); } }
void FileListTransfer::Send(FileList *fileList, RakPeerInterface *rakPeer, SystemAddress recipient, unsigned short setID, PacketPriority priority, char orderingChannel, bool compressData, IncrementalReadInterface *_incrementalReadInterface, unsigned int _chunkSize) { (void) compressData; if (callback) fileList->SetCallback(callback); unsigned int i, totalLength; RakNet::BitStream outBitstream; bool sendReference; char *dataBlocks[2]; int lengths[2]; totalLength=0; for (i=0; i < fileList->fileList.Size(); i++) { const FileListNode &fileListNode = fileList->fileList[i]; totalLength+=fileListNode.fileLengthBytes; } // Write the chunk header, which contains the frequency table, the total number of files, and the total number of bytes bool anythingToWrite; outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_HEADER); outBitstream.Write(setID); anythingToWrite=fileList->fileList.Size()>0; outBitstream.Write(anythingToWrite); if (anythingToWrite) { outBitstream.WriteCompressed(fileList->fileList.Size()); outBitstream.WriteCompressed(totalLength); if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); for (i=0; i < fileList->fileList.Size(); i++) { outBitstream.Reset(); sendReference = fileList->fileList[i].isAReference && _incrementalReadInterface!=0; if (sendReference) { StoreForPush(fileList->fileList[i].context, setID, fileList->fileList[i].filename, fileList->fileList[i].fullPathToFile, i, fileList->fileList[i].fileLengthBytes, fileList->fileList[i].dataLengthBytes, recipient, priority, orderingChannel, _incrementalReadInterface, _chunkSize); continue; } outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE); outBitstream.Write(fileList->fileList[i].context); outBitstream.Write(setID); stringCompressor->EncodeString(fileList->fileList[i].filename, 512, &outBitstream); outBitstream.WriteCompressed(i); outBitstream.WriteCompressed(fileList->fileList[i].dataLengthBytes); // Original length in bytes outBitstream.AlignWriteToByteBoundary(); dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=fileList->fileList[i].data; lengths[1]=fileList->fileList[i].dataLengthBytes; if (rakPeer) rakPeer->SendList(dataBlocks,lengths,2,priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendListUnified(dataBlocks,lengths,2,priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } } else { if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } }
void FileListTransfer::Send(FileList *fileList, RakPeerInterface *rakPeer, SystemAddress recipient, unsigned short setID, PacketPriority priority, char orderingChannel, bool compressData, IncrementalReadInterface *_incrementalReadInterface, unsigned int _chunkSize) { (void) compressData; if (callback) fileList->SetCallback(callback); unsigned int i, totalLength; RakNet::BitStream outBitstream; bool sendReference; const char *dataBlocks[2]; int lengths[2]; totalLength=0; for (i=0; i < fileList->fileList.Size(); i++) { const FileListNode &fileListNode = fileList->fileList[i]; totalLength+=fileListNode.fileLengthBytes; } // Write the chunk header, which contains the frequency table, the total number of files, and the total number of bytes bool anythingToWrite; outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_HEADER); outBitstream.Write(setID); anythingToWrite=fileList->fileList.Size()>0; outBitstream.Write(anythingToWrite); if (anythingToWrite) { outBitstream.WriteCompressed(fileList->fileList.Size()); outBitstream.WriteCompressed(totalLength); if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); DataStructures::Queue<FileToPush*> filesToPush; for (i=0; i < fileList->fileList.Size(); i++) { sendReference = fileList->fileList[i].isAReference && _incrementalReadInterface!=0; if (sendReference) { FileToPush *fileToPush = RakNet::OP_NEW<FileToPush>(__FILE__,__LINE__); fileToPush->fileListNode.context=fileList->fileList[i].context; fileToPush->setIndex=i; fileToPush->fileListNode.filename=fileList->fileList[i].filename; fileToPush->fileListNode.fullPathToFile=fileList->fileList[i].fullPathToFile; fileToPush->fileListNode.fileLengthBytes=fileList->fileList[i].fileLengthBytes; fileToPush->fileListNode.dataLengthBytes=fileList->fileList[i].dataLengthBytes; // fileToPush->systemAddress=recipient; fileToPush->setID=setID; fileToPush->packetPriority=priority; fileToPush->orderingChannel=orderingChannel; fileToPush->currentOffset=0; fileToPush->incrementalReadInterface=_incrementalReadInterface; fileToPush->chunkSize=_chunkSize; filesToPush.Push(fileToPush,__FILE__,__LINE__); } else { outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE); outBitstream.Write(fileList->fileList[i].context); outBitstream.Write(setID); stringCompressor->EncodeString(fileList->fileList[i].filename, 512, &outBitstream); outBitstream.WriteCompressed(i); outBitstream.WriteCompressed(fileList->fileList[i].dataLengthBytes); // Original length in bytes outBitstream.AlignWriteToByteBoundary(); dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=fileList->fileList[i].data; lengths[1]=fileList->fileList[i].dataLengthBytes; SendListUnified(dataBlocks,lengths,2,priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } } if (filesToPush.IsEmpty()==false) { FileToPushRecipient *ftpr=0; filesToPushAllSameAddressMutex.Lock(); for (unsigned int i=0; i < filesToPushAllSameAddress.Size(); i++) { if (filesToPushAllSameAddress[i]->systemAddress==recipient) { ftpr=filesToPushAllSameAddress[i]; break; } } if (ftpr==0) { ftpr = RakNet::OP_NEW<FileToPushRecipient>(__FILE__,__LINE__); ftpr->systemAddress=recipient; filesToPushAllSameAddress.Push(ftpr, __FILE__,__LINE__); } while (filesToPush.IsEmpty()==false) { ftpr->filesToPush.Push(filesToPush.Pop(), __FILE__,__LINE__); } filesToPushAllSameAddressMutex.Unlock(); SendIRIToAddress(recipient); return; } } else { if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } }
void FileListTransfer::Send(FileList *fileList, RakNet::RakPeerInterface *rakPeer, SystemAddress recipient, unsigned short setID, PacketPriority priority, char orderingChannel, IncrementalReadInterface *_incrementalReadInterface, unsigned int _chunkSize) { for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++) fileList->AddCallback(fileListProgressCallbacks[flpcIndex]); unsigned int i, totalLength; RakNet::BitStream outBitstream; bool sendReference; const char *dataBlocks[2]; int lengths[2]; totalLength=0; for (i=0; i < fileList->fileList.Size(); i++) { const FileListNode &fileListNode = fileList->fileList[i]; totalLength+=fileListNode.dataLengthBytes; } // Write the chunk header, which contains the frequency table, the total number of files, and the total number of bytes bool anythingToWrite; outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_HEADER); outBitstream.Write(setID); anythingToWrite=fileList->fileList.Size()>0; outBitstream.Write(anythingToWrite); if (anythingToWrite) { outBitstream.WriteCompressed(fileList->fileList.Size()); outBitstream.WriteCompressed(totalLength); if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); DataStructures::Queue<FileToPush*> filesToPush; for (i=0; i < fileList->fileList.Size(); i++) { sendReference = fileList->fileList[i].isAReference && _incrementalReadInterface!=0; if (sendReference) { FileToPush *fileToPush = RakNet::OP_NEW<FileToPush>(_FILE_AND_LINE_); fileToPush->fileListNode.context=fileList->fileList[i].context; fileToPush->setIndex=i; fileToPush->fileListNode.filename=fileList->fileList[i].filename; fileToPush->fileListNode.fullPathToFile=fileList->fileList[i].fullPathToFile; fileToPush->fileListNode.fileLengthBytes=fileList->fileList[i].fileLengthBytes; fileToPush->fileListNode.dataLengthBytes=fileList->fileList[i].dataLengthBytes; // fileToPush->systemAddress=recipient; //fileToPush->setID=setID; fileToPush->packetPriority=priority; fileToPush->orderingChannel=orderingChannel; fileToPush->currentOffset=0; fileToPush->incrementalReadInterface=_incrementalReadInterface; fileToPush->chunkSize=_chunkSize; filesToPush.Push(fileToPush,_FILE_AND_LINE_); } else { outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE); outBitstream << fileList->fileList[i].context; // outBitstream.Write(fileList->fileList[i].context); outBitstream.Write(setID); StringCompressor::Instance()->EncodeString(fileList->fileList[i].filename, 512, &outBitstream); outBitstream.WriteCompressed(i); outBitstream.WriteCompressed(fileList->fileList[i].dataLengthBytes); // Original length in bytes outBitstream.AlignWriteToByteBoundary(); dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=fileList->fileList[i].data; lengths[1]=fileList->fileList[i].dataLengthBytes; SendListUnified(dataBlocks,lengths,2,priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } } if (filesToPush.IsEmpty()==false) { FileToPushRecipient *ftpr; fileToPushRecipientListMutex.Lock(); for (unsigned int i=0; i < fileToPushRecipientList.Size(); i++) { if (fileToPushRecipientList[i]->systemAddress==recipient && fileToPushRecipientList[i]->setId==setId) { // ftpr=fileToPushRecipientList[i]; // ftpr->AddRef(); // break; RakAssert("setId already in use for this recipient" && 0); } } fileToPushRecipientListMutex.Unlock(); //if (ftpr==0) //{ ftpr = RakNet::OP_NEW<FileToPushRecipient>(_FILE_AND_LINE_); ftpr->systemAddress=recipient; ftpr->setId=setID; ftpr->refCount=2; // Allocated and in the list fileToPushRecipientList.Push(ftpr, _FILE_AND_LINE_); //} while (filesToPush.IsEmpty()==false) { ////ftpr->filesToPushMutex.Lock(); ftpr->filesToPush.Push(filesToPush.Pop(), _FILE_AND_LINE_); ////ftpr->filesToPushMutex.Unlock(); } // ftpr out of scope ftpr->Deref(); SendIRIToAddress(recipient, setID); return; } else { for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++) fileListProgressCallbacks[flpcIndex]->OnFilePushesComplete(recipient, setID); } } else { for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++) fileListProgressCallbacks[flpcIndex]->OnFilePushesComplete(recipient, setID); if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } }
void NatPunchthroughServer::Update(void) { ConnectionAttempt *connectionAttempt; User *user, *recipient; unsigned int i,j; RakNet::Time time = RakNet::GetTime(); if (time > lastUpdate+250) { lastUpdate=time; for (i=0; i < users.Size(); i++) { user=users[i]; for (j=0; j < user->connectionAttempts.Size(); j++) { connectionAttempt=user->connectionAttempts[j]; if (connectionAttempt->sender==user) { if (connectionAttempt->attemptPhase!=ConnectionAttempt::NAT_ATTEMPT_PHASE_NOT_STARTED && time > connectionAttempt->startTime && time > 10000 + connectionAttempt->startTime ) // Formerly 5000, but sometimes false positives { RakNet::BitStream outgoingBs; // that other system might not be running the plugin outgoingBs.Write((MessageID)ID_NAT_TARGET_UNRESPONSIVE); outgoingBs.Write(connectionAttempt->recipient->guid); outgoingBs.Write(connectionAttempt->sessionId); rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,connectionAttempt->sender->systemAddress,false); // 05/28/09 Previously only told sender about ID_NAT_CONNECTION_TO_TARGET_LOST // However, recipient may be expecting it due to external code // In that case, recipient would never get any response if the sender dropped outgoingBs.Reset(); outgoingBs.Write((MessageID)ID_NAT_TARGET_UNRESPONSIVE); outgoingBs.Write(connectionAttempt->sender->guid); outgoingBs.Write(connectionAttempt->sessionId); rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,connectionAttempt->recipient->systemAddress,false); connectionAttempt->sender->isReady=true; connectionAttempt->recipient->isReady=true; recipient=connectionAttempt->recipient; if (natPunchthroughServerDebugInterface) { char str[1024]; char addr1[128], addr2[128]; // 8/01/09 Fixed bug where this was after DeleteConnectionAttempt() connectionAttempt->sender->systemAddress.ToString(true,addr1); connectionAttempt->recipient->systemAddress.ToString(true,addr2); sprintf(str, "Sending ID_NAT_TARGET_UNRESPONSIVE to sender %s and recipient %s.", addr1, addr2); natPunchthroughServerDebugInterface->OnServerMessage(str); RakNet::RakString log; connectionAttempt->sender->LogConnectionAttempts(log); connectionAttempt->recipient->LogConnectionAttempts(log); } connectionAttempt->sender->DerefConnectionAttempt(connectionAttempt); connectionAttempt->recipient->DeleteConnectionAttempt(connectionAttempt); StartPunchthroughForUser(user); StartPunchthroughForUser(recipient); break; } } } } } }
void NatPunchthrough::Update(RakPeerInterface *peer) { (void) peer; if (connectionRequestList.Size()) { RakNetTime time = RakNet::GetTime(); RakNet::BitStream outBitstream; unsigned i; i=0; while (i < connectionRequestList.Size()) { // Remove old connection requests that get no answer if (connectionRequestList[i]->timeoutTime < time) { rakFree(connectionRequestList[i]->passwordData); delete connectionRequestList[i]; connectionRequestList.RemoveAtIndex(i); continue; } // If we are a facilitator, do pings if (connectionRequestList[i]->facilitatingConnection) { if (time >= connectionRequestList[i]->nextActionTime ) { if (connectionRequestList[i]->pingCount < PING_COUNT) { // Ping connectionRequestList[i]->pingCount++; rakPeer->Ping(connectionRequestList[i]->receiverPublic); rakPeer->Ping(connectionRequestList[i]->senderPublic); connectionRequestList[i]->nextActionTime=time+PING_INTERVAL; } else if (connectionRequestList[i]->pingCount == PING_COUNT) { // Done pinging. Wait till the next stage int receiverPing, senderPing; receiverPing=rakPeer->GetAveragePing(connectionRequestList[i]->receiverPublic); senderPing=rakPeer->GetAveragePing(connectionRequestList[i]->senderPublic); if (receiverPing > senderPing) connectionRequestList[i]->nextActionTime=(RakNetTime)(receiverPing*SEND_TIMESTAMP_DELAY_PING_MULTIPLE); else connectionRequestList[i]->nextActionTime=(RakNetTime)(senderPing*SEND_TIMESTAMP_DELAY_PING_MULTIPLE); connectionRequestList[i]->pingCount++; } else { // Send the timestamped message to both systems so they send datagrams to each other simultaneously int receiverPing, senderPing; RakNetTime delayTime; receiverPing=rakPeer->GetAveragePing(connectionRequestList[i]->receiverPublic); senderPing=rakPeer->GetAveragePing(connectionRequestList[i]->senderPublic); if (receiverPing > senderPing) delayTime=(RakNetTime)(receiverPing*SEND_PUNCHTHROUGH_DELAY_PING_MULTIPLE); else delayTime=(RakNetTime)(senderPing*SEND_PUNCHTHROUGH_DELAY_PING_MULTIPLE); if (delayTime < 500) delayTime=500; outBitstream.Reset(); outBitstream.Write((MessageID)ID_TIMESTAMP); outBitstream.Write(time+delayTime); outBitstream.Write((MessageID)ID_NAT_CONNECT_AT_TIME); // A few poorly behaved NATs are known to scan the body of UDP datagrams for 4-byte fields that look like IP addresses, and translate them as they would the IP address fields in the IP header. outBitstream.Write(true); outBitstream.Write(rakPeer->GetInternalID(connectionRequestList[i]->receiverPublic)); rakPeer->Send(&outBitstream, SYSTEM_PRIORITY, RELIABLE, 0, connectionRequestList[i]->senderPublic, false); outBitstream.Reset(); outBitstream.Write((MessageID)ID_TIMESTAMP); outBitstream.Write(time+delayTime); outBitstream.Write((MessageID)ID_NAT_SEND_OFFLINE_MESSAGE_AT_TIME); // A few poorly behaved NATs are known to scan the body of UDP datagrams for 4-byte fields that look like IP addresses, and translate them as they would the IP address fields in the IP header. outBitstream.Write(true); outBitstream.Write(connectionRequestList[i]->senderPublic); outBitstream.Write(rakPeer->GetInternalID(connectionRequestList[i]->senderPublic)); rakPeer->Send(&outBitstream, SYSTEM_PRIORITY, RELIABLE, 0, connectionRequestList[i]->receiverPublic, false); delete [] connectionRequestList[i]->passwordData; delete connectionRequestList[i]; connectionRequestList.RemoveAtIndex(i); continue; } } } // Else not a facilitator. If nextActionTime is non-zero, connect or send the offline message else if (connectionRequestList[i]->nextActionTime && time >= connectionRequestList[i]->nextActionTime && connectionRequestList[i]->attemptedConnection==false) { ConnectionRequest *connectionRequest = connectionRequestList[i]; DataStructures::List<SystemAddress> fallbackAddresses; // unsigned fallbackIndex; RakNet::BitStream oob; if (connectionRequest->receiverPublic!=UNASSIGNED_SYSTEM_ADDRESS) { // fallbackAddresses.Clear(); // connectionRequest->GetAddressList(peer, fallbackAddresses, connectionRequest->senderPublic, connectionRequest->senderPrivate, true); // for (unsigned fallbackIndex=0; fallbackIndex < fallbackAddresses.Size(); fallbackIndex++) // peer->Ping(fallbackAddresses[fallbackIndex].ToString(false),fallbackAddresses[fallbackIndex].port,false); // Connect to this system. LogOut(FormatString("Connecting to public address %s\n", connectionRequest->receiverPublic.ToString(true))); rakPeer->Connect(connectionRequest->receiverPublic.ToString(false), connectionRequest->receiverPublic.port, connectionRequest->passwordData, connectionRequest->passwordDataLength); connectionRequest->attemptedConnection=true; /* if (connectionRequestList[i]->receiverPrivate==connectionRequestList[i]->receiverPublic) { // Otherwise done with this connection, as it's a normal connection attempt rakFree(connectionRequestList[i]->passwordData); delete connectionRequestList[i]; connectionRequestList.RemoveAtIndex(i); continue; } */ } else { RakAssert(connectionRequestList[i]->senderPublic!=UNASSIGNED_SYSTEM_ADDRESS); // Send ID_NAT_ADVERTISE_RECIPIENT_PORT to all possible remote ports fallbackAddresses.Clear(); connectionRequest->GetAddressList(peer, fallbackAddresses, connectionRequest->senderPublic, connectionRequest->senderPrivate, true); /// 04/13/08 I think if I send to all possible fallbacks in order it starts reusing external ports or else assigns them in a random way /// Sending 4X to each port in order did work however. /// Timing matches that of RakPeer's failure notices and retries if ((unsigned int) connectionRequestList[i]->recipientOfflineCount < fallbackAddresses.Size()) { unsigned k; //for (k=0; k < 4; k++) for (k=0; k < (unsigned) connectionRequestList[i]->recipientOfflineCount && k < fallbackAddresses.Size(); k++) { oob.Write(ID_NAT_ADVERTISE_RECIPIENT_PORT); oob.Write(rakPeer->GetExternalID(connectionRequest->facilitator)); // This is duplicated intentionally, since the first packet is often dropped peer->SendOutOfBand(fallbackAddresses[k].ToString(false),fallbackAddresses[k].port,ID_OUT_OF_BAND_INTERNAL,(const char*) oob.GetData(),oob.GetNumberOfBytesUsed(),0); peer->SendOutOfBand(fallbackAddresses[k].ToString(false),fallbackAddresses[k].port,ID_OUT_OF_BAND_INTERNAL,(const char*) oob.GetData(),oob.GetNumberOfBytesUsed(),0); } LogOut(FormatString("Recipient sending ID_OUT_OF_BAND_INTERNAL to %s\n", fallbackAddresses[connectionRequestList[i]->recipientOfflineCount].ToString(true))); } /* for (fallbackIndex=0; fallbackIndex < fallbackAddresses.Size(); fallbackIndex++) { // This follows a similar path to the sender connecting to us. // If this message arrives, it lets the sender know our external port. // The sender can then use this port instead of just going down the fallbackAddresses guessing. // This saves us if the recipient is impossible to connect to, but the sender is not. oob.Reset(); oob.Write(ID_NAT_ADVERTISE_RECIPIENT_PORT); oob.Write(rakPeer->GetExternalID(connectionRequest->facilitator)); peer->SendOutOfBand(fallbackAddresses[fallbackIndex].ToString(false),fallbackAddresses[fallbackIndex].port,ID_OUT_OF_BAND_INTERNAL,(const char*) oob.GetData(),oob.GetNumberOfBytesUsed(),0); // bool SendOutOfBand(const char *host, unsigned short remotePort, MessageID header, const char *data, BitSize_t dataLength, unsigned connectionSocketIndex=0 ); } */ // LogOut(FormatString("Pinging %s\n", connectionRequest->senderPublic.ToString(true))); // rakPeer->Connect(connectionRequestList[i]->senderPublic.ToString(false),connectionRequestList[i]->senderPublic.port,0,0,0); /* SystemAddress senderAddrWithFPort; SystemAddress senderAddrWithRPort; SystemAddress senderAddrWithIPort; senderAddrWithFPort=connectionRequestList[i]->senderPublic; senderAddrWithFPort.port=connectionRequestList[i]->facilitator.port; senderAddrWithRPort=connectionRequestList[i]->senderPublic; senderAddrWithRPort.port=rakPeer->GetExternalID(connectionRequestList[i]->facilitator).port; senderAddrWithIPort=connectionRequestList[i]->senderPublic; senderAddrWithIPort.port=rakPeer->GetInternalID().port; */ // LogOut(FormatString("Recipient sending TTL %i hops to %s\n", TTL_HOPS, connectionRequestList[i]->senderPublic.ToString())); // rakPeer->SendTTL(connectionRequestList[i]->senderPublic.ToString(false), connectionRequestList[i]->senderPublic.port, false); // Send offline message to this system, hopefully at the exact same time that system tries to connect to us. // rakPeer->Ping(connectionRequestList[i]->senderPublic.ToString(false), connectionRequestList[i]->senderPublic.port, false); /* rakPeer->Ping(senderAddrWithFPort.ToString(false), senderAddrWithFPort.port, false); rakPeer->Ping(senderAddrWithRPort.ToString(false), senderAddrWithRPort.port, false); rakPeer->Ping(senderAddrWithIPort.ToString(false), senderAddrWithIPort.port, false); */ // if (connectionRequestList[i]->senderPrivate!=connectionRequestList[i]->senderPublic) // rakPeer->Ping(connectionRequestList[i]->senderPrivate.ToString(false), connectionRequestList[i]->senderPrivate.port, false); // LogOut(FormatString("Recipient sending TTL %i hops to %s\n", TTL_HOPS, connectionRequestList[i]->senderPublic.ToString(false))); // peer->SendTTL(connectionRequestList[i]->senderPublic.ToString(false),connectionRequestList[i]->senderPublic.port, TTL_HOPS+connectionRequestList[i]->recipientOfflineCount, 0); // peer->SendTTL(connectionRequestList[i]->senderPublic.ToString(false),connectionRequestList[i]->senderPublic.port+1, TTL_HOPS+connectionRequestList[i]->recipientOfflineCount, 0); // peer->SendTTL(connectionRequestList[i]->senderPrivate.ToString(false),connectionRequestList[i]->senderPrivate.port, TTL_HOPS+connectionRequestList[i]->recipientOfflineCount, 0); connectionRequestList[i]->recipientOfflineCount++; if (connectionRequestList[i]->recipientOfflineCount==RECIPIENT_OFFLINE_MAX_COUNT) { rakFree(connectionRequestList[i]->passwordData); delete connectionRequestList[i]; connectionRequestList.RemoveAtIndex(i); } else { connectionRequestList[i]->nextActionTime=time+RECIPIENT_OFFLINE_MESSAGE_INTERVAL; } continue; } } i++; } } }
void CVehiclePool::showVehicleForPlayer( _VehicleID vehicleid, _PlayerID playerid ) { RakNet::BitStream bStream; CVehicle* vehicle = GetVehicle( vehicleid ); if( vehicle == 0 ) return; float angle = 0.0f; if( vehicle->vehMatrix.up.X == 0.0f && vehicle->vehMatrix.up.Y == 0.0f || vehicle->GetSpawnInfo()->vehType == 0x219 || vehicle->GetSpawnInfo()->vehType == 0x21A ) { angle = vehicle->GetSpawnInfo()->vehRot; } else { angle = atan2( -vehicle->vehMatrix.up.X, vehicle->vehMatrix.up.Y ) * 57.2957763671875f; if( angle >= 360.0 ) angle -= 360.0f; else if( angle < 0.0f ) angle += 360.0f; } bStream.Write( ( _VehicleID ) vehicleid ); bStream.Write( ( uint32_t ) vehicle->GetSpawnInfo( )->vehType ); #ifdef _BIG_ENDIAN_SYSTEM bStream.Write(vehicle->vehMatrix.pos.X); bStream.Write(vehicle->vehMatrix.pos.Y); bStream.Write(vehicle->vehMatrix.pos.Z); #else bStream.Write( (char*)&vehicle->vehMatrix.pos, sizeof( tVector ) ); #endif bStream.Write( ( float ) angle ); bStream.Write( ( uint8_t )vehicle->GetSpawnInfo()->vehColor1 ); bStream.Write( ( uint8_t )vehicle->GetSpawnInfo()->vehColor2 ); bStream.Write( ( float ) vehicle->vehHealth ); bStream.Write( ( uint8_t ) vehicle->GetSpawnInfo()->vehInterior ); bStream.Write( ( uint32_t ) vehicle->vehDoorStatus ); bStream.Write( ( uint32_t ) vehicle->vehPanelStatus ); bStream.Write( ( uint8_t ) vehicle->vehLightStatus ); bStream.Write( ( uint8_t ) vehicle->vehTireStatus ); #ifdef _BIG_ENDIAN_SYSTEM bStream.Write( (char*)&vehicle->vehModInfo.vehModSlots, sizeof(vehicle->vehModInfo.vehModSlots)); bStream.Write(vehicle->vehModInfo.vehPaintJob); bStream.Write(vehicle->vehModInfo.vehColor1); bStream.Write(vehicle->vehModInfo.vehColor2); #else bStream.Write( (char*)&vehicle->vehModInfo, sizeof( VEHMOD_INFO ) ); #endif __NetGame->PlayerRPC( RPC_ShowVehicleToPlayer, &bStream, playerid, 2 ); if( strlen( vehicle->vehNumberPlate ) > 0 ) { bStream.Reset( ); bStream.Write( ( _VehicleID ) vehicleid ); bStream.Write( ( uint8_t )strlen( vehicle->vehNumberPlate ) ); bStream.Write( (char*)vehicle->vehNumberPlate, strlen( vehicle->vehNumberPlate ) ); char* RPC_SetVehicleNumberPlate = 0; __NetGame->PlayerRPC( RPC_SetVehicleNumberPlate, &bStream, playerid, 2); } if ( vehicle->hasParamExModified() ) { bStream.Reset( ); VEHPARAM_EX* params = vehicle->GetParamsEx(); bStream.Write( vehicleid ); bStream.Write( (char*)params, sizeof( VEHPARAM_EX ) ); __NetGame->PlayerRPC( RPC_SetVehicleParamsEx, &bStream, playerid, 2 ); } uint8_t paramsFlags = vehicle->GetParamsForPlayer( playerid ); vehicle->SetParamsForPlayer( playerid, paramsFlags & 1, ( paramsFlags & 2 ) ? 1 : 0 ); // Prevent lock/unlocking bug vehicle->UpdateVehicleColorForPlayer( playerid ); // prevent unsynced color }
int SendIRIToAddressCB(FileListTransfer::ThreadData threadData, bool *returnOutput, void* perThreadData) { (void) perThreadData; FileListTransfer *fileListTransfer = threadData.fileListTransfer; SystemAddress systemAddress = threadData.systemAddress; *returnOutput=false; // Was previously using GetStatistics to get outgoing buffer size, but TCP with UnifiedSend doesn't have this unsigned int bytesRead; const char *dataBlocks[2]; int lengths[2]; unsigned int smallFileTotalSize=0; RakNet::BitStream outBitstream; unsigned int ftpIndex; fileListTransfer->fileToPushRecipientListMutex.Lock(); for (ftpIndex=0; ftpIndex < fileListTransfer->fileToPushRecipientList.Size(); ftpIndex++) { FileListTransfer::FileToPushRecipient *ftpr = fileListTransfer->fileToPushRecipientList[ftpIndex]; // Referenced by both ftpr and list ftpr->AddRef(); fileListTransfer->fileToPushRecipientListMutex.Unlock(); if (ftpr->systemAddress==systemAddress) { FileListTransfer::FileToPush *ftp = ftpr->filesToPush.Peek(); // Read and send chunk. If done, delete at this index void *buff = rakMalloc_Ex(ftp->chunkSize, _FILE_AND_LINE_); if (buff==0) { ftpr->Deref(); notifyOutOfMemory(_FILE_AND_LINE_); return 0; } // Read the next file chunk bytesRead=ftp->incrementalReadInterface->GetFilePart(ftp->fileListNode.fullPathToFile, ftp->currentOffset, ftp->chunkSize, buff, ftp->fileListNode.context); bool done = ftp->fileListNode.dataLengthBytes == ftp->currentOffset+bytesRead; while (done && ftp->currentOffset==0 && ftpr->filesToPush.Size()>=2 && smallFileTotalSize<ftp->chunkSize) { // Send all small files at once, rather than wait for ID_FILE_LIST_REFERENCE_PUSH. But at least one ID_FILE_LIST_REFERENCE_PUSH must be sent outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE); // outBitstream.Write(ftp->fileListNode.context); outBitstream << ftp->fileListNode.context; outBitstream.Write(ftp->setID); StringCompressor::Instance()->EncodeString(ftp->fileListNode.filename, 512, &outBitstream); outBitstream.WriteCompressed(ftp->setIndex); outBitstream.WriteCompressed(ftp->fileListNode.dataLengthBytes); // Original length in bytes outBitstream.AlignWriteToByteBoundary(); dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=(const char*) buff; lengths[1]=bytesRead; fileListTransfer->SendListUnified(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, systemAddress, false); // LWS : fixed freed pointer reference // unsigned int chunkSize = ftp->chunkSize; RakNet::OP_DELETE(ftp,_FILE_AND_LINE_); ftpr->filesToPush.Pop(); smallFileTotalSize+=bytesRead; //done = bytesRead!=ftp->chunkSize; ftp = ftpr->filesToPush.Peek(); bytesRead=ftp->incrementalReadInterface->GetFilePart(ftp->fileListNode.fullPathToFile, ftp->currentOffset, ftp->chunkSize, buff, ftp->fileListNode.context); done = ftp->fileListNode.dataLengthBytes == ftp->currentOffset+bytesRead; } outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_REFERENCE_PUSH); // outBitstream.Write(ftp->fileListNode.context); outBitstream << ftp->fileListNode.context; outBitstream.Write(ftp->setID); StringCompressor::Instance()->EncodeString(ftp->fileListNode.filename, 512, &outBitstream); outBitstream.WriteCompressed(ftp->setIndex); outBitstream.WriteCompressed(ftp->fileListNode.dataLengthBytes); // Original length in bytes outBitstream.WriteCompressed(ftp->currentOffset); ftp->currentOffset+=bytesRead; outBitstream.WriteCompressed(bytesRead); outBitstream.Write(done); for (unsigned int flpcIndex=0; flpcIndex < fileListTransfer->fileListProgressCallbacks.Size(); flpcIndex++) fileListTransfer->fileListProgressCallbacks[flpcIndex]->OnFilePush(ftp->fileListNode.filename, ftp->fileListNode.fileLengthBytes, ftp->currentOffset-bytesRead, bytesRead, done, systemAddress, ftp->setID); dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=(char*) buff; lengths[1]=bytesRead; //rakPeerInterface->SendList(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, ftp->systemAddress, false); fileListTransfer->SendListUnified(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, systemAddress, false); // Mutex state: FileToPushRecipient (ftpr) has AddRef. fileToPushRecipientListMutex not locked. if (done) { // Done unsigned short setId = ftp->setID; RakNet::OP_DELETE(ftp,_FILE_AND_LINE_); ftpr->filesToPush.Pop(); if (ftpr->filesToPush.Size()==0) { for (unsigned int flpcIndex=0; flpcIndex < fileListTransfer->fileListProgressCallbacks.Size(); flpcIndex++) fileListTransfer->fileListProgressCallbacks[flpcIndex]->OnFilePushesComplete(systemAddress, setId); // Remove ftpr from fileToPushRecipientList fileListTransfer->RemoveFromList(ftpr); } } // ftpr out of scope ftpr->Deref(); rakFree_Ex(buff, _FILE_AND_LINE_ ); return 0; } else { ftpr->Deref(); fileListTransfer->fileToPushRecipientListMutex.Lock(); } } fileListTransfer->fileToPushRecipientListMutex.Unlock(); return 0; }
void NatPunchthroughServer::OnGetMostRecentPort(Packet *packet) { RakNet::BitStream bsIn(packet->data, packet->length, false); bsIn.IgnoreBytes(sizeof(MessageID)); uint16_t sessionId; unsigned short mostRecentPort; bsIn.Read(sessionId); bsIn.Read(mostRecentPort); unsigned int i,j; User *user; ConnectionAttempt *connectionAttempt; bool objectExists; i = users.GetIndexFromKey(packet->guid, &objectExists); if (natPunchthroughServerDebugInterface) { RakNet::RakString log; char addr1[128], addr2[128]; packet->systemAddress.ToString(true,addr1); packet->guid.ToString(addr2); log=RakNet::RakString("Got ID_NAT_GET_MOST_RECENT_PORT from systemAddress %s guid %s. port=%i. sessionId=%i. userFound=%i.", addr1, addr2, mostRecentPort, sessionId, objectExists); natPunchthroughServerDebugInterface->OnServerMessage(log.C_String()); } if (objectExists) { user=users[i]; user->mostRecentPort=mostRecentPort; RakNet::Time time = RakNet::GetTime(); for (j=0; j < user->connectionAttempts.Size(); j++) { connectionAttempt=user->connectionAttempts[j]; if (connectionAttempt->attemptPhase==ConnectionAttempt::NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS && connectionAttempt->sender->mostRecentPort!=0 && connectionAttempt->recipient->mostRecentPort!=0 && // 04/29/08 add sessionId to prevent processing for other systems connectionAttempt->sessionId==sessionId) { SystemAddress senderSystemAddress = connectionAttempt->sender->systemAddress; SystemAddress recipientSystemAddress = connectionAttempt->recipient->systemAddress; SystemAddress recipientTargetAddress = recipientSystemAddress; SystemAddress senderTargetAddress = senderSystemAddress; recipientTargetAddress.SetPortHostOrder(connectionAttempt->recipient->mostRecentPort); senderTargetAddress.SetPortHostOrder(connectionAttempt->sender->mostRecentPort); // Pick a time far enough in the future that both systems will have gotten the message int targetPing = rakPeerInterface->GetAveragePing(recipientTargetAddress); int senderPing = rakPeerInterface->GetAveragePing(senderSystemAddress); RakNet::Time simultaneousAttemptTime; if (targetPing==-1 || senderPing==-1) simultaneousAttemptTime = time + 1500; else { int largerPing = targetPing > senderPing ? targetPing : senderPing; if (largerPing * 4 < 100) simultaneousAttemptTime = time + 100; else simultaneousAttemptTime = time + (largerPing * 4); } if (natPunchthroughServerDebugInterface) { RakNet::RakString log; char addr1[128], addr2[128]; recipientSystemAddress.ToString(true,addr1); connectionAttempt->recipient->guid.ToString(addr2); log=RakNet::RakString("Sending ID_NAT_CONNECT_AT_TIME to recipient systemAddress %s guid %s", addr1, addr2); natPunchthroughServerDebugInterface->OnServerMessage(log.C_String()); } // Send to recipient timestamped message to connect at time RakNet::BitStream bsOut; bsOut.Write((MessageID)ID_TIMESTAMP); bsOut.Write(simultaneousAttemptTime); bsOut.Write((MessageID)ID_NAT_CONNECT_AT_TIME); bsOut.Write(connectionAttempt->sessionId); bsOut.Write(senderTargetAddress); // Public IP, using most recent port for (j=0; j < MAXIMUM_NUMBER_OF_INTERNAL_IDS; j++) // Internal IP bsOut.Write(rakPeerInterface->GetInternalID(senderSystemAddress,j)); bsOut.Write(connectionAttempt->sender->guid); bsOut.Write(false); rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,recipientSystemAddress,false); if (natPunchthroughServerDebugInterface) { RakNet::RakString log; char addr1[128], addr2[128]; senderSystemAddress.ToString(true,addr1); connectionAttempt->sender->guid.ToString(addr2); log=RakNet::RakString("Sending ID_NAT_CONNECT_AT_TIME to sender systemAddress %s guid %s", addr1, addr2); natPunchthroughServerDebugInterface->OnServerMessage(log.C_String()); } // Same for sender bsOut.Reset(); bsOut.Write((MessageID)ID_TIMESTAMP); bsOut.Write(simultaneousAttemptTime); bsOut.Write((MessageID)ID_NAT_CONNECT_AT_TIME); bsOut.Write(connectionAttempt->sessionId); bsOut.Write(recipientTargetAddress); // Public IP, using most recent port for (j=0; j < MAXIMUM_NUMBER_OF_INTERNAL_IDS; j++) // Internal IP bsOut.Write(rakPeerInterface->GetInternalID(recipientSystemAddress,j)); bsOut.Write(connectionAttempt->recipient->guid); bsOut.Write(true); rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,senderSystemAddress,false); connectionAttempt->recipient->DerefConnectionAttempt(connectionAttempt); connectionAttempt->sender->DeleteConnectionAttempt(connectionAttempt); // 04/29/08 missing return return; } } } else { if (natPunchthroughServerDebugInterface) { RakNet::RakString log; char addr1[128], addr2[128]; packet->systemAddress.ToString(true,addr1); packet->guid.ToString(addr2); log=RakNet::RakString("Ignoring ID_NAT_GET_MOST_RECENT_PORT from systemAddress %s guid %s", addr1, addr2); natPunchthroughServerDebugInterface->OnServerMessage(log.C_String()); } } }
void FileListTransfer::SendIRIToAddress(SystemAddress systemAddress) { // Was previously using GetStatistics to get outgoing buffer size, but TCP with UnifiedSend doesn't have this unsigned int bytesRead; const char *dataBlocks[2]; int lengths[2]; unsigned int smallFileTotalSize=0; RakNet::BitStream outBitstream; filesToPushAllSameAddressMutex.Lock(); for (unsigned int ftpIndex=0; ftpIndex < filesToPushAllSameAddress.Size(); ftpIndex++) { FileToPushRecipient *ftpr = filesToPushAllSameAddress[ftpIndex]; if (ftpr->systemAddress==systemAddress) { FileToPush *ftp = ftpr->filesToPush.Peek(); // Read and send chunk. If done, delete at this index void *buff = rakMalloc_Ex(ftp->chunkSize, __FILE__, __LINE__); if (buff==0) { filesToPushAllSameAddressMutex.Unlock(); notifyOutOfMemory(__FILE__, __LINE__); return; } bytesRead=ftp->incrementalReadInterface->GetFilePart(ftp->fileListNode.fullPathToFile, ftp->currentOffset, ftp->chunkSize, buff, ftp->fileListNode.context); bool done = bytesRead!=ftp->chunkSize; while (done && ftp->currentOffset==0 && ftpr->filesToPush.Size()>=2 && smallFileTotalSize<ftp->chunkSize) { // Send all small files at once, rather than wait for ID_FILE_LIST_REFERENCE_PUSH. But at least one ID_FILE_LIST_REFERENCE_PUSH must be sent outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE); outBitstream.Write(ftp->fileListNode.context); outBitstream.Write(ftp->setID); stringCompressor->EncodeString(ftp->fileListNode.filename, 512, &outBitstream); outBitstream.WriteCompressed(ftp->setIndex); outBitstream.WriteCompressed(ftp->fileListNode.dataLengthBytes); // Original length in bytes outBitstream.AlignWriteToByteBoundary(); dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=(const char*) buff; lengths[1]=bytesRead; SendListUnified(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, systemAddress, false); RakNet::OP_DELETE(ftp,__FILE__,__LINE__); ftpr->filesToPush.Pop(); smallFileTotalSize+=bytesRead; done = bytesRead!=ftp->chunkSize; ftp = ftpr->filesToPush.Peek(); bytesRead=ftp->incrementalReadInterface->GetFilePart(ftp->fileListNode.fullPathToFile, ftp->currentOffset, ftp->chunkSize, buff, ftp->fileListNode.context); } outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_REFERENCE_PUSH); outBitstream.Write(ftp->fileListNode.context); outBitstream.Write(ftp->setID); stringCompressor->EncodeString(ftp->fileListNode.filename, 512, &outBitstream); outBitstream.WriteCompressed(ftp->setIndex); outBitstream.WriteCompressed(ftp->fileListNode.dataLengthBytes); // Original length in bytes outBitstream.WriteCompressed(ftp->currentOffset); ftp->currentOffset+=bytesRead; outBitstream.WriteCompressed(bytesRead); outBitstream.Write(done); if (callback) { callback->OnFilePush(ftp->fileListNode.filename, ftp->fileListNode.fileLengthBytes, ftp->currentOffset-bytesRead, bytesRead, done, systemAddress); } dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=(char*) buff; lengths[1]=bytesRead; //rakPeerInterface->SendList(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, ftp->systemAddress, false); SendListUnified(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, systemAddress, false); if (done) { // Done RakNet::OP_DELETE(ftp,__FILE__,__LINE__); ftpr->filesToPush.Pop(); if (ftpr->filesToPush.Size()==0) { RakNet::OP_DELETE(ftpr,__FILE__,__LINE__); filesToPushAllSameAddress.RemoveAtIndexFast(ftpIndex); } } rakFree_Ex(buff, __FILE__, __LINE__ ); break; } } filesToPushAllSameAddressMutex.Unlock(); }