void PacketLogger::OnAck(unsigned int messageNumber, SystemAddress remoteSystemAddress, RakNetTime time) { char str[256]; char str1[64], str2[62]; SystemAddress localSystemAddress = rakPeerInterface->GetExternalID(remoteSystemAddress); localSystemAddress.ToString(true, str1); remoteSystemAddress.ToString(true, str2); char localtime[128]; GetLocalTime(localtime); sprintf(str, "%s,Rcv,Ack,%i,,,,%"PRINTF_64_BIT_MODIFIER"u,%s,%s,,,,,," , localtime , messageNumber , (unsigned long long) time , str1 , str2 ); AddToLog(str); }
void NetworkUtils::SendNetworkMessage( NetworkMessage& message, const SystemAddress& destination, RakPeerInterface* networkInterface ) { BitStream* bitStream = NetworkUtils::Serialize( message ); networkInterface->Send( bitStream, MEDIUM_PRIORITY, RELIABLE, 0, destination, false ); delete bitStream; if ( message.messageId == System::Messages::Network::ComponentUpdate.c_str( ) ) { std::string messageText = message.parameters[ System::Parameters::Network::ComponentMessage ].As< System::Message >( ); messageText = ( messageText.empty( ) ) ? message.messageId.C_String( ) : messageText; Debug( messageText, "to", destination.ToString( false ) ); } else { Debug( message.messageId, "to", destination.ToString( false ) ); } }
void PacketLogger::FormatLine( char* into, const char* dir, const char* type, unsigned int reliableMessageNumber, unsigned int frame, const char* idToPrint , const BitSize_t bitLen, unsigned long long time, const SystemAddress& local, const SystemAddress& remote, unsigned int splitPacketId, unsigned int splitPacketIndex, unsigned int splitPacketCount, unsigned int orderingIndex) { char str1[64], str2[62]; local.ToString(true, str1); remote.ToString(true, str2); char localtime[128]; GetLocalTime(localtime); char str3[64]; if (reliableMessageNumber==(unsigned int)-1) { str3[0]='N'; str3[1]='/'; str3[2]='A'; str3[3]=0; } else { sprintf(str3,"%5u",reliableMessageNumber); } sprintf(into, "%s,%s%s,%s,%s,%5u,%s,%u,%" PRINTF_64_BIT_MODIFIER "u,%s,%s,%i,%i,%i,%i,%s," , localtime , prefix , dir , type , str3 , frame , idToPrint , bitLen , time , str1 , str2 , splitPacketId , splitPacketIndex , splitPacketCount , orderingIndex , suffix ); }
void FullyConnectedMesh2::SendFCMGuidRequest(SystemAddress addr) { #ifdef DEBUG_FCM2 printf("SendFCMGuidRequest to %s. guid=%s.\n", addr.ToString(), rakPeerInterface->GetGuidFromSystemAddress(addr).ToString()); #endif RakNet::BitStream bsOut; bsOut.Write((MessageID)ID_FCM2_REQUEST_FCMGUID); bsOut.Write(GetElapsedRuntime()); rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,addr,false); }
void NatPunchthroughClient::SendTTL(SystemAddress sa) { if (sa==UNASSIGNED_SYSTEM_ADDRESS) return; if (sa.port==0) return; char ipAddressString[32]; sa.ToString(false, ipAddressString); rakPeerInterface->SendTTL(ipAddressString,sa.port, 3); }
void PacketLogger::WriteMiscellaneous(const char *type, const char *msg) { char str[1024]; char str1[64]; SystemAddress localSystemAddress = rakPeerInterface->GetInternalID(); localSystemAddress.ToString(true, str1); RakNetTime time = RakNet::GetTime(); char localtime[128]; GetLocalTime(localtime); sprintf(str, "%s,Lcl,%s,,,,,%"PRINTF_TIME_MODIFIER"u,%s,,,,,,,%s" , localtime , type , (unsigned long long) time , str1 , msg ); AddToLog(msg); }
void PacketLogger::OnPushBackPacket(const char *data, const BitSize_t bitsUsed, SystemAddress remoteSystemAddress) { char str[256]; char str1[64], str2[62]; SystemAddress localSystemAddress = rakPeerInterface->GetExternalID(remoteSystemAddress); localSystemAddress.ToString(true, str1); remoteSystemAddress.ToString(true, str2); RakNetTime time = RakNet::GetTime(); char localtime[128]; GetLocalTime(localtime); sprintf(str, "%s,Lcl,PBP,,,%s,%i,%"PRINTF_TIME_MODIFIER"u,%s,%s,,,,,," , localtime , BaseIDTOString(data[0]) , bitsUsed , (unsigned long long) time , str1 , str2 ); AddToLog(str); }
void MessageFilter::OnInvalidMessage(FilterSet *filterSet, SystemAddress systemAddress, unsigned char messageID) { if (filterSet->invalidMessageCallback) filterSet->invalidMessageCallback(rakPeerInterface, systemAddress, filterSet->filterSetID, filterSet->disallowedCallbackUserData, messageID); if (filterSet->banOnDisallowedMessage) { char str1[64]; systemAddress.ToString(false, str1); rakPeerInterface->AddToBanList(str1, filterSet->disallowedMessageBanTimeMS); } if (filterSet->kickOnDisallowedMessage) rakPeerInterface->CloseConnection(systemAddress, true, 0); }
void FullyConnectedMesh2::SendFCMGuidResponse(SystemAddress addr, unsigned int responseAssignedConnectionCount, unsigned int responseTotalConnectionCount) { #ifdef DEBUG_FCM2 printf("SendFCMGuidResponse to %s. guid=%s.\n", addr.ToString(), rakPeerInterface->GetGuidFromSystemAddress(addr).ToString()); #endif RakNet::BitStream bsOut; bsOut.Write((MessageID)ID_FCM2_RESPOND_FCMGUID); bsOut.Write(responseAssignedConnectionCount); bsOut.Write(responseTotalConnectionCount); rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,addr,false); }
void SystemAddress::FixForIPVersion(const SystemAddress &boundAddressToSocket) { char str[128]; ToString(false,str); if (strcmp(str, IPV6_LOOPBACK)==0) { if (boundAddressToSocket.GetIPVersion()==4) { FromString(IPV4_LOOPBACK,0,4); } } else if (strcmp(str, IPV4_LOOPBACK)==0) { #if VENET_SUPPORT_IPV6==1 if (boundAddressToSocket.GetIPVersion()==6) { FromString(IPV6_LOOPBACK,0,6); } #endif } }
void Server::Loop(){ while(1){ SystemAddress addresClient = peer->HasNewIncomingConnection(); if(addresClient!=UNASSIGNED_SYSTEM_ADDRESS){ std::cout << "[Client Connected]: "<<addresClient.ToString() <<std::endl; std::cout << "[Client Connected]: client count: " << peer->GetConnectionCount() <<std::endl; //std::cout << "[Client Connected]: client count: " << <<std::endl; SystemAddress iplist[Settings::maxPlayers]; unsigned short numberofSystems; peer->GetConnectionList(iplist,&numberofSystems); for(unsigned short i = 0;i<numberofSystems;i++){ std::cout << "[Client Connected]: client " << i << ":" << iplist[i].ToString() <<std::endl; } playersManager.AddPlayer(addresClient); SendPlayerList(); printf("\n"); }else{ break; } } while(1){ SystemAddress addresClient = peer->HasLostConnection(); if(addresClient!=UNASSIGNED_SYSTEM_ADDRESS){ peer->CloseConnection(addresClient); std::cout << "[Client DisConnected]: "<<addresClient.ToString() <<std::endl; playersManager.RemovePlayer(addresClient); SendPlayerList(); SendPlayerIsAdmin(); printf("\n"); }else{ break; } } if(game != NULL){ game->Loop(); } Connector::Loop(); }
PluginReceiveResult FullyConnectedMesh2::OnReceive(Packet *packet) { switch (packet->data[0]) { case ID_REMOTE_NEW_INCOMING_CONNECTION: { if (connectOnNewRemoteConnections) { unsigned int count; RakNet::BitStream bsIn(packet->data, packet->length, false); bsIn.IgnoreBytes(sizeof(MessageID)); bsIn.Read(count); SystemAddress remoteAddress; RakNetGUID remoteGuid; char str[64]; for (unsigned int i=0; i < count; i++) { bsIn.Read(remoteAddress); bsIn.Read(remoteGuid); remoteAddress.ToString(false,str); rakPeerInterface->Connect(str,remoteAddress.port,connectionPassword.C_String(),(int) connectionPassword.GetLength()); } } } break; case ID_FCM2_REQUEST_FCMGUID: OnRequestFCMGuid(packet); return RR_STOP_PROCESSING_AND_DEALLOCATE; case ID_FCM2_RESPOND_CONNECTION_COUNT: OnRespondConnectionCount(packet); return RR_STOP_PROCESSING_AND_DEALLOCATE; case ID_FCM2_INFORM_FCMGUID: OnInformFCMGuid(packet); return RR_STOP_PROCESSING_AND_DEALLOCATE; } return RR_CONTINUE_PROCESSING; }
void DoHandshake(RakPeerInterface *rakServer, const SystemAddress& systemAddress, RakNet::BitStream * data, std::string SERVER){ unsigned long s_remoteConnectionType = 4; if (SERVER == "AUTH") s_remoteConnectionType = 1; unsigned long version; data->Read(version); unsigned long unknown; data->Read(unknown); unsigned long remoteConnectionType; data->Read(remoteConnectionType); unsigned long processid; data->Read(processid); unsigned short port; data->Read(port); std::vector<unsigned char> addv; addv.reserve(33); bool flag = true; std::string address = PacketTools::ReadStrFromPacket(data, 33); //Unused, no data Logger::log(SERVER, "", "Client: " + std::string(systemAddress.ToString()), LOG_ALL); Logger::log(SERVER, "", "Client Handshake Request", LOG_DEBUG); Logger::log(SERVER, "", "Version: " + std::to_string(version), LOG_ALL); Logger::log(SERVER, "", "ProcessID: " + std::to_string(processid), LOG_ALL); Logger::log(SERVER, "", "ConnectionType: " + std::to_string(remoteConnectionType), LOG_ALL); Logger::log(SERVER, "", "Port: " + std::to_string(port), LOG_ALL); //Preparing answer: RakNet::BitStream *aw = new RakNet::BitStream(59); CreatePacketHeader(ID_USER_PACKET_ENUM, 0, 0, aw); unsigned long s_version = 171022UL; unsigned long s_unknown = 0x93; unsigned long s_processid = GetCurrentProcessId(); short s_unknown2 = -1; //port = 0xFFFF = -1 -> no port? std::string s_ip = rakServer->GetLocalIP(0); Logger::log(SERVER, "", "Server Handshake Response", LOG_DEBUG); Logger::log(SERVER, "", "Version: " + std::to_string(s_version), LOG_ALL); Logger::log(SERVER, "", "ProcessID: " + std::to_string(s_processid), LOG_ALL); Logger::log(SERVER, "", "ConnectionType: " + std::to_string(s_remoteConnectionType), LOG_ALL); Logger::log(SERVER, "", "Address: " + s_ip, LOG_ALL); aw->Write(s_version); aw->Write(s_unknown); aw->Write(s_remoteConnectionType); aw->Write(s_processid); aw->Write(s_unknown2); for (unsigned char k = 0; k < 33; k++){ if (k < s_ip.size()) aw->Write((unsigned char)s_ip.at(k)); else aw->Write((unsigned char)0); } rakServer->Send(aw, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, systemAddress, false); }
void NatPunchthroughClient::OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming) { (void) rakNetGUID; (void) isIncoming; // Try to track new port mappings on the router. Not reliable, but better than nothing. SystemAddress ourExternalId = rakPeerInterface->GetExternalID(systemAddress); if (ourExternalId!=UNASSIGNED_SYSTEM_ADDRESS) mostRecentNewExternalPort=ourExternalId.GetPort(); unsigned int i; i=0; while (i < groupRequestsInProgress.Size()) { if (groupRequestsInProgress[i].guid==rakNetGUID) { groupRequestsInProgress.RemoveAtIndexFast(i); } else { i++; } } }
void ManyClientsOneServerBlockingTest::WaitForConnectionRequestsToComplete(RakPeerInterface **clientList, int clientNum, bool isVerbose) { SystemAddress currentSystem; bool msgWasPrinted=false; for (int i=0;i<clientNum;i++) { currentSystem.SetBinaryAddress("127.0.0.1"); currentSystem.port=60000; while (CommonFunctions::ConnectionStateMatchesOptions (clientList[i],currentSystem,false,true,true) ) { if (msgWasPrinted==false) { printf("Waiting for connection requests to complete.\n"); msgWasPrinted=true; } RakSleep(30); } } }
void ManyClientsOneServerDeallocateBlockingTest::WaitForConnectionRequestsToComplete(RakPeerInterface **clientList, int clientNum, bool isVerbose) { SystemAddress currentSystem; bool msgWasPrinted=false; for (int i=0;i<clientNum;i++) { currentSystem.SetBinaryAddress("127.0.0.1"); currentSystem.port=60000; while (clientList[i]->IsConnectionAttemptPending (currentSystem) ) { if (msgWasPrinted==false) { printf("Waiting for connection requests to complete.\n"); msgWasPrinted=true; } RakSleep(30); } } }
// Implemented event callback from base class PluginInterface2 virtual void OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason ) { // Call down to the base class in case it does anything in the future (right now it does nothing) SQLite3ServerPlugin::OnClosedConnection(systemAddress, rakNetGUID, lostConnectionReason); // Get the database index associated with the table used for this class unsigned int idx = dbHandles.GetIndexOf(connectionStateIdentifier); if (idx==(unsigned int)-1) return; // Remove dropped system by primary key system address char systemAddressString[64]; systemAddress.ToString(true,systemAddressString); RakNet::RakString query("DELETE FROM connectionState WHERE systemAddress='%s';", RakNet::RakString(systemAddressString).SQLEscape().C_String()); sqlite3_exec(dbHandles[idx].dbHandle,query.C_String(),0,0,0); }
int InstancesTable::getInstanceId(SystemAddress addr){ std::stringstream str; str << "SELECT `instanceid` FROM `instances` WHERE `server_address` = '" << addr.ToString() << "');"; auto qr = Database::Query(str.str()); if (qr == NULL){ return -1; } else{ if (mysql_num_rows(qr) == 0){ return -1; } else{ auto row = mysql_fetch_row(qr); return std::stoi(row[0]); } } }
int RakNet::NatTypeRecvFrom(char *data, SOCKET socket, SystemAddress &sender) { sockaddr_in sa; socklen_t len2; const int flag=0; len2 = sizeof( sa ); sa.sin_family = AF_INET; sa.sin_port=0; int len = recvfrom( socket, data, MAXIMUM_MTU_SIZE, flag, ( sockaddr* ) & sa, ( socklen_t* ) & len2 ); if (len>0) { sender.address.addr4.sin_family=AF_INET; sender.address.addr4.sin_addr.s_addr = sa.sin_addr.s_addr; //sender.SetPort( ntohs( sa.sin_port ) ); sender.SetPort( ntohs( sa.sin_port ) ); } return len; }
int Lobby2Client_Steam_Impl::RakNetSendTo( const char *data, int length, const SystemAddress &systemAddress ) { bool objectExists; unsigned int i = roomMembersByAddr.GetIndexFromKey(systemAddress, &objectExists); if (objectExists) { if (SteamNetworking()->SendP2PPacket(roomMembersByAddr[i].steamIDRemote, data, length, k_EP2PSendUnreliable)) return length; else return 0; } else if (systemAddress.GetPort()!=STEAM_UNUSED_PORT) { // return SocketLayer::SendTo_PC(s,data,length,systemAddress,_FILE_AND_LINE_); return -1; } return 0; }
void AutopatcherServerLoadNotifier_Printf::OnQueueUpdate(SystemAddress remoteSystem, AutopatcherServerLoadNotifier::RequestType requestType, AutopatcherServerLoadNotifier::QueueOperation queueOperation, AutopatcherServerLoadNotifier::AutopatcherState *autopatcherState) { char *operationString; char *requestTypeString; char systemAddressString[32]; remoteSystem.ToString(true, systemAddressString); if (requestType==ASUMC_GET_CHANGELIST) requestTypeString="GetChangelist"; else requestTypeString="GetPatch"; if (queueOperation==QO_WAS_ADDED) operationString="added"; else if (queueOperation==QO_POPPED_ONTO_TO_PROCESSING_THREAD) operationString="processing"; else if (queueOperation==QO_WAS_ABORTED) operationString="aborted"; printf("%s %s %s. %i queued. %i working.\n", systemAddressString, requestTypeString, operationString, autopatcherState->requestsQueued, autopatcherState->requestsWorking); }
void AutopatcherServerLoadNotifier_Printf::OnGetPatchCompleted(SystemAddress remoteSystem, AutopatcherServerLoadNotifier::PatchResult patchResult, AutopatcherServerLoadNotifier::AutopatcherState *autopatcherState) { char systemAddressString[32]; remoteSystem.ToString(true, systemAddressString); char *patchResultString; if (patchResult==PR_NO_FILES_NEEDED_PATCHING) patchResultString="No files needed patching"; else if (patchResult==PR_REPOSITORY_ERROR) patchResultString="Repository error"; else if (patchResult==PR_PATCHES_WERE_SENT) patchResultString="Files pushed for patching"; else if (patchResult==PR_ABORTED_FROM_INPUT_THREAD) patchResultString="Aborted from input thread"; else if (patchResult==PR_ABORTED_FROM_DOWNLOAD_THREAD) patchResultString="Aborted from download thread"; printf("%s GetPatch complete. %s. %i queued. %i working.\n", systemAddressString, patchResultString, autopatcherState->requestsQueued, autopatcherState->requestsWorking); }
void RoomsBrowserGFx3_RakNet::OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming) { if (systemAddress==lobby2Client->GetServerAddress()) { // is connected FxResponseArgs<0> rargs; FxDelegate::Invoke2(movie, "c2f_NotifyConnectionAttemptToServerSuccess", rargs); } else { FxResponseArgs<3> rargs; char saString[64]; systemAddress.ToString(true,saString); char guidString[64]; rakNetGUID.ToString(guidString); rargs.Add(saString); rargs.Add(guidString); rargs.Add(isIncoming); FxDelegate::Invoke2(movie, "c2f_NotifyNewConnection", rargs); } }
// Implemented event callback from base class PluginInterface2 virtual void OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming) { // Call down to the base class in case it does anything in the future (right now it does nothing) SQLite3ServerPlugin::OnNewConnection(systemAddress, rakNetGUID, isIncoming); // Get the database index associated with the table used for this class unsigned int idx = dbHandles.GetIndexOf(connectionStateIdentifier); if (idx==(unsigned int)-1) return; // Store new system's system address and guid. rowCreationTime column is created automatically char systemAddressString[64]; systemAddress.ToString(true,systemAddressString); char guidString[128]; rakNetGUID.ToString(guidString); RakNet::RakString query( "INSERT INTO connectionState (systemAddress,rakNetGUID) VALUES ('%s','%s');", RakNet::RakString(systemAddressString).SQLEscape().C_String(), RakNet::RakString(guidString).SQLEscape().C_String()); sqlite3_exec(dbHandles[idx].dbHandle,query.C_String(),0,0,0); }
void NatPunchthrough::OnCloseConnection(RakPeerInterface *peer, SystemAddress systemAddress) { (void) peer; if (allowFacilitation==false) return; // If in ping mode, send ID_NAT_TARGET_CONNECTION_LOST if (connectionRequestList.Size()) { unsigned i; i=0; while (i < connectionRequestList.Size()) { if (connectionRequestList[i]->facilitatingConnection && (connectionRequestList[i]->receiverPublic==systemAddress || connectionRequestList[i]->senderPublic==systemAddress)) { LogOut(FormatString("Facilitator: Lost connection to %s\n", systemAddress.ToString(true))); // This field is not used by the facilitator. RakAssert(connectionRequestList[i]->passwordData==0); if (connectionRequestList[i]->senderPublic==systemAddress) { RakNet::BitStream outBitstream; outBitstream.Write((MessageID)ID_NAT_TARGET_CONNECTION_LOST); outBitstream.Write(connectionRequestList[i]->receiverPublic); rakPeer->Send(&outBitstream, HIGH_PRIORITY, RELIABLE, 0, connectionRequestList[i]->senderPublic, false); } rakFree(connectionRequestList[i]->passwordData); delete connectionRequestList[i]; connectionRequestList.RemoveAtIndex(i); } else i++; } } }
void AutopatcherServerLoadNotifier_Printf::OnGetChangelistCompleted( SystemAddress remoteSystem, AutopatcherServerLoadNotifier::GetChangelistResult getChangelistResult, AutopatcherServerLoadNotifier::AutopatcherState *autopatcherState) { char systemAddressString[32]; remoteSystem.ToString(true, systemAddressString); char *changelistString; if (getChangelistResult==GCR_DELETE_FILES) changelistString="Delete files"; else if (getChangelistResult==GCR_ADD_FILES) changelistString="Add files"; else if (getChangelistResult==GCR_ADD_AND_DELETE_FILES) changelistString="Add and delete files"; else if (getChangelistResult==GCR_NOTHING_TO_DO) changelistString="No files in changelist"; else if (getChangelistResult==GCR_REPOSITORY_ERROR) changelistString="Repository error"; printf("%s GetChangelist complete. %s. %i queued. %i working.\n", systemAddressString, changelistString, autopatcherState->requestsQueued, autopatcherState->requestsWorking); }
void NatPunchthroughClient::FindRouterPortStride(const SystemAddress &facilitator) { ConnectionState cs = rakPeerInterface->GetConnectionState(facilitator); if (cs!=IS_CONNECTED) return; if (hasPortStride!=UNKNOWN_PORT_STRIDE) return; hasPortStride=CALCULATING_PORT_STRIDE; portStrideCalTimeout = RakNet::GetTime()+5000; if (natPunchthroughDebugInterface) { natPunchthroughDebugInterface->OnClientMessage(RakString("Calculating port stride from %s", facilitator.ToString(true))); } RakNet::BitStream outgoingBs; outgoingBs.Write((MessageID)ID_NAT_REQUEST_BOUND_ADDRESSES); rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,facilitator,false); }
void FLP_Printf::OnSendAborted( SystemAddress systemAddress ) { char str[32]; systemAddress.ToString(true, (char*) str); RAKNET_DEBUG_PRINTF("Send aborted to %s\n", str); }
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 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++; } }