accounthandler.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: accounthandler.cpp 3229 2007-03-23 00:38:23Z b_lindeijer $
00022  */
00023 
00024 #include "account-server/accounthandler.hpp"
00025 
00026 #include "defines.h"
00027 #include "configuration.h"
00028 #include "point.h"
00029 #include "account-server/account.hpp"
00030 #include "account-server/accountclient.hpp"
00031 #include "account-server/characterdata.hpp"
00032 #include "account-server/serverhandler.hpp"
00033 #include "account-server/storage.hpp"
00034 #include "chat-server/chathandler.hpp"
00035 #include "net/connectionhandler.hpp"
00036 #include "net/messagein.hpp"
00037 #include "net/messageout.hpp"
00038 #include "net/netcomputer.hpp"
00039 #include "utils/logger.h"
00040 #include "utils/stringfilter.h"
00041 #include "utils/tokencollector.hpp"
00042 #include "utils/tokendispenser.hpp"
00043 
00044 AccountHandler::AccountHandler():
00045     mTokenCollector(this)
00046 {
00047 }
00048 
00049 bool
00050 AccountHandler::startListen(enet_uint16 port)
00051 {
00052     LOG_INFO("Account handler started:");
00053     return ConnectionHandler::startListen(port);
00054 }
00055 
00056 NetComputer*
00057 AccountHandler::computerConnected(ENetPeer *peer)
00058 {
00059     return new AccountClient(peer);
00060 }
00061 
00062 void
00063 AccountHandler::computerDisconnected(NetComputer *comp)
00064 {
00065     AccountClient* computer = static_cast< AccountClient * >(comp);
00066 
00067     if (computer->status == CLIENT_QUEUED)
00068         // Delete it from the pendingClient list
00069         mTokenCollector.deletePendingClient(computer);
00070 
00071     delete computer; // ~AccountClient unsets the account
00072 }
00073 
00079 void
00080 AccountHandler::processMessage(NetComputer *comp, MessageIn &message)
00081 {
00082     AccountClient &computer = *static_cast< AccountClient * >(comp);
00083 
00084     Storage &store = Storage::instance("tmw");
00085 
00086 #if defined (SQLITE_SUPPORT)
00087     // Reopen the db in this thread for sqlite, to avoid
00088     // Library Call out of sequence problem due to thread safe.
00089     store.setUser(config.getValue("dbuser", ""));
00090     store.setPassword(config.getValue("dbpass", ""));
00091     store.close();
00092     store.open();
00093 #endif
00094 
00095     switch (message.getId())
00096     {
00097         case PAMSG_LOGIN:
00098             LOG_DEBUG("Received msg ... PAMSG_LOGIN");
00099             handleLoginMessage(computer, message);
00100             break;
00101 
00102         case PAMSG_LOGOUT:
00103             LOG_DEBUG("Received msg ... PAMSG_LOGOUT");
00104             handleLogoutMessage(computer);
00105             break;
00106 
00107         case PAMSG_RECONNECT:
00108             LOG_DEBUG("Received msg ... PAMSG_RECONNECT");
00109             handleReconnectMessage(computer, message);
00110             break;
00111 
00112         case PAMSG_REGISTER:
00113             LOG_DEBUG("Received msg ... PAMSG_REGISTER");
00114             handleRegisterMessage(computer, message);
00115             break;
00116 
00117         case PAMSG_UNREGISTER:
00118             LOG_DEBUG("Received msg ... PAMSG_UNREGISTER");
00119             handleUnregisterMessage(computer, message);
00120             break;
00121 
00122         case PAMSG_EMAIL_CHANGE:
00123             LOG_DEBUG("Received msg ... PAMSG_EMAIL_CHANGE");
00124             handleEmailChangeMessage(computer, message);
00125             break;
00126 
00127         case PAMSG_EMAIL_GET:
00128             LOG_DEBUG("Received msg ... PAMSG_EMAIL_GET");
00129             handleEmailGetMessage(computer);
00130             break;
00131 
00132         case PAMSG_PASSWORD_CHANGE:
00133             LOG_DEBUG("Received msg ... PAMSG_PASSWORD_CHANGE");
00134             handlePasswordChangeMessage(computer, message);
00135             break;
00136 
00137         case PAMSG_CHAR_CREATE:
00138             LOG_DEBUG("Received msg ... PAMSG_CHAR_CREATE");
00139             handleCharacterCreateMessage(computer, message);
00140             break;
00141 
00142         case PAMSG_CHAR_SELECT:
00143             LOG_DEBUG("Received msg ... PAMSG_CHAR_SELECT");
00144             handleCharacterSelectMessage(computer, message);
00145             break;
00146 
00147         case PAMSG_CHAR_DELETE:
00148             LOG_DEBUG("Received msg ... PAMSG_CHAR_DELETE");
00149             handleCharacterDeleteMessage(computer, message);
00150             break;
00151 
00152         default:
00153             LOG_WARN("AccountHandler::processMessage, Invalid message type "
00154                      << message.getId());
00155             MessageOut result(XXMSG_INVALID);
00156             computer.send(result);
00157             break;
00158     }
00159 }
00160 
00161 void
00162 AccountHandler::handleLoginMessage(AccountClient &computer, MessageIn &msg)
00163 {
00164     MessageOut reply(APMSG_LOGIN_RESPONSE);
00165 
00166     if (computer.status != CLIENT_LOGIN)
00167     {
00168         reply.writeByte(ERRMSG_FAILURE);
00169         computer.send(reply);
00170         return;
00171     }
00172 
00173     unsigned long clientVersion = msg.readLong();
00174 
00175     if (clientVersion < config.getValue("clientVersion", 0))
00176     {
00177         reply.writeByte(LOGIN_INVALID_VERSION);
00178         computer.send(reply);
00179         return;
00180     }
00181 
00182     std::string username = msg.readString();
00183     std::string password = msg.readString();
00184 
00185     if (stringFilter->findDoubleQuotes(username))
00186     {
00187         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00188         computer.send(reply);
00189         return;
00190     }
00191 
00192     if (getClientNumber() >= MAX_CLIENTS )
00193     {
00194         reply.writeByte(LOGIN_SERVER_FULL);
00195         computer.send(reply);
00196         return;
00197     }
00198 
00199     // Check if the account exists
00200     Storage &store = Storage::instance("tmw");
00201     AccountPtr acc = store.getAccount(username);
00202 
00203     if (!acc.get() || acc->getPassword() != password)
00204     {
00205         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00206         computer.send(reply);
00207         return;
00208     }
00209 
00210     // Associate account with connection
00211     computer.setAccount(acc);
00212     computer.status = CLIENT_CONNECTED;
00213 
00214     reply.writeByte(ERRMSG_OK);
00215     computer.send(reply); // Acknowledge login
00216 
00217     // Return information about available characters
00218     Characters &chars = computer.getAccount()->getCharacters();
00219 
00220     // Send characters list
00221     for (unsigned int i = 0; i < chars.size(); i++)
00222     {
00223         MessageOut charInfo(APMSG_CHAR_INFO);
00224         charInfo.writeByte(i); // Slot
00225         charInfo.writeString(chars[i]->getName());
00226         charInfo.writeByte((unsigned char) chars[i]->getGender());
00227         charInfo.writeByte(chars[i]->getHairStyle());
00228         charInfo.writeByte(chars[i]->getHairColor());
00229         charInfo.writeByte(chars[i]->getLevel());
00230         charInfo.writeLong(chars[i]->getMoney());
00231 
00232         for (int j = 0; j < NB_BASE_ATTRIBUTES; ++j)
00233             charInfo.writeShort(chars[i]->getBaseAttribute(j));
00234 
00235         computer.send(charInfo);
00236     }
00237     return;
00238 }
00239 
00240 void
00241 AccountHandler::handleLogoutMessage(AccountClient &computer)
00242 {
00243     MessageOut reply(APMSG_LOGOUT_RESPONSE);
00244 
00245     if (computer.status == CLIENT_LOGIN)
00246     {
00247         reply.writeByte(ERRMSG_NO_LOGIN);
00248     }
00249     else if (computer.status == CLIENT_CONNECTED)
00250     {
00251         computer.unsetAccount();
00252         computer.status = CLIENT_LOGIN;
00253         reply.writeByte(ERRMSG_OK);
00254     }
00255     else if (computer.status == CLIENT_QUEUED)
00256     {
00257         // Delete it from the pendingClient list
00258         mTokenCollector.deletePendingClient(&computer);
00259         // deletePendingClient makes sure that the client get's the message
00260         return;
00261     }
00262     computer.send(reply);
00263 }
00264 
00265 void AccountHandler::
00266 handleReconnectMessage(AccountClient &computer, MessageIn &msg)
00267 {
00268     if (computer.status != CLIENT_LOGIN)
00269     {
00270         LOG_DEBUG("Account tried to reconnect, but was already logged in "
00271                  << "or queued.");
00272         return;
00273     }
00274 
00275     std::string magic_token = msg.readString(MAGIC_TOKEN_LENGTH);
00276     computer.status = CLIENT_QUEUED; // Before the addPendingClient
00277     mTokenCollector.addPendingClient(magic_token, &computer);
00278 }
00279 
00280 void
00281 AccountHandler::handleRegisterMessage(AccountClient &computer, MessageIn &msg)
00282 {
00283     unsigned long clientVersion = msg.readLong();
00284     std::string username = msg.readString();
00285     std::string password = msg.readString();
00286     std::string email = msg.readString();
00287 
00288     MessageOut reply(APMSG_REGISTER_RESPONSE);
00289 
00290     if (computer.status != CLIENT_LOGIN)
00291     {
00292         reply.writeByte(ERRMSG_FAILURE);
00293     }
00294     else if (clientVersion < config.getValue("clientVersion", 0))
00295     {
00296         reply.writeByte(REGISTER_INVALID_VERSION);
00297     }
00298     else if (stringFilter->findDoubleQuotes(username))
00299     {
00300         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00301     }
00302     else if (stringFilter->findDoubleQuotes(email))
00303     {
00304         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00305     }
00306     else if ((username.length() < MIN_LOGIN_LENGTH) ||
00307             (username.length() > MAX_LOGIN_LENGTH))
00308     {
00309         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00310     }
00311     else if ((password.length() < MIN_PASSWORD_LENGTH) ||
00312             (password.length() > MAX_PASSWORD_LENGTH))
00313     {
00314         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00315     }
00316     else if (!stringFilter->isEmailValid(email))
00317     {
00318         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00319     }
00320     // Checking if the Name is slang's free.
00321     else if (!stringFilter->filterContent(username))
00322     {
00323         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00324     }
00325     else
00326     {
00327         Storage &store = Storage::instance("tmw");
00328         AccountPtr accPtr = store.getAccount(username);
00329 
00330         // Check whether the account already exists.
00331         if (accPtr.get())
00332         {
00333             reply.writeByte(REGISTER_EXISTS_USERNAME);
00334         }
00335         // Find out whether the email is already in use.
00336         else if (store.doesEmailAddressExist(email))
00337         {
00338             reply.writeByte(REGISTER_EXISTS_EMAIL);
00339         }
00340         else
00341         {
00342             AccountPtr acc(new Account(username, password, email));
00343             store.addAccount(acc);
00344             reply.writeByte(ERRMSG_OK);
00345 
00346             // Associate account with connection
00347             computer.setAccount(acc);
00348             computer.status = CLIENT_CONNECTED;
00349         }
00350     }
00351 
00352     computer.send(reply);
00353 }
00354 
00355 void
00356 AccountHandler::handleUnregisterMessage(AccountClient &computer,
00357                                         MessageIn &msg)
00358 {
00359     LOG_DEBUG("AccountHandler::handleUnregisterMessage");
00360     std::string username = msg.readString();
00361     std::string password = msg.readString();
00362 
00363     MessageOut reply(APMSG_UNREGISTER_RESPONSE);
00364 
00365     if (computer.status != CLIENT_LOGIN)
00366     {
00367         reply.writeByte(ERRMSG_FAILURE);
00368         computer.send(reply);
00369         return;
00370     }
00371 
00372     if (stringFilter->findDoubleQuotes(username))
00373     {
00374         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00375         computer.send(reply);
00376         return;
00377     }
00378 
00379     // See if the account exists
00380     Storage &store = Storage::instance("tmw");
00381     AccountPtr accPtr = store.getAccount(username);
00382 
00383     if (!accPtr.get() || accPtr->getPassword() != password)
00384     {
00385         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00386         computer.send(reply);
00387         return;
00388     }
00389 
00390     // Delete account and associated characters
00391     LOG_DEBUG("Unregistered \"" << username
00392               << "\", AccountID: " << accPtr->getID());
00393     store.delAccount(accPtr);
00394     reply.writeByte(ERRMSG_OK);
00395 
00396     // If the account to delete is the current account we're loggedin
00397     // on, get out of it in memory.
00398     if (computer.getAccount().get() != NULL &&
00399                                  computer.getAccount()->getName() == username)
00400     {
00401         computer.unsetAccount();
00402         computer.status = CLIENT_LOGIN;
00403     }
00404     computer.send(reply);
00405 }
00406 
00407 void AccountHandler::
00408 handleEmailChangeMessage(AccountClient &computer, MessageIn &msg)
00409 {
00410     MessageOut reply(APMSG_EMAIL_CHANGE_RESPONSE);
00411 
00412     if (computer.status != CLIENT_CONNECTED ||
00413         computer.getAccount().get() == NULL)
00414     {
00415         reply.writeByte(ERRMSG_NO_LOGIN);
00416         computer.send(reply);
00417         return;
00418     }
00419 
00420     std::string email = msg.readString();
00421 
00422     Storage &store = Storage::instance("tmw");
00423 
00424     if (!stringFilter->isEmailValid(email))
00425     {
00426         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00427     }
00428     else if (stringFilter->findDoubleQuotes(email))
00429     {
00430         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00431     }
00432     else if (store.doesEmailAddressExist(email))
00433     {
00434         reply.writeByte(EMAILCHG_EXISTS_EMAIL);
00435     }
00436     else
00437     {
00438         computer.getAccount()->setEmail(email);
00439         reply.writeByte(ERRMSG_OK);
00440     }
00441     computer.send(reply);
00442 }
00443 
00444 void AccountHandler::
00445 handleEmailGetMessage(AccountClient &computer)
00446 {
00447     MessageOut reply(APMSG_EMAIL_GET_RESPONSE);
00448 
00449     if (computer.status != CLIENT_CONNECTED ||
00450         computer.getAccount().get() == NULL)
00451     {
00452         reply.writeByte(ERRMSG_NO_LOGIN);
00453         computer.send(reply);
00454         return;
00455     }
00456 
00457     reply.writeByte(ERRMSG_OK);
00458     reply.writeString(computer.getAccount()->getEmail());
00459 
00460     computer.send(reply);
00461 }
00462 
00463 void
00464 AccountHandler::handlePasswordChangeMessage(AccountClient &computer,
00465                                             MessageIn &msg)
00466 {
00467     std::string oldPassword = msg.readString();
00468     std::string newPassword = msg.readString();
00469 
00470     MessageOut reply(APMSG_PASSWORD_CHANGE_RESPONSE);
00471 
00472     if (computer.status != CLIENT_CONNECTED ||
00473         computer.getAccount().get() == NULL)
00474     {
00475         reply.writeByte(ERRMSG_NO_LOGIN);
00476     }
00477     else if (newPassword.length() < MIN_PASSWORD_LENGTH ||
00478             newPassword.length() > MAX_PASSWORD_LENGTH)
00479     {
00480         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00481     }
00482     else if (stringFilter->findDoubleQuotes(newPassword))
00483     {
00484         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00485     }
00486     else if (oldPassword != computer.getAccount()->getPassword())
00487     {
00488         reply.writeByte(ERRMSG_FAILURE);
00489     }
00490     else
00491     {
00492         computer.getAccount()->setPassword(newPassword);
00493         reply.writeByte(ERRMSG_OK);
00494     }
00495 
00496     computer.send(reply);
00497 }
00498 
00499 void
00500 AccountHandler::handleCharacterCreateMessage(AccountClient &computer,
00501                                              MessageIn &msg)
00502 {
00503     std::string name = msg.readString();
00504     int hairStyle = msg.readByte();
00505     int hairColor = msg.readByte();
00506     int gender = msg.readByte();
00507 
00508     MessageOut reply(APMSG_CHAR_CREATE_RESPONSE);
00509 
00510     if (computer.status != CLIENT_CONNECTED ||
00511         computer.getAccount().get() == NULL)
00512     {
00513         reply.writeByte(ERRMSG_NO_LOGIN);
00514     }
00515     else if (!stringFilter->filterContent(name))
00516     {
00517         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00518     }
00519     else if (stringFilter->findDoubleQuotes(name))
00520     {
00521         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00522     }
00523     else if (hairStyle < 0 || hairStyle > MAX_HAIRSTYLE_VALUE)
00524     {
00525         reply.writeByte(CREATE_INVALID_HAIRSTYLE);
00526     }
00527     else if (hairColor < 0 || hairColor > MAX_HAIRCOLOR_VALUE)
00528     {
00529         reply.writeByte(CREATE_INVALID_HAIRCOLOR);
00530     }
00531     else if (gender < 0 || gender > MAX_GENDER_VALUE)
00532     {
00533         reply.writeByte(CREATE_INVALID_GENDER);
00534     }
00535     else if ((name.length() < MIN_CHARACTER_LENGTH) ||
00536              (name.length() > MAX_CHARACTER_LENGTH))
00537     {
00538         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00539     }
00540     else
00541     {
00542         Storage &store = Storage::instance("tmw");
00543         if (store.doesCharacterNameExist(name))
00544         {
00545             reply.writeByte(CREATE_EXISTS_NAME);
00546             computer.send(reply);
00547             return;
00548         }
00549 
00550         // An account shouldn't have more than MAX_OF_CHARACTERS characters.
00551         Characters &chars = computer.getAccount()->getCharacters();
00552         if (chars.size() >= MAX_OF_CHARACTERS)
00553         {
00554             reply.writeByte(CREATE_TOO_MUCH_CHARACTERS);
00555             computer.send(reply);
00556             return;
00557         }
00558 
00559         // LATER_ON: Add race, face and maybe special attributes.
00560 
00561         // Customization of character's attributes...
00562         unsigned short attributes[NB_BASE_ATTRIBUTES];
00563         for (int i = 0; i < NB_BASE_ATTRIBUTES; ++i)
00564             attributes[i] = msg.readShort();
00565 
00566         unsigned int totalAttributes = 0;
00567         bool validNonZeroAttributes = true;
00568         for (int i = 0; i < NB_BASE_ATTRIBUTES; ++i)
00569         {
00570             // For good total attributes check.
00571             totalAttributes += attributes[i];
00572 
00573             // For checking if all stats are at least > 0
00574             if (attributes[i] <= 0) validNonZeroAttributes = false;
00575         }
00576 
00577         if (totalAttributes > POINTS_TO_DISTRIBUTES_AT_LVL1)
00578         {
00579             reply.writeByte(CREATE_ATTRIBUTES_TOO_HIGH);
00580         }
00581         else if (totalAttributes < POINTS_TO_DISTRIBUTES_AT_LVL1)
00582         {
00583             reply.writeByte(CREATE_ATTRIBUTES_TOO_LOW);
00584         }
00585         else if (!validNonZeroAttributes)
00586         {
00587             reply.writeByte(CREATE_ATTRIBUTES_EQUAL_TO_ZERO);
00588         }
00589         else
00590         {
00591             CharacterPtr newCharacter(new CharacterData(name));
00592             for (int i = 0; i < NB_BASE_ATTRIBUTES; ++i)
00593                 newCharacter->setBaseAttribute(i, attributes[i]);
00594             newCharacter->setMoney(0);
00595             newCharacter->setLevel(1);
00596             newCharacter->setGender(gender);
00597             newCharacter->setHairStyle(hairStyle);
00598             newCharacter->setHairColor(hairColor);
00599             newCharacter->setMapId((int) config.getValue("defaultMap", 1));
00600             Point startingPos((int) config.getValue("startX", 512),
00601                                   (int) config.getValue("startY", 512));
00602             newCharacter->setPosition(startingPos);
00603             computer.getAccount()->addCharacter(newCharacter);
00604 
00605             LOG_INFO("Character " << name << " was created for "
00606                      << computer.getAccount()->getName() << "'s account.");
00607 
00608             store.flush(computer.getAccount()); // flush changes
00609             reply.writeByte(ERRMSG_OK);
00610             computer.send(reply);
00611 
00612             // Send new characters infos back to client
00613             MessageOut charInfo(APMSG_CHAR_INFO);
00614             int slot = chars.size() - 1;
00615             charInfo.writeByte(slot);
00616             charInfo.writeString(chars[slot]->getName());
00617             charInfo.writeByte((unsigned char) chars[slot]->getGender());
00618             charInfo.writeByte(chars[slot]->getHairStyle());
00619             charInfo.writeByte(chars[slot]->getHairColor());
00620             charInfo.writeByte(chars[slot]->getLevel());
00621             charInfo.writeShort(chars[slot]->getMoney());
00622             for (int j = 0; j < NB_BASE_ATTRIBUTES; ++j)
00623                 charInfo.writeShort(chars[slot]->getBaseAttribute(j));
00624             computer.send(charInfo);
00625             return;
00626         }
00627     }
00628 
00629     computer.send(reply);
00630 }
00631 
00632 void AccountHandler::
00633 handleCharacterSelectMessage(AccountClient &computer, MessageIn &msg)
00634 {
00635     MessageOut reply(APMSG_CHAR_SELECT_RESPONSE);
00636 
00637     if (computer.status != CLIENT_CONNECTED ||
00638         computer.getAccount().get() == NULL)
00639     {
00640         reply.writeByte(ERRMSG_NO_LOGIN);
00641         computer.send(reply);
00642         return; // not logged in
00643     }
00644 
00645     unsigned char charNum = msg.readByte();
00646     Characters &chars = computer.getAccount()->getCharacters();
00647 
00648     // Character ID = 0 to Number of Characters - 1.
00649     if (charNum >= chars.size())
00650     {
00651         // invalid char selection
00652         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00653         computer.send(reply);
00654         return;
00655     }
00656 
00657     std::string address;
00658     short port;
00659     if (!serverHandler->getGameServerFromMap(
00660                                  chars[charNum]->getMapId(), address, port))
00661     {
00662         LOG_ERROR("Character Selection: No game server for the map.");
00663         reply.writeByte(ERRMSG_FAILURE);
00664         computer.send(reply);
00665         return;
00666     }
00667 
00668     // set character
00669     computer.setCharacter(chars[charNum]);
00670     CharacterPtr selectedChar = computer.getCharacter();
00671     reply.writeByte(ERRMSG_OK);
00672 
00673     LOG_DEBUG(selectedChar->getName() << " is trying to enter the servers.");
00674 
00675     std::string magic_token(utils::getMagicToken());
00676     reply.writeString(magic_token, MAGIC_TOKEN_LENGTH);
00677     reply.writeString(address);
00678     reply.writeShort(port);
00679 
00680     // TODO: get correct address and port for the chat server
00681     reply.writeString(config.getValue("accountServerAddress", "localhost"));
00682     reply.writeShort(int(config.getValue("accountServerPort",
00683                                                    DEFAULT_SERVER_PORT)) + 2);
00684 
00685     serverHandler->registerGameClient(magic_token, selectedChar);
00686     registerChatClient(magic_token, selectedChar->getName(), AL_NORMAL);
00687 
00688     computer.send(reply);
00689 }
00690 
00691 void AccountHandler::
00692 handleCharacterDeleteMessage(AccountClient &computer, MessageIn &msg)
00693 {
00694     MessageOut reply(APMSG_CHAR_DELETE_RESPONSE);
00695 
00696     if (computer.status != CLIENT_CONNECTED ||
00697         computer.getAccount().get() == NULL)
00698     {
00699         reply.writeByte(ERRMSG_NO_LOGIN);
00700         computer.send(reply);
00701         return; // not logged in
00702     }
00703 
00704     unsigned char charNum = msg.readByte();
00705     Characters &chars = computer.getAccount()->getCharacters();
00706 
00707     // Character ID = 0 to Number of Characters - 1.
00708     if (charNum >= chars.size())
00709     {
00710         // invalid char selection
00711         reply.writeByte(ERRMSG_INVALID_ARGUMENT);
00712         computer.send(reply);
00713         return; // not logged in
00714     }
00715 
00716     // Delete the character. If the character to delete is the current
00717     // character, get off of it in memory.
00718     if (computer.getCharacter().get() != NULL &&
00719         computer.getCharacter()->getName() == chars[charNum].get()->getName())
00720             computer.unsetCharacter();
00721 
00722     std::string deletedCharacter = chars[charNum].get()->getName();
00723     computer.getAccount()->delCharacter(deletedCharacter);
00724 
00725     Storage &store = Storage::instance("tmw");
00726     store.flush(computer.getAccount());
00727 
00728     LOG_INFO(deletedCharacter << ": Character deleted...");
00729 
00730     reply.writeByte(ERRMSG_OK);
00731 
00732     computer.send(reply);
00733 }
00734 
00735 void
00736 AccountHandler::tokenMatched(AccountClient *computer, int accountID)
00737 {
00738     MessageOut reply(APMSG_RECONNECT_RESPONSE);
00739 
00740     // Check if the account exists
00741     Storage &store = Storage::instance("tmw");
00742     AccountPtr acc = store.getAccountByID(accountID);
00743 
00744     // Associate account with connection
00745     computer->setAccount(acc);
00746     computer->status = CLIENT_CONNECTED;
00747 
00748     reply.writeByte(ERRMSG_OK);
00749     computer->send(reply);
00750 
00751     // Return information about available characters
00752     Characters &chars = computer->getAccount()->getCharacters();
00753 
00754     // Send characters list
00755     for (unsigned int i = 0; i < chars.size(); i++)
00756     {
00757         MessageOut charInfo(APMSG_CHAR_INFO);
00758         charInfo.writeByte(i); // Slot
00759         charInfo.writeString(chars[i]->getName());
00760         charInfo.writeByte((unsigned char) chars[i]->getGender());
00761         charInfo.writeByte(chars[i]->getHairStyle());
00762         charInfo.writeByte(chars[i]->getHairColor());
00763         charInfo.writeByte(chars[i]->getLevel());
00764         charInfo.writeShort(chars[i]->getMoney());
00765 
00766         for (int j = 0; j < NB_BASE_ATTRIBUTES; ++j)
00767         {
00768             charInfo.writeShort(chars[i]->getBaseAttribute(j));
00769         }
00770         computer->send(charInfo);
00771     }
00772 }
00773 
00774 void
00775 AccountHandler::deletePendingClient(AccountClient* computer)
00776 {
00777     // Something might have changed since it was inserted
00778     if (computer->status != CLIENT_QUEUED) return;
00779 
00780     MessageOut msg(APMSG_CONNECTION_TIMEDOUT);
00781     computer->disconnect(msg);
00782     // The computer will be deleted when the disconnect event is processed
00783 }
00784 
00785 void
00786 AccountHandler::deletePendingConnect(int accountID)
00787 {
00788     // NOOP
00789     // No memory was allocated for the PendingConnect (that was not
00790     // allocated to a countedPtr).
00791 }

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