diff --git a/Samples/ChatExample/Client/Chat Example Client.cpp b/Samples/ChatExample/Client/Chat Example Client.cpp index 88a1ddcce..37ae9c165 100644 --- a/Samples/ChatExample/Client/Chat Example Client.cpp +++ b/Samples/ChatExample/Client/Chat Example Client.cpp @@ -41,6 +41,7 @@ #include "mafianet/Gets.h" #include "mafianet/linux_adapter.h" #include "mafianet/osx_adapter.h" +#include "mafianet/guid_util.h" #if LIBCAT_SECURITY==1 #include "mafianet/SecureHandshake.h" // Include header for secure handshake @@ -144,7 +145,7 @@ int main(void) printf("%i. %s\n", i+1, client->GetLocalIP(i)); } - printf("My GUID is %s\n", client->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("My GUID is %s\n", MafiaNet::to_string(client->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS)).c_str()); puts("'quit' to quit. 'stat' to show stats. 'ping' to ping.\n'disconnect' to disconnect. 'connect' to reconnnect. Type to talk."); char message[2048]; @@ -325,7 +326,7 @@ int main(void) case ID_CONNECTION_REQUEST_ACCEPTED: // This tells the client they have connected - printf("ID_CONNECTION_REQUEST_ACCEPTED to %s with GUID %s\n", p->systemAddress.ToString(true), p->guid.ToString()); + printf("ID_CONNECTION_REQUEST_ACCEPTED to %s with GUID %s\n", p->systemAddress.ToString(true), MafiaNet::to_string(p->guid).c_str()); printf("My external address is %s\n", client->GetExternalID(p->systemAddress).ToString(true)); break; case ID_CONNECTED_PING: diff --git a/Samples/ChatExample/Server/Chat Example Server.cpp b/Samples/ChatExample/Server/Chat Example Server.cpp index f6cf6d919..5c424f8ba 100644 --- a/Samples/ChatExample/Server/Chat Example Server.cpp +++ b/Samples/ChatExample/Server/Chat Example Server.cpp @@ -38,6 +38,7 @@ #include "mafianet/Gets.h" #include "mafianet/linux_adapter.h" #include "mafianet/osx_adapter.h" +#include "mafianet/guid_util.h" #if LIBCAT_SECURITY==1 #include "mafianet/SecureHandshake.h" // Include header for secure handshake @@ -146,7 +147,7 @@ int main(void) printf("%i. %s (LAN=%i)\n", i+1, sa.ToString(false), sa.IsLANAddress()); } - printf("\nMy GUID is %s\n", server->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("\nMy GUID is %s\n", MafiaNet::to_string(server->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS)).c_str()); puts("'quit' to quit. 'stat' to show stats. 'ping' to ping.\n'pingip' to ping an ip address\n'ban' to ban an IP from connecting.\n'kick to kick the first connected player.\nType to talk."); char message[2048]; @@ -273,7 +274,7 @@ int main(void) case ID_NEW_INCOMING_CONNECTION: // Somebody connected. We have their IP now - printf("ID_NEW_INCOMING_CONNECTION from %s with GUID %s\n", p->systemAddress.ToString(true), p->guid.ToString()); + printf("ID_NEW_INCOMING_CONNECTION from %s with GUID %s\n", p->systemAddress.ToString(true), MafiaNet::to_string(p->guid).c_str()); clientID=p->systemAddress; // Record the player ID of the client printf("Remote internal IDs:\n"); diff --git a/Samples/ComprehensivePCGame/ComprehensivePCGame.cpp b/Samples/ComprehensivePCGame/ComprehensivePCGame.cpp index d0e059190..1a45af720 100644 --- a/Samples/ComprehensivePCGame/ComprehensivePCGame.cpp +++ b/Samples/ComprehensivePCGame/ComprehensivePCGame.cpp @@ -45,6 +45,7 @@ #include "mafianet/linux_adapter.h" #include "mafianet/osx_adapter.h" #include "mafianet/LinuxStrings.h" +#include "mafianet/guid_util.h" // See http://www.digip.org/jansson/doc/2.4/ // This is used to make it easier to parse the JSON returned from the master server #include "jansson.h" @@ -754,7 +755,7 @@ RPC4GlobalRegistration __InGameChat("InGameChat", InGameChat, nullptr, 0); // Write roomName and a list of NATTypeDetectionResult to a bitStream void SerializeToJSON(RakString &outputString, RakString &roomName, DataStructures::List &natTypes) { - outputString.Set("'roomName': '%s', 'guid': '%s', 'natTypes' : [ ", roomName.C_String(), rakPeer->GetMyGUID().ToString()); + outputString.Set("'roomName': '%s', 'guid': '%s', 'natTypes' : [ ", roomName.C_String(), MafiaNet::to_string(rakPeer->GetMyGUID()).c_str()); for (unsigned short i=0; i < natTypes.Size(); i++) { if (i!=0) @@ -1060,7 +1061,7 @@ int main(void) // Setup my own user User *user = new User; user->SetNetworkIDManager(networkIDManager); - user->userName = rakPeer->GetMyGUID().ToString(); + user->userName = MafiaNet::to_string(rakPeer->GetMyGUID()).c_str(); // Inform TeamManager of my user's team member info teamManager->GetWorldAtIndex(0)->ReferenceTeamMember(&user->tmTeamMember,user->GetNetworkID()); @@ -1073,7 +1074,7 @@ int main(void) SLNET_VERIFY(rakPeer->Startup(8, &sd, 1) == RAKNET_STARTED); rakPeer->SetMaximumIncomingConnections(8); rakPeer->SetTimeoutTime(30000, MafiaNet::UNASSIGNED_SYSTEM_ADDRESS); - printf("Our guid is %s\n", rakPeer->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("Our guid is %s\n", MafiaNet::to_string(rakPeer->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS)).c_str()); printf("Started on %s\n", rakPeer->GetMyBoundAddress().ToString(true)); // Start TCPInterface and begin connecting to the NAT punchthrough server @@ -1095,12 +1096,12 @@ int main(void) { case ID_NEW_INCOMING_CONNECTION: { - printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); } break; case ID_CONNECTION_REQUEST_ACCEPTED: { - printf("ID_CONNECTION_REQUEST_ACCEPTED from %s,guid=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_CONNECTION_REQUEST_ACCEPTED from %s,guid=%s\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); if (game->phase==Game::CONNECTING_TO_SERVER) { @@ -1204,9 +1205,9 @@ int main(void) else { if (oldHost!=UNASSIGNED_RAKNET_GUID) - printf("ID_FCM2_NEW_HOST: A new system %s has become host, GUID=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_FCM2_NEW_HOST: A new system %s has become host, GUID=%s\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); else - printf("ID_FCM2_NEW_HOST: System %s is host, GUID=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_FCM2_NEW_HOST: System %s is host, GUID=%s\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); } if (oldHost==UNASSIGNED_RAKNET_GUID) @@ -1266,7 +1267,7 @@ int main(void) { // As with connection failed, this does not automatically mean we cannot join the session // We only fail on ID_FCM2_VERIFIED_JOIN_FAILED - printf("NAT punch to %s failed. Reason %s\n", packet->guid.ToString(), PacketLogger::BaseIDTOString(packet->data[0])); + printf("NAT punch to %s failed. Reason %s\n", MafiaNet::to_string(packet->guid).c_str(), PacketLogger::BaseIDTOString(packet->data[0])); if (game->phase==Game::NAT_PUNCH_TO_GAME_HOST) game->EnterPhase(Game::SEARCH_FOR_GAMES); @@ -1396,7 +1397,7 @@ int main(void) if (thisSystemAccepted) printf("Game join request accepted\n"); else - printf("System %s joined the mesh\n", systemsAccepted[0].ToString()); + printf("System %s joined the mesh\n", MafiaNet::to_string(systemsAccepted[0]).c_str()); // Add the new participant to the game if we already know who the host is. Otherwise do this // once ID_FCM2_NEW_HOST arrives diff --git a/Samples/FCMHost/FCM2HostTest.cpp b/Samples/FCMHost/FCM2HostTest.cpp index 66f068688..142a8a861 100644 --- a/Samples/FCMHost/FCM2HostTest.cpp +++ b/Samples/FCMHost/FCM2HostTest.cpp @@ -28,6 +28,7 @@ #include "mafianet/Kbhit.h" #include "mafianet/PacketLogger.h" #include "mafianet/BitStream.h" +#include "mafianet/guid_util.h" using namespace MafiaNet; @@ -49,7 +50,7 @@ int main() SLNET_VERIFY(rakPeer->Startup(8, &sd, 1) == RAKNET_STARTED); rakPeer->SetMaximumIncomingConnections(8); rakPeer->SetTimeoutTime(1000, MafiaNet::UNASSIGNED_SYSTEM_ADDRESS); - printf("Our guid is %s\n", rakPeer->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("Our guid is %s\n", MafiaNet::to_string(rakPeer->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS)).c_str()); printf("Started on %s\n", rakPeer->GetMyBoundAddress().ToString(true)); // BitStream contextBs; // contextBs.Write(RakString("Our guid is %s\n", rakPeer->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString())); @@ -76,12 +77,12 @@ int main() case ID_NEW_INCOMING_CONNECTION: // Somebody connected. We have their IP now - printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); break; case ID_CONNECTION_REQUEST_ACCEPTED: // Somebody connected. We have their IP now - printf("ID_CONNECTION_REQUEST_ACCEPTED from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_CONNECTION_REQUEST_ACCEPTED from %s. guid=%s.\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); break; @@ -101,14 +102,14 @@ int main() if (packet->guid==rakPeer->GetMyGUID()) printf("Got new host (ourselves)"); else - printf("Got new host %s, GUID=%s", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("Got new host %s, GUID=%s", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); MafiaNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(1); RakNetGUID oldHost; bs.Read(oldHost); // If oldHost is different then the current host, then we lost connection to the host if (oldHost!=UNASSIGNED_RAKNET_GUID) - printf(". Oldhost Guid=%s\n", oldHost.ToString()); + printf(". Oldhost Guid=%s\n", MafiaNet::to_string(oldHost).c_str()); else printf(". (First reported host)\n"); } diff --git a/Samples/FCMHostSimultaneous/FCM2HostSimultaneousTest.cpp b/Samples/FCMHostSimultaneous/FCM2HostSimultaneousTest.cpp index 670a2f380..5907e5b01 100644 --- a/Samples/FCMHostSimultaneous/FCM2HostSimultaneousTest.cpp +++ b/Samples/FCMHostSimultaneous/FCM2HostSimultaneousTest.cpp @@ -29,6 +29,7 @@ #include "mafianet/Kbhit.h" #include "mafianet/PacketLogger.h" #include "mafianet/Gets.h" +#include "mafianet/guid_util.h" using namespace MafiaNet; @@ -51,7 +52,7 @@ int main() SLNET_VERIFY(rakPeer[i]->Startup(NUM_PEERS, &sd, 1) == RAKNET_STARTED); rakPeer[i]->SetMaximumIncomingConnections(NUM_PEERS); rakPeer[i]->SetTimeoutTime(1000, MafiaNet::UNASSIGNED_SYSTEM_ADDRESS); - printf("Our guid is %s\n", rakPeer[i]->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("Our guid is %s\n", MafiaNet::to_string(rakPeer[i]->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS)).c_str()); } for (unsigned short i=0; i < NUM_PEERS; i++) @@ -85,12 +86,12 @@ int main() case ID_NEW_INCOMING_CONNECTION: // Somebody connected. We have their IP now - printf("%i. ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", i, packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("%i. ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", i, packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); break; case ID_CONNECTION_REQUEST_ACCEPTED: // Somebody connected. We have their IP now - printf("%i. ID_CONNECTION_REQUEST_ACCEPTED from %s. guid=%s.\n", i, packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("%i. ID_CONNECTION_REQUEST_ACCEPTED from %s. guid=%s.\n", i, packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); break; @@ -105,7 +106,7 @@ int main() if (packet->systemAddress== MafiaNet::UNASSIGNED_SYSTEM_ADDRESS) printf("%i. Got new host (ourselves)\n", i); else - printf("%i. Got new host %s, %s\n", i, packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("%i. Got new host %s, %s\n", i, packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); break; } } @@ -129,9 +130,9 @@ int main() hostGuid=fcm2[i].GetHostSystem(); if (weAreHost) - printf("%i. %iP myGuid=%s, hostGuid=%s tcc=%i (Y)\n",i, participantList, rakPeer[i]->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString(), hostGuid.ToString(), fcm2[i].GetTotalConnectionCount()); + printf("%i. %iP myGuid=%s, hostGuid=%s tcc=%i (Y)\n",i, participantList, MafiaNet::to_string(rakPeer[i]->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS)).c_str(), MafiaNet::to_string(hostGuid).c_str(), fcm2[i].GetTotalConnectionCount()); else - printf("%i. %iP myGuid=%s, hostGuid=%s tcc=%i (N)\n",i, participantList, rakPeer[i]->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString(), hostGuid.ToString(), fcm2[i].GetTotalConnectionCount()); + printf("%i. %iP myGuid=%s, hostGuid=%s tcc=%i (N)\n",i, participantList, MafiaNet::to_string(rakPeer[i]->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS)).c_str(), MafiaNet::to_string(hostGuid).c_str(), fcm2[i].GetTotalConnectionCount()); } } if (ch=='d' || ch=='D') diff --git a/Samples/FCMVerifiedJoinSimultaneous/FCM2VerifiedJoinSimultaneousTest.cpp b/Samples/FCMVerifiedJoinSimultaneous/FCM2VerifiedJoinSimultaneousTest.cpp index d20376ff8..b2c1f0d00 100644 --- a/Samples/FCMVerifiedJoinSimultaneous/FCM2VerifiedJoinSimultaneousTest.cpp +++ b/Samples/FCMVerifiedJoinSimultaneous/FCM2VerifiedJoinSimultaneousTest.cpp @@ -29,6 +29,7 @@ #include "mafianet/PacketLogger.h" #include "mafianet/Gets.h" #include "mafianet/BitStream.h" +#include "mafianet/guid_util.h" using namespace MafiaNet; @@ -38,7 +39,7 @@ MafiaNet::RakPeerInterface *rakPeer[NUM_PEERS]; class FullyConnectedMesh2_UserData : public FullyConnectedMesh2 { virtual void WriteVJCUserData(MafiaNet::BitStream *bsOut) {bsOut->Write(RakString("WriteVJCUserData test"));} - virtual void WriteVJSUserData(MafiaNet::BitStream *bsOut, RakNetGUID userGuid) {bsOut->Write(RakString("WriteVJSUserData test, userGuid=%s", userGuid.ToString()));} + virtual void WriteVJSUserData(MafiaNet::BitStream *bsOut, RakNetGUID userGuid) {bsOut->Write(RakString("WriteVJSUserData test, userGuid=%s", MafiaNet::to_string(userGuid).c_str()));} }; int main() @@ -56,7 +57,7 @@ int main() SLNET_VERIFY(rakPeer[i]->Startup(NUM_PEERS, &sd, 1) == RAKNET_STARTED); rakPeer[i]->SetMaximumIncomingConnections(NUM_PEERS); rakPeer[i]->SetTimeoutTime(1000, MafiaNet::UNASSIGNED_SYSTEM_ADDRESS); - printf("%i. Our guid is %s\n", i, rakPeer[i]->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("%i. Our guid is %s\n", i, MafiaNet::to_string(rakPeer[i]->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS)).c_str()); } RakSleep(100); @@ -87,14 +88,14 @@ int main() { case ID_FCM2_VERIFIED_JOIN_START: { - printf("%s: Got ID_FCM2_VERIFIED_JOIN_START from %s. address=", rakPeer[peerIndex]->GetMyGUID().ToString(), packet->guid.ToString()); + printf("%s: Got ID_FCM2_VERIFIED_JOIN_START from %s. address=", MafiaNet::to_string(rakPeer[peerIndex]->GetMyGUID()).c_str(), MafiaNet::to_string(packet->guid).c_str()); DataStructures::List addresses; DataStructures::List guids; DataStructures::List userData; fcm2[peerIndex].GetVerifiedJoinRequiredProcessingList(packet->guid, addresses, guids, userData); for (unsigned int i=0; i < guids.Size(); i++) { - printf("%s:", guids[i].ToString()); + printf("%s:", MafiaNet::to_string(guids[i]).c_str()); ConnectionAttemptResult car = rakPeer[peerIndex]->Connect(addresses[i].ToString(false), addresses[i].GetPort(), 0, 0); switch (car) { @@ -121,7 +122,7 @@ int main() break; case ID_FCM2_VERIFIED_JOIN_FAILED: - printf("%s: ID_FCM2_VERIFIED_JOIN_FAILED from %s\n", rakPeer[peerIndex]->GetMyGUID().ToString(), packet->guid.ToString()); + printf("%s: ID_FCM2_VERIFIED_JOIN_FAILED from %s\n", MafiaNet::to_string(rakPeer[peerIndex]->GetMyGUID()).c_str(), MafiaNet::to_string(packet->guid).c_str()); break; case ID_FCM2_VERIFIED_JOIN_CAPABLE: @@ -131,7 +132,7 @@ int main() RakString testStr; bs.Read(testStr); - printf("%s: ID_FCM2_VERIFIED_JOIN_CAPABLE from %s\n", rakPeer[peerIndex]->GetMyGUID().ToString(), packet->guid.ToString()); + printf("%s: ID_FCM2_VERIFIED_JOIN_CAPABLE from %s\n", MafiaNet::to_string(rakPeer[peerIndex]->GetMyGUID()).c_str(), MafiaNet::to_string(packet->guid).c_str()); printf("STR: %s\n", testStr.C_String()); fcm2[peerIndex].RespondOnVerifiedJoinCapable(packet, true, 0); } @@ -145,21 +146,21 @@ int main() fcm2[peerIndex].GetVerifiedJoinAcceptedAdditionalData(packet, &thisSystemAccepted, systemsAccepted, &additionalData); if (thisSystemAccepted) { - printf("%s: ID_FCM2_VERIFIED_JOIN_ACCEPTED from %s. systemsAccepted=", rakPeer[peerIndex]->GetMyGUID().ToString(), packet->guid.ToString()); + printf("%s: ID_FCM2_VERIFIED_JOIN_ACCEPTED from %s. systemsAccepted=", MafiaNet::to_string(rakPeer[peerIndex]->GetMyGUID()).c_str(), MafiaNet::to_string(packet->guid).c_str()); for (unsigned int i=0; i < systemsAccepted.Size(); i++) - printf("%s ", systemsAccepted[i].ToString()); + printf("%s ", MafiaNet::to_string(systemsAccepted[i]).c_str()); printf("\n"); } break; } case ID_FCM2_VERIFIED_JOIN_REJECTED: - printf("%s: ID_FCM2_VERIFIED_JOIN_REJECTED from %s\n", rakPeer[peerIndex]->GetMyGUID().ToString(), packet->guid.ToString()); + printf("%s: ID_FCM2_VERIFIED_JOIN_REJECTED from %s\n", MafiaNet::to_string(rakPeer[peerIndex]->GetMyGUID()).c_str(), MafiaNet::to_string(packet->guid).c_str()); rakPeer[peerIndex]->CloseConnection(packet->guid, true); break; default: - printf("%s: %s from %s\n", rakPeer[peerIndex]->GetMyGUID().ToString(), PacketLogger::BaseIDTOString(packet->data[0]), packet->guid.ToString()); + printf("%s: %s from %s\n", MafiaNet::to_string(rakPeer[peerIndex]->GetMyGUID()).c_str(), PacketLogger::BaseIDTOString(packet->data[0]), MafiaNet::to_string(packet->guid).c_str()); } } } diff --git a/Samples/LANServerDiscovery/LANServerDiscovery.cpp b/Samples/LANServerDiscovery/LANServerDiscovery.cpp index c792c1a8f..be0bbba1e 100644 --- a/Samples/LANServerDiscovery/LANServerDiscovery.cpp +++ b/Samples/LANServerDiscovery/LANServerDiscovery.cpp @@ -34,6 +34,7 @@ #include "mafianet/Gets.h" #include "mafianet/linux_adapter.h" #include "mafianet/osx_adapter.h" +#include "mafianet/guid_util.h" int main(void) { @@ -161,11 +162,11 @@ int main(void) } else if (p->data[0]==ID_UNCONNECTED_PING) { - printf("ID_UNCONNECTED_PING from %s\n",p->guid.ToString()); + printf("ID_UNCONNECTED_PING from %s\n",MafiaNet::to_string(p->guid).c_str()); } else if (p->data[0]==ID_UNCONNECTED_PING_OPEN_CONNECTIONS) { - printf("ID_UNCONNECTED_PING_OPEN_CONNECTIONS from %s\n",p->guid.ToString()); + printf("ID_UNCONNECTED_PING_OPEN_CONNECTIONS from %s\n",MafiaNet::to_string(p->guid).c_str()); } client->DeallocatePacket(p); } diff --git a/Samples/NATCompleteClient/main.cpp b/Samples/NATCompleteClient/main.cpp index 91840541c..f987a5bb0 100644 --- a/Samples/NATCompleteClient/main.cpp +++ b/Samples/NATCompleteClient/main.cpp @@ -33,6 +33,7 @@ #include "mafianet/Itoa.h" #include "mafianet/linux_adapter.h" #include "mafianet/osx_adapter.h" +#include "mafianet/guid_util.h" // To include miniupnp, see Samples\NATCompleteClient\readme.txt #include "miniupnpc.h" @@ -428,7 +429,7 @@ struct NatPunchthoughClientFramework : public SampleFramework, public NatPunchth else { printf("Listening\n"); - printf("My GUID is %s\n", rakPeer->GetMyGUID().ToString()); + printf("My GUID is %s\n", MafiaNet::to_string(rakPeer->GetMyGUID()).c_str()); isListening=true; // Find the stride of our router in advance @@ -657,7 +658,7 @@ struct UDPProxyClientFramework : public SampleFramework, public UDPProxyClientRe else { printf("Listening\n"); - printf("My GUID is %s\n", rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("My GUID is %s\n", MafiaNet::to_string(rakPeer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS)).c_str()); isListening=true; } @@ -818,7 +819,7 @@ void PrintPacketMessages(Packet *packet, RakPeerInterface *rakPeer) case ID_CONNECTION_REQUEST_ACCEPTED: // This tells the client they have connected - printf("ID_CONNECTION_REQUEST_ACCEPTED to %s with GUID %s\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_CONNECTION_REQUEST_ACCEPTED to %s with GUID %s\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); printf("My external address is %s\n", rakPeer->GetExternalID(packet->systemAddress).ToString(true)); break; } diff --git a/Samples/OfflineMessagesTest/OfflineMessagesTest.cpp b/Samples/OfflineMessagesTest/OfflineMessagesTest.cpp index c8643dc68..056a47563 100644 --- a/Samples/OfflineMessagesTest/OfflineMessagesTest.cpp +++ b/Samples/OfflineMessagesTest/OfflineMessagesTest.cpp @@ -22,6 +22,7 @@ #include "mafianet/MessageIdentifiers.h" #include "mafianet/GetTime.h" #include "mafianet/Gets.h" +#include "mafianet/guid_util.h" #ifdef _WIN32 #include "mafianet/WindowsIncludes.h" // Sleep @@ -50,8 +51,8 @@ int main(void) peer2->Startup(1, &socketDescriptor, 1); peer1->SetOfflinePingResponse("Offline Ping Data", (int)strlen("Offline Ping Data")+1); - printf("Peer 1 guid = %s\n", peer1->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); - printf("Peer 2 guid = %s\n", peer2->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("Peer 1 guid = %s\n", MafiaNet::to_string(peer1->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS)).c_str()); + printf("Peer 2 guid = %s\n", MafiaNet::to_string(peer2->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS)).c_str()); printf("Systems started. Waiting for advertise system packet\n"); // Wait for connection to complete @@ -61,7 +62,7 @@ int main(void) usleep(300 * 1000); #endif - printf("Sending advertise system from %s\n", peer1->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("Sending advertise system from %s\n", MafiaNet::to_string(peer1->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS)).c_str()); peer1->AdvertiseSystem("127.0.0.1", 60002,"hello world", (int)strlen("hello world")+1); while (nextTest!=2) @@ -76,9 +77,9 @@ int main(void) printf("Got Advertise system with data: %s\n", packet->data+1); else printf("Got Advertise system with no data\n"); - printf("Was sent from GUID %s\n", packet->guid.ToString()); + printf("Was sent from GUID %s\n", MafiaNet::to_string(packet->guid).c_str()); - printf("Sending ping from %s\n", peer2->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("Sending ping from %s\n", MafiaNet::to_string(peer2->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS)).c_str()); peer2->Ping("127.0.0.1", 60001, false); nextTest++; } @@ -96,7 +97,7 @@ int main(void) else printf( "ID_UNCONNECTED_PONG from"); printf(" %s on %p.\nPing is %i\nData is %i bytes long.\n", packet->systemAddress.ToString(), peer2, curTime-packetTime, dataLength ); - printf("Was sent from GUID %s\n", packet->guid.ToString()); + printf("Was sent from GUID %s\n", MafiaNet::to_string(packet->guid).c_str()); if ( dataLength > 0 ) { diff --git a/Samples/RakVoice/main.cpp b/Samples/RakVoice/main.cpp index 2b737ac30..aafca026c 100644 --- a/Samples/RakVoice/main.cpp +++ b/Samples/RakVoice/main.cpp @@ -30,6 +30,7 @@ #include "mafianet/Gets.h" #include "mafianet/linux_adapter.h" #include "mafianet/osx_adapter.h" +#include "mafianet/guid_util.h" /// To test sending to myself. Also uncomment in RakVoice.cpp //#define _TEST_LOOPBACK @@ -160,7 +161,7 @@ int main(void) MafiaNet::SystemAddress facilitator; if (useNatPunchthrough) { - printf("My GUID is %s\n", rakPeer->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("My GUID is %s\n", MafiaNet::to_string(rakPeer->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS)).c_str()); printf("Enter IP of facilitator (enter for default): "); Gets(facilitatorIP,sizeof(facilitatorIP)); @@ -297,7 +298,7 @@ int main(void) MafiaNet::BitStream b(p->data, p->length, false); b.IgnoreBits(8); // Ignore the ID_... b.Read(g); - printf("ID_NAT_TARGET_NOT_CONNECTED for %s\n", g.ToString()); + printf("ID_NAT_TARGET_NOT_CONNECTED for %s\n", MafiaNet::to_string(g).c_str()); } else if (p->data[0]==ID_NAT_TARGET_UNRESPONSIVE) { @@ -305,7 +306,7 @@ int main(void) MafiaNet::BitStream b(p->data, p->length, false); b.IgnoreBits(8); // Ignore the ID_... b.Read(g); - printf("ID_NAT_TARGET_UNRESPONSIVE for %s\n", g.ToString()); + printf("ID_NAT_TARGET_UNRESPONSIVE for %s\n", MafiaNet::to_string(g).c_str()); } else if (p->data[0]==ID_NAT_CONNECTION_TO_TARGET_LOST) { @@ -313,7 +314,7 @@ int main(void) MafiaNet::BitStream b(p->data, p->length, false); b.IgnoreBits(8); // Ignore the ID_... b.Read(g); - printf("ID_NAT_CONNECTION_TO_TARGET_LOST for %s\n", g.ToString()); + printf("ID_NAT_CONNECTION_TO_TARGET_LOST for %s\n", MafiaNet::to_string(g).c_str()); } else if (p->data[0]==ID_NAT_ALREADY_IN_PROGRESS) { @@ -321,15 +322,15 @@ int main(void) MafiaNet::BitStream b(p->data, p->length, false); b.IgnoreBits(8); // Ignore the ID_... b.Read(g); - printf("ID_NAT_ALREADY_IN_PROGRESS for %s\n", g.ToString()); + printf("ID_NAT_ALREADY_IN_PROGRESS for %s\n", MafiaNet::to_string(g).c_str()); } else if (p->data[0]==ID_NAT_PUNCHTHROUGH_FAILED) { - printf("ID_NAT_PUNCHTHROUGH_FAILED for %s\n", p->guid.ToString()); + printf("ID_NAT_PUNCHTHROUGH_FAILED for %s\n", MafiaNet::to_string(p->guid).c_str()); } else if (p->data[0]==ID_NAT_PUNCHTHROUGH_SUCCEEDED) { - printf("ID_NAT_PUNCHTHROUGH_SUCCEEDED for %s. Connecting...\n", p->guid.ToString()); + printf("ID_NAT_PUNCHTHROUGH_SUCCEEDED for %s. Connecting...\n", MafiaNet::to_string(p->guid).c_str()); rakPeer->Connect(p->systemAddress.ToString(false),p->systemAddress.GetPort(),0,0); } else if (p->data[0]==ID_ALREADY_CONNECTED) diff --git a/Samples/ReadyEvent/ReadyEventSample.cpp b/Samples/ReadyEvent/ReadyEventSample.cpp index 50c18e8fe..e53493838 100644 --- a/Samples/ReadyEvent/ReadyEventSample.cpp +++ b/Samples/ReadyEvent/ReadyEventSample.cpp @@ -31,6 +31,7 @@ #include "mafianet/linux_adapter.h" #include "mafianet/osx_adapter.h" #include "mafianet/Gets.h" +#include "mafianet/guid_util.h" void PrintConnections(); @@ -204,15 +205,15 @@ int main(void) readyEventPlugin.AddToWaitList(0, p->guid); break; case ID_READY_EVENT_ALL_SET: - printf("Got ID_READY_EVENT_ALL_SET from %s\n", p->guid.ToString()); + printf("Got ID_READY_EVENT_ALL_SET from %s\n", MafiaNet::to_string(p->guid).c_str()); break; case ID_READY_EVENT_SET: - printf("Got ID_READY_EVENT_SET from %s\n", p->guid.ToString()); + printf("Got ID_READY_EVENT_SET from %s\n", MafiaNet::to_string(p->guid).c_str()); break; case ID_READY_EVENT_UNSET: - printf("Got ID_READY_EVENT_UNSET from %s\n", p->guid.ToString()); + printf("Got ID_READY_EVENT_UNSET from %s\n", MafiaNet::to_string(p->guid).c_str()); break; case ID_DISCONNECTION_NOTIFICATION: diff --git a/Samples/ReplicaManager3/main.cpp b/Samples/ReplicaManager3/main.cpp index 3305d54b9..e211f0a35 100644 --- a/Samples/ReplicaManager3/main.cpp +++ b/Samples/ReplicaManager3/main.cpp @@ -36,6 +36,7 @@ #include "mafianet/Gets.h" #include "mafianet/linux_adapter.h" #include "mafianet/osx_adapter.h" +#include "mafianet/guid_util.h" enum { @@ -508,7 +509,7 @@ int main(void) rakPeer->AttachPlugin(&replicaManager); replicaManager.SetNetworkIDManager(&networkIdManager); rakPeer->SetMaximumIncomingConnections(32); - printf("\nMy GUID is %s\n", rakPeer->GetMyGUID().ToString()); + printf("\nMy GUID is %s\n", MafiaNet::to_string(rakPeer->GetMyGUID()).c_str()); printf("\n"); if (topology==CLIENT) diff --git a/Samples/ReplicatedLogin/ReplicatedLogin.cpp b/Samples/ReplicatedLogin/ReplicatedLogin.cpp index ee52d7bef..a6d2f63d3 100644 --- a/Samples/ReplicatedLogin/ReplicatedLogin.cpp +++ b/Samples/ReplicatedLogin/ReplicatedLogin.cpp @@ -23,6 +23,7 @@ #include "mafianet/ReplicaManager3.h" #include "mafianet/peerinterface.h" #include "mafianet/NetworkIDManager.h" +#include "mafianet/guid_util.h" using namespace MafiaNet; @@ -262,17 +263,17 @@ int serverMain(void) switch (packet->data[0]) { case ID_NEW_INCOMING_CONNECTION: - printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); break; case ID_CONNECTION_REQUEST_ACCEPTED: - printf("ID_CONNECTION_REQUEST_ACCEPTED from %s,guid=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_CONNECTION_REQUEST_ACCEPTED from %s,guid=%s\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); break; case ID_CONNECTION_LOST: - printf("ID_CONNECTION_LOST from %s,guid=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_CONNECTION_LOST from %s,guid=%s\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); User::DeleteUserWithGuid(packet->guid); break; case ID_DISCONNECTION_NOTIFICATION: - printf("ID_DISCONNECTION_NOTIFICATION from %s,guid=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_DISCONNECTION_NOTIFICATION from %s,guid=%s\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); User::DeleteUserWithGuid(packet->guid); break; // Login @@ -317,25 +318,25 @@ int clientMain(void) switch (packet->data[0]) { case ID_NEW_INCOMING_CONNECTION: - printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); break; case ID_CONNECTION_REQUEST_ACCEPTED: { - printf("ID_CONNECTION_REQUEST_ACCEPTED from %s,guid=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_CONNECTION_REQUEST_ACCEPTED from %s,guid=%s\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); printf("Logging in...\n"); BitStream bsOut; // Login bsOut.WriteCasted(ID_USER_PACKET_ENUM); - RakString username("User %s", rakPeer->GetMyGUID().ToString()); + RakString username("User %s", MafiaNet::to_string(rakPeer->GetMyGUID()).c_str()); bsOut.Write(username); rakPeer->Send(&bsOut, MafiaNet::Priority::High, MafiaNet::Reliability::ReliableOrdered, 0, packet->guid, false); } break; case ID_CONNECTION_LOST: - printf("ID_CONNECTION_LOST from %s,guid=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_CONNECTION_LOST from %s,guid=%s\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); break; case ID_DISCONNECTION_NOTIFICATION: - printf("ID_DISCONNECTION_NOTIFICATION from %s,guid=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_DISCONNECTION_NOTIFICATION from %s,guid=%s\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); break; } } diff --git a/Samples/Router2/Router2Sample.cpp b/Samples/Router2/Router2Sample.cpp index aaf38c649..ad87df28c 100644 --- a/Samples/Router2/Router2Sample.cpp +++ b/Samples/Router2/Router2Sample.cpp @@ -31,6 +31,7 @@ #include "mafianet/Gets.h" #include "mafianet/linux_adapter.h" #include "mafianet/osx_adapter.h" +#include "mafianet/guid_util.h" using namespace MafiaNet; @@ -73,7 +74,7 @@ void ReadAllPackets(void) MafiaNet::BitStream bs(packet->data, packet->length, false); bs.IgnoreBytes(sizeof(MessageID)); bs.Read(endpointGuid); - printf("Routing through %s to %s successful. Connecting.\n", str, endpointGuid.ToString()); + printf("Routing through %s to %s successful. Connecting.\n", str, MafiaNet::to_string(endpointGuid).c_str()); unsigned short sourceToDestPort; bs.Read(sourceToDestPort); char ipAddressString[32]; diff --git a/Samples/SteamLobby/main.cpp b/Samples/SteamLobby/main.cpp index 5e326f8e3..426c2b359 100644 --- a/Samples/SteamLobby/main.cpp +++ b/Samples/SteamLobby/main.cpp @@ -27,6 +27,7 @@ #include #include "mafianet/Gets.h" #include "mafianet/FullyConnectedMesh2.h" +#include "mafianet/guid_util.h" #pragma warning( push ) #pragma warning(disable:4127) // conditional expression is constant (with Steamworks 1.23a) #include "steam_api.h" @@ -179,7 +180,7 @@ int main(int argc, char **argv) case ID_CONNECTION_REQUEST_ACCEPTED: // This tells the client they have connected - printf("ID_CONNECTION_REQUEST_ACCEPTED to %s with GUID %s\n", packet->systemAddress.ToString(), packet->guid.ToString()); + printf("ID_CONNECTION_REQUEST_ACCEPTED to %s with GUID %s\n", packet->systemAddress.ToString(), MafiaNet::to_string(packet->guid).c_str()); break; case ID_NEW_INCOMING_CONNECTION: @@ -191,14 +192,14 @@ int main(int argc, char **argv) if (packet->systemAddress== MafiaNet::UNASSIGNED_SYSTEM_ADDRESS) printf("Got new host (ourselves)"); else - printf("Got new host %s, GUID=%s", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("Got new host %s, GUID=%s", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); MafiaNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(1); RakNetGUID oldHost; bs.Read(oldHost); // If the old host is different, then this message was due to losing connection to the host. if (oldHost!=packet->guid) - printf(". Oldhost Guid=%s\n", oldHost.ToString()); + printf(". Oldhost Guid=%s\n", MafiaNet::to_string(oldHost).c_str()); else printf("\n"); } diff --git a/Samples/TeamManager/TeamManagerTest.cpp b/Samples/TeamManager/TeamManagerTest.cpp index 550843d4a..11a9e62ed 100644 --- a/Samples/TeamManager/TeamManagerTest.cpp +++ b/Samples/TeamManager/TeamManagerTest.cpp @@ -31,6 +31,7 @@ #include "mafianet/NetworkIDManager.h" #include "mafianet/osx_adapter.h" #include "mafianet/Gets.h" +#include "mafianet/guid_util.h" using namespace MafiaNet; @@ -441,7 +442,7 @@ int main(void) // Setup my own User *user = new User; - user->userName = rakPeer->GetMyGUID().ToString(); + user->userName = MafiaNet::to_string(rakPeer->GetMyGUID()).c_str(); // Inform ReplicaManager3 of my user replicaManager3->Reference(user); @@ -457,7 +458,7 @@ int main(void) SLNET_VERIFY(rakPeer->Startup(8, &sd, 1) == RAKNET_STARTED); rakPeer->SetMaximumIncomingConnections(8); rakPeer->SetTimeoutTime(30000, MafiaNet::UNASSIGNED_SYSTEM_ADDRESS); - printf("Our guid is %s\n", rakPeer->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("Our guid is %s\n", MafiaNet::to_string(rakPeer->GetGuidFromSystemAddress(MafiaNet::UNASSIGNED_SYSTEM_ADDRESS)).c_str()); printf("Started on %s\n", rakPeer->GetMyBoundAddress().ToString(true)); for (unsigned short i=0; i < 32; i++) @@ -483,7 +484,7 @@ int main(void) break; case ID_NEW_INCOMING_CONNECTION: { - printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); // Add mid-game joins to ReplicaManager3 as long as we know who the host is if (fullyConnectedMesh2->GetConnectedHost()!=UNASSIGNED_RAKNET_GUID) { @@ -494,7 +495,7 @@ int main(void) break; case ID_CONNECTION_REQUEST_ACCEPTED: { - printf("ID_CONNECTION_REQUEST_ACCEPTED from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("ID_CONNECTION_REQUEST_ACCEPTED from %s. guid=%s.\n", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); // Add mid-game joins to ReplicaManager3 as long as we know who the host is if (fullyConnectedMesh2->GetConnectedHost()!=UNASSIGNED_RAKNET_GUID) { @@ -515,14 +516,14 @@ int main(void) if (packet->guid==rakPeer->GetMyGUID()) printf("Got new host (ourselves)"); else - printf("Got new host %s, GUID=%s", packet->systemAddress.ToString(true), packet->guid.ToString()); + printf("Got new host %s, GUID=%s", packet->systemAddress.ToString(true), MafiaNet::to_string(packet->guid).c_str()); MafiaNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(1); RakNetGUID oldHost; bs.Read(oldHost); // If the old host is different, then this message was due to losing connection to the host. if (oldHost!=packet->guid) - printf(". Oldhost Guid=%s\n", oldHost.ToString()); + printf(". Oldhost Guid=%s\n", MafiaNet::to_string(oldHost).c_str()); else printf("\n"); diff --git a/Samples/Tests/DisconnectReasonTest.cpp b/Samples/Tests/DisconnectReasonTest.cpp index 8ab1e0f37..8530341ab 100644 --- a/Samples/Tests/DisconnectReasonTest.cpp +++ b/Samples/Tests/DisconnectReasonTest.cpp @@ -16,6 +16,33 @@ using namespace MafiaNet; namespace { + // How many times to retry a full connect -> close -> receive cycle before + // declaring failure. Delivering ID_DISCONNECTION_NOTIFICATION to Receive() + // depends on a reliable ACK round-trip completing, which in turn needs both + // peers' internal network threads to be scheduled. On a CPU-starved CI runner + // running the whole suite in one process, a single cycle can intermittently + // miss its window even with a generous timeout. Re-driving a fresh exchange + // recovers from that transient starvation. Wrong-payload failures are NOT + // retried (see below), so this only absorbs transient misses, never real bugs. + const int kMaxAttempts = 3; + // Per-attempt wait for the notification. Comfortably above a healthy loopback + // round-trip (milliseconds) even under load, and bounded so kMaxAttempts + // attempts can't stall CI for long on a genuine failure. + const int kReceiveTimeoutMs = 12000; + + // TryDisconnectCase outcomes. Non-negative values are concrete ErrorCodeToString + // codes; negative values are transient signals the caller may retry. + const int kTransientNeverReceived = -1; // connected, but notification never surfaced + const int kTransientConnectFailed = -2; // never established the connection + + SystemAddress LoopbackServerAddress(unsigned short serverPort) + { + SystemAddress serverAddr; + serverAddr.SetBinaryAddress("127.0.0.1"); + serverAddr.SetPortHostOrder(serverPort); + return serverAddr; + } + // Connect the client to the server over loopback and return the client's // guid as observed by the server (via ID_NEW_INCOMING_CONNECTION). Returns // UNASSIGNED_RAKNET_GUID on failure. @@ -32,6 +59,138 @@ namespace server->DeallocatePacket(inc); return clientGuid; } + + // Force both peers to drop any connection between them and drain their queues, + // so a fresh connect can succeed. Used between cases and between retry attempts. + // Closes silently (no notification) on both sides: after a transient miss the + // server may still hold the connection (waiting for an ACK that never came), + // which would make the client's reconnect race against an "already connected" + // rejection. Explicitly tearing down both sides removes that race. + void ResetConnection(RakPeerInterface *server, RakPeerInterface *client, const RakNetGUID &clientGuid, unsigned short serverPort) + { + SystemAddress serverAddr = LoopbackServerAddress(serverPort); + client->CloseConnection(serverAddr, false); + if (clientGuid != UNASSIGNED_RAKNET_GUID) + server->CloseConnection(clientGuid, false); + + TimeMS entry = GetTimeMS(); + while (GetTimeMS() - entry < 10000) + { + Packet *p; + for (p = client->Receive(); p; client->DeallocatePacket(p), p = client->Receive()) + ; + for (p = server->Receive(); p; server->DeallocatePacket(p), p = server->Receive()) + ; + if (!CommonFunctions::ConnectionStateMatchesOptions(client, serverAddr, true, true, true, true)) + break; + RakSleep(30); + } + } + + // Run one connect -> CloseConnection(reason) -> receive-notification cycle and + // verify the delivered notification. + // + // Returns: + // 0 success (notification delivered and verified) + // kTransientConnectFailed never connected — caller may retry + // kTransientNeverReceived connected, no notification — caller may retry + // > 0 hard verification failure (wrong payload) — do NOT retry + // + // On every non-success path the connection is reset, leaving a clean slate for + // a retry or the next case. + int TryDisconnectCase(RakPeerInterface *server, RakPeerInterface *client, unsigned short serverPort, + const MafiaNet::BitStream *reasonData, bool expectPayload, + unsigned char expectCode, const RakString &expectText, + int noPayloadErr, int deserialErr, int codeErr, int textErr, + bool isVerbose, const char *okMsg) + { + RakNetGUID clientGuid = ConnectAndGetClientGuid(server, client, serverPort); + if (clientGuid == UNASSIGNED_RAKNET_GUID) + { + ResetConnection(server, client, clientGuid, serverPort); + return kTransientConnectFailed; + } + + server->CloseConnection(clientGuid, true, 0, MafiaNet::Priority::Low, reasonData); + + Packet *note = CommonFunctions::WaitAndReturnMessageWithID(client, ID_DISCONNECTION_NOTIFICATION, kReceiveTimeoutMs); + if (note == 0) + { + // Transient: the reliable round-trip didn't surface the notification in + // time. A fresh exchange (retry) typically recovers under load. + ResetConnection(server, client, clientGuid, serverPort); + return kTransientNeverReceived; + } + + if (!expectPayload) + { + // Default / empty reason: the notification must be a bare 1-byte message. + unsigned int len = note->length; + client->DeallocatePacket(note); + ResetConnection(server, client, clientGuid, serverPort); + if (len != 1) + return noPayloadErr; // hard failure: payload present when none was sent + if (isVerbose) + printf("%s\n", okMsg); + return 0; + } + + // Reason supplied: the notification must carry more than the bare 1-byte ID. + if (note->length <= 1) + { + client->DeallocatePacket(note); + ResetConnection(server, client, clientGuid, serverPort); + return noPayloadErr; + } + + // The body after the ID must round-trip the exact reason we sent. + BitStream readBack(note->data + 1, note->length - 1, false); + unsigned char gotCode = 0; + RakString gotText; + readBack.Read(gotCode); + bool textOk = gotText.Deserialize(&readBack); + client->DeallocatePacket(note); + ResetConnection(server, client, clientGuid, serverPort); + + // Content mismatches are hard failures: a real regression in the reason + // payload would fail these identically on every attempt, so they are never + // retried away. + if (!textOk) + return deserialErr; + if (gotCode != expectCode) + return codeErr; + if (gotText != expectText) + return textErr; + + if (isVerbose) + printf("%s code=%u text=\"%s\"\n", okMsg, (unsigned)gotCode, gotText.C_String()); + return 0; + } + + // Run a case with bounded retries. Transient outcomes are retried up to + // kMaxAttempts; a hard verification failure returns immediately. If every + // attempt is transient, the dominant CI symptom (never received) is reported, + // or the connect failure if we never managed to connect on the last attempt. + int RunDisconnectCaseWithRetries(RakPeerInterface *server, RakPeerInterface *client, unsigned short serverPort, + const MafiaNet::BitStream *reasonData, bool expectPayload, + unsigned char expectCode, const RakString &expectText, + int connectErr, int neverReceivedErr, + int noPayloadErr, int deserialErr, int codeErr, int textErr, + bool isVerbose, const char *okMsg) + { + int lastTransient = kTransientNeverReceived; + for (int attempt = 0; attempt < kMaxAttempts; ++attempt) + { + int result = TryDisconnectCase(server, client, serverPort, reasonData, expectPayload, + expectCode, expectText, noPayloadErr, deserialErr, codeErr, textErr, isVerbose, okMsg); + if (result >= 0) + return result; // success (0) or hard failure (> 0) + lastTransient = result; + if (isVerbose && attempt + 1 < kMaxAttempts) + printf("(transient miss, retrying %d/%d)\n", attempt + 2, kMaxAttempts); + } + return (lastTransient == kTransientConnectFailed) ? connectErr : neverReceivedErr; + } } int DisconnectReasonTest::RunTest(DataStructures::List params, bool isVerbose, bool noPauses) @@ -64,20 +223,16 @@ int DisconnectReasonTest::RunTest(DataStructures::List params, bool i // Keep connections alive well past the default 10s timeout. The whole suite // runs in one process and CI runners are CPU-starved; if a peer's internal - // thread is starved the connection can time out at ~10s — right as our 10s - // receive wait expires — and the reliable disconnect notification (still being - // retransmitted from the resend buffer) is dropped when the connection dies. - // A generous timeout lets the notification get through under load; it costs - // nothing on a healthy run, where it arrives in milliseconds. + // thread is starved the connection can time out at ~10s and the reliable + // disconnect notification (still being retransmitted from the resend buffer) + // is dropped when the connection dies. A generous timeout lets the + // notification get through under load; it costs nothing on a healthy run, + // where it arrives in milliseconds. server->SetTimeoutTime(30000, UNASSIGNED_SYSTEM_ADDRESS); client->SetTimeoutTime(30000, UNASSIGNED_SYSTEM_ADDRESS); // --- Case 1: graceful disconnect WITH a reason payload --- { - RakNetGUID clientGuid = ConnectAndGetClientGuid(server, client, serverPort); - if (clientGuid == UNASSIGNED_RAKNET_GUID) - return 3; - // A representative reason: an enum code plus an admin-typed custom string, // exactly the "Kicked: " use case the feature targets. const unsigned char kReasonCode = 7; @@ -87,119 +242,40 @@ int DisconnectReasonTest::RunTest(DataStructures::List params, bool i reason.Write(kReasonCode); kReasonText.Serialize(&reason); - server->CloseConnection(clientGuid, true, 0, MafiaNet::Priority::Low, &reason); - - Packet *note = CommonFunctions::WaitAndReturnMessageWithID(client, ID_DISCONNECTION_NOTIFICATION, 20000); - if (note == 0) - return 4; - - // The notification must carry more than the bare 1-byte ID. - if (note->length <= 1) - { - client->DeallocatePacket(note); - return 5; - } - - // The body after the ID must round-trip the exact reason we sent. - BitStream readBack(note->data + 1, note->length - 1, false); - unsigned char gotCode = 0; - RakString gotText; - readBack.Read(gotCode); - bool textOk = gotText.Deserialize(&readBack); - client->DeallocatePacket(note); - - if (!textOk) - return 6; - if (gotCode != kReasonCode) - return 7; - if (gotText != kReasonText) - return 8; - - if (isVerbose) - printf("Case 1 OK: reason code=%u text=\"%s\" delivered.\n", (unsigned)gotCode, gotText.C_String()); - } - - // Make sure the client has fully torn down before reconnecting on the same port. - { - SystemAddress serverAddr; - serverAddr.SetBinaryAddress("127.0.0.1"); - serverAddr.SetPortHostOrder(serverPort); - TimeMS entry = GetTimeMS(); - while (CommonFunctions::ConnectionStateMatchesOptions(client, serverAddr, true, true, true, true) && GetTimeMS() - entry < 10000) - { - Packet *p; - for (p = client->Receive(); p; client->DeallocatePacket(p), p = client->Receive()) - ; - for (p = server->Receive(); p; server->DeallocatePacket(p), p = server->Receive()) - ; - RakSleep(30); - } + int err = RunDisconnectCaseWithRetries(server, client, serverPort, &reason, true, + kReasonCode, kReasonText, + /*connectErr*/ 3, /*neverReceivedErr*/ 4, /*noPayloadErr*/ 5, + /*deserialErr*/ 6, /*codeErr*/ 7, /*textErr*/ 8, + isVerbose, "Case 1 OK: reason delivered."); + if (err != 0) + return err; } // --- Case 2: graceful disconnect WITHOUT a reason (nullptr default) --- { - RakNetGUID clientGuid = ConnectAndGetClientGuid(server, client, serverPort); - if (clientGuid == UNASSIGNED_RAKNET_GUID) - return 9; - // Default reasonData == nullptr: notification must stay payload-less. - server->CloseConnection(clientGuid, true, 0, MafiaNet::Priority::Low); - - Packet *note = CommonFunctions::WaitAndReturnMessageWithID(client, ID_DISCONNECTION_NOTIFICATION, 20000); - if (note == 0) - return 10; - - unsigned int len = note->length; - client->DeallocatePacket(note); - - if (len != 1) - return 11; - - if (isVerbose) - printf("Case 2 OK: reasonless notification is a bare 1-byte message.\n"); - } - - // Make sure the client has fully torn down before reconnecting on the same port. - { - SystemAddress serverAddr; - serverAddr.SetBinaryAddress("127.0.0.1"); - serverAddr.SetPortHostOrder(serverPort); - TimeMS entry = GetTimeMS(); - while (CommonFunctions::ConnectionStateMatchesOptions(client, serverAddr, true, true, true, true) && GetTimeMS() - entry < 10000) - { - Packet *p; - for (p = client->Receive(); p; client->DeallocatePacket(p), p = client->Receive()) - ; - for (p = server->Receive(); p; server->DeallocatePacket(p), p = server->Receive()) - ; - RakSleep(30); - } + int err = RunDisconnectCaseWithRetries(server, client, serverPort, nullptr, false, + 0, RakString(), + /*connectErr*/ 9, /*neverReceivedErr*/ 10, /*noPayloadErr*/ 11, + /*deserialErr*/ 11, /*codeErr*/ 11, /*textErr*/ 11, + isVerbose, "Case 2 OK: reasonless notification is a bare 1-byte message."); + if (err != 0) + return err; } // --- Case 3: graceful disconnect with an EMPTY (non-null) reason BitStream --- { - RakNetGUID clientGuid = ConnectAndGetClientGuid(server, client, serverPort); - if (clientGuid == UNASSIGNED_RAKNET_GUID) - return 12; - // A non-null but empty BitStream exercises the GetNumberOfBytesUsed() > 0 // guard (distinct from the nullptr check): no bytes were written, so the // notification must stay payload-less just like the nullptr case. BitStream emptyReason; - server->CloseConnection(clientGuid, true, 0, MafiaNet::Priority::Low, &emptyReason); - - Packet *note = CommonFunctions::WaitAndReturnMessageWithID(client, ID_DISCONNECTION_NOTIFICATION, 20000); - if (note == 0) - return 13; - - unsigned int len = note->length; - client->DeallocatePacket(note); - - if (len != 1) - return 14; - - if (isVerbose) - printf("Case 3 OK: empty reason BitStream yields a bare 1-byte message.\n"); + int err = RunDisconnectCaseWithRetries(server, client, serverPort, &emptyReason, false, + 0, RakString(), + /*connectErr*/ 12, /*neverReceivedErr*/ 13, /*noPayloadErr*/ 14, + /*deserialErr*/ 14, /*codeErr*/ 14, /*textErr*/ 14, + isVerbose, "Case 3 OK: empty reason BitStream yields a bare 1-byte message."); + if (err != 0) + return err; } return 0; diff --git a/Samples/Tests/GuidUtilTest.cpp b/Samples/Tests/GuidUtilTest.cpp new file mode 100644 index 000000000..c9ecdd5d4 --- /dev/null +++ b/Samples/Tests/GuidUtilTest.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2026, MafiaHub + * + * This source code is licensed under the MIT-style license found in the + * license.txt file in the root directory of this source tree. + */ + +#include "GuidUtilTest.h" + +#include "mafianet/guid_util.h" +#include "mafianet/types.h" + +#include +#include +#include +#include + +using namespace MafiaNet; + +int GuidUtilTest::RunTest(DataStructures::List params, bool isVerbose, bool noPauses) +{ + (void) params; (void) noPauses; + + destroyList.Clear(false, _FILE_AND_LINE_); + + const uint64_t samples[] = { 0u, 1u, 42u, 0x123456789ABCDEF0ull, (uint64_t)-2 }; + const size_t sampleCount = sizeof(samples) / sizeof(samples[0]); + + // --- to_string matches the legacy thread-safe member, value-for-value --- + for (size_t i = 0; i < sampleCount; ++i) + { + const RakNetGUID g(samples[i]); + char buffer[64]; + g.ToString(buffer, sizeof(buffer)); + if (to_string(g) != std::string(buffer)) + { + if (isVerbose) printf("to_string(0x%llx)=\"%s\" != member ToString \"%s\"\n", + (unsigned long long) samples[i], to_string(g).c_str(), buffer); + return 1; + } + } + + // --- the UNASSIGNED sentinel stringifies to the documented label --- + if (to_string(UNASSIGNED_RAKNET_GUID) != std::string("UNASSIGNED_RAKNET_GUID")) + { + if (isVerbose) printf("to_string(UNASSIGNED_RAKNET_GUID)=\"%s\"\n", + to_string(UNASSIGNED_RAKNET_GUID).c_str()); + return 2; + } + + // --- thread-safety: many threads stringify distinct GUIDs concurrently --- + // The legacy member used a process-wide rotating static buffer, so two + // concurrent callers could read each other's half-written output. to_string + // owns a local buffer, so every result must equal its own expected text no + // matter how many threads run. A shared buffer would corrupt these. + { + const unsigned threadCount = 16; + const unsigned iterations = 20000; + std::atomic corrupted(false); + + std::vector threads; + threads.reserve(threadCount); + for (unsigned t = 0; t < threadCount; ++t) + { + // Each thread owns a distinct value, so its expected string is fixed. + const uint64_t value = 0x1000000000000000ull + t; + const RakNetGUID g(value); + const std::string expected = to_string(g); + threads.emplace_back([g, expected, iterations, &corrupted]() { + for (unsigned k = 0; k < iterations && !corrupted.load(std::memory_order_relaxed); ++k) + { + if (to_string(g) != expected) + corrupted.store(true, std::memory_order_relaxed); + } + }); + } + for (std::thread &th : threads) + th.join(); + + if (corrupted.load()) + { + if (isVerbose) printf("to_string produced a corrupted result under concurrency\n"); + return 3; + } + } + + // --- connected_address maps the "none" sentinel to std::nullopt --- + RakPeerInterface *peer = RakPeerInterface::GetInstance(); + destroyList.Push(peer, _FILE_AND_LINE_); + SocketDescriptor sd(0, 0); + if (peer->Startup(8, &sd, 1) != RAKNET_STARTED) + return 4; + + // GetSystemAddressFromGuid(UNASSIGNED_RAKNET_GUID) returns the sentinel. + if (connected_address(*peer, UNASSIGNED_RAKNET_GUID).has_value()) + { + if (isVerbose) printf("connected_address(UNASSIGNED_RAKNET_GUID) should be nullopt\n"); + return 5; + } + + // An arbitrary guid we are not connected to also has no address. + if (connected_address(*peer, RakNetGUID(0xDEADBEEFull)).has_value()) + { + if (isVerbose) printf("connected_address(unknown guid) should be nullopt\n"); + return 6; + } + + // --- the wrapper faithfully mirrors the legacy lookup it wraps --- + // has_value() iff the legacy call did not return the sentinel, and when + // engaged the address is exactly what the legacy call returned. + for (size_t i = 0; i < sampleCount; ++i) + { + const RakNetGUID g(samples[i]); + const SystemAddress legacy = peer->GetSystemAddressFromGuid(g); + const std::optional modern = connected_address(*peer, g); + const bool legacyHas = (legacy != UNASSIGNED_SYSTEM_ADDRESS); + if (modern.has_value() != legacyHas || (legacyHas && modern.value() != legacy)) + { + if (isVerbose) printf("connected_address disagrees with GetSystemAddressFromGuid for 0x%llx\n", + (unsigned long long) samples[i]); + return 7; + } + } + + printf("guid_util: to_string is thread-safe and connected_address maps the sentinel to nullopt\n"); + return 0; +} + +GuidUtilTest::GuidUtilTest(void) +{ +} + +GuidUtilTest::~GuidUtilTest(void) +{ +} + +RakString GuidUtilTest::GetTestName(void) +{ + return "GuidUtilTest"; +} + +RakString GuidUtilTest::ErrorCodeToString(int errorCode) +{ + switch (errorCode) + { + case 0: return "No error"; + case 1: return "to_string did not match the legacy ToString(char*, size_t) member"; + case 2: return "to_string(UNASSIGNED_RAKNET_GUID) was not \"UNASSIGNED_RAKNET_GUID\""; + case 3: return "to_string produced a corrupted result under concurrent calls"; + case 4: return "Peer failed to start"; + case 5: return "connected_address(UNASSIGNED_RAKNET_GUID) was not std::nullopt"; + case 6: return "connected_address(unknown guid) was not std::nullopt"; + case 7: return "connected_address disagreed with GetSystemAddressFromGuid"; + default: return "Undefined Error"; + } +} + +void GuidUtilTest::DestroyPeers(void) +{ + int theSize = destroyList.Size(); + for (int i = 0; i < theSize; i++) + destroyList[i]->Shutdown(100); + for (int i = 0; i < theSize; i++) + RakPeerInterface::DestroyInstance(destroyList[i]); +} diff --git a/Samples/Tests/GuidUtilTest.h b/Samples/Tests/GuidUtilTest.h new file mode 100644 index 000000000..8189bed07 --- /dev/null +++ b/Samples/Tests/GuidUtilTest.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2026, MafiaHub + * + * This source code is licensed under the MIT-style license found in the + * license.txt file in the root directory of this source tree. + */ + +#pragma once + + +#include "TestInterface.h" + +#include "mafianet/string.h" +#include "mafianet/DS_List.h" +#include "mafianet/peerinterface.h" + +using namespace MafiaNet; + +/// Verifies the modern value-type accessors from "mafianet/guid_util.h" (issue +/// #15): +/// - to_string(guid) returns the same text as the legacy thread-safe +/// ToString(char*, size_t) member, handles the UNASSIGNED sentinel, and is +/// safe to call concurrently from many threads (no shared static buffer). +/// - connected_address(peer, guid) maps the UNASSIGNED_SYSTEM_ADDRESS "none" +/// sentinel to std::nullopt and otherwise forwards the legacy lookup. +class GuidUtilTest : public TestInterface +{ +public: + GuidUtilTest(void); + ~GuidUtilTest(void); + int RunTest(DataStructures::List params, bool isVerbose, bool noPauses); + RakString GetTestName(); + RakString ErrorCodeToString(int errorCode); + void DestroyPeers(); + +private: + DataStructures::List destroyList; +}; diff --git a/Samples/Tests/IncludeAllTests.h b/Samples/Tests/IncludeAllTests.h index eff6e9bbf..2e1a2648d 100644 --- a/Samples/Tests/IncludeAllTests.h +++ b/Samples/Tests/IncludeAllTests.h @@ -31,6 +31,7 @@ #include "BitStreamStringTest.h" #include "RPC4ContextTest.h" #include "VirtualWorldTest.h" +#include "GuidUtilTest.h" #include "DisconnectReasonTest.h" #include "PeerGuidTest.h" #include "PointGridSectorizerTest.h" diff --git a/Samples/Tests/OfflineMessagesConvertTest.cpp b/Samples/Tests/OfflineMessagesConvertTest.cpp index fa52c47c0..be03d47a0 100644 --- a/Samples/Tests/OfflineMessagesConvertTest.cpp +++ b/Samples/Tests/OfflineMessagesConvertTest.cpp @@ -9,6 +9,7 @@ */ #include "OfflineMessagesConvertTest.h" +#include "mafianet/guid_util.h" /* Description: @@ -74,9 +75,9 @@ int OfflineMessagesConvertTest::RunTest(DataStructures::List params,b } if (isVerbose) - printf("Peer 1 guid = %s\n", peer1->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("Peer 1 guid = %s\n", MafiaNet::to_string(peer1->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS)).c_str()); if (isVerbose) - printf("Peer 2 guid = %s\n", peer2->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("Peer 2 guid = %s\n", MafiaNet::to_string(peer2->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS)).c_str()); if (isVerbose) printf("Systems started. Waiting for advertise system packet\n"); @@ -84,7 +85,7 @@ int OfflineMessagesConvertTest::RunTest(DataStructures::List params,b RakSleep(300); if (isVerbose) - printf("Sending advertise system from %s\n", peer1->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("Sending advertise system from %s\n", MafiaNet::to_string(peer1->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS)).c_str()); peer1->AdvertiseSystem("127.0.0.1", 60002,"hello world", (int)strlen("hello world")+1); TimeMS entryTime=GetTimeMS();//Loop entry time @@ -122,9 +123,9 @@ int OfflineMessagesConvertTest::RunTest(DataStructures::List params,b return 1; } if (isVerbose) - printf("Was sent from GUID %s\n", packet->guid.ToString()); + printf("Was sent from GUID %s\n", MafiaNet::to_string(packet->guid).c_str()); if (isVerbose) - printf("Sending ping from %s\n", peer2->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS).ToString()); + printf("Sending ping from %s\n", MafiaNet::to_string(peer2->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS)).c_str()); peer2->Ping("127.0.0.1", 60001, false); nextTest++; } @@ -148,7 +149,7 @@ int OfflineMessagesConvertTest::RunTest(DataStructures::List params,b if (isVerbose) { printf(" %s on %p.\nPing is %i\nData is %i bytes long.\n", packet->systemAddress.ToString(), peer2, curTime-packetTime, dataLength ); - printf("Was sent from GUID %s\n", packet->guid.ToString()); + printf("Was sent from GUID %s\n", MafiaNet::to_string(packet->guid).c_str()); } const char * recString=(const char *)(packet->data + sizeof( unsigned char ) + sizeof( TimeMS )); diff --git a/Samples/Tests/Tests.cpp b/Samples/Tests/Tests.cpp index 1d8f2b11c..3787f51ed 100644 --- a/Samples/Tests/Tests.cpp +++ b/Samples/Tests/Tests.cpp @@ -59,6 +59,7 @@ int main(int argc, char *argv[]) testList.Push(new BitStreamStringTest(),_FILE_AND_LINE_); testList.Push(new RPC4ContextTest(),_FILE_AND_LINE_); testList.Push(new VirtualWorldTest(),_FILE_AND_LINE_); + testList.Push(new GuidUtilTest(),_FILE_AND_LINE_); testList.Push(new DisconnectReasonTest(),_FILE_AND_LINE_); testList.Push(new PeerGuidTest(),_FILE_AND_LINE_); testList.Push(new PointGridSectorizerTest(),_FILE_AND_LINE_); diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index bfaca360d..bae5041ed 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -37,6 +37,7 @@ set(MAFIANET_SOURCES src/GetTime.cpp src/gettimeofday.cpp src/GridSectorizer.cpp + src/guid_util.cpp src/HTTPConnection.cpp src/HTTPConnection2.cpp src/IncrementalReadInterface.cpp @@ -183,6 +184,7 @@ set(MAFIANET_HEADERS include/mafianet/GetTime.h include/mafianet/gettimeofday.h include/mafianet/GridSectorizer.h + include/mafianet/guid_util.h include/mafianet/HTTPConnection.h include/mafianet/HTTPConnection2.h include/mafianet/IncrementalReadInterface.h diff --git a/Source/include/mafianet/guid_util.h b/Source/include/mafianet/guid_util.h new file mode 100644 index 000000000..c1d47cd34 --- /dev/null +++ b/Source/include/mafianet/guid_util.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024, MafiaHub + * + * This source code is licensed under the MIT-style license found in the + * license.txt file in the root directory of this source tree. + */ + +/// \file +/// \brief Modern, additive value-type accessors layered over the legacy +/// RakNet/SLikeNet value types (\a RakNetGUID, \a SystemAddress). +/// +/// These free functions live alongside the legacy struct methods rather than +/// inside them, so they don't touch the wire-transmitted ABI of \a RakNetGUID. +/// They favour ownership over shared static buffers and \a std::optional over +/// sentinel return values, giving callers thread-safe, leak-free primitives to +/// build cleaner APIs on top of. + +#ifndef __MAFIANET_GUID_UTIL_H +#define __MAFIANET_GUID_UTIL_H + +#include +#include + +#include "types.h" +#include "peerinterface.h" + +namespace MafiaNet { + +/// Return the GUID as an owned \a std::string. +/// +/// Unlike the legacy \a RakNetGUID::ToString() member (which returned a pointer +/// into a rotating, process-wide static buffer and was explicitly NOT thread +/// safe), this allocates a fresh string on every call and shares no state, so +/// it is safe to call concurrently from multiple threads. It is implemented on +/// top of the thread-safe \a RakNetGUID::ToString(char*, size_t) member. +RAK_DLL_EXPORT std::string to_string(const RakNetGUID& g); + +/// Look up the SystemAddress currently connected to \a g. +/// +/// A thin facade over \a RakPeerInterface::GetSystemAddressFromGuid that maps +/// the legacy \a UNASSIGNED_SYSTEM_ADDRESS "none" sentinel to \a std::nullopt, +/// so callers can use ordinary optional handling instead of comparing against a +/// magic value. +RAK_DLL_EXPORT std::optional connected_address(RakPeerInterface& peer, const RakNetGUID& g); + +} // namespace MafiaNet + +#endif // __MAFIANET_GUID_UTIL_H diff --git a/Source/include/mafianet/mafianet.h b/Source/include/mafianet/mafianet.h index 1d664c377..938727fea 100644 --- a/Source/include/mafianet/mafianet.h +++ b/Source/include/mafianet/mafianet.h @@ -29,3 +29,4 @@ #include "mafianet/statistics.h" // RakNetStatistics — return type of GetStatistics() #include "mafianet/BitStream.h" // binary serialization #include "mafianet/GetTime.h" // MafiaNet::GetTime / TimeMS +#include "mafianet/guid_util.h" // MafiaNet::to_string / connected_address diff --git a/Source/include/mafianet/types.h b/Source/include/mafianet/types.h index cebd02411..05f3a31ac 100644 --- a/Source/include/mafianet/types.h +++ b/Source/include/mafianet/types.h @@ -300,12 +300,9 @@ struct RAK_DLL_EXPORT RakNetGUID // uint32_t g[6]; uint64_t g; - // Return the GUID as a string - // Returns a static string - // NOT THREADSAFE - const char *ToString(void) const; - - // Return the GUID as a string + // Return the GUID as a string. + // For an owning, thread-safe std::string use MafiaNet::to_string(guid) + // from "mafianet/guid_util.h". // dest must be large enough to hold the output // THREADSAFE void ToString(char *dest) const; diff --git a/Source/src/FullyConnectedMesh2.cpp b/Source/src/FullyConnectedMesh2.cpp index e69025272..e22d1fe64 100644 --- a/Source/src/FullyConnectedMesh2.cpp +++ b/Source/src/FullyConnectedMesh2.cpp @@ -22,6 +22,7 @@ #include "mafianet/FullyConnectedMesh2.h" #include "mafianet/peerinterface.h" +#include "mafianet/guid_util.h" #include "mafianet/MessageIdentifiers.h" #include "mafianet/assert.h" #include "mafianet/GetTime.h" @@ -165,7 +166,7 @@ void FullyConnectedMesh2::AddParticipant( RakNetGUID rakNetGuid ) if (rakPeerInterface->GetConnectionState(rakPeerInterface->GetSystemAddressFromGuid(rakNetGuid))!=IS_CONNECTED) { #ifdef DEBUG_FCM2 - printf("AddParticipant to %s failed (not connected)\n", rakNetGuid.ToString()); + printf("AddParticipant to %s failed (not connected)\n", to_string(rakNetGuid).c_str()); #endif return; } @@ -361,7 +362,7 @@ void FullyConnectedMesh2::OnClosedConnection(const SystemAddress &systemAddress, { fcm2ParticipantList[idx]=fcm2ParticipantList[fcm2ParticipantList.Size()-1]; #ifdef DEBUG_FCM2 - printf("Popping participant %s\n", fcm2ParticipantList[fcm2ParticipantList.Size()-1].rakNetGuid.ToString()); + printf("Popping participant %s\n", to_string(fcm2ParticipantList[fcm2ParticipantList.Size()-1]->rakNetGuid).c_str()); #endif fcm2ParticipantList.Pop(); diff --git a/Source/src/RakNetTypes.cpp b/Source/src/RakNetTypes.cpp index 865daaf4b..46c94aead 100644 --- a/Source/src/RakNetTypes.cpp +++ b/Source/src/RakNetTypes.cpp @@ -65,7 +65,17 @@ unsigned long AddressOrGUID::ToInteger( const AddressOrGUID &aog ) const char *AddressOrGUID::ToString(bool writePort) const { if (rakNetGuid!=UNASSIGNED_RAKNET_GUID) - return rakNetGuid.ToString(); + { + // Rotating static buffer, mirroring SystemAddress::ToString below. + // NOT THREADSAFE — for an owning, thread-safe string use + // MafiaNet::to_string(guid) from "mafianet/guid_util.h". + static unsigned char strIndex=0; + static char str[8][64]; + unsigned char lastStrIndex=strIndex; + strIndex++; + rakNetGuid.ToString(str[lastStrIndex&7], 64); + return (char*) str[lastStrIndex&7]; + } return systemAddress.ToString(writePort); } void AddressOrGUID::ToString(bool writePort, char *dest) const @@ -727,16 +737,6 @@ bool RakNetGUID::operator < ( const RakNetGUID& right ) const { return g < right.g; } -const char *RakNetGUID::ToString(void) const -{ - static unsigned char strIndex=0; - static char str[8][64]; - - unsigned char lastStrIndex=strIndex; - strIndex++; - ToString(str[lastStrIndex&7], 64); - return (char*) str[lastStrIndex&7]; -} void RakNetGUID::ToString(char *dest) const { if (*this == UNASSIGNED_RAKNET_GUID) diff --git a/Source/src/guid_util.cpp b/Source/src/guid_util.cpp new file mode 100644 index 000000000..62ac484c1 --- /dev/null +++ b/Source/src/guid_util.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, MafiaHub + * + * This source code is licensed under the MIT-style license found in the + * license.txt file in the root directory of this source tree. + */ + +#include "mafianet/guid_util.h" + +namespace MafiaNet { + +std::string to_string(const RakNetGUID& g) +{ + // The longest possible output is "UNASSIGNED_RAKNET_GUID" (22 chars) or a + // 64-bit decimal (20 chars); 64 bytes matches the legacy buffer size and + // leaves ample headroom. Buffer is local, so this is thread-safe. + char buffer[64]; + g.ToString(buffer, sizeof(buffer)); + return std::string(buffer); +} + +std::optional connected_address(RakPeerInterface& peer, const RakNetGUID& g) +{ + const SystemAddress address = peer.GetSystemAddressFromGuid(g); + if (address == UNASSIGNED_SYSTEM_ADDRESS) + return std::nullopt; + return address; +} + +} // namespace MafiaNet