diff --git a/src/network/network_manager.cpp b/src/network/network_manager.cpp index 096b2e0c0..d60d59cc8 100644 --- a/src/network/network_manager.cpp +++ b/src/network/network_manager.cpp @@ -111,20 +111,29 @@ void NetworkManager::notifyEvent(Event* event) Log::info("NetworkManager", "Message, Sender : %u, message = \"%s\"", event->peer->getAddress(), event->data.c_str()); break; case EVENT_TYPE_DISCONNECTED: + { Log::info("NetworkManager", "Somebody is now disconnected. There are now %lu peers.", m_peers.size()); Log::info("NetworkManager", "Disconnected host: %i.%i.%i.%i:%i", event->peer->getAddress()>>24&0xff, event->peer->getAddress()>>16&0xff, event->peer->getAddress()>>8&0xff, event->peer->getAddress()&0xff,event->peer->getPort()); // remove the peer: + bool removed = false; for (unsigned int i = 0; i < m_peers.size(); i++) { - if (m_peers[i] == event->peer) + if (m_peers[i] == event->peer && !removed) // remove only one { delete m_peers[i]; m_peers.erase(m_peers.begin()+i, m_peers.begin()+i+1); - break; + Log::info("NetworkManager", "The peer has been removed from the Network Manager."); + removed = true; + } + else if (m_peers[i] == event->peer) + { + Log::fatal("NetworkManager", "Multiple peers match the disconnected one."); } } - Log::fatal("NetworkManager", "The peer that has been disconnected was not registered by the Network Manager."); + if (!removed) + Log::fatal("NetworkManager", "The peer that has been disconnected was not registered by the Network Manager."); break; + } case EVENT_TYPE_CONNECTED: Log::info("NetworkManager", "A client has just connected. There are now %lu peers.", m_peers.size() + 1); // create the new peer: diff --git a/src/network/protocols/connect_to_peer.cpp b/src/network/protocols/connect_to_peer.cpp index fd75ed419..05713b12a 100644 --- a/src/network/protocols/connect_to_peer.cpp +++ b/src/network/protocols/connect_to_peer.cpp @@ -84,8 +84,16 @@ void ConnectToPeer::update() if (m_listener->getProtocolState(m_current_protocol_id) == PROTOCOL_STATE_TERMINATED) // we know the peer address { - m_state = CONNECTING; - m_current_protocol_id = m_listener->requestStart(new PingProtocol(m_peer_address, 2.0)); + if (m_peer_address.ip != 0 && m_peer_address.port != 0) + { + m_state = CONNECTING; + m_current_protocol_id = m_listener->requestStart(new PingProtocol(m_peer_address, 2.0)); + } + else + { + Log::error("ConnectToPeer", "The peer you want to connect to has hidden his address."); + m_state = DONE; + } } break; case CONNECTING: // waiting the peer to connect diff --git a/src/network/protocols/lobby_room_protocol.cpp b/src/network/protocols/lobby_room_protocol.cpp index a872e5dcd..3adf82b0e 100644 --- a/src/network/protocols/lobby_room_protocol.cpp +++ b/src/network/protocols/lobby_room_protocol.cpp @@ -24,6 +24,7 @@ #include "network/protocols/get_public_address.hpp" #include "network/protocols/show_public_address.hpp" #include "network/protocols/connect_to_peer.hpp" +#include "network/protocols/start_server.hpp" #include "online/current_online_user.hpp" #include "online/http_connector.hpp" #include "config/user_config.hpp" @@ -253,16 +254,16 @@ void ServerLobbyRoomProtocol::update() if (ProtocolManager::getInstance()->getProtocolState(m_current_protocol_id) == PROTOCOL_STATE_TERMINATED) { NetworkManager::getInstance()->setPublicAddress(m_public_address); - m_current_protocol_id = ProtocolManager::getInstance()->requestStart(new ShowPublicAddress()); - m_state = SHOWING_PUBLIC_ADDRESS; + m_current_protocol_id = ProtocolManager::getInstance()->requestStart(new StartServer()); + m_state = LAUNCHING_SERVER; Log::info("ServerLobbyRoomProtocol", "Public address known."); } break; - case SHOWING_PUBLIC_ADDRESS: + case LAUNCHING_SERVER: if (ProtocolManager::getInstance()->getProtocolState(m_current_protocol_id) == PROTOCOL_STATE_TERMINATED) { m_state = WORKING; - Log::info("ServerLobbyRoomProtocol", "Public address visible."); + Log::info("ServerLobbyRoomProtocol", "Server setup"); } break; case WORKING: diff --git a/src/network/protocols/lobby_room_protocol.hpp b/src/network/protocols/lobby_room_protocol.hpp index f04b4e894..0866dada2 100644 --- a/src/network/protocols/lobby_room_protocol.hpp +++ b/src/network/protocols/lobby_room_protocol.hpp @@ -89,7 +89,7 @@ class ServerLobbyRoomProtocol : public LobbyRoomProtocol { NONE, GETTING_PUBLIC_ADDRESS, - SHOWING_PUBLIC_ADDRESS, + LAUNCHING_SERVER, WORKING, DONE }; diff --git a/src/network/protocols/start_server.cpp b/src/network/protocols/start_server.cpp new file mode 100644 index 000000000..17ccdfe27 --- /dev/null +++ b/src/network/protocols/start_server.cpp @@ -0,0 +1,61 @@ +#include "network/protocols/start_server.hpp" + +#include "network/network_manager.hpp" +#include "online/current_online_user.hpp" +#include "online/http_connector.hpp" +#include "config/user_config.hpp" + +StartServer::StartServer() : Protocol(NULL, PROTOCOL_SILENT) +{ +} + +StartServer::~StartServer() +{ +} + +void StartServer::notifyEvent(Event* event) +{ +} + +void StartServer::setup() +{ + m_state = NONE; +} + +void StartServer::update() +{ + if (m_state == NONE) + { + HTTPConnector * connector = new HTTPConnector((std::string)UserConfigParams::m_server_multiplayer + "address-management.php"); + connector->setParameter("id",CurrentOnlineUser::get()->getUserID()); + connector->setParameter("token",CurrentOnlineUser::get()->getToken()); + TransportAddress addr = NetworkManager::getInstance()->getPublicAddress(); + connector->setParameter("address",addr.ip); + connector->setParameter("port",addr.port); + connector->setParameter("action","start-server"); + + const XMLNode * result = connector->getXMLFromPage(); + std::string rec_success; + + if(result->get("success", &rec_success)) + { + if(rec_success == "yes") + { + Log::info("StartServer", "Server is now online."); + } + else + { + Log::error("StartServer", "Fail to start server."); + } + } + else + { + Log::error("StartServer", "Fail to start server."); + } + m_state = DONE; + } + else if (m_state == DONE) + { + m_listener->requestTerminate(this); + } +} diff --git a/src/network/protocols/start_server.hpp b/src/network/protocols/start_server.hpp new file mode 100644 index 000000000..9982a3bd3 --- /dev/null +++ b/src/network/protocols/start_server.hpp @@ -0,0 +1,29 @@ +#ifndef START_SERVER_HPP +#define START_SERVER_HPP + +#include "network/protocol.hpp" + +/*! + * This protocol tells to the database that the server is up and running, + * and shows online the public IP:port that stores the NetworkManager. + */ +class StartServer : public Protocol +{ + public: + StartServer(); + virtual ~StartServer(); + + virtual void notifyEvent(Event* event); + virtual void setup(); + virtual void update(); + + protected: + enum STATE + { + NONE, + DONE + }; + STATE m_state; +}; + +#endif // START_SERVER_HPP diff --git a/src/network/protocols/stop_server.cpp b/src/network/protocols/stop_server.cpp new file mode 100644 index 000000000..b74f3f4c7 --- /dev/null +++ b/src/network/protocols/stop_server.cpp @@ -0,0 +1,61 @@ +#include "network/protocols/stop_server.hpp" + +#include "network/network_manager.hpp" +#include "online/current_online_user.hpp" +#include "online/http_connector.hpp" +#include "config/user_config.hpp" + +StopServer::StopServer() : Protocol(NULL, PROTOCOL_SILENT) +{ +} + +StopServer::~StopServer() +{ +} + +void StopServer::notifyEvent(Event* event) +{ +} + +void StopServer::setup() +{ + m_state = NONE; +} + +void StopServer::update() +{ + if (m_state == NONE) + { + TransportAddress addr = NetworkManager::getInstance()->getPublicAddress(); + HTTPConnector * connector = new HTTPConnector((std::string)UserConfigParams::m_server_multiplayer + "address-management.php"); + connector->setParameter("id",CurrentOnlineUser::get()->getUserID()); + connector->setParameter("token",CurrentOnlineUser::get()->getToken()); + connector->setParameter("address",addr.ip); + connector->setParameter("port",addr.port); + connector->setParameter("action","stop-server"); + + const XMLNode * result = connector->getXMLFromPage(); + std::string rec_success; + + if(result->get("success", &rec_success)) + { + if(rec_success == "yes") + { + Log::info("StopServer", "Server is now offline."); + } + else + { + Log::error("StopServer", "Fail to stop server."); + } + } + else + { + Log::error("StopServer", "Fail to stop server."); + } + m_state = DONE; + } + else if (m_state == DONE) + { + m_listener->requestTerminate(this); + } +} diff --git a/src/network/protocols/stop_server.hpp b/src/network/protocols/stop_server.hpp new file mode 100644 index 000000000..3c07f2e98 --- /dev/null +++ b/src/network/protocols/stop_server.hpp @@ -0,0 +1,29 @@ +#ifndef STOP_SERVER_HPP +#define STOP_SERVER_HPP + +#include "network/protocol.hpp" + + +/*! \brief Removes the server info from the database + */ + +class StopServer : public Protocol +{ + public: + StopServer(); + virtual ~StopServer(); + + virtual void notifyEvent(Event* event); + virtual void setup(); + virtual void update(); + + protected: + enum STATE + { + NONE, + DONE + }; + STATE m_state; +}; + +#endif // STOP_SERVER_HPP diff --git a/src/network/server_network_manager.cpp b/src/network/server_network_manager.cpp index 095036456..eae2e6ce3 100644 --- a/src/network/server_network_manager.cpp +++ b/src/network/server_network_manager.cpp @@ -23,19 +23,51 @@ #include "network/protocols/show_public_address.hpp" #include "network/protocols/get_peer_address.hpp" #include "network/protocols/connect_to_server.hpp" +#include "network/protocols/stop_server.hpp" +#include "main_loop.hpp" #include "utils/log.hpp" #include #include +#include +#include +#include + +void* waitInput(void* data) +{ + std::string str = ""; + bool stop = false; + while(!stop) + { + getline(std::cin, str); + if (str == "quit") + { + stop = true; + } + } + + uint32_t id = ProtocolManager::getInstance()->requestStart(new StopServer()); + while(ProtocolManager::getInstance()->getProtocolState(id) != PROTOCOL_STATE_TERMINATED) + { + } + + main_loop->abort(); + exit(0); + + return NULL; +} ServerNetworkManager::ServerNetworkManager() { m_localhost = NULL; + m_thread_keyboard = NULL; } ServerNetworkManager::~ServerNetworkManager() { + if (m_thread_keyboard) + pthread_cancel(*m_thread_keyboard);//, SIGKILL); } void ServerNetworkManager::run() @@ -49,6 +81,10 @@ void ServerNetworkManager::run() m_localhost->setupServer(STKHost::HOST_ANY, 7321, 16, 2, 0, 0); m_localhost->startListening(); + // listen keyboard console input + m_thread_keyboard = (pthread_t*)(malloc(sizeof(pthread_t))); + pthread_create(m_thread_keyboard, NULL, waitInput, NULL); + NetworkManager::run(); } diff --git a/src/network/server_network_manager.hpp b/src/network/server_network_manager.hpp index 2ac0a3a02..e06b969b9 100644 --- a/src/network/server_network_manager.hpp +++ b/src/network/server_network_manager.hpp @@ -42,6 +42,8 @@ class ServerNetworkManager : public NetworkManager protected: ServerNetworkManager(); virtual ~ServerNetworkManager(); + + pthread_t* m_thread_keyboard; };