serverhandler.cpp

Go to the documentation of this file.
00001 /*
00002  *  The Mana World Server
00003  *  Copyright 2004 The Mana World Development Team
00004  *
00005  *  This file is part of The Mana World.
00006  *
00007  *  The Mana World is free software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation; either version 2 of the License, or
00010  *  any later version.
00011  *
00012  *  The Mana World is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *  GNU General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU General Public License
00018  *  along with The Mana World; if not, write to the Free Software
00019  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  *  $Id: serverhandler.cpp 3197 2007-03-18 18:10:31Z rogier_polak $
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); //Characterdata
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             // TODO: check the credentials of the game server
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             // TODO: Store it in memory, only update the database when needed.
00127             //       That should get rid of the
00128             //       no_update_on_switch_character_bug as well.
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     // return result
00187     if (result.getLength() > 0)
00188         comp->send(result);
00189 }

Generated on Fri Mar 30 15:39:16 2007 for TMW Server by  doxygen 1.3.9.1