diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 11 | ||||
-rw-r--r-- | src/account-server/accountclient.h | 1 | ||||
-rw-r--r-- | src/account-server/accounthandler.cpp | 186 | ||||
-rw-r--r-- | src/account-server/accounthandler.h | 10 | ||||
-rw-r--r-- | src/account-server/main-account.cpp | 131 | ||||
-rw-r--r-- | src/account-server/serverhandler.cpp | 5 | ||||
-rw-r--r-- | src/account-server/serverhandler.h | 5 | ||||
-rw-r--r-- | src/common/manaserv_protocol.h | 2 | ||||
-rw-r--r-- | src/net/connectionhandler.cpp | 21 | ||||
-rw-r--r-- | src/net/connectionhandler.h | 23 |
10 files changed, 323 insertions, 72 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b7e7c48a..26658271 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,7 @@ find_package(LibXml2 REQUIRED) find_package(PhysFS REQUIRED) find_package(ZLIB REQUIRED) find_package(SigC++ REQUIRED) +find_package(RapidJSON REQUIRED) if(CMAKE_COMPILER_IS_GNUCXX) # Help getting compilation warnings @@ -46,7 +47,7 @@ set(FLAGS "${FLAGS} -DPACKAGE_VERSION=\\\"${VERSION}\\\"") set(FLAGS "${FLAGS} -DPKG_DATADIR=\\\"${PKG_DATADIR}/\\\"") set(FLAGS "${FLAGS} -DLOCALEDIR=\\\"${LOCALEDIR}/\\\"") -set(FLAGS "${FLAGS} -std=c++0x") +set(FLAGS "${FLAGS} -std=c++17") set(FLAGS "${FLAGS} -Woverloaded-virtual") # Prevent clashes with icu namespace @@ -312,6 +313,14 @@ set(PROGRAMS manaserv-account manaserv-game) add_executable(manaserv-game WIN32 ${SRCS} ${SRCS_MANASERVGAME}) add_executable(manaserv-account WIN32 ${SRCS} ${SRCS_MANASERVACCOUNT}) +target_include_directories(manaserv-account SYSTEM PRIVATE + ${CMAKE_SOURCE_DIR}/libs/uWebSockets/src + ${CMAKE_SOURCE_DIR}/libs/uWebSockets/uSockets/src + ${RAPIDJSON_INCLUDE_DIRS}) + +target_link_libraries(manaserv-account + ${CMAKE_SOURCE_DIR}/libs/uWebSockets/uSockets/uSockets.a) + foreach(program ${PROGRAMS}) target_link_libraries( ${program} diff --git a/src/account-server/accountclient.h b/src/account-server/accountclient.h index 3973d60b..5ccb0f1d 100644 --- a/src/account-server/accountclient.h +++ b/src/account-server/accountclient.h @@ -51,6 +51,7 @@ class AccountClient : public NetComputer AccountClientStatus status; int version; + std::string stellarToken; private: std::unique_ptr<Account> mAccount; diff --git a/src/account-server/accounthandler.cpp b/src/account-server/accounthandler.cpp index 2275e015..b13b4580 100644 --- a/src/account-server/accounthandler.cpp +++ b/src/account-server/accounthandler.cpp @@ -40,7 +40,6 @@ #include "utils/tokencollector.h" #include "utils/tokendispenser.h" #include "utils/sha256.h" -#include "utils/string.h" #include "utils/xml.h" using namespace ManaServ; @@ -68,6 +67,10 @@ public: void deletePendingConnect(int) {} /** + */ + void handleStellarLogin(const std::string &token, const std::string &pubKey); + + /** * Token collector for connecting a client coming from a game server * without having to provide username and password a second time. */ @@ -85,6 +88,7 @@ protected: private: void handleLoginRandTriggerMessage(AccountClient &client, MessageIn &msg); + void handleStellarLoginMessage(AccountClient &client, MessageIn &msg); void handleLoginMessage(AccountClient &client, MessageIn &msg); void handleLogoutMessage(AccountClient &client); void handleReconnectMessage(AccountClient &client, MessageIn &msg); @@ -97,7 +101,10 @@ private: void handleCharacterSelectMessage(AccountClient &client, MessageIn &msg); void handleCharacterDeleteMessage(AccountClient &client, MessageIn &msg); - void addServerInfo(MessageOut *msg); + std::unique_ptr<Account> createAccount(const std::string &username, + const std::string &password, + const std::string &email); + void addServerInfo(MessageOut &msg); /** List of all accounts which requested a random seed, but are not logged * yet. This list will be regularly remove (after timeout) old accounts @@ -239,9 +246,9 @@ void AccountClientHandler::deinitialize() accountHandler = nullptr; } -void AccountClientHandler::process() +ConnectionHandler *AccountClientHandler::getConnectionHandler() { - accountHandler->process(50); + return accountHandler; } void AccountClientHandler::prepareReconnect(const std::string &token, int id) @@ -249,6 +256,12 @@ void AccountClientHandler::prepareReconnect(const std::string &token, int id) accountHandler->mTokenCollector.addPendingConnect(token, id); } +void AccountClientHandler::handleStellarLogin(const std::string &token, const std::string &pubKey) +{ + accountHandler->handleStellarLogin(token, pubKey); +} + + NetComputer *AccountHandler::computerConnected(ENetPeer *peer) { return new AccountClient(peer); @@ -306,7 +319,7 @@ static void sendFullCharacterData(AccountClient *client, client->send(msg); } -static std::string getRandomString(int length) +static std::string getRandomData(int length) { std::string s; s.resize(length); @@ -318,9 +331,31 @@ static std::string getRandomString(int length) return s; } +/** + * Generates a random string containing lowercase and uppercase characters as + * well as numbers. + */ +static std::string getRandomString(int length) +{ + std::string s; + s.resize(length); + for (int i = 0; i < length; ++i) + { + int r = rand() % 62; + if (r < 10) + s[i] = '0' + r; + else if (r < 36) + s[i] = 'a' + r - 10; + else + s[i] = 'A' + r - 36; + } + + return s; +} + void AccountHandler::handleLoginRandTriggerMessage(AccountClient &client, MessageIn &msg) { - std::string salt = getRandomString(4); + std::string salt = getRandomData(4); std::string username = msg.readString(); if (auto acc = storage->getAccount(username)) @@ -333,6 +368,34 @@ void AccountHandler::handleLoginRandTriggerMessage(AccountClient &client, Messag client.send(reply); } +void AccountHandler::handleStellarLoginMessage(AccountClient &client, MessageIn &msg) +{ + client.version = msg.readInt32(); + + MessageOut reply(APMSG_STELLAR_LOGIN_RESPONSE); + + if (client.status != CLIENT_LOGIN) + { + reply.writeInt8(ERRMSG_FAILURE); + client.send(reply); + return; + } + + if (client.version < MIN_PROTOCOL_VERSION) + { + reply.writeInt8(LOGIN_INVALID_VERSION); + client.send(reply); + return; + } + + client.stellarToken = getRandomString(8); + + reply.writeInt8(ERRMSG_OK); + reply.writeString(client.stellarToken); + + client.send(reply); +} + void AccountHandler::handleLoginMessage(AccountClient &client, MessageIn &msg) { MessageOut reply(APMSG_LOGIN_RESPONSE); @@ -425,7 +488,7 @@ void AccountHandler::handleLoginMessage(AccountClient &client, MessageIn &msg) storage->updateLastLogin(*acc); reply.writeInt8(ERRMSG_OK); - addServerInfo(&reply); + addServerInfo(reply); const Characters &chars = acc->getCharacters(); @@ -534,24 +597,14 @@ void AccountHandler::handleRegisterMessage(AccountClient &client, } else { - std::unique_ptr<Account> acc { new Account }; - acc->setName(username); - acc->setPassword(sha256(password)); - // We hash email server-side for additional privacy - // we ask for it again when we need it and verify it - // through comparing it with the hash. - acc->setEmail(sha256(email)); - acc->setLevel(AL_PLAYER); - - // Set the date and time of the account registration, and the last login - time_t regdate; - time(®date); - acc->setRegistrationDate(regdate); - acc->setLastLogin(regdate); - - storage->addAccount(*acc); + // We hash email server-side for additional privacy we ask for it again + // when we need it and verify it through comparing it with the hash. + std::unique_ptr<Account> acc = createAccount(username, + sha256(password), + sha256(email)); + reply.writeInt8(ERRMSG_OK); - addServerInfo(&reply); + addServerInfo(reply); // Associate account with connection client.setAccount(std::move(acc)); @@ -960,6 +1013,26 @@ void AccountHandler::handleCharacterDeleteMessage(AccountClient &client, client.send(reply); } +std::unique_ptr<Account> AccountHandler::createAccount(const std::string &username, + const std::string &password, + const std::string &email) +{ + std::unique_ptr<Account> acc { new Account }; + acc->setName(username); + acc->setPassword(password); + acc->setEmail(email); + acc->setLevel(AL_PLAYER); + + // Set the date and time of the account registration, and the last login + time_t regdate; + time(®date); + acc->setRegistrationDate(regdate); + acc->setLastLogin(regdate); + + storage->addAccount(*acc); + return acc; +} + /** * Adds server specific info to the current message * @@ -968,11 +1041,11 @@ void AccountHandler::handleCharacterDeleteMessage(AccountClient &client, * (String) Client Data URL (or "") * (Byte) Number of maximum character slots (empty or not) */ -void AccountHandler::addServerInfo(MessageOut *msg) +void AccountHandler::addServerInfo(MessageOut &msg) { - msg->writeString(mUpdateHost); - msg->writeString(mDataUrl); - msg->writeInt8(mMaxCharacters); + msg.writeString(mUpdateHost); + msg.writeString(mDataUrl); + msg.writeInt8(mMaxCharacters); } void AccountHandler::tokenMatched(AccountClient *client, int accountID) @@ -1001,6 +1074,58 @@ void AccountHandler::deletePendingClient(AccountClient *client) // The client will be deleted when the disconnect event is processed } +void AccountHandler::handleStellarLogin(const std::string &token, const std::string &pubKey) +{ + auto it = std::find_if(clients.begin(), clients.end(), + [token](NetComputer *client) -> bool + { + auto c = static_cast<AccountClient *>(client); + return c->stellarToken == token; + }); + + if (it == clients.end()) + { + LOG_DEBUG("Stellar login: No client with token " << token); + return; + } + + auto client = static_cast<AccountClient*>(*it); + auto acc = storage->getAccount(pubKey); + if (acc) + { + // Set lastLogin date of the account. + time_t login; + time(&login); + acc->setLastLogin(login); + storage->updateLastLogin(*acc); + } + else if (!mRegistrationAllowed) + { + MessageOut reply(APMSG_REGISTER_RESPONSE); + reply.writeInt8(ERRMSG_FAILURE); + client->send(reply); + return; + } + else + { + // On-demand account creation for public keys + acc = createAccount(pubKey, std::string(), std::string()); + } + + MessageOut reply(APMSG_LOGIN_RESPONSE); + reply.writeInt8(ERRMSG_OK); + addServerInfo(reply); + + for (auto &charIt : acc->getCharacters()) + sendCharacterData(reply, charIt.second); + + client->send(reply); + + // Associate account with connection. + client->setAccount(std::move(acc)); + client->status = CLIENT_CONNECTED; +} + void AccountHandler::processMessage(NetComputer *comp, MessageIn &message) { AccountClient &client = *static_cast< AccountClient * >(comp); @@ -1017,6 +1142,11 @@ void AccountHandler::processMessage(NetComputer *comp, MessageIn &message) handleLoginMessage(client, message); break; + case PAMSG_STELLAR_LOGIN: + LOG_DEBUG("Received msg ... PAMSG_STELLAR_LOGIN"); + handleStellarLoginMessage(client, message); + break; + case PAMSG_LOGOUT: LOG_DEBUG("Received msg ... PAMSG_LOGOUT"); handleLogoutMessage(client); diff --git a/src/account-server/accounthandler.h b/src/account-server/accounthandler.h index f1ffcfe2..c27b00ed 100644 --- a/src/account-server/accounthandler.h +++ b/src/account-server/accounthandler.h @@ -23,6 +23,8 @@ #include <string> +class ConnectionHandler; + namespace AccountClientHandler { /** @@ -37,14 +39,18 @@ namespace AccountClientHandler void deinitialize(); /** + * Returns the connection handler. + */ + ConnectionHandler *getConnectionHandler(); + + /** * Prepares a connection for a client coming from a game server. */ void prepareReconnect(const std::string &token, int accountID); /** - * Processes messages received by the connection handler. */ - void process(); + void handleStellarLogin(const std::string &token, const std::string &pubKey); } #endif // ACCOUNTHANDLER_H diff --git a/src/account-server/main-account.cpp b/src/account-server/main-account.cpp index 73382f23..4d5bf02a 100644 --- a/src/account-server/main-account.cpp +++ b/src/account-server/main-account.cpp @@ -45,7 +45,6 @@ #include "utils/processorutils.h" #include "utils/stringfilter.h" #include "utils/time.h" -#include "utils/timer.h" #include <cstdlib> #include <getopt.h> @@ -54,6 +53,8 @@ #include <fstream> #include <physfs.h> #include <enet/enet.h> +#include <rapidjson/document.h> +#include <App.h> using utils::Logger; @@ -185,20 +186,26 @@ static void deinitializeServer() /** * Dumps statistics. */ -static void dumpStatistics(std::string accountAddress, int accountClientPort, - int accountGamePort, int chatClientPort) +static void dumpStatistics() { - std::ofstream os(statisticsFile.c_str()); + std::ofstream os(statisticsFile); + os << "<statistics>\n"; + // Print last heartbeat os << "<heartbeat=\"" << utils::getCurrentDate() << "_" - << utils::getCurrentTime() << "\" />\n"; + << utils::getCurrentTime() << "\" />\n"; + // Add account server information - os << "<accountserver address=\"" << accountAddress << "\" clientport=\"" - << accountClientPort << "\" gameport=\"" << accountGamePort - << "\" chatclientport=\"" << chatClientPort << "\" />\n"; + auto accountHandler = AccountClientHandler::getConnectionHandler(); + auto gameHandler = GameServerHandler::getConnectionHandler(); + os << "<accountserver address=\"" << accountHandler->getHostname() << "\" clientport=\"" + << accountHandler->getPort() << "\" gameport=\"" << gameHandler->getPort() + << "\" chatclientport=\"" << chatHandler->getPort() << "\" />\n"; + // Add game servers information GameServerHandler::dumpStatistics(os); + os << "</statistics>\n"; } @@ -333,6 +340,8 @@ int main(int argc, char *argv[]) "localhost"); std::string accountListenToGameHost = Configuration::getValue("net_accountListenToGameHost", accountHost); + std::string accountListenToStellarBridgeHost = Configuration::getValue("net_accountListenToStellarBridgeHost", + accountListenToGameHost); // We separate the chat host as the chat server will be separated out // from the account server. @@ -350,6 +359,8 @@ int main(int argc, char *argv[]) options.port + 1); int chatClientPort = Configuration::getValue("net_chatListenToClientPort", options.port + 2); + int accountStellarBridgePort = Configuration::getValue("net_accountListenToStellarBridgePort", + options.port + 4); bool debugNetwork = Configuration::getBoolValue("net_debugMode", false); MessageOut::setDebugModeEnabled(debugNetwork); @@ -363,13 +374,78 @@ int main(int argc, char *argv[]) return EXIT_NET_EXCEPTION; } - // Dump statistics every 10 seconds. - utils::Timer statTimer(10000); - // Check for expired bans every 30 seconds - utils::Timer banTimer(30000); - - statTimer.start(); - banTimer.start(); + struct us_loop_t *loop = (struct us_loop_t *) uWS::Loop::get(); + struct us_timer_t *processTimer = us_create_timer(loop, 0, 0); + struct us_timer_t *statTimer = us_create_timer(loop, 0, 0); + struct us_timer_t *banTimer = us_create_timer(loop, 0, 0); + + constexpr int processTimerIntervalMs = 1000 / 20; // 20 times per second + constexpr int statTimerIntervalMs = 10 * 1000; // dump statistics every 10 seconds + constexpr int banTimerIntervalMs = 30 * 1000; // check bans every 30 seconds + + us_timer_set(processTimer, [](struct us_timer_t *) { + AccountClientHandler::getConnectionHandler()->process(); + GameServerHandler::getConnectionHandler()->process(); + chatHandler->process(); + }, processTimerIntervalMs, processTimerIntervalMs); + + us_timer_set(statTimer, [](struct us_timer_t *) { + dumpStatistics(); + }, statTimerIntervalMs, statTimerIntervalMs); + + us_timer_set(banTimer, [](struct us_timer_t *) { + storage->checkBannedAccounts(); + }, banTimerIntervalMs, banTimerIntervalMs); + + uWS::App wsApp; + + struct PerSocketData {}; + wsApp.ws<PerSocketData>("/stellar-auth", { + .maxPayloadLength = 1024, // we only expect small messages + .open = [](auto *ws) { + std::cout << "WebSocket opened " << ws->getRemoteAddressAsText() << std::endl; + }, + .message = [](auto *ws, std::string_view message, uWS::OpCode /*opCode*/) { + rapidjson::Document d; + d.Parse(message.data(), message.size()); + if (d.HasParseError()) { + LOG_ERROR("WebSocket: received JSON parse error"); + return; + } + if (!d.IsObject()) { + std::cout << "not an object" << std::endl; + LOG_ERROR("WebSocket: received JSON not an object"); + return; + } + + const auto pubkeyMember = d.FindMember("pubkey"); + const auto tokenMember = d.FindMember("token"); + + if (pubkeyMember == d.MemberEnd() || tokenMember == d.MemberEnd()) { + LOG_ERROR("WebSocket: received JSON missing pubkey or token"); + return; + } + if (!pubkeyMember->value.IsString() || !tokenMember->value.IsString()) { + LOG_ERROR("WebSocket: received JSON pubkey or token not a string"); + return; + } + + const std::string pubkey = pubkeyMember->value.GetString(); + const std::string token = tokenMember->value.GetString(); + + AccountClientHandler::handleStellarLogin(token, pubkey); + }, + .close = [](auto *ws, int code, std::string_view message) { + std::cout << "WebSocket closed " << ws->getRemoteAddressAsText() << " with code " << code << ": " << message << std::endl; + } + }).listen(accountListenToStellarBridgeHost, accountStellarBridgePort, [](us_listen_socket_t *listen_socket) { + if (listen_socket) { + /* Note that us_listen_socket_t is castable to us_socket_t */ + std::cout << "WebSocket: Thread " << std::this_thread::get_id() << " listening on port " << us_socket_local_port(1, (struct us_socket_t *) listen_socket) << std::endl; + } else { + std::cout << "WebSocket: Thread " << std::this_thread::get_id() << " failed to listen on port 3000" << std::endl; + } + }); // Write startup time to database as system world state variable std::stringstream timestamp; @@ -377,19 +453,22 @@ int main(int argc, char *argv[]) storage->setWorldStateVar("accountserver_startup", timestamp.str(), Storage::SystemMap); - while (running) - { - AccountClientHandler::process(); - GameServerHandler::process(); - chatHandler->process(50); + // Start a thread to close the sockets and timers when running is set to false + std::thread([&wsApp,processTimer,statTimer,banTimer] { + while (running) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } - if (statTimer.poll()) - dumpStatistics(accountHost, options.port, accountGamePort, - chatClientPort); + LOG_INFO("Closing uWebSockets app..."); + wsApp.close(); - if (banTimer.poll()) - storage->checkBannedAccounts(); - } + LOG_INFO("Closing uSockets timers..."); + us_timer_close(processTimer); + us_timer_close(statTimer); + us_timer_close(banTimer); + }).detach(); + + wsApp.run(); LOG_INFO("Received: Quit signal, closing down..."); chatHandler->stopListen(); diff --git a/src/account-server/serverhandler.cpp b/src/account-server/serverhandler.cpp index cc53eace..54754546 100644 --- a/src/account-server/serverhandler.cpp +++ b/src/account-server/serverhandler.cpp @@ -109,11 +109,12 @@ void GameServerHandler::deinitialize() { serverHandler->stopListen(); delete serverHandler; + serverHandler = nullptr; } -void GameServerHandler::process() +ConnectionHandler *GameServerHandler::getConnectionHandler() { - serverHandler->process(50); + return serverHandler; } NetComputer *ServerHandler::computerConnected(ENetPeer *peer) diff --git a/src/account-server/serverhandler.h b/src/account-server/serverhandler.h index 6f4c61fe..916a0224 100644 --- a/src/account-server/serverhandler.h +++ b/src/account-server/serverhandler.h @@ -27,6 +27,7 @@ #include "net/messagein.h" class CharacterData; +class ConnectionHandler; namespace GameServerHandler { @@ -57,9 +58,9 @@ namespace GameServerHandler void dumpStatistics(std::ostream &); /** - * Processes messages received by the connection handler. + * Returns the connection handler. */ - void process(); + ConnectionHandler *getConnectionHandler(); /** * Sends chat party information diff --git a/src/common/manaserv_protocol.h b/src/common/manaserv_protocol.h index ce41c723..77b8e5ac 100644 --- a/src/common/manaserv_protocol.h +++ b/src/common/manaserv_protocol.h @@ -79,6 +79,8 @@ enum { APMSG_LOGOUT_RESPONSE = 0x0014, // B error PAMSG_LOGIN_RNDTRGR = 0x0015, // S username APMSG_LOGIN_RNDTRGR_RESPONSE = 0x0016, // S random seed + PAMSG_STELLAR_LOGIN = 0x0017, // D version + APMSG_STELLAR_LOGIN_RESPONSE = 0x0018, // B error, S token PAMSG_CHAR_CREATE = 0x0020, // S name, B hair style, B hair color, B gender, B slot, {W stats}* APMSG_CHAR_CREATE_RESPONSE = 0x0021, // B error, on success: B slot, S name, B gender, B hair style, B hair color, // W character points, W correction points, B amount of items equipped, diff --git a/src/net/connectionhandler.cpp b/src/net/connectionhandler.cpp index 4edb1fd2..ee98a18b 100644 --- a/src/net/connectionhandler.cpp +++ b/src/net/connectionhandler.cpp @@ -36,16 +36,20 @@ #endif bool ConnectionHandler::startListen(enet_uint16 port, - const std::string &listenHost) + const std::string &hostname) { + // Remember unresolved host for debugging purposes. + this->hostname = hostname; + // Bind the server to the default localhost. + ENetAddress address; address.host = ENET_HOST_ANY; address.port = port; - if (!listenHost.empty()) - enet_address_set_host(&address, listenHost.c_str()); + if (!hostname.empty()) + enet_address_set_host(&address, hostname.c_str()); - LOG_INFO("Listening on " << listenHost << ":" << port << "..."); + LOG_INFO("Listening on " << hostname << ":" << port << "..."); #if defined(ENET_VERSION) && ENET_VERSION >= ENET_CUTOFF host = enet_host_create( &address /* the address to bind the server host to */, @@ -86,6 +90,11 @@ void ConnectionHandler::stopListen() // FIXME: memory leak on NetComputers } +enet_uint16 ConnectionHandler::getPort() const +{ + return host ? host->address.port : 0; +} + void ConnectionHandler::flush() { enet_host_flush(host); @@ -93,9 +102,11 @@ void ConnectionHandler::flush() void ConnectionHandler::process(enet_uint32 timeout) { + enet_host_service(host, nullptr, timeout); + ENetEvent event; // Process Enet events and do not block. - while (enet_host_service(host, &event, timeout) > 0) { + while (enet_host_check_events(host, &event) > 0) { switch (event.type) { case ENET_EVENT_TYPE_CONNECT: { diff --git a/src/net/connectionhandler.h b/src/net/connectionhandler.h index e49d49a9..2d0a2a6a 100644 --- a/src/net/connectionhandler.h +++ b/src/net/connectionhandler.h @@ -41,11 +41,12 @@ class ConnectionHandler /** * Open the server socket. - * @param port the port to listen to - * @host the host IP to listen on, defaults to the default localhost + * + * @param port the port to listen to + * @param hostname the host IP to listen on, defaults to the default localhost */ bool startListen(enet_uint16 port, - const std::string &host = std::string()); + const std::string &hostname = std::string()); /** * Disconnect all the clients and close the server socket. @@ -53,13 +54,23 @@ class ConnectionHandler void stopListen(); /** + * Return the port the handler is listening on, or 0 if not listening. + */ + enet_uint16 getPort() const; + + /** + * Return the host the handler was asked to listen on. + */ + const std::string &getHostname() const { return hostname; } + + /** * Process outgoing messages and listen to the server socket for * incoming messages and new connections. * * @timeout an optional timeout in milliseconds to wait for something * to happen when there is nothing to do */ - virtual void process(enet_uint32 timeout = 0); + void process(enet_uint32 timeout = 0); /** * Process outgoing messages. @@ -82,8 +93,8 @@ class ConnectionHandler unsigned getClientCount() const; private: - ENetAddress address; /**< Includes the port to listen to. */ - ENetHost *host; /**< The host that listen for connections. */ + std::string hostname; /**< The unresolved host the handler was asked to listen on. */ + ENetHost *host; /**< The ENet host that listen for connections. */ protected: /** |