Fixed some errors related to disconnecting
This commit is contained in:
parent
9649135f43
commit
65436429b8
7 changed files with 119 additions and 56 deletions
|
|
@ -45,12 +45,22 @@ void NetClient::update() {
|
|||
if(isDisconnected)
|
||||
return;
|
||||
if(std::chrono::steady_clock::now() - lastMessageTime >= NetLibrary::TIMEOUT_DURATION) {
|
||||
Logger::get().log("INFO", "Connection timed out");
|
||||
Logger::get().log("INFO", "[NetClient::update] Connection timed out");
|
||||
isDisconnected = true;
|
||||
return;
|
||||
}
|
||||
parse_received_messages();
|
||||
send_queued_messages();
|
||||
try {
|
||||
parse_received_messages();
|
||||
send_queued_messages();
|
||||
}
|
||||
catch(const std::exception& e) {
|
||||
Logger::get().log("INFO", "[NetClient::update] Exception thrown while parsing and sending messages: " + std::string(e.what()));
|
||||
isDisconnected = true;
|
||||
}
|
||||
catch(...) {
|
||||
Logger::get().log("INFO", "[NetClient::update] Unknown exception thrown while parsing and sending messages.");
|
||||
isDisconnected = true;
|
||||
}
|
||||
}
|
||||
|
||||
void NetClient::parse_received_messages() {
|
||||
|
|
|
|||
|
|
@ -26,8 +26,20 @@ void NetServer::update() {
|
|||
if(client->setToDisconnect)
|
||||
disconnectCallback(client);
|
||||
else {
|
||||
client->parse_received_messages(*this);
|
||||
client->send_queued_messages(*this);
|
||||
try {
|
||||
client->parse_received_messages(*this);
|
||||
client->send_queued_messages(*this);
|
||||
}
|
||||
catch(const std::exception& e) {
|
||||
Logger::get().log("INFO", "[NetServer::update] Exception thrown while parsing and sending messages for a client: " + std::string(e.what()));
|
||||
client->setToDisconnect = true;
|
||||
disconnectCallback(client);
|
||||
}
|
||||
catch(...) {
|
||||
Logger::get().log("INFO", "[NetServer::update] Unknown exception thrown while parsing and sending messages for a client.");
|
||||
client->setToDisconnect = true;
|
||||
disconnectCallback(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,19 +101,24 @@ namespace NetworkingObjects {
|
|||
uint32_t actualPosToInsertAt = posToInsertAt = std::min<uint32_t>(posToInsertAt, data.size());
|
||||
|
||||
// Find duplicate. If found, erase the duplicate before inserting
|
||||
std::shared_ptr<NetObjOrderedListObjectInfo<T>> newObjInfoPtr;
|
||||
auto itObjAlreadyInData = idToDataMap.find(newObj.get_net_id());
|
||||
if(itObjAlreadyInData != idToDataMap.end()) {
|
||||
uint32_t posToErase = itObjAlreadyInData->second->pos;
|
||||
newObjInfoPtr = data[posToErase];
|
||||
data.erase(data.begin() + posToErase);
|
||||
idToDataMap.erase(itObjAlreadyInData);
|
||||
if(posToErase < actualPosToInsertAt) // Shift insert position if an element was erased before the insert position
|
||||
actualPosToInsertAt--;
|
||||
newObjInfoPtr->pos = actualPosToInsertAt;
|
||||
data.insert(data.begin() + actualPosToInsertAt, newObjInfoPtr);
|
||||
}
|
||||
else {
|
||||
// Insert the new object if no duplicate found
|
||||
newObjInfoPtr = std::make_shared<NetObjOrderedListObjectInfo<T>>(newObj, 0, false);
|
||||
data.insert(data.begin() + actualPosToInsertAt, newObjInfoPtr);
|
||||
idToDataMap.emplace(newObjInfoPtr->obj.get_net_id(), newObjInfoPtr);
|
||||
}
|
||||
|
||||
// Insert the new object
|
||||
auto newObjInfoPtr = std::make_shared<NetObjOrderedListObjectInfo<T>>(newObj, actualPosToInsertAt, false);
|
||||
data.insert(data.begin() + actualPosToInsertAt, newObjInfoPtr);
|
||||
idToDataMap.emplace(newObjInfoPtr->obj.get_net_id(), newObjInfoPtr);
|
||||
l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr, posToInsertAt](const NetObjPtr<NetObjOrderedList<T>>&, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(ObjPtrOrderedListCommand_StoC::INSERT_SINGLE, posToInsertAt); // Dont send actual pos to insert at, since client will check for duplicates on its own and shift the index if necessary
|
||||
newObjInfoPtr->obj.write_create_message(a);
|
||||
|
|
@ -182,20 +187,28 @@ namespace NetworkingObjects {
|
|||
virtual void insert(const NetObjPtr<NetObjOrderedList<T>>& l, uint32_t posToInsertAt, const NetObjPtr<T>& newObj) {
|
||||
uint32_t actualPosToInsertAt = posToInsertAt = std::min<uint32_t>(posToInsertAt, clientData.size());
|
||||
|
||||
// Find duplicate. If found, erase the duplicate before inserting
|
||||
NetObjOrderedListObjectInfoPtr<T> newObjInfoPtr;
|
||||
auto itObjAlreadyInData = clientIdToDataMap.find(newObj.get_net_id());
|
||||
if(itObjAlreadyInData != clientIdToDataMap.end()) {
|
||||
uint32_t posToErase = itObjAlreadyInData->second->pos;
|
||||
newObjInfoPtr = clientData[posToErase];
|
||||
clientData.erase(clientData.begin() + posToErase);
|
||||
clientIdToDataMap.erase(itObjAlreadyInData);
|
||||
if(posToErase < actualPosToInsertAt) // Shift insert position if an element was erased before the insert position
|
||||
actualPosToInsertAt--;
|
||||
clientData.insert(clientData.begin() + actualPosToInsertAt, newObjInfoPtr);
|
||||
}
|
||||
else {
|
||||
auto serverIt = serverIdToDataMap.find(newObj.get_net_id()); // No duplicate in client data, but check if it's already in server data
|
||||
if(serverIt != serverIdToDataMap.end())
|
||||
newObjInfoPtr = serverIt->second;
|
||||
else
|
||||
newObjInfoPtr = std::make_shared<NetObjOrderedListObjectInfo<T>>(newObj, 0, true);
|
||||
clientData.insert(clientData.begin() + actualPosToInsertAt, newObjInfoPtr);
|
||||
clientIdToDataMap.emplace(newObjInfoPtr->obj.get_net_id(), newObjInfoPtr);
|
||||
}
|
||||
|
||||
// Insert the new object
|
||||
auto newObjInfoPtr = std::make_shared<NetObjOrderedListObjectInfo<T>>(newObj, actualPosToInsertAt, false);
|
||||
clientData.insert(clientData.begin() + actualPosToInsertAt, newObjInfoPtr);
|
||||
clientIdToDataMap.emplace(newObjInfoPtr->obj.get_net_id(), newObjInfoPtr);
|
||||
newObjInfoPtr->syncIgnore = true;
|
||||
|
||||
l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr, posToInsertAt](const NetObjPtr<NetObjOrderedList<T>>&, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(ObjPtrOrderedListCommand_CtoS::INSERT_SINGLE, posToInsertAt); // Don't put actual pos to insert at, since the server will check for duplicates and might shift the index on its own
|
||||
newObjInfoPtr->obj.write_create_message(a);
|
||||
|
|
@ -235,26 +248,43 @@ namespace NetworkingObjects {
|
|||
a(c);
|
||||
switch(c) {
|
||||
case ObjPtrOrderedListCommand_StoC::INSERT_SINGLE: {
|
||||
uint32_t newPos;
|
||||
a(newPos);
|
||||
auto toInsert = std::make_shared<NetObjOrderedListObjectInfo<T>>(l.get_obj_man()->template read_create_message<T>(a, nullptr), newPos, false);
|
||||
auto it = serverIdToDataMap.find(toInsert->obj.get_net_id());
|
||||
uint32_t newServerPos;
|
||||
a(newServerPos);
|
||||
auto objToInsert = l.get_obj_man()->template read_create_message<T>(a, nullptr);
|
||||
auto it = serverIdToDataMap.find(objToInsert.get_net_id());
|
||||
if(it != serverIdToDataMap.end()) {
|
||||
uint32_t posToErase = it->second->pos;
|
||||
serverData.erase(serverData.begin() + posToErase);
|
||||
serverIdToDataMap.erase(it);
|
||||
if(posToErase < newPos)
|
||||
newPos--; // Shift if there was a duplicate before this
|
||||
uint32_t serverPosErased = std::numeric_limits<uint32_t>::max();
|
||||
std::erase_if(serverData, [&](auto& objInfo) {
|
||||
if(objToInsert.get_net_id() == objInfo->obj.get_net_id()) {
|
||||
serverPosErased = &objInfo - &serverData[0];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
assert(serverPosErased != std::numeric_limits<uint32_t>::max());
|
||||
if(serverPosErased < newServerPos)
|
||||
newServerPos--; // Shift if there was a duplicate before this
|
||||
//it->second->pos = newServerPos; // NOTE: DO NOT set the pos variable here, as pos is reserved for the position in the client vector
|
||||
serverData.insert(serverData.begin() + newServerPos, it->second);
|
||||
}
|
||||
else {
|
||||
NetObjOrderedListObjectInfoPtr<T> objInfoToInsert;
|
||||
auto clientIt = clientIdToDataMap.find(objToInsert.get_net_id());
|
||||
if(clientIt != clientIdToDataMap.end())
|
||||
objInfoToInsert = clientIt->second;
|
||||
else
|
||||
objInfoToInsert = std::make_shared<NetObjOrderedListObjectInfo<T>>(objToInsert, 0, false);
|
||||
objInfoToInsert->syncIgnore = false;
|
||||
serverData.insert(serverData.begin() + newServerPos, objInfoToInsert);
|
||||
serverIdToDataMap.emplace(objInfoToInsert->obj.get_net_id(), objInfoToInsert);
|
||||
}
|
||||
serverIdToDataMap.emplace(toInsert->obj.get_net_id(), toInsert);
|
||||
serverData.insert(serverData.begin() + newPos, toInsert);
|
||||
break;
|
||||
}
|
||||
case ObjPtrOrderedListCommand_StoC::ERASE_SINGLE: {
|
||||
uint32_t posToErase;
|
||||
a(posToErase);
|
||||
NetObjID objID = serverData[posToErase]->obj.get_net_id();
|
||||
serverData.erase(serverData.begin() + posToErase);
|
||||
uint32_t serverPosToErase;
|
||||
a(serverPosToErase);
|
||||
NetObjID objID = serverData[serverPosToErase]->obj.get_net_id();
|
||||
serverData.erase(serverData.begin() + serverPosToErase);
|
||||
serverIdToDataMap.erase(objID);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "Server/CommandList.hpp"
|
||||
#include <chrono>
|
||||
#include "World.hpp"
|
||||
#include <Helpers/Logger.hpp>
|
||||
|
||||
void ConnectionManager::init_local_p2p(World& initWorld, const std::string& serverLocalID) {
|
||||
localServer = std::make_unique<MainServer>(initWorld, serverLocalID);
|
||||
|
|
@ -18,8 +19,9 @@ void ConnectionManager::connect_p2p(World& initWorld, const std::string& serverF
|
|||
}
|
||||
|
||||
void ConnectionManager::update() {
|
||||
if(localServer)
|
||||
if(localServer) {
|
||||
localServer->update();
|
||||
}
|
||||
if(client) {
|
||||
client->update();
|
||||
if(std::chrono::steady_clock::now() - lastKeepAliveTime > std::chrono::seconds(2)) {
|
||||
|
|
|
|||
|
|
@ -96,6 +96,10 @@ void MainProgram::update() {
|
|||
setTabToClose.reset();
|
||||
}
|
||||
|
||||
std::erase_if(worlds, [&](const std::shared_ptr<World>& w) {
|
||||
return w->setToDestroy;
|
||||
});
|
||||
|
||||
if(worldIndex >= worlds.size())
|
||||
worldIndex = worlds.size() - 1;
|
||||
if(worlds.size() == 0)
|
||||
|
|
|
|||
|
|
@ -77,11 +77,6 @@ World::World(MainProgram& initMain, OpenWorldInfo& worldInfo):
|
|||
stringListTest->emplace_back_direct(stringListTest, "Hello");
|
||||
stringListTest = netObjMan.make_obj<NetObjOrderedList<std::string>>();
|
||||
stringListTest->emplace_back_direct(stringListTest, "World!");
|
||||
|
||||
//stringListTest->emplace_back_direct(stringListTest, "World");
|
||||
//stringListTest->emplace_back_direct(stringListTest, "Test");
|
||||
//for(const NetObjOrderedListObjectInfoPtr<std::string>& o : stringListTest->get_data())
|
||||
// std::cout << "At position: " << o->get_pos() << " we have string: \"" << *o->get_obj() << "\" with object id " << o->get_obj().get_net_id().to_string() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -103,9 +98,10 @@ void World::init_client_callbacks() {
|
|||
drawProg.initialize_draw_data(message);
|
||||
message(bMan, gridMan);
|
||||
stringListTest = netObjMan.read_create_message<NetworkingObjects::NetObjOrderedList<std::string>>(message, nullptr);
|
||||
std::cout << "Client print: " << std::endl;
|
||||
for(const NetworkingObjects::NetObjOrderedListObjectInfoPtr<std::string>& o : stringListTest->get_data())
|
||||
std::cout << "At position: " << o->get_pos() << " we have string: \"" << *o->get_obj() << "\" with object id " << o->get_obj().get_net_id().to_string() << std::endl;
|
||||
//std::cout << "============================================" << std::endl;
|
||||
//std::cout << "Client print: " << std::endl;
|
||||
//for(const NetworkingObjects::NetObjOrderedListObjectInfoPtr<std::string>& o : stringListTest->get_data())
|
||||
// std::cout << "At position: " << o->get_pos() << " we have string: \"" << *o->get_obj() << "\" with object id " << o->get_obj().get_net_id().to_string() << std::endl;
|
||||
}
|
||||
nextClientID = get_max_id(ownID);
|
||||
clientStillConnecting = false;
|
||||
|
|
@ -120,11 +116,13 @@ void World::init_client_callbacks() {
|
|||
add_chat_message(clients[id].displayName, "joined", Toolbar::ChatMessage::Type::JOIN);
|
||||
});
|
||||
con.client_add_recv_callback(CLIENT_UPDATE_NETWORK_OBJECT, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
if(!con.host_exists()) { // Dont update a direct connected client (which is just the server)
|
||||
if(!con.host_exists() && !clientStillConnecting) { // Dont update a direct connected client (which is just the server), and dont process these until the CLIENT_INITIAL_DATA message is received first
|
||||
netObjMan.read_update_message(message, nullptr);
|
||||
std::cout << "Client print update: " << std::endl;
|
||||
for(const NetworkingObjects::NetObjOrderedListObjectInfoPtr<std::string>& o : stringListTest->get_data())
|
||||
std::cout << "At position: " << o->get_pos() << " we have string: \"" << *o->get_obj() << "\" with object id " << o->get_obj().get_net_id().to_string() << std::endl;
|
||||
//std::cout << "============================================\n";
|
||||
//std::cout << "Client print update: \n";
|
||||
//for(const NetworkingObjects::NetObjOrderedListObjectInfoPtr<std::string>& o : stringListTest->get_data())
|
||||
// std::cout << "At position: " << o->get_pos() << " we have string: \"" << *o->get_obj() << "\" with object id " << o->get_obj().get_net_id().to_string() << '\n';
|
||||
//std::cout << std::endl;
|
||||
}
|
||||
});
|
||||
con.client_add_recv_callback(CLIENT_USER_DISCONNECT, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
|
|
@ -180,13 +178,6 @@ size_t strToAddNum = 0;
|
|||
void World::focus_update() {
|
||||
con.update();
|
||||
|
||||
//testTimer++;
|
||||
//if(testTimer == 1000) {
|
||||
// std::cout << "added: " << strToAddNum << std::endl;
|
||||
// stringListTest->emplace_back_direct(stringListTest, std::to_string(strToAddNum++));
|
||||
// testTimer = 0;
|
||||
//}
|
||||
|
||||
if(con.is_host_disconnected()) {
|
||||
Logger::get().log("USERINFO", "Host connection failed");
|
||||
clientStillConnecting = false;
|
||||
|
|
@ -198,11 +189,8 @@ void World::focus_update() {
|
|||
|
||||
if(con.is_client_disconnected()) {
|
||||
Logger::get().log("USERINFO", "Client connection failed");
|
||||
clientStillConnecting = false;
|
||||
clients.clear();
|
||||
netSource.clear();
|
||||
conType = CONNECTIONTYPE_LOCAL;
|
||||
con = ConnectionManager();
|
||||
setToDestroy = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!clientStillConnecting) {
|
||||
|
|
@ -220,6 +208,17 @@ void World::focus_update() {
|
|||
}
|
||||
con.client_send_items_to_server(UNRELIABLE_COMMAND_CHANNEL, SERVER_MOVE_SCREEN_MOUSE, main.input.mouse.pos);
|
||||
drawProg.update();
|
||||
|
||||
testTimer++;
|
||||
if(testTimer == 1) {
|
||||
std::string strToAdd = (netObjMan.is_server() ? "Server " : "Client ") + std::to_string(strToAddNum++);
|
||||
//std::cout << "============================================\n";
|
||||
//std::cout << "Added: " << strToAdd << std::endl;
|
||||
stringListTest->emplace_back_direct(stringListTest, strToAdd);
|
||||
//for(const NetworkingObjects::NetObjOrderedListObjectInfoPtr<std::string>& o : stringListTest->get_data())
|
||||
// std::cout << "At position: " << o->get_pos() << " we have string: \"" << *o->get_obj() << "\" with object id " << o->get_obj().get_net_id().to_string() << std::endl;
|
||||
testTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
drawData.cam.update_main(*this);
|
||||
|
|
@ -247,6 +246,10 @@ void World::redo_with_checks() {
|
|||
|
||||
void World::unfocus_update() {
|
||||
con.update();
|
||||
if(con.is_client_disconnected()) {
|
||||
Logger::get().log("USERINFO", "Client connection failed");
|
||||
setToDestroy = true;
|
||||
}
|
||||
}
|
||||
|
||||
void World::set_canvas_background_color(const Vector3f& newBackColor, bool sendChangeOverNetwork) {
|
||||
|
|
|
|||
|
|
@ -106,6 +106,8 @@ class World {
|
|||
void scale_up_step();
|
||||
|
||||
uint64_t canvasScale = 0;
|
||||
|
||||
bool setToDestroy = false;
|
||||
private:
|
||||
|
||||
ClientPortionID get_max_id(ServerPortionID serverID);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue