00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <cassert>
00025 #include <sstream>
00026
00027 #include "account-server/characterdata.hpp"
00028 #include "account-server/serverhandler.hpp"
00029 #include "account-server/storage.hpp"
00030 #include "net/messagein.hpp"
00031 #include "net/messageout.hpp"
00032 #include "net/netcomputer.hpp"
00033 #include "utils/logger.h"
00034 #include "utils/tokendispenser.hpp"
00035 #include "utils/tokencollector.hpp"
00036
00037 bool ServerHandler::startListen(enet_uint16 port)
00038 {
00039 LOG_INFO("Game server handler started:");
00040 return ConnectionHandler::startListen(port);
00041 }
00042
00043 NetComputer *ServerHandler::computerConnected(ENetPeer *peer)
00044 {
00045 return new NetComputer(peer);
00046 }
00047
00048 void ServerHandler::computerDisconnected(NetComputer *comp)
00049 {
00050 Servers::iterator i = servers.begin();
00051 while (i != servers.end())
00052 {
00053 if (i->second.server == comp)
00054 {
00055 LOG_INFO("Unregistering map " << i->first << '.');
00056 servers.erase(i++);
00057 }
00058 else
00059 {
00060 ++i;
00061 }
00062 }
00063 delete comp;
00064 }
00065
00066 bool ServerHandler::getGameServerFromMap(unsigned mapId, std::string &address,
00067 short &port)
00068 {
00069 Servers::const_iterator i = servers.find(mapId);
00070 if (i == servers.end()) return false;
00071 address = i->second.address;
00072 port = i->second.port;
00073 return true;
00074 }
00075
00076 void ServerHandler::registerGameClient(std::string const &token, CharacterPtr ptr)
00077 {
00078 unsigned mapId = ptr->getMapId();
00079
00080 MessageOut msg(AGMSG_PLAYER_ENTER);
00081 msg.writeString(token, MAGIC_TOKEN_LENGTH);
00082 ptr->serialize(msg);
00083
00084 Servers::const_iterator i = servers.find(mapId);
00085 assert(i != servers.end());
00086 i->second.server->send(msg);
00087 }
00088
00089 void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg)
00090 {
00091 MessageOut result;
00092
00093 switch (msg.getId())
00094 {
00095 case GAMSG_REGISTER:
00096 {
00097 LOG_DEBUG("GAMSG_REGISTER");
00098
00099 std::string address = msg.readString();
00100 int port = msg.readShort();
00101 Server s = { address, port, comp };
00102 LOG_INFO("Game server " << address << ':' << port
00103 << " wants to register " << (msg.getUnreadLength() / 2)
00104 << " maps.");
00105
00106 while (msg.getUnreadLength())
00107 {
00108 int id = msg.readShort();
00109 LOG_INFO("Registering map " << id << '.');
00110 if (servers.insert(std::make_pair(id, s)).second)
00111 {
00112 MessageOut outMsg(AGMSG_ACTIVE_MAP);
00113 outMsg.writeShort(id);
00114 comp->send(outMsg);
00115 }
00116 else
00117 {
00118 LOG_ERROR("Server Handler: map is already registered.");
00119 }
00120 }
00121 } break;
00122
00123 case GAMSG_PLAYER_DATA:
00124 {
00125 LOG_DEBUG("GAMSG_PLAYER_DATA");
00126
00127
00128
00129 Storage &store = Storage::instance("tmw");
00130 CharacterPtr ptr(new CharacterData(msg));
00131
00132 if (!store.updateCharacter(ptr))
00133 LOG_ERROR("Received character data for non-existing" <<
00134 " character " << ptr->getDatabaseID() << ".");
00135
00136 } break;
00137
00138 case GAMSG_REDIRECT:
00139 {
00140 LOG_DEBUG("GAMSG_REDIRECT");
00141 int id = msg.readLong();
00142 std::string magic_token(utils::getMagicToken());
00143 Storage &store = Storage::instance("tmw");
00144 CharacterPtr ptr = store.getCharacter(id);
00145 std::string address;
00146 short port;
00147 if (serverHandler->getGameServerFromMap(ptr->getMapId(), address,
00148 port))
00149 {
00150 registerGameClient(magic_token, ptr);
00151 result.writeShort(AGMSG_REDIRECT_RESPONSE);
00152 result.writeLong(ptr->getDatabaseID());
00153 result.writeString(magic_token, MAGIC_TOKEN_LENGTH);
00154 result.writeString(address);
00155 result.writeShort(port);
00156 }
00157 else
00158 {
00159 LOG_ERROR("Server Change: No game server for map " <<
00160 ptr->getMapId() << ".");
00161 }
00162 } break;
00163
00164 case GAMSG_PLAYER_RECONNECT:
00165 {
00166 LOG_DEBUG("GAMSG_PLAYER_RECONNECT");
00167 int characterID = msg.readLong();
00168 std::string magic_token = msg.readString(MAGIC_TOKEN_LENGTH);
00169
00170 Storage &store = Storage::instance("tmw");
00171 CharacterPtr ptr = store.getCharacter(characterID);
00172
00173 int accountID = ptr->getAccountID();
00174 accountHandler->
00175 mTokenCollector.addPendingConnect(magic_token, accountID);
00176
00177 } break;
00178
00179 default:
00180 LOG_WARN("ServerHandler::processMessage, Invalid message type: "
00181 << msg.getId());
00182 result.writeShort(XXMSG_INVALID);
00183 break;
00184 }
00185
00186
00187 if (result.getLength() > 0)
00188 comp->send(result);
00189 }