From e3904db37ccaeca30b016795e3d428b08cd48315 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 10 Feb 2016 17:18:45 +0100 Subject: [PATCH] Rewrite network interface. --- src/Components/Modules/Dedicated.cpp | 3 +- src/Components/Modules/Discovery.cpp | 7 ++-- src/Components/Modules/Download.cpp | 16 ++++----- src/Components/Modules/Network.cpp | 50 ++++++++++++++++++--------- src/Components/Modules/Network.hpp | 8 +++-- src/Components/Modules/Node.cpp | 40 ++++++++++----------- src/Components/Modules/Party.cpp | 6 ++-- src/Components/Modules/Playlist.cpp | 4 +-- src/Components/Modules/ServerInfo.cpp | 4 +-- src/Components/Modules/ServerList.cpp | 8 ++--- src/Utils/Utils.cpp | 6 ++-- 11 files changed, 85 insertions(+), 67 deletions(-) diff --git a/src/Components/Modules/Dedicated.cpp b/src/Components/Modules/Dedicated.cpp index d388df9b..1132cc2e 100644 --- a/src/Components/Modules/Dedicated.cpp +++ b/src/Components/Modules/Dedicated.cpp @@ -141,8 +141,7 @@ namespace Components Network::Address master(Utils::VA("%s:%u", masterServerName, masterPort)); Logger::Print("Sending heartbeat to master: %s:%u\n", masterServerName, masterPort); - - Network::Send(master, Utils::VA("heartbeat %s\n", "IW4")); + Network::SendCommand(master, "heartbeat", "IW4"); } void Dedicated::OnFrame(Dedicated::Callback callback) diff --git a/src/Components/Modules/Discovery.cpp b/src/Components/Modules/Discovery.cpp index c5b74556..364ad81f 100644 --- a/src/Components/Modules/Discovery.cpp +++ b/src/Components/Modules/Discovery.cpp @@ -28,12 +28,11 @@ namespace Components Logger::Print("Starting local server discovery...\n"); - Discovery::DiscoveryContainer.Challenge = Utils::VA("%d", Utils::Cryptography::Rand::GenerateInt()); + Discovery::DiscoveryContainer.Challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt()); - //Network::BroadcastAll("discovery\n"); unsigned int minPort = Dvar::Var("net_discoveryPortRangeMin").Get(); unsigned int maxPort = Dvar::Var("net_discoveryPortRangeMax").Get(); - Network::BroadcastRange(minPort, maxPort, Utils::VA("discovery\n%s", Discovery::DiscoveryContainer.Challenge.data())); + Network::BroadcastRange(minPort, maxPort, Utils::VA("discovery %s", Discovery::DiscoveryContainer.Challenge.data())); Logger::Print("Discovery sent within %dms, awaiting responses...\n", Game::Com_Milliseconds() - start); @@ -55,7 +54,7 @@ namespace Components } Logger::Print("Received discovery request from %s\n", address.GetString()); - Network::Send(address, Utils::VA("discoveryResponse\n%s", data.data())); + Network::SendCommand(address, "discoveryResponse", data); }); Network::Handle("discoveryResponse", [] (Network::Address address, std::string data) diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index 8396b5eb..93f236e3 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -121,11 +121,11 @@ namespace Components download->lastPing = Game::Com_Milliseconds(); download->maxParts = request->maxPackets; - std::string packet = "dlAckResponse\n"; + std::string packet; packet.append(reinterpret_cast(&download->id), sizeof(int)); packet.append(challenge); - Network::SendRaw(target, packet); + Network::SendCommand(target, "dlAckResponse", packet); } } @@ -232,13 +232,13 @@ namespace Components request.length = download.challenge.size(); - std::string packet = "dlAckRequest\n"; + std::string packet; packet.append(reinterpret_cast(&request), sizeof(request)); packet.append(download.challenge); Download::DataContainer.ServerDownloads.push_back(download); - Network::SendRaw(target, packet); + Network::SendCommand(target, "dlAckRequest", packet); } std::string Download::AssembleBuffer(Download::Container::DownloadCL* download) @@ -260,7 +260,7 @@ namespace Components { download->lastPing = Game::Com_Milliseconds(); - std::string data = "dlMissRequest\n"; + std::string data; data.append(reinterpret_cast(&download->id), sizeof(int)); for (auto &packet : packets) @@ -268,7 +268,7 @@ namespace Components data.append(reinterpret_cast(&packet), sizeof(int)); } - Network::SendRaw(download->target, data); + Network::SendCommand(download->target, "dlMissRequest", data); } } @@ -308,7 +308,7 @@ namespace Components response.append(reinterpret_cast(&packetContainer), sizeof(packetContainer)); response.append(data); - Network::SendRaw(download->target, response); + Network::SendCommand(download->target, "dlPacketResponse", response); } void Download::Frame() @@ -384,7 +384,7 @@ namespace Components response.append(reinterpret_cast(&download.id), sizeof(int)); response.append(file); - Network::SendRaw(target, response); + Network::SendCommand(target, "dlRequest", response); return download.id; } diff --git a/src/Components/Modules/Network.cpp b/src/Components/Modules/Network.cpp index a3e32f1d..6ec8ee11 100644 --- a/src/Components/Modules/Network.cpp +++ b/src/Components/Modules/Network.cpp @@ -79,8 +79,6 @@ namespace Components } } - // TODO: Check the external IP as well! - return false; } @@ -89,35 +87,52 @@ namespace Components Network::PacketHandlers[Utils::StrToLower(packet)] = callback; } - void Network::Send(Game::netsrc_t type, Address target, std::string data) + void Network::Send(Game::netsrc_t type, Network::Address target, std::string data) { - Game::NET_OutOfBandPrint(type, *target.Get(), data.data()); + // NET_OutOfBandPrint only supports non-binary data! + //Game::NET_OutOfBandPrint(type, *target.Get(), data.data()); + + std::string rawData; + rawData.append("\xFF\xFF\xFF\xFF", 4); + rawData.append(data); + //rawData.append("\0", 1); + + Network::SendRaw(type, target, rawData); } - void Network::Send(Address target, std::string data) + void Network::Send(Network::Address target, std::string data) { Network::Send(Game::netsrc_t::NS_CLIENT, target, data); } - void Network::SendRaw(Game::netsrc_t type, Address target, std::string data) + void Network::SendRaw(Game::netsrc_t type, Network::Address target, std::string data) { - DWORD header = 0xFFFFFFFF; - - std::string rawData; - rawData.append(reinterpret_cast(&header), 4); - rawData.append(data.begin(), data.end()); - rawData.append("\0", 1); - // NET_OutOfBandData doesn't seem to work properly //Game::NET_OutOfBandData(type, *target.Get(), data.data(), data.size()); - Game::Sys_SendPacket(type, rawData.size(), rawData.data(), *target.Get()); + Game::Sys_SendPacket(type, data.size(), data.data(), *target.Get()); } - void Network::SendRaw(Address target, std::string data) + void Network::SendRaw(Network::Address target, std::string data) { Network::SendRaw(Game::netsrc_t::NS_CLIENT, target, data); } + void Network::SendCommand(Game::netsrc_t type, Network::Address target, std::string command, std::string data) + { + // Use space a separator (possible separators are '\n', ' ') + std::string packet; + packet.append(command); + packet.append(" ", 1); + packet.append(data); + + Network::Send(type, target, packet); + } + + void Network::SendCommand(Network::Address target, std::string command, std::string data) + { + Network::SendCommand(Game::netsrc_t::NS_CLIENT, target, command, data); + } + void Network::Broadcast(unsigned short port, std::string data) { Address target; @@ -126,7 +141,7 @@ namespace Components target.SetIP(INADDR_BROADCAST); target.SetType(Game::netadrtype_t::NA_BROADCAST); - Network::SendRaw(Game::netsrc_t::NS_CLIENT, target, data); + Network::Send(Game::netsrc_t::NS_CLIENT, target, data); } void Network::BroadcastRange(unsigned int min, unsigned int max, std::string data) @@ -181,7 +196,8 @@ namespace Components } // Remove trailing 0x00 byte - if (data.size() && !data[data.size() - 1]) data.pop_back(); + // Actually, don't remove it, it might be part of the packet. Send correctly formatted packets instead! + //if (data.size() && !data[data.size() - 1]) data.pop_back(); Network::PacketHandlers[Network::SelectedPacket](from, data); } diff --git a/src/Components/Modules/Network.hpp b/src/Components/Modules/Network.hpp index 29339df3..1ca20009 100644 --- a/src/Components/Modules/Network.hpp +++ b/src/Components/Modules/Network.hpp @@ -42,14 +42,18 @@ namespace Components static void Handle(std::string packet, Callback callback); - // Only non-binary data + // Send quake-styled binary data static void Send(Address target, std::string data); static void Send(Game::netsrc_t type, Address target, std::string data); - // Allows sending binary data + // Allows sending raw data without quake header static void SendRaw(Address target, std::string data); static void SendRaw(Game::netsrc_t type, Address target, std::string data); + // Send quake-style command using binary data + static void SendCommand(Address target, std::string command, std::string data = ""); + static void SendCommand(Game::netsrc_t type, Address target, std::string command, std::string data = ""); + static void Broadcast(unsigned short port, std::string data); static void BroadcastRange(unsigned int min, unsigned int max, std::string data); static void BroadcastAll(std::string data); diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index e92996a3..c6c597f0 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -121,21 +121,21 @@ namespace Components if (entries.size() >= NODE_PACKET_LIMIT) { - std::string packet = "nodeListResponse\n"; + std::string packet; packet.append((Dedicated::IsDedicated() ? "\x01" : "\0"), 1); packet.append(reinterpret_cast(entries.data()), entries.size() * sizeof(Node::AddressEntry)); - Network::SendRaw(address, packet); + Network::SendCommand(address, "nodeListResponse", packet); entries.clear(); } } - std::string packet = "nodeListResponse\n"; + std::string packet; packet.append((Dedicated::IsDedicated() ? "\x01" : "\0"), 1); packet.append(reinterpret_cast(entries.data()), entries.size() * sizeof(Node::AddressEntry)); - Network::SendRaw(address, packet); + Network::SendCommand(address, "nodeListResponse", packet); } void Node::DeleteInvalidSessions() @@ -234,12 +234,12 @@ namespace Components packet.SerializeToString(&data); Logger::Print("Sending registration request to %s\n", node.address.GetString()); - Network::SendRaw(node.address, "nodeRegisterRequest\n" + data); + Network::SendCommand(node.address, "nodeRegisterRequest", data); } else { Logger::Print("Sending session request to %s\n", node.address.GetString()); - Network::Send(node.address, "sessionRequest\n"); + Network::SendCommand(node.address, "sessionRequest"); } } } @@ -254,11 +254,11 @@ namespace Components if (Dedicated::IsDedicated()) { - Network::Send(node.address, "nodeListRequest\n"); + Network::SendCommand(node.address, "nodeListRequest"); } else { - Network::Send(node.address, "sessionRequest\n"); + Network::SendCommand(node.address, "sessionRequest"); } } } @@ -312,7 +312,7 @@ namespace Components QuickPatch::OnShutdown([] () { std::string data, challenge; - challenge = Utils::VA("X", Utils::Cryptography::Rand::GenerateInt()); + challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt()); Proto::NodePacket packet; packet.set_challenge(challenge); @@ -321,7 +321,7 @@ namespace Components for (auto node : Node::Nodes) { - Network::SendRaw(node.address, "nodeDeregister\n" + data); + Network::SendCommand(node.address, "nodeDeregister", data); } }); @@ -359,7 +359,7 @@ namespace Components entry->challenge = challenge; entry->state = Node::STATE_NEGOTIATING; - Network::SendRaw(address, "nodeRegisterSynchronize\n" + response); + Network::SendCommand(address, "nodeRegisterSynchronize", response); }); Network::Handle("nodeRegisterSynchronize", [] (Network::Address address, std::string data) @@ -406,7 +406,7 @@ namespace Components packet.set_publickey(publicKey); packet.SerializeToString(&data); - Network::SendRaw(address, "nodeRegisterAcknowledge\n" + data); + Network::SendCommand(address, "nodeRegisterAcknowledge", data); }); Network::Handle("nodeRegisterAcknowledge", [] (Network::Address address, std::string data) @@ -474,7 +474,7 @@ namespace Components { // Unallowed connection Logger::Print("Node list requested by %s, but no valid session was present!\n", address.GetString()); - Network::Send(address, "nodeListError\n"); + Network::SendCommand(address, "nodeListError"); } }); @@ -521,7 +521,7 @@ namespace Components Node::Sessions.push_back(session); - Network::Send(address, "sessionInitialize\n" + session.challenge); + Network::SendCommand(address, "sessionInitialize", session.challenge); }); Network::Handle("sessionSynchronize", [] (Network::Address address, std::string data) @@ -534,7 +534,7 @@ namespace Components { Logger::Print("Session for %s validated.\n", address.GetString()); session->valid = true; - Network::Send(address, "sessionAcknowledge\n"); + Network::SendCommand(address, "sessionAcknowledge"); } else { @@ -553,7 +553,7 @@ namespace Components Logger::Print("Session initialization received. Synchronizing...\n", address.GetString()); entry->lastTime = Game::Com_Milliseconds(); - Network::Send(address, "sessionSynchronize\n" + data); + Network::SendCommand(address, "sessionSynchronize", data); }); Network::Handle("sessionAcknowledge", [] (Network::Address address, std::string data) @@ -566,7 +566,7 @@ namespace Components entry->lastTime = Game::Com_Milliseconds(); Logger::Print("Session acknowledged, synchronizing node list...\n", address.GetString()); - Network::Send(address, "nodeListRequest\n"); + Network::SendCommand(address, "nodeListRequest"); Node::SendNodeList(address); }); } @@ -700,7 +700,7 @@ namespace Components for (int i = 0; i < 10; ++i) { - std::string message = Utils::VA("%d", Utils::Cryptography::Rand::GenerateInt()); + std::string message = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt()); std::string signature = Utils::Cryptography::ECDSA::SignMessage(Node::SignatureKey, message); if (!Utils::Cryptography::ECDSA::VerifyMessage(Node::SignatureKey, message, signature)) @@ -716,7 +716,7 @@ namespace Components for (int i = 0; i < 10; ++i) { - std::string message = Utils::VA("%d", Utils::Cryptography::Rand::GenerateInt()); + std::string message = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt()); std::string signature = Utils::Cryptography::ECDSA::SignMessage(Node::SignatureKey, message); // Invalidate the message... @@ -734,7 +734,7 @@ namespace Components printf("Testing ECDSA key import..."); std::string pubKey = Node::SignatureKey.GetPublicKey(); - std::string message = Utils::VA("%d", Utils::Cryptography::Rand::GenerateInt()); + std::string message = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt()); std::string signature = Utils::Cryptography::ECDSA::SignMessage(Node::SignatureKey, message); Utils::Cryptography::ECDSA::Key testKey; diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index ab4b3209..21e361af 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -30,7 +30,7 @@ namespace Components Party::Container.Target = target; Party::Container.Challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt()); - Network::Send(Party::Container.Target, Utils::VA("getinfo %s\n", Party::Container.Challenge.data())); + Network::SendCommand(Party::Container.Target, "getinfo", Party::Container.Challenge); Command::Execute("openmenu popup_reconnectingtoparty"); } @@ -308,7 +308,7 @@ namespace Components info.Set("matchtype", "0"); } - Network::Send(address, Utils::VA("infoResponse\n\\%s\n", info.Build().data())); + Network::SendCommand(address, "infoResponse", "\\" + info.Build()); }); Network::Handle("infoResponse", [] (Network::Address address, std::string data) @@ -339,7 +339,7 @@ namespace Components // Send playlist request Party::Container.RequestTime = Game::Com_Milliseconds(); Party::Container.AwaitingPlaylist = true; - Network::Send(address, "getplaylist\n"); + Network::SendCommand(address, "getplaylist"); // This is not a safe method // TODO: Fix actual error! diff --git a/src/Components/Modules/Playlist.cpp b/src/Components/Modules/Playlist.cpp index fd2618cf..65cd2af1 100644 --- a/src/Components/Modules/Playlist.cpp +++ b/src/Components/Modules/Playlist.cpp @@ -49,12 +49,12 @@ namespace Components unsigned int size = compressedList.size(); unsigned int hash = Utils::OneAtATime(compressedList.data(), compressedList.size()); - std::string response = "playlistresponse\n"; + std::string response; response.append(reinterpret_cast(&hash), 4); response.append(reinterpret_cast(&size), 4); response.append(compressedList); - Network::SendRaw(address, response); + Network::SendCommand(address, "playlistresponse", response); } void Playlist::PlaylistReponse(Network::Address address, std::string data) diff --git a/src/Components/Modules/ServerInfo.cpp b/src/Components/Modules/ServerInfo.cpp index 6cd4031f..aa8ab538 100644 --- a/src/Components/Modules/ServerInfo.cpp +++ b/src/Components/Modules/ServerInfo.cpp @@ -64,7 +64,7 @@ namespace Components } ServerInfo::PlayerContainer.Target = info->Addr; - Network::Send(ServerInfo::PlayerContainer.Target, "getstatus\n"); + Network::SendCommand(ServerInfo::PlayerContainer.Target, "getstatus"); } } @@ -157,7 +157,7 @@ namespace Components playerList.append(Utils::VA("%i %i \"%s\"\n", score, ping, name.data())); } - Network::Send(address, Utils::VA("statusResponse\n\\%s\n%s\n", info.Build().data(), playerList.data())); + Network::SendCommand(address, "statusResponse", "\\" + info.Build() + "\n" + playerList + "\n"); }); Network::Handle("statusResponse", [] (Network::Address address, std::string data) diff --git a/src/Components/Modules/ServerList.cpp b/src/Components/Modules/ServerList.cpp index f7fefef1..31b70633 100644 --- a/src/Components/Modules/ServerList.cpp +++ b/src/Components/Modules/ServerList.cpp @@ -224,8 +224,8 @@ namespace Components Logger::Print("Sending serverlist request to master: %s:%u\n", masterServerName, masterPort); - Network::Send(ServerList::RefreshContainer.Host, Utils::VA("getservers IW4 %i full empty", PROTOCOL)); - //Network::Send(ServerList::RefreshContainer.Host, "getservers 0 full empty\n"); + Network::SendCommand(ServerList::RefreshContainer.Host, "getservers", Utils::VA("IW4 %i full empty", PROTOCOL)); + //Network::SendCommand(ServerList::RefreshContainer.Host, "getservers", "0 full empty"); #else ServerList::RefreshContainer.Mutex.lock(); @@ -500,11 +500,11 @@ namespace Components SendServers--; server->SendTime = Game::Com_Milliseconds(); - server->Challenge = Utils::VA("%d", Utils::Cryptography::Rand::GenerateInt()); + server->Challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt()); ServerList::RefreshContainer.SentCount++; - Network::Send(server->Target, Utils::VA("getinfo %s\n", server->Challenge.data())); + Network::SendCommand(server->Target, "getinfo", server->Challenge); // Display in the menu, like in COD4 Localization::Set("MPUI_SERVERQUERIED", Utils::VA("Sent requests: %d/%d", ServerList::RefreshContainer.SentCount, ServerList::RefreshContainer.SendCount)); diff --git a/src/Utils/Utils.cpp b/src/Utils/Utils.cpp index d3e0cf67..cbd1b586 100644 --- a/src/Utils/Utils.cpp +++ b/src/Utils/Utils.cpp @@ -131,9 +131,9 @@ namespace Utils std::string ParseChallenge(std::string data) { - // Ensure line break - data.append("\n"); - return data.substr(0, data.find_first_of("\n")).data(); + auto pos = data.find_first_of("\n "); + if (pos == std::string::npos) return data; + return data.substr(0, pos).data(); } // TODO: Use modern file reading methods