src/Clientfsm.cpp

00001 #include "Clientfsm.h"
00002 
00003 #include "Connection.h"
00004 #include "MessageIn.h"
00005 #include "MessageOut.h"
00006 #include "Logger.h"
00007 #include "Server.h"
00008 #include "crc32.h"
00009 #include "sha1.h"
00010 #include "cppsqlite3.h"
00011 #include "Account.h"
00012 #include "Client.h"
00013 #include "Char.h"
00014 
00015 ClientFSM::ClientFSM(ConnectionData * data, Server* server,Client* client)
00016         : endFSM(false),
00017         data(data),
00018         set(SDLNet_AllocSocketSet(1)), // Allocate a new set for the client.
00019         lastKA(SDL_GetTicks()),
00020         logger(Logger::getInstance()),
00021         myServer(server),
00022         myClient(client)
00023 {
00024         if(!set) {
00025                 std::cerr << "SDLNet_AllocSocketSet: " << SDLNet_GetError() << endl;
00026                 exit(0);
00027         }
00028         SDLNet_TCP_AddSocket(this->set, this->data->socket); // Add our TCP socket to the set.
00029         std::cerr <<"Client thread socket id: "<< data->socket << std::endl;
00030 }
00031 
00032 void ClientFSM::Start(){
00033         ExecState = &ClientFSM::Login;
00034 }
00035 
00036 void ClientFSM::Evolve(){
00037         (this->*ExecState)();
00038 }
00039 
00040 void ClientFSM::Stop(){
00041 }
00042 
00043 bool ClientFSM::ExecTrans(client_fsm_trans t){
00044         switch (t)
00045         {
00046         case t_login_ok:
00047                 ExecState = &ClientFSM::Ready;
00048                 break;
00049         case t_ka_received:
00050                 ExecState = &ClientFSM::ResetKATime;
00051                 break;
00052         case t_ack_time:
00053                 ExecState = &ClientFSM::SendKA_ACK;
00054                 break;
00055         case t_ka_ack_sent:
00056                 ExecState = &ClientFSM::Ready;
00057                 break;
00058         case t_ka_timeout:
00059                 ExecState = &ClientFSM::Disconnect;
00060                 break;
00061         case t_disconnect:
00062                 ExecState = &ClientFSM::Disconnect;
00063                 break;
00064         default:
00065                 std::cerr << "Unsupported transition in ClientFSM" << std::endl;
00066         }
00067 
00068 return true;
00069 }
00070 
00071 
00072 
00073 void ClientFSM::Login(){
00074         Sint32 ready = 0;
00075         MessageIn* message = NULL;
00076 
00077         ready = SDLNet_CheckSockets(this->set, 10000);// Check for socket's activity
00078         if(ready==-1){ // An error occurred, disconnect the socket.
00079                 std::cerr << "SDLNet_CheckSockets: " << SDLNet_GetError() << endl;
00080                 ExecTrans(t_disconnect);
00081         }
00082         if(SDLNet_SocketReady(data->socket)){
00083                 message = Connection::getMessage(data->socket);
00084                 if (message->getType() == MSG_LOGIN) // We now proceed with the autentication process
00085                 {
00086                         bool authenticated = false;
00087                         authenticated = authenticate(message);
00088                         if (authenticated == true)
00089                         {
00090                                 ExecTrans(t_login_ok);
00091                         }
00092                         else
00093                         {
00094                                 ExecTrans(t_disconnect);
00095                         }
00096                 }
00097                 else
00098                 {
00099                         ExecTrans(t_disconnect);
00100                 }
00101                 delete message;
00102         }
00103         else
00104         {
00105                 ExecTrans(t_disconnect); // No data to read means no username and pasword, something went wrong.
00106         }
00107 }
00108 
00109 void ClientFSM::SendKA_ACK(){
00110         MessageOut* messageout;
00111         messageout = new MessageOut(MSG_KA_ACK);
00112 
00113         messageout->write2(0);
00114         messageout->addCRC();
00115         Connection::putMessage(data->socket, messageout);
00116 
00117         delete messageout;
00118 
00119         ExecTrans(t_ka_ack_sent);
00120 }
00121 
00122 void ClientFSM::Ready(){
00123 
00124         if ((SDL_GetTicks() - lastKA) > KEEPALIVE_TIMEOUT){
00125                 std::cerr<<"KEEPALIVE_TIMEOUT occoured\n";
00126                 ExecTrans(t_ka_timeout);
00127         }
00128         else{
00129                 Sint32 ready = 0;
00130                 MessageIn* messagein = NULL;
00131 
00132                 ready = SDLNet_CheckSockets(this->set,0); // Check for socket's activity.
00133                 if(ready==-1){
00134                         std::cerr << "SDLNet_CheckSockets: " << SDLNet_GetError() << std::endl; // An error occurred, disconnect the socket.
00135                         ExecTrans(t_disconnect);
00136                 }
00137                 if(SDLNet_SocketReady(data->socket)){
00138                         messagein = Connection::getMessage(data->socket);
00139                 if (messagein){
00140                     if (messagein->getType() == MSG_KA){
00141                         ExecTrans(t_ka_received);
00142                     }
00143                     else if (messagein->getType() == MSG_CHAT){ // General chat message received.
00144                         chat(messagein);
00145                     }
00146                     else if (messagein->getType() == MSG_MOVE){ // A movement message received.
00147                         move(messagein);
00148                     }
00149                 }
00150                 else{
00151                     logger->log("Error crating a valid MessageIn in ClientFSM ready loop! <Additional client info here>", LOGMODE_ERROR);
00152                 }
00153                         delete messagein;
00154                 }
00155         }
00156 }
00157 
00158 void ClientFSM::Disconnect(){
00159         std::cout << "Closing connection with Client " << this->data->socket << "...";
00160         SDLNet_FreeSocketSet(this->set);
00161         this->set = NULL;
00162         SDLNet_TCP_Close(this->data->socket);
00163         this->data->socket = NULL;
00164         this->data->running = false;
00165         this->endFSM = true;
00166         std::cout << "OK"<< std::endl;
00167 }
00168 
00169 void ClientFSM::ResetKATime(){
00170         lastKA = SDL_GetTicks();
00171         ExecTrans(t_ack_time);
00172         //std::cerr<<"ResetKATime\n";
00173 }
00174 
00175 bool ClientFSM::authenticate(MessageIn *msg){
00176         bool ret = false;
00177         CppSQLite3DB db;
00178 
00179         string login_data = msg->readString();
00180         std::cout << "Received a login request, processing it..." << std::endl;
00181 
00182         if (msg->checkCRC()){
00183         try{
00184             db.open("accounts.db");
00185             string tmpQuery = "SELECT * FROM registered_users WHERE index_hash = '"+login_data+"';";
00186 
00187             CppSQLite3Query q = db.execQuery(tmpQuery.data());
00188             if (!q.eof()){ // found a valid hash.
00189                 this->myClient->setAccount(new Account(myServer, myClient, q.getIntField(0),q.fieldValue(1),q.fieldValue(3),q.fieldValue(4),q.fieldValue(5),q.getIntField(6))); // Attach an account to the Client.
00190                 ret = true;
00191             }
00192 
00193             db.close();
00194             }
00195             catch(CppSQLite3Exception& e){
00196                 logger->log("Authentication failed due to a database problem.", LOGMODE_AUTH);
00197             logger->log(e.errorMessage(), LOGMODE_DB);
00198             }
00199 
00200         }
00201         else{
00202                 logger->log("Failed CRC check during authentification", LOGMODE_AUTH);
00203         }
00204 
00205         return ret;
00206 }
00207 
00208 void ClientFSM::chat(MessageIn* message){
00209     Uint32 tmp = reinterpret_cast<Uint32>(this->data->self); // Client* to an int in order to find the client in mClients map.
00210     // A MSG_CHAT has been received
00211     myServer->generalChatMsg(tmp, message->readString());
00212 
00213 }
00214 
00215 void ClientFSM::move(MessageIn* message){
00216     Uint16 len, x, y ,z;
00217     len = message->read2();
00218     if (len == 6){
00219         x = message->read2();
00220         y = message->read2();
00221         z = message->read2();
00222         std::cout << "Received a Move message, new coord are x:" << x << " y:" << y << std::endl;
00223         //myServer->getMapManager()->validateMove(ORIG,DEST); <- to be implemented!
00224         myClient->getAccount()->getChar()->setDestination(Location(x,y,z));
00225     }
00226     else
00227         logger->log("Bad lenght in MSG_MOVE message <additional info here>", LOGMODE_ERROR);
00228 }
00229 
00230 bool ClientFSM::getStatus(){
00231         return this->endFSM;
00232 }

Generated on Mon Dec 3 04:30:12 2007 for lo-testserver by  doxygen 1.3.9.1