Implement client side node synchronization.
This commit is contained in:
parent
40d6c6d715
commit
d87a6ced42
@ -50,7 +50,7 @@ namespace Components
|
|||||||
|
|
||||||
Node::NodeEntry* Node::FindNode(Network::Address address)
|
Node::NodeEntry* Node::FindNode(Network::Address address)
|
||||||
{
|
{
|
||||||
for (auto i = Node::Nodes.begin(); i != Node::Nodes.end(); i++)
|
for (auto i = Node::Nodes.begin(); i != Node::Nodes.end(); ++i)
|
||||||
{
|
{
|
||||||
if (i->address == address)
|
if (i->address == address)
|
||||||
{
|
{
|
||||||
@ -63,7 +63,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
Node::ClientSession* Node::FindSession(Network::Address address)
|
Node::ClientSession* Node::FindSession(Network::Address address)
|
||||||
{
|
{
|
||||||
for (auto i = Node::Sessions.begin(); i != Node::Sessions.end(); i++)
|
for (auto i = Node::Sessions.begin(); i != Node::Sessions.end(); ++i)
|
||||||
{
|
{
|
||||||
if (i->address == address)
|
if (i->address == address)
|
||||||
{
|
{
|
||||||
@ -105,13 +105,13 @@ namespace Components
|
|||||||
|
|
||||||
void Node::SendNodeList(Network::Address address)
|
void Node::SendNodeList(Network::Address address)
|
||||||
{
|
{
|
||||||
if (address.IsSelf() || !Dedicated::IsDedicated()) return;
|
if (address.IsSelf()) return;
|
||||||
|
|
||||||
std::vector<Node::AddressEntry> entries;
|
std::vector<Node::AddressEntry> entries;
|
||||||
|
|
||||||
for (auto entry : Node::Nodes)
|
for (auto entry : Node::Nodes)
|
||||||
{
|
{
|
||||||
if (entry.state == Node::STATE_VALID && entry.registered) // Only send valid nodes, or shall we send invalid ones as well?
|
if (entry.state == Node::STATE_VALID && entry.registered)
|
||||||
{
|
{
|
||||||
Node::AddressEntry thisAddress;
|
Node::AddressEntry thisAddress;
|
||||||
thisAddress.fromNetAddress(entry.address);
|
thisAddress.fromNetAddress(entry.address);
|
||||||
@ -122,7 +122,7 @@ namespace Components
|
|||||||
if (entries.size() >= NODE_PACKET_LIMIT)
|
if (entries.size() >= NODE_PACKET_LIMIT)
|
||||||
{
|
{
|
||||||
std::string packet = "nodeListResponse\n";
|
std::string packet = "nodeListResponse\n";
|
||||||
packet.append("\x01", 1); // Yes, we are a dedi
|
packet.append((Dedicated::IsDedicated() ? "\x01" : "\0"), 1);
|
||||||
packet.append(reinterpret_cast<char*>(entries.data()), entries.size() * sizeof(Node::AddressEntry));
|
packet.append(reinterpret_cast<char*>(entries.data()), entries.size() * sizeof(Node::AddressEntry));
|
||||||
|
|
||||||
Network::SendRaw(address, packet);
|
Network::SendRaw(address, packet);
|
||||||
@ -132,7 +132,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string packet = "nodeListResponse\n";
|
std::string packet = "nodeListResponse\n";
|
||||||
packet.append("\x01", 1); // Yes, we are a dedi
|
packet.append((Dedicated::IsDedicated() ? "\x01" : "\0"), 1);
|
||||||
packet.append(reinterpret_cast<char*>(entries.data()), entries.size() * sizeof(Node::AddressEntry));
|
packet.append(reinterpret_cast<char*>(entries.data()), entries.size() * sizeof(Node::AddressEntry));
|
||||||
|
|
||||||
Network::SendRaw(address, packet);
|
Network::SendRaw(address, packet);
|
||||||
@ -144,11 +144,11 @@ namespace Components
|
|||||||
|
|
||||||
for (auto session : Node::Sessions)
|
for (auto session : Node::Sessions)
|
||||||
{
|
{
|
||||||
if (session.terminated) continue;
|
if (session.lastTime > 0 && (Game::Com_Milliseconds() - session.lastTime) <= SESSION_TIMEOUT)
|
||||||
if ((Game::Com_Milliseconds() - session.lastTime) > SESSION_TIMEOUT) return;
|
{
|
||||||
|
|
||||||
cleanSessions.push_back(session);
|
cleanSessions.push_back(session);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cleanSessions.size() != Node::Sessions.size())
|
if (cleanSessions.size() != Node::Sessions.size())
|
||||||
{
|
{
|
||||||
@ -232,7 +232,8 @@ namespace Components
|
|||||||
Utils::Message::WriteBuffer(data, node.challenge);
|
Utils::Message::WriteBuffer(data, node.challenge);
|
||||||
|
|
||||||
Logger::Print("Sending registration request to %s\n", node.address.GetString());
|
Logger::Print("Sending registration request to %s\n", node.address.GetString());
|
||||||
Network::SendRaw(node.address, "nodeRegisterRequest\n" + data); }
|
Network::SendRaw(node.address, "nodeRegisterRequest\n" + data);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logger::Print("Sending session request to %s\n", node.address.GetString());
|
Logger::Print("Sending session request to %s\n", node.address.GetString());
|
||||||
@ -441,8 +442,8 @@ namespace Components
|
|||||||
Node::ClientSession* session = Node::FindSession(address);
|
Node::ClientSession* session = Node::FindSession(address);
|
||||||
if (session)
|
if (session)
|
||||||
{
|
{
|
||||||
allowed = (session->valid && !session->terminated);
|
session->lastTime = Game::Com_Milliseconds();
|
||||||
session->terminated = true;
|
allowed = session->valid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,10 +454,35 @@ namespace Components
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Unallowed connection
|
// Unallowed connection
|
||||||
|
Logger::Print("Node list requested by %s, but no valid session was present!\n", address.GetString());
|
||||||
Network::Send(address, "nodeListError\n");
|
Network::Send(address, "nodeListError\n");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Network::Handle("nodeDeregister", [] (Network::Address address, std::string data)
|
||||||
|
{
|
||||||
|
Node::NodeEntry* entry = Node::FindNode(address);
|
||||||
|
if (!entry || !entry->registered) return;
|
||||||
|
|
||||||
|
std::string challenge, signature;
|
||||||
|
if (!Utils::Message::ReadBuffer(data, challenge)) return;
|
||||||
|
if (!Utils::Message::ReadBuffer(data, signature)) return;
|
||||||
|
|
||||||
|
if (Utils::Cryptography::ECDSA::VerifyMessage(entry->publicKey, challenge, signature))
|
||||||
|
{
|
||||||
|
entry->lastHeard = Game::Com_Milliseconds();
|
||||||
|
entry->lastTime = Game::Com_Milliseconds();
|
||||||
|
entry->registered = false;
|
||||||
|
entry->state = Node::STATE_INVALID;
|
||||||
|
|
||||||
|
Logger::Print("Node %s unregistered\n", address.GetString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger::Print("Node %s tried to unregister using an invalid signature!\n", address.GetString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Network::Handle("sessionRequest", [] (Network::Address address, std::string data)
|
Network::Handle("sessionRequest", [] (Network::Address address, std::string data)
|
||||||
{
|
{
|
||||||
// Return if we already have a session for this address
|
// Return if we already have a session for this address
|
||||||
@ -468,7 +494,6 @@ namespace Components
|
|||||||
session.address = address;
|
session.address = address;
|
||||||
session.challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
|
session.challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
|
||||||
session.lastTime = Game::Com_Milliseconds();
|
session.lastTime = Game::Com_Milliseconds();
|
||||||
session.terminated = false;
|
|
||||||
session.valid = false;
|
session.valid = false;
|
||||||
|
|
||||||
Node::Sessions.push_back(session);
|
Node::Sessions.push_back(session);
|
||||||
@ -480,7 +505,7 @@ namespace Components
|
|||||||
{
|
{
|
||||||
// Return if we don't have a session for this address
|
// Return if we don't have a session for this address
|
||||||
Node::ClientSession* session = Node::FindSession(address);
|
Node::ClientSession* session = Node::FindSession(address);
|
||||||
if (!session || session->terminated || session->valid) return;
|
if (!session || session->valid) return;
|
||||||
|
|
||||||
if (session->challenge == data)
|
if (session->challenge == data)
|
||||||
{
|
{
|
||||||
@ -490,8 +515,8 @@ namespace Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
session->lastTime = -1;
|
||||||
Logger::Print("Challenge mismatch. Validating session for %s failed.\n", address.GetString());
|
Logger::Print("Challenge mismatch. Validating session for %s failed.\n", address.GetString());
|
||||||
session->terminated = true;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -513,12 +538,13 @@ namespace Components
|
|||||||
Node::NodeEntry* entry = Node::FindNode(address);
|
Node::NodeEntry* entry = Node::FindNode(address);
|
||||||
if (!entry) return;
|
if (!entry) return;
|
||||||
|
|
||||||
Logger::Print("Session acknowledged, requesting node list...\n", address.GetString());
|
|
||||||
|
|
||||||
entry->state = Node::STATE_VALID;
|
entry->state = Node::STATE_VALID;
|
||||||
entry->registered = true;
|
entry->registered = true;
|
||||||
entry->lastTime = Game::Com_Milliseconds();
|
entry->lastTime = Game::Com_Milliseconds();
|
||||||
|
|
||||||
|
Logger::Print("Session acknowledged, synchronizing node list...\n", address.GetString());
|
||||||
Network::Send(address, "nodeListRequest\n");
|
Network::Send(address, "nodeListRequest\n");
|
||||||
|
Node::SendNodeList(address);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,7 +580,18 @@ namespace Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Node::AddNode(address);
|
//Node::AddNode(address);
|
||||||
|
|
||||||
|
Node::ClientSession* session = Node::FindSession(address);
|
||||||
|
if (session && session->valid)
|
||||||
|
{
|
||||||
|
session->lastTime = Game::Com_Milliseconds();
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
Node::AddNode(addresses[i].toNetAddress());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -585,30 +622,6 @@ namespace Components
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Network::Handle("nodeDeregister", [] (Network::Address address, std::string data)
|
|
||||||
{
|
|
||||||
Node::NodeEntry* entry = Node::FindNode(address);
|
|
||||||
if (!entry || !entry->registered) return;
|
|
||||||
|
|
||||||
std::string challenge, signature;
|
|
||||||
if (!Utils::Message::ReadBuffer(data, challenge)) return;
|
|
||||||
if (!Utils::Message::ReadBuffer(data, signature)) return;
|
|
||||||
|
|
||||||
if (Utils::Cryptography::ECDSA::VerifyMessage(entry->publicKey, challenge, signature))
|
|
||||||
{
|
|
||||||
entry->lastHeard = Game::Com_Milliseconds();
|
|
||||||
entry->lastTime = Game::Com_Milliseconds();
|
|
||||||
entry->registered = false;
|
|
||||||
entry->state = Node::STATE_INVALID;
|
|
||||||
|
|
||||||
Logger::Print("Node %s unregistered\n", address.GetString());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger::Print("Node %s tried to unregister using an invalid signature!\n", address.GetString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Command::Add("listnodes", [] (Command::Params params)
|
Command::Add("listnodes", [] (Command::Params params)
|
||||||
{
|
{
|
||||||
Logger::Print("Nodes: %d\n", Node::Nodes.size());
|
Logger::Print("Nodes: %d\n", Node::Nodes.size());
|
||||||
@ -625,6 +638,13 @@ namespace Components
|
|||||||
|
|
||||||
Network::Address address(params[1]);
|
Network::Address address(params[1]);
|
||||||
Node::AddNode(address);
|
Node::AddNode(address);
|
||||||
|
|
||||||
|
Node::NodeEntry* entry = Node::FindNode(address);
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
entry->state = Node::STATE_UNKNOWN;
|
||||||
|
entry->registered = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Install frame handlers
|
// Install frame handlers
|
||||||
@ -655,7 +675,7 @@ namespace Components
|
|||||||
printf("Success\n");
|
printf("Success\n");
|
||||||
printf("Testing 10 valid signatures...");
|
printf("Testing 10 valid signatures...");
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++)
|
for (int i = 0; i < 10; ++i)
|
||||||
{
|
{
|
||||||
std::string message = Utils::VA("%d", Utils::Cryptography::Rand::GenerateInt());
|
std::string message = Utils::VA("%d", Utils::Cryptography::Rand::GenerateInt());
|
||||||
std::string signature = Utils::Cryptography::ECDSA::SignMessage(Node::SignatureKey, message);
|
std::string signature = Utils::Cryptography::ECDSA::SignMessage(Node::SignatureKey, message);
|
||||||
@ -671,7 +691,7 @@ namespace Components
|
|||||||
printf("Success\n");
|
printf("Success\n");
|
||||||
printf("Testing 10 invalid signatures...");
|
printf("Testing 10 invalid signatures...");
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++)
|
for (int i = 0; i < 10; ++i)
|
||||||
{
|
{
|
||||||
std::string message = Utils::VA("%d", Utils::Cryptography::Rand::GenerateInt());
|
std::string message = Utils::VA("%d", Utils::Cryptography::Rand::GenerateInt());
|
||||||
std::string signature = Utils::Cryptography::ECDSA::SignMessage(Node::SignatureKey, message);
|
std::string signature = Utils::Cryptography::ECDSA::SignMessage(Node::SignatureKey, message);
|
||||||
|
@ -41,7 +41,6 @@ namespace Components
|
|||||||
int lastListQuery; // Last time we got the list of the node
|
int lastListQuery; // Last time we got the list of the node
|
||||||
|
|
||||||
// This is only relevant for clients
|
// This is only relevant for clients
|
||||||
// Other nodes or dedis don't need to know if the entry is a dedi or not.
|
|
||||||
bool isDedi;
|
bool isDedi;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -50,7 +49,7 @@ namespace Components
|
|||||||
Network::Address address;
|
Network::Address address;
|
||||||
std::string challenge;
|
std::string challenge;
|
||||||
bool valid;
|
bool valid;
|
||||||
bool terminated;
|
//bool terminated; // Sessions can't explicitly be terminated, they can only timeout
|
||||||
int lastTime;
|
int lastTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ namespace Components
|
|||||||
// This whole procedure is potentially unsafe.
|
// This whole procedure is potentially unsafe.
|
||||||
// If any index changes, everything gets shifted and the stats are fucked.
|
// If any index changes, everything gets shifted and the stats are fucked.
|
||||||
int lastIndex = 0;
|
int lastIndex = 0;
|
||||||
for (int i = 0; i < dataEnum->numIndices; i++)
|
for (int i = 0; i < dataEnum->numIndices; ++i)
|
||||||
{
|
{
|
||||||
if (dataEnum->indices[i].index > lastIndex)
|
if (dataEnum->indices[i].index > lastIndex)
|
||||||
{
|
{
|
||||||
@ -56,7 +56,7 @@ namespace Components
|
|||||||
StructuredData::Indices[type] = StructuredData::GetSingleton()->MemAllocator.AllocateArray<Game::StructuredDataEnumEntry>(StructuredData::IndexCount[type]);
|
StructuredData::Indices[type] = StructuredData::GetSingleton()->MemAllocator.AllocateArray<Game::StructuredDataEnumEntry>(StructuredData::IndexCount[type]);
|
||||||
memcpy(StructuredData::Indices[type], dataEnum->indices, sizeof(Game::StructuredDataEnumEntry) * dataEnum->numIndices);
|
memcpy(StructuredData::Indices[type], dataEnum->indices, sizeof(Game::StructuredDataEnumEntry) * dataEnum->numIndices);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < entries.size(); i++)
|
for (unsigned int i = 0; i < entries.size(); ++i)
|
||||||
{
|
{
|
||||||
unsigned int pos = 0;
|
unsigned int pos = 0;
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ namespace Components
|
|||||||
|
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < ARR_SIZE(StructuredData::Entries); i++)
|
for (int i = 0; i < ARR_SIZE(StructuredData::Entries); ++i)
|
||||||
{
|
{
|
||||||
if (StructuredData::Entries[i].size())
|
if (StructuredData::Entries[i].size())
|
||||||
{
|
{
|
||||||
@ -164,7 +164,7 @@ namespace Components
|
|||||||
|
|
||||||
StructuredData::~StructuredData()
|
StructuredData::~StructuredData()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < ARR_SIZE(StructuredData::Entries); i++)
|
for (int i = 0; i < ARR_SIZE(StructuredData::Entries); ++i)
|
||||||
{
|
{
|
||||||
StructuredData::Entries[i].clear();
|
StructuredData::Entries[i].clear();
|
||||||
}
|
}
|
||||||
|
@ -271,7 +271,7 @@ namespace Game
|
|||||||
char* zoneIndices = reinterpret_cast<char*>(0x16B8A34);
|
char* zoneIndices = reinterpret_cast<char*>(0x16B8A34);
|
||||||
char* zoneData = reinterpret_cast<char*>(0x14C0F80);
|
char* zoneData = reinterpret_cast<char*>(0x14C0F80);
|
||||||
|
|
||||||
for (int i = 0; i < zoneCount; i++)
|
for (int i = 0; i < zoneCount; ++i)
|
||||||
{
|
{
|
||||||
std::string name = zoneData + 4 + 0xA4 * (zoneIndices[i] & 0xFF);
|
std::string name = zoneData + 4 + 0xA4 * (zoneIndices[i] & 0xFF);
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ namespace Utils
|
|||||||
{
|
{
|
||||||
char* memArr = reinterpret_cast<char*>(mem);
|
char* memArr = reinterpret_cast<char*>(mem);
|
||||||
|
|
||||||
for (size_t i = 0; i < length; i++)
|
for (size_t i = 0; i < length; ++i)
|
||||||
{
|
{
|
||||||
if (memArr[i] != chr)
|
if (memArr[i] != chr)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user