More proto stuff.

We should add a version identifier before releasing!
This commit is contained in:
momo5502 2016-02-12 15:06:06 +01:00
parent 4fa8ebd3c5
commit a11f004a7e
19 changed files with 113 additions and 126 deletions

View File

@ -111,6 +111,7 @@ workspace "iw4x"
buildoptions {
"/wd4100", -- "Unused formal parameter"
"/wd6011", -- "Dereferencing NULL pointer"
"/wd4125", -- "Decimal digit terminates octal escape sequence"
}
defines {
"_SCL_SECURE_NO_WARNINGS",

View File

@ -102,7 +102,7 @@ namespace Assets
textureList.push_back(textureDef);
}
if (textureList.size())
if (!textureList.empty())
{
Game::MaterialTextureDef* textureTable = builder->GetAllocator()->AllocateArray<Game::MaterialTextureDef>(textureList.size());

View File

@ -74,7 +74,7 @@ namespace Components
Logger::Print("Rotating map...\n");
// if nothing, just restart
if (!Dvar::Var("sv_mapRotation").Get<std::string>().size())
if (Dvar::Var("sv_mapRotation").Get<std::string>().empty())
{
Logger::Print("No rotation defined, restarting map.\n");
Command::Execute(Utils::VA("map %s", Dvar::Var("mapname").Get<const char*>()), true);
@ -82,7 +82,7 @@ namespace Components
}
// first, check if the string contains nothing
if (!Dvar::Var("sv_mapRotationCurrent").Get<std::string>().size())
if (Dvar::Var("sv_mapRotationCurrent").Get<std::string>().empty())
{
Logger::Print("Current map rotation has finished, reloading...\n");
Dvar::Var("sv_mapRotationCurrent").Set(Dvar::Var("sv_mapRotation").Get<const char*>());

View File

@ -69,7 +69,7 @@ namespace Components
bool Download::HasReceivedPacket(Download::Container::DownloadCL* download, int packet)
{
if (download->parts.size())
if (!download->parts.empty())
{
for (auto i = download->parts.begin(); i != download->parts.end(); ++i)
{
@ -256,7 +256,7 @@ namespace Components
void Download::RequestMissingPackets(Download::Container::DownloadCL* download, std::vector<int> packets)
{
if (packets.size())
if (!packets.empty())
{
download->lastPing = Game::Com_Milliseconds();
@ -274,7 +274,7 @@ namespace Components
void Download::MarkPacketAsDirty(Download::Container::DownloadSV* download, int packet)
{
if (download->sentParts.size())
if (!download->sentParts.empty())
{
for (auto i = download->sentParts.begin(); i != download->sentParts.end(); ++i)
{
@ -313,7 +313,7 @@ namespace Components
void Download::Frame()
{
if (Download::DataContainer.ClientDownloads.size())
if (!Download::DataContainer.ClientDownloads.empty())
{
for (auto i = Download::DataContainer.ClientDownloads.begin(); i != Download::DataContainer.ClientDownloads.end(); ++i)
{
@ -341,7 +341,7 @@ namespace Components
}
}
if (Download::DataContainer.ServerDownloads.size())
if (!Download::DataContainer.ServerDownloads.empty())
{
for (auto i = Download::DataContainer.ServerDownloads.begin(); i != Download::DataContainer.ServerDownloads.end(); ++i)
{

View File

@ -218,7 +218,7 @@ namespace Components
{
std::vector<Game::menuDef_t*> menus = Menus::LoadMenu(Utils::VA("ui_mp\\%s.menu", menudef->window.name));
if (!menus.size())
if (menus.empty())
{
// Try loading the original menu, if we can't load our custom one
Game::menuDef_t* originalMenu = AssetHandler::FindOriginalAsset(Game::XAssetType::ASSET_TYPE_MENU, menudef->window.name).menu;
@ -239,7 +239,7 @@ namespace Components
Game::MenuList* Menus::LoadScriptMenu(const char* menu)
{
std::vector<Game::menuDef_t*> menus = Menus::LoadMenu(menu);
if (!menus.size()) return nullptr;
if (menus.empty()) return nullptr;
// Allocate new menu list
Game::MenuList* newList = Utils::Memory::AllocateArray<Game::MenuList>(1);

View File

@ -81,6 +81,17 @@ namespace Components
return false;
}
void Network::Address::Serialize(Proto::Network::Address* protoAddress)
{
protoAddress->set_ip(this->GetIP().full);
protoAddress->set_port(htons(this->GetPort()));
}
void Network::Address::Deserialize(const Proto::Network::Address& protoAddress)
{
this->SetIP({ protoAddress.ip() });
this->SetPort(ntohs(static_cast<uint16_t>(protoAddress.port())));
this->SetType(Game::netadrtype_t::NA_IP);
}
void Network::Handle(std::string packet, Network::Callback* callback)
{

View File

@ -30,6 +30,9 @@ namespace Components
bool IsLocal();
bool IsSelf();
void Serialize(Proto::Network::Address* protoAddress);
void Deserialize(const Proto::Network::Address& protoAddress);
private:
Game::netadr_t address;
};

View File

@ -54,7 +54,7 @@ namespace Components
std::string data = Utils::WebIO("IW4x", "https://iw4xcachep26muba.onion.to/iw4/motd.txt").SetTimeout(5000)->Get();
if (data.size())
if (!data.empty())
{
Localization::Set("MPUI_MOTD_TEXT", data.data());
}

View File

@ -9,16 +9,16 @@ namespace Components
void Node::LoadNodes()
{
std::string nodes = Utils::ReadFile("players/nodes.dat");
if (nodes.empty()) return;
// Invalid
if (!nodes.size() || nodes.size() % 6) return;
Proto::Node::List list;
list.ParseFromString(nodes);
unsigned int size = (nodes.size() / sizeof(Node::AddressEntry));
Node::AddressEntry* addresses = reinterpret_cast<Node::AddressEntry*>(const_cast<char*>(nodes.data()));
for (unsigned int i = 0; i < size; ++i)
for (int i = 0; i < list.address_size(); ++i)
{
Node::AddNode(addresses[i].toNetAddress());
Network::Address address;
address.Deserialize(list.address(i));
Node::AddNode(address);
}
}
void Node::StoreNodes(bool force)
@ -29,23 +29,18 @@ namespace Components
if ((Game::Com_Milliseconds() - lastStorage) < NODE_STORE_INTERVAL && !force) return;
lastStorage = Game::Com_Milliseconds();
std::vector<Node::AddressEntry> entries;
Proto::Node::List list;
for (auto node : Node::Nodes)
{
if (node.state == Node::STATE_VALID && node.registered)
{
Node::AddressEntry thisAddress;
thisAddress.fromNetAddress(node.address);
entries.push_back(thisAddress);
node.address.Serialize(list.add_address());
}
}
std::string nodeStream(reinterpret_cast<char*>(entries.data()), entries.size() * sizeof(Node::AddressEntry));
CreateDirectoryW(L"players", NULL);
Utils::WriteFile("players/nodes.dat", nodeStream);
Utils::WriteFile("players/nodes.dat", list.SerializeAsString());
}
Node::NodeEntry* Node::FindNode(Network::Address address)
@ -107,35 +102,27 @@ namespace Components
{
if (address.IsSelf()) return;
std::vector<Node::AddressEntry> entries;
Proto::Node::List list;
list.set_is_dedi(Dedicated::IsDedicated());
for (auto entry : Node::Nodes)
for (auto node : Node::Nodes)
{
if (entry.state == Node::STATE_VALID && entry.registered)
if (node.state == Node::STATE_VALID && node.registered)
{
Node::AddressEntry thisAddress;
thisAddress.fromNetAddress(entry.address);
entries.push_back(thisAddress);
node.address.Serialize(list.add_address());
}
if (entries.size() >= NODE_PACKET_LIMIT)
if (list.address_size() >= NODE_PACKET_LIMIT)
{
std::string packet;
packet.append((Dedicated::IsDedicated() ? "\x01" : "\0"), 1);
packet.append(reinterpret_cast<char*>(entries.data()), entries.size() * sizeof(Node::AddressEntry));
Network::SendCommand(address, "nodeListResponse", packet);
entries.clear();
Network::SendCommand(address, "nodeListResponse", list.SerializeAsString());
list.clear_address();
}
}
std::string packet;
packet.append((Dedicated::IsDedicated() ? "\x01" : "\0"), 1);
packet.append(reinterpret_cast<char*>(entries.data()), entries.size() * sizeof(Node::AddressEntry));
Network::SendCommand(address, "nodeListResponse", packet);
if (list.address_size() > 0)
{
Network::SendCommand(address, "nodeListResponse", list.SerializeAsString());
}
}
void Node::DeleteInvalidSessions()
@ -228,13 +215,11 @@ namespace Components
{
node.challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
std::string data;
Proto::NodePacket packet;
Proto::Node::Packet packet;
packet.set_challenge(node.challenge);
packet.SerializeToString(&data);
Logger::Print("Sending registration request to %s\n", node.address.GetString());
Network::SendCommand(node.address, "nodeRegisterRequest", data);
Network::SendCommand(node.address, "nodeRegisterRequest", packet.SerializeAsString());
}
else
{
@ -291,8 +276,6 @@ namespace Components
Node::Node()
{
Assert_Size(Node::AddressEntry, 6);
// ZoneBuilder doesn't require node stuff
if (ZoneBuilder::IsEnabled()) return;
@ -311,17 +294,15 @@ namespace Components
{
QuickPatch::OnShutdown([] ()
{
std::string data, challenge;
challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
std::string challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
Proto::NodePacket packet;
Proto::Node::Packet packet;
packet.set_challenge(challenge);
packet.set_signature(Utils::Cryptography::ECDSA::SignMessage(Node::SignatureKey, challenge));
packet.SerializeToString(&data);
for (auto node : Node::Nodes)
{
Network::SendCommand(node.address, "nodeDeregister", data);
Network::SendCommand(node.address, "nodeDeregister", packet.SerializeAsString());
}
});
@ -341,11 +322,10 @@ namespace Components
Logger::Print("Received registration request from %s\n", address.GetString());
Proto::NodePacket packet;
Proto::Node::Packet packet;
if (!packet.ParseFromString(data)) return;
if (!packet.challenge().size()) return;
if (packet.challenge().empty()) return;
std::string response;
std::string signature = Utils::Cryptography::ECDSA::SignMessage(Node::SignatureKey, packet.challenge());
std::string challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
@ -353,13 +333,12 @@ namespace Components
packet.set_challenge(challenge);
packet.set_signature(signature);
packet.set_publickey(Node::SignatureKey.GetPublicKey());
packet.SerializeToString(&response);
entry->lastTime = Game::Com_Milliseconds();
entry->challenge = challenge;
entry->state = Node::STATE_NEGOTIATING;
Network::SendCommand(address, "nodeRegisterSynchronize", response);
Network::SendCommand(address, "nodeRegisterSynchronize", packet.SerializeAsString());
});
Network::Handle("nodeRegisterSynchronize", [] (Network::Address address, std::string data)
@ -369,11 +348,11 @@ namespace Components
Logger::Print("Received synchronization data for registration from %s!\n", address.GetString());
Proto::NodePacket packet;
Proto::Node::Packet packet;
if (!packet.ParseFromString(data)) return;
if (!packet.challenge().size()) return;
if (!packet.publickey().size()) return;
if (!packet.signature().size()) return;
if (packet.challenge().empty()) return;
if (packet.publickey().empty()) return;
if (packet.signature().empty()) return;
std::string challenge = packet.challenge();
std::string publicKey = packet.publickey();
@ -397,16 +376,14 @@ namespace Components
Logger::Print("Node %s registered\n", address.GetString());
// Build response
data.clear();
publicKey = Node::SignatureKey.GetPublicKey();
signature = Utils::Cryptography::ECDSA::SignMessage(Node::SignatureKey, challenge);
packet.Clear();
packet.set_signature(signature);
packet.set_publickey(publicKey);
packet.SerializeToString(&data);
Network::SendCommand(address, "nodeRegisterAcknowledge", data);
Network::SendCommand(address, "nodeRegisterAcknowledge", packet.SerializeAsString());
});
Network::Handle("nodeRegisterAcknowledge", [] (Network::Address address, std::string data)
@ -417,10 +394,10 @@ namespace Components
Logger::Print("Received acknowledgment from %s\n", address.GetString());
Proto::NodePacket packet;
Proto::Node::Packet packet;
if (!packet.ParseFromString(data)) return;
if (!packet.signature().size()) return;
if (!packet.publickey().size()) return;
if (packet.signature().empty()) return;
if (packet.publickey().empty()) return;
std::string publicKey = packet.publickey();
std::string signature = packet.signature();
@ -483,10 +460,10 @@ namespace Components
Node::NodeEntry* entry = Node::FindNode(address);
if (!entry || !entry->registered) return;
Proto::NodePacket packet;
Proto::Node::Packet packet;
if (!packet.ParseFromString(data)) return;
if (!packet.challenge().size()) return;
if (!packet.signature().size()) return;
if (packet.challenge().empty()) return;
if (packet.signature().empty()) return;
std::string challenge = packet.challenge();
std::string signature = packet.signature();
@ -573,31 +550,31 @@ namespace Components
Network::Handle("nodeListResponse", [] (Network::Address address, std::string data)
{
if (data.size() % sizeof(Node::AddressEntry) != 1)
Proto::Node::List list;
if (data.empty() || !list.ParseFromString(data))
{
Logger::Print("Received invalid node list from %s!\n", address.GetString());
return;
}
unsigned int size = ((data.size() - 1) / sizeof(Node::AddressEntry));
Node::AddressEntry* addresses = reinterpret_cast<Node::AddressEntry*>(const_cast<char*>(data.data() + 1));
bool isDedicated = (*data.data() != 0);
Node::NodeEntry* entry = Node::FindNode(address);
if (entry)
{
if (entry->registered)
{
Logger::Print("Received valid node list with %d entries from %s\n", size, address.GetString());
Logger::Print("Received valid node list with %i entries from %s\n", list.address_size(), address.GetString());
entry->isDedi = isDedicated;
entry->isDedi = list.is_dedi();
entry->state = Node::STATE_VALID;
entry->lastTime = Game::Com_Milliseconds();
entry->lastListQuery = Game::Com_Milliseconds();
for (unsigned int i = 0; i < size; ++i)
for (int i = 0; i < list.address_size(); ++i)
{
Node::AddNode(addresses[i].toNetAddress());
Network::Address addr;
addr.Deserialize(list.address(i));
Node::AddNode(addr);
}
}
}
@ -610,9 +587,11 @@ namespace Components
{
session->lastTime = Game::Com_Milliseconds();
for (unsigned int i = 0; i < size; ++i)
for (int i = 0; i < list.address_size(); ++i)
{
Node::AddNode(addresses[i].toNetAddress());
Network::Address addr;
addr.Deserialize(list.address(i));
Node::AddNode(addr);
}
}
}

View File

@ -6,9 +6,6 @@
#define NODE_STORE_INTERVAL 1000 * 60* 1 // Store nodes every minute
#define SESSION_TIMEOUT 1000 * 10 // 10 seconds session timeout
// Protobuf
#include "proto/node.pb.h"
namespace Components
{
class Node : public Component
@ -56,31 +53,6 @@ namespace Components
int lastTime;
};
#pragma pack(push, 1)
struct AddressEntry
{
Game::netIP_t ip;
unsigned short port;
Network::Address toNetAddress()
{
Network::Address address;
address.SetIP(this->ip);
address.SetPort(ntohs(this->port));
address.SetType(Game::netadrtype_t::NA_IP);
return address;
}
void fromNetAddress(Network::Address address)
{
this->ip = address.GetIP();
this->port = htons(address.GetPort());
}
};
#pragma pack(pop)
static Utils::Cryptography::ECDSA::Key SignatureKey;
static std::vector<NodeEntry> Nodes;

View File

@ -285,7 +285,7 @@ namespace Components
info.Set("hc", (Dvar::Var("g_hardcore").Get<bool>() ? "1" : "0"));
// Ensure mapname is set
if (!info.Get("mapname").size())
if (info.Get("mapname").empty())
{
info.Set("mapname", Dvar::Var("ui_mapname").Get<const char*>());
}

View File

@ -106,7 +106,7 @@ namespace Components
info.Set("isPrivate", (Dvar::Var("g_password").Get<std::string>().size() ? "1" : "0"));
// Ensure mapname is set
if (!info.Get("mapname").size())
if (info.Get("mapname").empty())
{
info.Set("mapname", Dvar::Var("ui_mapname").Get<const char*>());
}

View File

@ -236,7 +236,7 @@ namespace Components
zoneHeader.assetList.assets = reinterpret_cast<Game::XAsset*>(-1);
// Increment ScriptStrings count (for empty script string) if available
if (ZoneBuilder::Zone::ScriptStrings.size())
if (!ZoneBuilder::Zone::ScriptStrings.empty())
{
zoneHeader.assetList.stringList.count = ZoneBuilder::Zone::ScriptStrings.size() + 1;
zoneHeader.assetList.stringList.strings = reinterpret_cast<const char**>(-1);
@ -247,7 +247,7 @@ namespace Components
ZoneBuilder::Zone::Buffer.PushBlock(Game::XFILE_BLOCK_VIRTUAL); // Push main stream onto the stream stack
// Write ScriptStrings, if available
if (ZoneBuilder::Zone::ScriptStrings.size())
if (!ZoneBuilder::Zone::ScriptStrings.empty())
{
ZoneBuilder::Zone::Buffer.SaveNull(4); // Empty script string?
// This actually represents a NULL string, but as scriptString.
@ -361,7 +361,7 @@ namespace Components
// Might optimize that later
if (!gameIndex)
{
if (!ZoneBuilder::Zone::ScriptStrings.size())
if (ZoneBuilder::Zone::ScriptStrings.empty())
{
ZoneBuilder::Zone::ScriptStrings.push_back("");
}

10
src/Proto/network.proto Normal file
View File

@ -0,0 +1,10 @@
syntax = "proto3";
package Proto.Network;
// TODO: Add support for IPv6, once the game supports it (I assume we'll implement it :P)
message Address
{
uint32 ip = 1;
uint32 port = 2; // Actually only 16 bits, but apparently protobuf handles that (https://groups.google.com/d/msg/protobuf/Er39mNGnRWU/x6Srz_GrZPgJ)
}

View File

@ -1,10 +1,17 @@
syntax = "proto3";
package Proto;
package Proto.Node;
import "network.proto";
message NodePacket
message Packet
{
bytes challenge = 1;
bytes signature = 2;
bytes publicKey = 3;
bytes publickey = 3;
}
message List
{
bool is_dedi = 1;
repeated Network.Address address = 2;
}

View File

@ -61,6 +61,10 @@
#include <tomcrypt.h>
#include <wink/signal.hpp>
// Protobuf
#include "proto/network.pb.h"
#include "proto/node.pb.h"
#pragma warning(pop)
// Version number

View File

@ -78,7 +78,7 @@ namespace Utils
buffer = file;
}
if (buffer.size())
if (!buffer.empty())
{
auto rows = Utils::Explode(buffer, '\n');

View File

@ -146,7 +146,7 @@ namespace Utils
bool Stream::PopBlock()
{
if (Stream::StreamStack.size())
if (!Stream::StreamStack.empty())
{
Stream::StreamStack.pop_back();
return true;
@ -175,7 +175,7 @@ namespace Utils
Game::XFILE_BLOCK_TYPES Stream::GetCurrentBlock()
{
if (Stream::StreamStack.size())
if (!Stream::StreamStack.empty())
{
return Stream::StreamStack[Stream::StreamStack.size() - 1];
}

View File

@ -121,7 +121,7 @@ namespace Utils
std::string key = param->first;
std::string value = param->second;
if (body.size()) body.append("&");
if (!body.empty()) body.append("&");
body.append(key);
body.append("=");