diff --git a/server/clients/client_manager.cpp b/server/clients/client_manager.cpp index 8fa0cb1..d2ae9bf 100644 --- a/server/clients/client_manager.cpp +++ b/server/clients/client_manager.cpp @@ -21,46 +21,89 @@ */ #include "client_manager.hpp" +#include "udp_network_utility.hpp" + +#include + +int ClientManager::CheckConnections() { + for (auto& it : elementMap) { + //3 seconds between beats + if (ClientData::Clock::now() - it.second.GetLastBeat() > std::chrono::seconds(3)) { + ServerPacket newPacket; + newPacket.type = SerialPacketType::PING; + UDPNetworkUtility::GetSingleton().SendTo(it.second.GetAddress(), &newPacket); + it.second.IncrementAttempts(); + } + } + + for (auto& it : elementMap) { + if (it.second.GetAttempts() > 2) { + int ret = it.first; + elementMap.erase(it.first); + return ret; + } + } + + return -1; +} + +void ClientManager::HandlePong(ServerPacket* const argPacket) { + //find and update the specified client + for (auto& it : elementMap) { + if (it.second.GetAddress().host == argPacket->srcAddress.host && + it.second.GetAddress().port == argPacket->srcAddress.port + ) { + it.second.ResetAttempts(); + return; + } + } +} + int ClientManager::Create(IPaddress add) { - //TODO -} - -int ClientManager::Load(IPaddress add) { - //TODO -} - -int ClientManager::Save(int uid) { - //TODO + ClientData& client = elementMap[counter]; + client.SetAddress(add); + return counter++; } void ClientManager::Unload(int uid) { - //TODO -} - -void ClientManager::Delete(int uid) { - //TODO + elementMap.erase(uid); } void ClientManager::UnloadAll() { - //TODO + elementMap.clear(); } void ClientManager::UnloadIf(std::function)> fn) { - //TODO + std::map::iterator it = elementMap.begin(); + while (it != elementMap.end()) { + if (fn(*it)) { + it = elementMap.erase(it); + //TODO: ? disconnect, unload characters, notify other clients + } + else { + ++it; + } + } } ClientData* ClientManager::Get(int uid) { - //TODO + std::map::iterator it = elementMap.find(uid); + + if (it == elementMap.end()) { + return nullptr; + } + + return &it->second; } int ClientManager::GetLoadedCount() { - //TODO + return elementMap.size(); } int ClientManager::GetTotalCount() { - //TODO + return elementMap.size(); } std::map* ClientManager::GetContainer() { - //TODO + return &elementMap; } \ No newline at end of file diff --git a/server/clients/client_manager.hpp b/server/clients/client_manager.hpp index 756fe0d..d90fb57 100644 --- a/server/clients/client_manager.hpp +++ b/server/clients/client_manager.hpp @@ -24,6 +24,7 @@ #include "client_data.hpp" #include "manager_interface.hpp" +#include "server_packet.hpp" #include "singleton.hpp" #include "SDL/SDL_net.h" @@ -31,16 +32,17 @@ #include class ClientManager: - Singleton, - ManagerInterface + public Singleton, + public ManagerInterface { public: + //methods + int CheckConnections(); + void HandlePong(ServerPacket* const argPacket); + //common public methods int Create(IPaddress) override; - int Load(IPaddress) override; - int Save(int uid) override; void Unload(int uid) override; - void Delete(int uid) override; void UnloadAll() override; void UnloadIf(std::function)> fn) override; @@ -57,6 +59,11 @@ private: ClientManager() = default; ~ClientManager() = default; + //EMPTY + int Load(IPaddress) override { return -1; } + int Save(int uid) override { return -1; } + void Delete(int uid) override { return; } + int counter = 0; }; diff --git a/server/clients/makefile b/server/clients/makefile index 2a5c671..4eb98bd 100644 --- a/server/clients/makefile +++ b/server/clients/makefile @@ -1,5 +1,5 @@ #config -INCLUDES+=. ../server_utilities ../../common/utilities +INCLUDES+=. ../server_utilities ../../common/network ../../common/network/packet_types ../../common/utilities LIBS+= CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) diff --git a/server/doors/door_manager.hpp b/server/doors/door_manager.hpp index 2933b52..bfed8ed 100644 --- a/server/doors/door_manager.hpp +++ b/server/doors/door_manager.hpp @@ -31,8 +31,8 @@ #include class DoorManager: - Singleton, - ManagerInterface + public Singleton, + public ManagerInterface { public: //common public methods diff --git a/server/monsters/monster_manager.hpp b/server/monsters/monster_manager.hpp index 8a12fbd..5fcc56b 100644 --- a/server/monsters/monster_manager.hpp +++ b/server/monsters/monster_manager.hpp @@ -38,8 +38,8 @@ #include class MonsterManager: - Singleton, - ManagerInterface + public Singleton, + public ManagerInterface { public: //common public methods diff --git a/server/server_application.hpp b/server/server_application.hpp index 64fe13c..e5e578a 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -22,16 +22,8 @@ #ifndef SERVERAPPLICATION_HPP_ #define SERVERAPPLICATION_HPP_ -//server specific stuff, mostly managers -#include "client_data.hpp" -#include "account_manager.hpp" -#include "character_manager.hpp" -#include "room_manager.hpp" - //common utilities -#include "udp_network_utility.hpp" #include "serial_packet.hpp" -#include "config_utility.hpp" #include "singleton.hpp" //APIs @@ -67,8 +59,6 @@ private: void HandlePacket(SerialPacket* const); //basic connections - void HandlePing(ServerPacket* const); - void HandlePong(ServerPacket* const); void HandleBroadcastRequest(ServerPacket* const); void HandleJoinRequest(ClientPacket* const); void HandleDisconnect(ClientPacket* const); @@ -86,7 +76,6 @@ private: void HandleSynchronize(ClientPacket* const); //utility methods - void CheckClientConnections(); //TODO: a function that only sends to characters in a certain proximity void CleanupLostConnection(int index); void PumpPacket(SerialPacket* const); diff --git a/server/server_logic.cpp b/server/server_logic.cpp index 5afdf99..ef25106 100644 --- a/server/server_logic.cpp +++ b/server/server_logic.cpp @@ -21,10 +21,21 @@ */ #include "server_application.hpp" +//managers +#include "account_manager.hpp" +#include "character_manager.hpp" +#include "client_manager.hpp" +#include "room_manager.hpp" + +//utilities +#include "config_utility.hpp" +#include "udp_network_utility.hpp" + //utility functions #include "sql_tools.hpp" #include "utility.hpp" +//std & STL #include #include #include @@ -41,7 +52,8 @@ void ServerApplication::Init(int argc, char* argv[]) { //NOTE: I might need to rearrange the init process so that lua & SQL can interact with the map system as needed. std::cout << "Beginning " << argv[0] << std::endl; - //load the prerequisites + //load the config settings + ConfigUtility& config = ConfigUtility::GetSingleton(); config.Load("rsc/config.cfg", argc, argv); //------------------------- @@ -58,7 +70,7 @@ void ServerApplication::Init(int argc, char* argv[]) { if (SDLNet_Init()) { throw(std::runtime_error("Failed to initialize SDL_net")); } - network.Open(config.Int("server.port")); + UDPNetworkUtility::GetSingleton().Open(config.Int("server.port")); std::cout << "Initialized SDL_net" << std::endl; //Init SQL @@ -77,7 +89,7 @@ void ServerApplication::Init(int argc, char* argv[]) { std::cout << "Initialized lua" << std::endl; - //append config["dir.scripts"] to the module path + //prepend config["dir.scripts"] to the module path if (config["dir.scripts"].size() > 0) { //get the original path lua_getglobal(luaState, "package"); @@ -100,10 +112,10 @@ void ServerApplication::Init(int argc, char* argv[]) { //------------------------- //set the hooks - accountMgr.SetDatabase(database); - characterMgr.SetDatabase(database); + AccountManager::GetSingleton().SetDatabase(database); + CharacterManager::GetSingleton().SetDatabase(database); - roomMgr.SetLuaState(luaState); + RoomManager::GetSingleton().SetLuaState(luaState); std::cout << "Internal managers initialized" << std::endl; @@ -164,14 +176,17 @@ void ServerApplication::Proc() { SerialPacket* packetBuffer = reinterpret_cast(new char[MAX_PACKET_SIZE]); while(running) { //suck in the waiting packets & process them - while(network.Receive(packetBuffer)) { + while(UDPNetworkUtility::GetSingleton().Receive(packetBuffer)) { HandlePacket(packetBuffer); } //update the internals //... //Check connections - CheckClientConnections(); + int disconnected = ClientManager::GetSingleton().CheckConnections(); + if (disconnected != -1) { + //TODO: clean up after this disconnection + } //give the computer a break SDL_Delay(10); @@ -183,17 +198,15 @@ void ServerApplication::Quit() { std::cout << "Shutting down" << std::endl; //close the managers - clientMap.clear(); - accountMgr.UnloadAll(); - characterMgr.UnloadAll(); - //TODO: unload combats - //TODO: unload enemies - roomMgr.UnloadAll(); + ClientManager::GetSingleton().UnloadAll(); + AccountManager::GetSingleton().UnloadAll(); + CharacterManager::GetSingleton().UnloadAll(); + RoomManager::GetSingleton().UnloadAll(); //APIs lua_close(luaState); sqlite3_close_v2(database); - network.Close(); + UDPNetworkUtility::GetSingleton().Close(); SDLNet_Quit(); SDL_Quit(); @@ -206,13 +219,18 @@ void ServerApplication::Quit() { void ServerApplication::HandlePacket(SerialPacket* const argPacket) { switch(argPacket->type) { - //basic connections - case SerialPacketType::PING: - HandlePing(static_cast(argPacket)); + //heartbeat system + case SerialPacketType::PING: { + ServerPacket newPacket; + newPacket.type = SerialPacketType::PONG; + UDPNetworkUtility::GetSingleton().SendTo(argPacket->srcAddress, &newPacket); + } break; case SerialPacketType::PONG: - HandlePong(static_cast(argPacket)); + ClientManager::GetSingleton().HandlePong(static_cast(argPacket)); break; + + //connections case SerialPacketType::BROADCAST_REQUEST: HandleBroadcastRequest(static_cast(argPacket)); break; diff --git a/server/server_methods.cpp b/server/server_methods.cpp index 0d07d01..e13bc47 100644 --- a/server/server_methods.cpp +++ b/server/server_methods.cpp @@ -28,26 +28,6 @@ //basic connections //------------------------- -//SET: utility -void ServerApplication::HandlePing(ServerPacket* const argPacket) { - ServerPacket newPacket; - newPacket.type = SerialPacketType::PONG; - network.SendTo(argPacket->srcAddress, &newPacket); -} - -//SET: utility/manager -void ServerApplication::HandlePong(ServerPacket* const argPacket) { - //find and update the specified client - for (auto& it : clientMap) { - if (it.second.GetAddress().host == argPacket->srcAddress.host && - it.second.GetAddress().port == argPacket->srcAddress.port - ) { - it.second.ResetAttempts(); - break; - } - } -} - //SET: utility void ServerApplication::HandleBroadcastRequest(ServerPacket* const argPacket) { //send the server's data @@ -293,24 +273,6 @@ void ServerApplication::HandleSynchronize(ClientPacket* const argPacket) { //utility methods //------------------------- -//SET: utility/manager -void ServerApplication::CheckClientConnections() { - for (auto& it : clientMap) { - if (std::chrono::steady_clock::now() - it.second.GetLastBeat() > std::chrono::seconds(3)) { - ServerPacket newPacket; - newPacket.type = SerialPacketType::PING; - network.SendTo(it.second.GetAddress(), &newPacket); - it.second.IncrementAttempts(); - } - - if (it.second.GetAttempts() > 2) { - CleanupLostConnection(it.first); - //all iterators are invalid, so we can't continue - break; - } - } -} - //SET: utility/manager void ServerApplication::CleanupLostConnection(int clientIndex) { //NOTE: This assumes each player has only one account and character at a time