diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/chat-server/chathandler.cpp | 125 | ||||
-rw-r--r-- | src/chat-server/chathandler.hpp | 56 | ||||
-rw-r--r-- | src/defines.h | 6 |
3 files changed, 83 insertions, 104 deletions
diff --git a/src/chat-server/chathandler.cpp b/src/chat-server/chathandler.cpp index d202dd99..8710168d 100644 --- a/src/chat-server/chathandler.cpp +++ b/src/chat-server/chathandler.cpp @@ -39,44 +39,19 @@ #include "utils/stringfilter.h" #include "utils/tokendispenser.hpp" - -struct ChatPendingLogin -{ - std::string character; - AccountLevel level; - int timeout; -}; - -typedef std::map< std::string, ChatPendingLogin > ChatPendingLogins; -static ChatPendingLogins pendingLogins; - -typedef std::map< std::string, ChatClient * > ChatPendingClients; -static ChatPendingClients pendingClients; - void registerChatClient(const std::string &token, const std::string &name, int level) { - ChatPendingClients::iterator i = pendingClients.find(token); - if (i != pendingClients.end()) - { - ChatClient *computer = i->second; - computer->characterName = name; - computer->accountLevel = (AccountLevel) level; - pendingClients.erase(i); - MessageOut result; - result.writeShort(CPMSG_CONNECT_RESPONSE); - result.writeByte(ERRMSG_OK); - computer->send(result); - } - else - { - ChatPendingLogin p; - p.character = name; - p.level = (AccountLevel) level; - p.timeout = 300; // world ticks - pendingLogins.insert(std::make_pair(token, p)); - } + ChatHandler::Pending *p = new ChatHandler::Pending; + p->character = name; + p->level = (AccountLevel) level; + chatHandler->mTokenCollector.addPendingConnect(token, p); +} + +ChatHandler::ChatHandler(): + mTokenCollector(this) +{ } bool ChatHandler::startListen(enet_uint16 port) @@ -85,15 +60,27 @@ bool ChatHandler::startListen(enet_uint16 port) return ConnectionHandler::startListen(port); } -void ChatHandler::removeOutdatedPending() +void ChatHandler::deletePendingClient(ChatClient *c) { - ChatPendingLogins::iterator i = pendingLogins.begin(), next; - while (i != pendingLogins.end()) - { - next = i; ++next; - if (--i->second.timeout <= 0) pendingLogins.erase(i); - i = next; - } + MessageOut msg(GPMSG_CONNECTION_TIMEDOUT); + + // The computer will be deleted when the disconnect event is processed + c->disconnect(msg); +} + +void ChatHandler::deletePendingConnect(Pending *p) +{ + delete p; +} + +void ChatHandler::tokenMatched(ChatClient *c, Pending *p) +{ + c->characterName = p->character; + c->accountLevel = p->level; + delete p; + MessageOut msg(CPMSG_CONNECT_RESPONSE); + msg.writeByte(ERRMSG_OK); + c->send(msg); } NetComputer *ChatHandler::computerConnected(ENetPeer *peer) @@ -101,28 +88,22 @@ NetComputer *ChatHandler::computerConnected(ENetPeer *peer) return new ChatClient(peer); } -void ChatHandler::computerDisconnected(NetComputer *computer) +void ChatHandler::computerDisconnected(NetComputer *comp) { - // Remove user from all channels - chatChannelManager-> - removeUserFromAllChannels(static_cast<ChatClient*>(computer)); - ChatPendingClients::iterator i_end = pendingClients.end(); - for (ChatPendingClients::iterator i = pendingClients.begin(); - i != i_end; ++i) + ChatClient *computer = static_cast< ChatClient * >(comp); + + if (computer->characterName.empty()) { - if (i->second == computer) - { - pendingClients.erase(i); - break; - } + // Not yet fully logged in, remove it from pending clients. + mTokenCollector.deletePendingClient(computer); + } + else + { + // Remove user from all channels. + chatChannelManager->removeUserFromAllChannels(computer); } - delete computer; -} -void ChatHandler::process(enet_uint32 timeout) -{ - ConnectionHandler::process(timeout); - removeOutdatedPending(); + delete computer; } void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) @@ -133,26 +114,9 @@ void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) if (computer.characterName.empty()) { if (message.getId() != PCMSG_CONNECT) return; - std::string magic_token = message.readString(MAGIC_TOKEN_LENGTH); - ChatPendingLogins::iterator i = pendingLogins.find(magic_token); - if (i == pendingLogins.end()) - { - ChatPendingClients::iterator i_end = pendingClients.end(); - for (ChatPendingClients::iterator i = pendingClients.begin(); - i != i_end; ++i) - { - if (i->second == &computer) return; - } - pendingClients.insert(std::make_pair(magic_token, &computer)); - return; - } - computer.characterName = i->second.character; - computer.accountLevel = i->second.level; - pendingLogins.erase(i); - result.writeShort(CPMSG_CONNECT_RESPONSE); - result.writeByte(ERRMSG_OK); - computer.send(result); + std::string magic_token = message.readString(MAGIC_TOKEN_LENGTH); + mTokenCollector.addPendingClient(magic_token, &computer); // sendGuildRejoin(computer); return; } @@ -481,8 +445,7 @@ ChatHandler::handleUnregisterChannelMessage(ChatClient &client, MessageIn &msg) client.send(reply); } - void -ChatHandler::handleEnterChannelMessage(ChatClient &client, MessageIn &msg) +void ChatHandler::handleEnterChannelMessage(ChatClient &client, MessageIn &msg) { MessageOut reply(CPMSG_ENTER_CHANNEL_RESPONSE); diff --git a/src/chat-server/chathandler.hpp b/src/chat-server/chathandler.hpp index 72f0ef31..43e70013 100644 --- a/src/chat-server/chathandler.hpp +++ b/src/chat-server/chathandler.hpp @@ -29,6 +29,7 @@ #include "net/connectionhandler.hpp" class ChatClient; +enum AccountLevel; /** * Manages chat related things like private messaging, chat channel handling @@ -40,14 +41,19 @@ class ChatClient; */ class ChatHandler : public ConnectionHandler { - public: + /** - * Overridden from ConnectionHandler to also clean connected clients - * that haven't sent in a magic token. - * - * @see ConnectionHandler::process + * Data needed for initializing a ChatClient. */ - void process(enet_uint32 timeout = 0); + struct Pending + { + std::string character; + AccountLevel level; + }; + + public: + + ChatHandler(); /** * Start the handler. @@ -78,6 +84,21 @@ class ChatHandler : public ConnectionHandler const std::string &inviterName, const std::string &guildName); + /** + * Called by TokenCollector when a client wrongly connected. + */ + void deletePendingClient(ChatClient *); + + /** + * Called by TokenCollector when a client failed to connect. + */ + void deletePendingConnect(Pending *); + + /** + * Called by TokenCollector when a client succesfully connected. + */ + void tokenMatched(ChatClient *, Pending *); + protected: /** * Process chat related messages. @@ -147,28 +168,14 @@ class ChatHandler : public ConnectionHandler const std::string &text); /** - * Sends a message to every client in a registered channel. O(c*u), - * where <b>c</b> is the amount of connected clients and <b>u</b> the - * number of users in the given channel. + * Sends a message to every client in a registered channel. * * @param channel the channel to send the message in, must not be NULL * @param msg the message to be sent - * - * @todo <b>b_lindeijer:</b> Currently this method is looping through - * the channel users for each connected client in order to - * determine whether it should receive the message. It would be - * much better to directly associate the connected clients with - * the channel. */ void sendInChannel(ChatChannel *channel, MessageOut &msg); /** - * Removes outdated pending logins. These are connected clients that - * still haven't sent in their magic token. - */ - void removeOutdatedPending(); - - /** * Send user joined message. * * @param channel the channel to send the message in, must not be NULL @@ -183,6 +190,13 @@ class ChatHandler : public ConnectionHandler * @param name the name of the user who left */ void sendUserLeft(ChatChannel *channel, const std::string &name); + + /** + * Container for pending clients and pending connections. + */ + TokenCollector<ChatHandler, ChatClient *, Pending *> mTokenCollector; + friend void registerChatClient(const std::string &, const std::string &, int); + }; /** diff --git a/src/defines.h b/src/defines.h index 4db9b081..5d82c86f 100644 --- a/src/defines.h +++ b/src/defines.h @@ -36,13 +36,14 @@ * It may be better to wait and see what permissions we'd want to grant to or * take from users, and then come up with a convenient way to handle that. */ -typedef enum { +enum AccountLevel +{ AL_NORMAL, // User has regular rights AL_ADMIN, // User can perform administrator tasks AL_GM, // User can perform a subset of administrator tasks AL_BANNED, // This user is currently banned AL_RESTRICTED // User rights have been restricted -} AccountLevel; +}; enum { @@ -138,6 +139,7 @@ enum { APMSG_CONNECTION_TIMEDOUT = 0x0070, // - GPMSG_CONNECTION_TIMEDOUT = 0x0071, // - + CPMSG_CONNECTION_TIMEDOUT = 0x0072, // - // Game GPMSG_PLAYER_MAP_CHANGE = 0x0100, // S filename, W x, W y |