/Desktop/MGS-MultithreadedGameServer/ConnectionHandler.cc

Vai alla documentazione di questo file.
00001 //
00002 // File: ConnectionHandler.cc
00003 // Created by: <Detro /> aka Ivan De Marino 
00004 // <detro@mandolinux.org, demarino@studenti.unina.it, demarino@na.astro.it>
00005 // Created on: Sun Oct 24 13:52:38 2004
00006 //
00007 
00008 #include "ConnectionHandler.h"
00009 
00010 Mutex ConnectionHandler::mutex;
00011 
00012 /**
00013  * Costruttore della Classe ConnectionHandler.
00014  *
00015  * @param server Server (<code>TCPSocket</code) da cui 
00016  *    prende la Connessione da Gestire
00017  * @param activeG Vettore dei Giochi in esecuzione su MGS */
00018 ConnectionHandler::ConnectionHandler(TCPSocket &server, 
00019    vector <Game *> &activeG,
00020    vector < pair< string, TFactory<Game*> *> *> &availableG) : 
00021 TCPSession(server), activeGames(activeG), availableGames(availableG) {
00022    cout << "<ConnHand msg> Creating New ConnectionHandler." << endl;
00023    cout << "<ConnHand msg> " << getIPV4Local() << " is now Handled." << endl;
00024 }
00025 
00026 /** Distruttore ConnectionHandler. */
00027 ConnectionHandler::~ConnectionHandler(void) { exit(); }
00028 
00029 /**
00030  * Attivazione del ConnectionHandler.
00031  * Questo metodo, overlodato rispetto alla Classe <code>Thread</code>,
00032  * e' il corpo principale del flusso di controllo di questa Classe.
00033  * Qui' avviene tutta l'interazione con l'utente (<code>Player</code>). */
00034 void ConnectionHandler::run(void) {
00035    char *buffer;
00036    buffer = new char[NAME_MAX_LENGTH];
00037    char selection;
00038    char gameSelection;
00039    
00040    InetAddress address = getIPV4Local();
00041    /* "tcp()" e' ereditato dalla classe TCPStream;
00042     * e' importante perche' attraverso il puntatore che ritorna
00043     * avviene tutta la comunicazione con l'utente/giocatore */
00044    *tcp() << ">>> MGS - Multithreaded Game Server <<<" << endl;
00045    *tcp() << "<ConnHand msg> Welcome to MGS on " 
00046       << address.getHostname() << " from socket " 
00047       << so << endl << endl;
00048    
00049    *tcp() << "<ConnHand msg> Please, Insert your nick (only one word): ";
00050    TCPStream::sync();
00051 
00052    if( isPending(Socket::pendingInput, 30000) ) {
00053       *tcp() >> buffer;
00054       /* Creazione giocatore */
00055       player = new Player (buffer , *this, this);
00056    
00057       do {
00058          /* Stampa del Menu per l'utente */
00059          *tcp() << "\n\n\n\n\n";
00060          *tcp() << "--- --- --- --- ---" << endl;
00061          *tcp() << "(n)\t- Create New Game" << endl;
00062          *tcp() << "(j)\t- Join Active Game" << endl;
00063          *tcp() << "(q)\t- Quit from MGS" << endl;
00064          *tcp() << "--- --- --- --- ---" << endl;
00065          *tcp() << "--- "<< player->getName() << 
00066             ", please make your selection (case sensitive): ";
00067          TCPStream::sync();
00068          *tcp() >> selection;
00069          /* Elimina dallo stream il carattere "\n" */
00070          tcp()->ignore(256,'\n');
00071       
00072          switch (selection) {
00073             case 'n':
00074                /* Menu Creazione Nuovo Game */
00075                *tcp() << "\n\n\n\n\n";
00076                printAvailableGameList();
00077                *tcp() << "--- "<< player->getName() << 
00078                   ", please make your selection: ";
00079                TCPStream::sync();
00080                *tcp() >> gameSelection;
00081                tcp()->ignore(256,'\n');
00082                if ( joinPlayerToAvailableGame(player, gameSelection) )
00083                   player->suspendConnHandler();
00084                else
00085                   *tcp() << "--- ERROR: Game not found!" << endl;
00086                break;
00087             case 'j':
00088                /* Menu Join Game attivo */
00089                *tcp() << "\n\n\n\n\n";
00090                printActiveGameList();
00091                *tcp() << "--- "<< player->getName() << 
00092                   ", please make your selection: ";
00093                TCPStream::sync();
00094                *tcp() >> gameSelection;
00095                tcp()->ignore(256,'\n');
00096                if ( joinPlayerToActiveGame(player, gameSelection) )
00097                   player->suspendConnHandler();
00098                else
00099                   *tcp() << "--- ERROR: Game not found!" << endl;
00100                break;
00101             case 'q':
00102                /* Quit */
00103                break;
00104             default:
00105                /* Errore di selezione */
00106                *tcp() << "\n\n\n\n\n";
00107                *tcp() << "Input error!" << endl;
00108                break;
00109          }
00110       }while ( selection != 'q' );
00111    }
00112    else {
00113       *tcp() << "\n<ConnHand msg> 30 Seconds without type your name." << endl;
00114       *tcp() << "<ConnHand msg> Connection TimeOut!" << endl;
00115    }
00116    *tcp() << "<ConnHand msg> Bye bye, from MGS" << endl;
00117 }
00118 
00119 /**
00120  * Chiusura del ConnectionHandler.
00121  * Questo metodo viene richiamato automaticamente
00122  * al termine del metodo <code>run()</code>.
00123  * Permette di gestire al meglio la chiusura del <code>Thread</code>. 
00124  * Ha il compito di deallocare il Player creato. */
00125 void ConnectionHandler::final(void) {
00126    delete player;
00127    delete this;
00128 }
00129 
00130 /** Stampa la lista dei Game attivi verso lo stream dell'utente connesso */
00131 void ConnectionHandler::printActiveGameList(void) {
00132    int activeGamesNumber;
00133    mutex.enterMutex();
00134    
00135    activeGamesNumber = activeGames.size();
00136    *tcp() << "\n------------------------" << endl;
00137    *tcp() << "--> Active Game List <--" << endl;
00138    *tcp() << "------------------------\n" << endl;
00139    *tcp() << "Active Games: " << activeGamesNumber << endl;
00140    *tcp() << "(<num>)\t- [<game name>]" << endl;
00141    
00142    for ( int i = 0; i < activeGamesNumber; i++ ) {
00143       *tcp() << "( " << (i+1) 
00144          << " )\t- [" << activeGames[i]->getName() << "]" << endl;
00145       activeGames[i]->printPlayersList(tcp());
00146    }
00147 
00148    mutex.leaveMutex();
00149 }
00150 
00151 /**
00152  * Inserisci un @c Player in un @c Game attivo.
00153  * Viene controllato se il @c Game scelto esiste (dato che e'
00154  * l'utente a digitare i comandi, quindi gli errori sono possibili).
00155  *
00156  * @param toJoin Puntatore al Player da Aggiungere
00157  * @param gameNum Carattere contenente il numero relativo al Game selezionato
00158  * @return @c true se il Player viene aggiunto al Game, @c false altrimenti */
00159 bool ConnectionHandler::joinPlayerToActiveGame(Player *toJoin, const char gameNum) {
00160    int game = atoi(&gameNum);
00161    int activeGamesNumber;
00162    mutex.enterMutex();
00163    
00164    activeGamesNumber = activeGames.size();
00165    if ( game > 0 && game <= activeGamesNumber ) {
00166       activeGames[game-1]->addPlayer(toJoin);
00167    
00168       mutex.leaveMutex();
00169       return true;
00170    }
00171    
00172    mutex.leaveMutex();
00173    return false;
00174 }
00175 
00176 /** 
00177  * Stampa la lista dei Game disponibili su MGS, verso lo stream dell'utente.
00178  * Sfrutta le peculiarita' della variabile privata @c availableGames. */
00179 void ConnectionHandler::printAvailableGameList(void) {
00180    *tcp() << "\n---------------------------" << endl;
00181    *tcp() << "--> Available Game List <--" << endl;
00182    *tcp() << "---------------------------" << endl;
00183    *tcp() << "(<num>)\t- [<game name>]" << endl;
00184    for ( int i = 0; i < availableGames.size(); i++ ) {
00185          *tcp() << "( " << (i+1) << " )\t- [" <<
00186             availableGames[i]->first << "]" << endl;
00187    }
00188 }
00189 
00190 /**
00191  * Inserisci un @c Player in un nuovo @c Game.
00192  * Viene controllato se il @c Game scelto esiste (dato che e'
00193  * l'utente a digitare i comandi, quindi gli errori sono possibili). <br>
00194  * I Game vengono istanziati usando Classi Plug-In (Vedere @c TFactory)
00195  * le cui Factory sono conservate in @c availableGames.
00196  *
00197  * @param toJoin Puntatore al Player da Aggiungere
00198  * @param gameNum Carattere contenente il numero relativo al Game selezionato 
00199  * @return @c true se il Player viene aggiunto al Game, @c false altrimenti */
00200 bool ConnectionHandler::joinPlayerToAvailableGame(Player *toJoin, const char gameNum) {
00201    int game = atoi(&gameNum);
00202    int availableGamesNumber;
00203    mutex.enterMutex();
00204    
00205    availableGamesNumber = availableGames.size();
00206    if ( game > 0 && game <= availableGamesNumber ) {
00207       /* Crea il nuovo Game usando la TFactory */
00208       Game *newGame = availableGames[game-1]->second->build();
00209    
00210       cout << "<ConnHand msg> Created new Game: " << 
00211          newGame->getName() << endl;
00212    
00213       /* Unisce il nuovo Player al Game */
00214       newGame->addPlayer(toJoin);
00215       /* Inserisce il nuovo Game tra quelli Attivi */
00216       activeGames.push_back(newGame);
00217       mutex.leaveMutex();
00218       return true;
00219    }
00220    
00221    mutex.leaveMutex();
00222    return false;
00223 }

Generato il Sun Nov 28 13:27:03 2004 per MGS - Multithreaded Game Server da doxygen 1.3.4