#include "SpielServer.h" #include #include #include #include #ifdef WIN32 #include "..\Datenbank\Datenbank.h" #else #include "Datenbank.h" #endif // Inhalt der SpielServer Klasse aus SpielServer.h // Konstruktor SpielServer::SpielServer( InitDatei *zIni ) : Thread() { Network::Start( 100 ); std::cout << "SS: Verbindung mit Datenbank wird hergestellt...\n"; db = new SSDatenbank( zIni ); empfangen = 0; gesendet = 0; fehler = new Text(); ini = zIni->getThis(); id = *zIni->zWert( "ServerId" ); server = new Server(); aServer = new Server(); std::cout << "SS: Starten des Admin Servers...\n"; if( !aServer->verbinde( (unsigned short)TextZuInt( ini->zWert( "AdminServerPort" )->getText(), 10 ), 10 ) ) { std::cout << "SS: Der Admin Server konnte nicht gestartet werden. Das Programm wird beendet.\n"; exit( 1 ); } db->setServerStatus( id, 2 ); end = 0; nichtPausiert = 0; InitializeCriticalSection( &cs ); ref = 1; startSpielThread = new SpielFinden( this ); if( zIni->zWert( "Aktiv" )->istGleich( "TRUE" ) ) { serverStarten(); serverFortsetzen(); } erstellt = new RCArray< SpielErstellt >(); spiele = new RCArray< Spiel >(); klients = new RCArray< SSKlient >(); spielHistorieId = new Array< int >(); spielErstelltAnzahl = 0; spielAnzahl = 0; klientAnzahl = 0; klientAnzahl2 = 0; historieS = new HistorieSender( this ); historieS->start(); } // Destruktor SpielServer::~SpielServer() { historieS->setEnde(); historieS->warteAufThread( 20000 ); historieS->ende(); historieS->release(); fehler->release(); server->trenne(); server->release(); aServer->trenne(); aServer->release(); ini->release(); db->release(); DeleteCriticalSection( &cs ); startSpielThread->release(); erstellt->release(); spiele->release(); if( klients ) klients->release(); spielHistorieId->release(); } // nicht constant void SpielServer::lock() { EnterCriticalSection( &cs ); } void SpielServer::unlock() { LeaveCriticalSection( &cs ); } void SpielServer::runn() { while( !end ) { SKlient *klient; klient = aServer->getKlient(); if( end && klient ) { klient->trenne(); klient = klient->release(); Sleep( 1000 ); return; } if( !klient ) return; SSAKlient *slHandle = new SSAKlient( klient, getThis() ); slHandle->start(); } } void SpielServer::thread() { while( 1 ) { SKlient *klient; klient = server->getKlient(); if( !klient ) break; Framework::getThreadRegister()->cleanUpClosedThreads(); SSKlient *slHandle = new SSKlient( klient, getThis() ); klientAnzahl2++; slHandle->start(); } } void SpielServer::close() { db->setServerStatus( id, 1 ); server->trenne(); #ifdef WIN32 warteAufThread( 1000 ); #endif lock(); for( int i = 0; i < klientAnzahl; i++ ) klients->z( i )->absturz(); if( klients ) klients = klients->release(); klientAnzahl = 0; unlock(); ende(); run = 0; end = 1; Klient *klient = new Klient(); klient->verbinde( aServer->getPort(), "127.0.0.1" ); Sleep( 500 ); aServer->trenne(); klient->release(); } bool SpielServer::serverStarten() { if( nichtPausiert ) { fehler->setText( "Der Server konnte nicht gestartet werden: Der Server läuft bereits." ); return 0; } if( server ) server->release(); server = new Server(); if( server->verbinde( (unsigned short)TextZuInt( ini->zWert( "ServerPort" )->getText(), 10 ), 10 ) ) { nichtPausiert = 1; start(); startSpielThread->setSpielServerId( id ); startSpielThread->start(); return 1; } else { serverBeenden(); fehler->setText( "Der Server konnte nicht gestartet werden: Eventuell ist der Port in benutzung." ); return 0; } } bool SpielServer::serverPause() { if( !nichtPausiert ) { fehler->setText( "Der Server konnte nicht pausiert werden: Der Server läuft nicht." ); return 0; } if( !db->setServerStatus( id, 2 ) ) { fehler->setText( "Der Server konnte nicht pausiert werden: " ); fehler->append( db->getLetzterFehler() ); return 0; } return 1; } bool SpielServer::serverFortsetzen() { if( !nichtPausiert ) { fehler->setText( "Der Server konnte nicht fortgesetzt werden: Der Server läuft nicht." ); return 0; } if( !db->setServerStatus( id, 3 ) ) { fehler->setText( "Der Server konnte nicht fortgesetzt werden: " ); fehler->append( db->getLetzterFehler() ); return 0; } return 1; } bool SpielServer::serverBeenden() { if( !nichtPausiert ) { fehler->setText( "Der Server konnte nicht beendet werden: Der Server läuft nicht." ); return 0; } if( db->serverIstNichtPausiert( id ) ) { fehler->setText( "Der Server konnte nicht beendet werden: Der Server muss erst pausiert werden." ); return 0; } startSpielThread->setEnde(); startSpielThread->warteAufThread( 2000 ); startSpielThread->ende(); nichtPausiert = 0; ende(); if( server ) server->trenne(); return 1; } bool SpielServer::setMaxSpiele( int ms ) { if( !db->setMaxSpiele( id, ms ) ) { fehler->setText( "Die maximale Anzahl der Spiele konnte nicht gesetzt werden:\n" ); fehler->append( db->getLetzterFehler() ); return 0; } ini->setWert( "MaxSpiele", Text() += ms ); return 1; } void SpielServer::addSpielErstellt( SpielErstellt *erstellt ) { lock(); this->erstellt->set( erstellt, spielErstelltAnzahl ); spielErstelltAnzahl++; unlock(); } void SpielServer::SpielErstelltAbbruch( int spielErstelltId ) { lock(); for( int i = 0; i < spielErstelltAnzahl; i++ ) { if( erstellt->z( i )->getId() == spielErstelltId ) { erstellt->z( i )->abbruch(); break; } } unlock(); } void SpielServer::removeSpielErstellt( int id ) { lock(); bool gefunden = 0; for( int i = 0; i < spielErstelltAnzahl; i++ ) { if( erstellt->z( i )->getId() == id ) { spielErstelltAnzahl--; SpielErstellt *zse = erstellt->get( i ); erstellt->remove( i ); unlock(); zse->release(); gefunden = 1; break; } } if( !gefunden ) unlock(); } bool SpielServer::registerKlient( SSKlient *klient ) { lock(); bool gefunden = 0; for( int i = 0; i < klientAnzahl; i++ ) { SSKlient *tmp = klients->z( i ); if( tmp ) { if( tmp->getAccountId() == klient->getAccountId() ) { klient->getThis(); tmp->setSenden( klient ); klient->release(); gefunden = 1; unlock(); return 1; } } } if( !gefunden ) { klients->set( klient, klientAnzahl ); klientAnzahl++; } unlock(); return 0; } bool SpielServer::absturzKlient( int klientId ) { lock(); SSKlient *zKlient = 0; for( int i = 0; i < klientAnzahl; i++ ) { if( klients->z( i )->getKlientNummer() == klientId ) { zKlient = klients->z( i ); break; } } if( !zKlient ) { unlock(); return 0; } int id = 0; int ak = db->getAktionForKlient( this->id, zKlient->getAccountId(), &id ); switch( ak ) { case 0: // Information Über Verwendung des Klient ist verlorengegangen (überall abmelden) for( int i = 0; i < spielErstelltAnzahl; i++ ) { SpielErstellt *tmp = erstellt->z( i ); if( tmp ) tmp->klientGetrennt( zKlient ); } for( int i = 0; i < spielAnzahl; i++ ) { Spiel *tmp = spiele->z( i ); if( tmp ) tmp->klientGetrennt( zKlient ); } break; case 1: // Spiel Erstellt for( int i = 0; i < spielErstelltAnzahl; i++ ) { SpielErstellt *tmp = erstellt->z( i ); if( tmp ) { if( tmp->getId() == id ) { tmp->klientGetrennt( zKlient ); break; } } } break; case 2: // Spielt for( int i = 0; i < spielAnzahl; i++ ) { Spiel *tmp = spiele->z( i ); if( tmp && tmp->getId() == id ) { tmp->klientGetrennt( zKlient ); break; } } break; } bool gefunden = 0; for( int i = 0; i < klientAnzahl; i++ ) { if( klients->z( i ) == zKlient ) { zKlient->absturz(); klientAnzahl--; zKlient->getThis(); klients->remove( i ); unlock(); zKlient->release(); gefunden = 1; break; } } if( !gefunden ) unlock(); return 1; } bool SpielServer::verteileKlient( SSKlient *klient ) { lock(); int id = 0; int ak = db->getAktionForKlient( this->id, klient->getAccountId(), &id ); switch( ak ) { case 0: // Keine Verwendung für den Klient unlock(); return 0; break; case 1: // Spiel Erstellt for( int i = 0; i < spielErstelltAnzahl; i++ ) { SpielErstellt *tmp = erstellt->z( i ); if( tmp ) { if( tmp->getId() == id ) { tmp->klientVerbunden( (SSKlient*)klient->getThis() ); unlock(); return 1; } } } break; case 2: // Spielt for( int i = 0; i < spielAnzahl; i++ ) { Spiel *tmp = spiele->z( i ); if( tmp ) { if( tmp->getId() == id ) { tmp->klientVerbunden( (SSKlient*)klient->getThis() ); unlock(); return 1; } } } break; } unlock(); return 0; } void SpielServer::unregisterKlient( SSKlient *zKlient ) { lock(); int id = 0; int ak = db->getAktionForKlient( this->id, zKlient->getAccountId(), &id ); switch( ak ) { case 0: // Information Über Verwendung des Klient ist verlorengegangen (überall abmelden) for( int i = 0; i < spielErstelltAnzahl; i++ ) { SpielErstellt *tmp = erstellt->z( i ); if( tmp ) tmp->klientGetrennt( zKlient ); } for( int i = 0; i < spielAnzahl; i++ ) { Spiel *tmp = spiele->z( i ); if( tmp ) tmp->klientGetrennt( zKlient ); } break; case 1: // Spiel Erstellt for( int i = 0; i < spielErstelltAnzahl; i++ ) { SpielErstellt *tmp = erstellt->z( i ); if( tmp ) { if( tmp->getId() == id ) { tmp->klientGetrennt( zKlient ); break; } } } break; case 2: // Spielt for( int i = 0; i < spielAnzahl; i++ ) { Spiel *tmp = spiele->z( i ); if( tmp && tmp->getId() == id ) { tmp->klientGetrennt( zKlient ); break; } } break; } bool gefunden = 0; for( int i = 0; i < klientAnzahl; i++ ) { if( klients->z( i ) == zKlient ) { klientAnzahl--; zKlient->getThis(); klients->remove( i ); unlock(); zKlient->release(); gefunden = 1; break; } } if( !gefunden ) { unlock(); zKlient->release(); } } void SpielServer::klientsMM( SSKlient *k ) { lock(); for( int i = 0; i < klientAnzahl; i++ ) { if( klients->z( i ) == k ) { klients->z( i )->getThis(); klients->z( i )->getThis(); klients->remove( i ); } } unlock(); klientAnzahl2--; } void SpielServer::addSpiel( Spiel *spiel ) { lock(); spiele->add( spiel, spielAnzahl ); spielAnzahl++; unlock(); } void SpielServer::removeSpiel( int spielId ) { lock(); bool gefunden = 0; for( int i = 0; i < spielAnzahl; i++ ) { if( spiele->z( i ) && spiele->z( i )->getId() == spielId ) { spielAnzahl--; Spiel *zs = spiele->get( i ); spiele->remove( i ); unlock(); zs->release(); gefunden = 1; break; } } if( !gefunden ) unlock(); } void SpielServer::addGesendet( int bytes ) { gesendet += bytes; } void SpielServer::addEmpfangen( int bytes ) { empfangen += bytes; } void SpielServer::addSpielHistorieId( int id ) { lock(); spielHistorieId->add( id ); unlock(); } bool SpielServer::hatSpielHistorieId( int id ) { bool ret = 0; lock(); int anz = spielHistorieId->getEintragAnzahl(); for( int i = 0; i < anz; i++ ) { if( spielHistorieId->hat( i ) && spielHistorieId->get( i ) == id ) { ret = 1; break; } } unlock(); return ret; } void SpielServer::removeSpielHistorieId( int id ) { lock(); int anz = spielHistorieId->getEintragAnzahl(); for( int i = 0; i < anz; i++ ) { if( spielHistorieId->hat( i ) && spielHistorieId->get( i ) == id ) { spielHistorieId->remove( i ); break; } } unlock(); } // constant bool SpielServer::istAn() const { return db->serverIstNichtPausiert( id ); } Server *SpielServer::zServer() const { return server; } SSDatenbank *SpielServer::zDB() const { return db; } InitDatei *SpielServer::zInit() const { return ini; } bool SpielServer::hatClients() const { return klientAnzahl > 0; } int SpielServer::getId() const { return id; } char *SpielServer::getLetzterFehler() const { return fehler->getText(); } char *SpielServer::getIp() const { return ini->zWert( "ServerIp" )->getText(); } int SpielServer::getPort() const { if( !ini->wertExistiert( "ServerPort" ) ) return 0; return TextZuInt( ini->zWert( "ServerPort" )->getText(), 10 ); } // Reference Counting SpielServer *SpielServer::getThis() { ref++; return this; } SpielServer *SpielServer::release() { ref--; if( !ref ) delete this; return 0; } // Inhalt der SSAKlient Klasse aus SpielServer.h // Konstruktor SSAKlient::SSAKlient( SKlient *klient, SpielServer *ss ) : Thread() { this->klient = klient; unsigned char key[ 20 ] = { 148, 52, 231, 50, 20, 138, 243, 178, 149, 24, 69, 60, 68, 116, 10, 161, 178, 148, 32, 212 }; klient->setSendeKey( (char*)key, 20 ); klient->setEmpfangKey( (char*)key, 20 ); name = new Text( "" ); passwort = new Text( "" ); adminId = 0; version = 0; this->ss = ss; } // Destruktor SSAKlient::~SSAKlient() { klient->trenne(); klient->release(); ss->release(); name->release(); passwort->release(); } // nicht constant void SSAKlient::thread() { while( 1 ) { char c = 0; if( !klient->getNachrichtEncrypted( &c, 1 ) ) break; else { bool br = 0; switch( c ) { case 1: // Login if( 1 ) { klient->sendeEncrypted( "\1", 1 ); char nLen = 0; klient->getNachrichtEncrypted( &nLen, 1 ); char *n = new char[ nLen + 1 ]; n[ (int)nLen ] = 0; if( nLen ) klient->getNachrichtEncrypted( n, nLen ); char pLen = 0; klient->getNachrichtEncrypted( &pLen, 1 ); char *p = new char[ pLen + 1 ]; p[ (int)pLen ] = 0; if( pLen ) klient->getNachrichtEncrypted( p, pLen ); int adminId = ss->zDB()->istAdministrator( n, p ); if( adminId ) { klient->sendeEncrypted( "\1", 1 ); name->setText( n ); passwort->setText( p ); this->adminId = adminId; } else errorZuKlient( "Falsche Kombination aus Name und Passwort." ); delete[] n; delete[] p; } break; case 2: // Logout adminId = 0; name->setText( "" ); passwort->setText( "" ); klient->sendeEncrypted( "\1", 1 ); break; case 3: // Trennen br = 1; klient->sendeEncrypted( "\1", 1 ); break; case 4: // Server starten if( !adminId ) errorZuKlient( "Du musst dich einloggen." ); else { if( ss->zDB()->adminHatRecht( adminId, Admin_Recht::SSStarten ) ) { if( !ss->serverStarten() ) { Text *err = new Text(); err->append( ss->getLetzterFehler() ); errorZuKlient( err->getText() ); err->release(); } else klient->sendeEncrypted( "\1", 1 ); } else errorZuKlient( "Du bist nicht berechtigt den Server zu starten." ); } break; case 5: // Server beenden if( !adminId ) errorZuKlient( "Du musst dich einloggen." ); else { if( ss->zDB()->adminHatRecht( adminId, Admin_Recht::SSBeenden ) ) { if( ss->serverBeenden() ) klient->sendeEncrypted( "\1", 1 ); else { Text *err = new Text(); err->append( ss->getLetzterFehler() ); errorZuKlient( err->getText() ); err->release(); } } else errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." ); } break; case 6: // Programm Schließen if( !adminId ) errorZuKlient( "Du musst dich einloggen." ); else { bool ok = 0; if( ss->isRunning() ) { if( ss->zDB()->adminHatRecht( adminId, Admin_Recht::SSBeenden ) ) { if( ss->serverBeenden() ) ok = 1; else { Text *err = new Text(); err->append( ss->getLetzterFehler() ); errorZuKlient( err->getText() ); err->release(); } } else errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." ); } else ok = 1; if( ok && ss->hatClients() ) { errorZuKlient( "Es sind noch Klients Online. Bitte versuche es später erneut." ); break; } if( ok ) { klient->sendeEncrypted( "\1", 1 ); std::cout << "SS: Der Server wird von Benutzer " << adminId << " heruntergefahren.\n"; ss->close(); br = 1; } } break; case 7: // Progtamm abstürzen if( !adminId ) errorZuKlient( "Du musst dich einloggen." ); else { bool ok = 0; if( ss->isRunning() ) { if( ss->zDB()->adminHatRecht( adminId, Admin_Recht::SSBeenden ) ) { ss->serverBeenden(); ok = 1; } else errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." ); } else ok = 1; if( ok ) { klient->sendeEncrypted( "\1", 1 ); std::cout << "sS: Der Server wurde von Benutzer " << adminId << " terminiert.\n"; ss->close(); br = 1; } } break; case 8: // Status Frage if( 1 ) { char status = 0; if( ss->isRunning() ) { status = 1; if( ss->istAn() ) status = 2; } klient->sendeEncrypted( "\1", 1 ); klient->sendeEncrypted( &status, 1 ); } break; case 9: // Server pausieren if( !adminId ) errorZuKlient( "Du musst dich einloggen." ); else { klient->sendeEncrypted( "\1", 1 ); char pause = 0; klient->getNachrichtEncrypted( &pause, 1 ); if( ss->zDB()->adminHatRecht( adminId, Admin_Recht::SSPausieren ) ) { bool ok = 0; if( pause ) ok = ss->serverPause(); else ok = ss->serverFortsetzen(); if( ok ) klient->sendeEncrypted( "\1", 1 ); else { Text *err = new Text(); err->append( ss->getLetzterFehler() ); errorZuKlient( err->getText() ); err->release(); } } else { if( pause ) errorZuKlient( "Du bist nicht berechtigt den Server zu pausieren." ); else errorZuKlient( "Du bist nicht berechtigt den Server fortzusetzen." ); } } break; case 0xA: // maximale Anzahl der Spiele setzen if( !adminId ) errorZuKlient( "Du musst dich einloggen." ); else { klient->sendeEncrypted( "\1", 1 ); int maxS = 0; klient->getNachrichtEncrypted( (char*)&maxS, 4 ); if( ss->zDB()->adminHatRecht( adminId, Admin_Recht::SSMSChange ) ) { if( ss->setMaxSpiele( maxS ) ) klient->sendeEncrypted( "\1", 1 ); else { Text *err = new Text(); err->append( ss->getLetzterFehler() ); errorZuKlient( err->getText() ); err->release(); } } else errorZuKlient( "Du bist nicht berechtigt die maximale Anzahl der Clients zu verändern." ); } break; case 0xB: // Spiel Historie downloaden if( adminId ) errorZuKlient( "Zugriff verweigert." ); else { klient->sendeEncrypted( "\1", 1 ); int spielId = 0; klient->getNachrichtEncrypted( (char*)&spielId, 4 ); if( !ss->hatSpielHistorieId( spielId ) ) { errorZuKlient( "Zugriff auf Spiel-Historie verweigert." ); break; } Text *pfad = new Text( "../spiel log/" ); *pfad += spielId; *pfad += "/fertig"; if( !DateiExistiert( *pfad ) ) { pfad->release(); errorZuKlient( "Die Spiel-Historie wurde nicht gefunden." ); break; } klient->sendeEncrypted( "\1", 1 ); pfad->remove( "/fertig" ); sendeVerzeichnisAnKlient( *pfad, pfad->getLength() + 1 ); pfad->release(); klient->sendeEncrypted( "\0", 1 ); } break; case 0xC: // klient absturtz if( 1 ) { klient->sendeEncrypted( "\1", 1 ); int klientId = 0; klient->getNachrichtEncrypted( (char*)&klientId, 4 ); if( klientId && ss->absturzKlient( klientId ) ) klient->sendeEncrypted( "\1", 1 ); else klient->sendeEncrypted( "\0", 1 ); } break; default: errorZuKlient( "Unbekannte Nachricht!" ); break; } if( br ) break; ss->addEmpfangen( klient->getDownloadBytes( 1 ) ); ss->addGesendet( klient->getUploadBytes( 1 ) ); } } ss->addEmpfangen( klient->getDownloadBytes( 1 ) ); ss->addGesendet( klient->getUploadBytes( 1 ) ); delete this; } void SSAKlient::sendeVerzeichnisAnKlient( char *pfad, int gpl ) { Datei *d = new Datei(); d->setDatei( pfad ); if( d->istOrdner() ) { int dAnz = d->getUnterdateiAnzahl(); RCArray< Text > *list = d->getDateiListe(); for( int i = 0; i < dAnz; i++ ) { if( list->z( i ) ) { Text *pf = new Text( pfad ); pf->append( "/" ); pf->append( list->z( i )->getText() ); sendeVerzeichnisAnKlient( *pf, gpl ); pf->release(); } } list->release(); } else if( d->existiert() ) { __int64 gr = d->getSize(); if( gr && d->zPfad()->getLength() - gpl > 0 && d->open( Datei::Style::lesen ) ) { char pfLen = (char)( d->zPfad()->getLength() - gpl ); klient->sendeEncrypted( &pfLen, 1 ); klient->sendeEncrypted( d->zPfad()->getText() + gpl, pfLen ); klient->sendeEncrypted( (char*)&gr, 8 ); char *bytes = new char[ 2048 ]; while( gr ) { short len = gr > 2048 ? 2048 : (short)gr; d->lese( bytes, len ); klient->sende( bytes, len ); gr -= len; } delete[] bytes; d->close(); } } d->release(); } void SSAKlient::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient { klient->sendeEncrypted( "\3", 1 ); char len = (char)textLength( nachricht ); klient->sendeEncrypted( &len, 1 ); klient->sendeEncrypted( nachricht, len ); } // Inhalt der SSKlient Klasse aus SpielServer.h // Konstruktor SSKlient::SSKlient( SKlient *klient, SpielServer *ss ) : SSKlientV() { empfangen = klient; unsigned char key[ 20 ] = { 253, 234, 211, 132, 121, 230, 95, 145, 201, 13, 43, 77, 153, 223, 253, 69, 234, 43, 52, 99 }; klient->setSendeKey( (char*)key, 20 ); klient->setEmpfangKey( (char*)key, 20 ); senden = 0; this->ss = ss; accountId = 0; klientNummer = 0; termThread = 1; verbunden = 0; zErstellt = 0; zSpiel = 0; InitializeCriticalSection( &cs ); ref = 1; } // Destruktor SSKlient::~SSKlient() { lock(); unlock(); if( verbunden ) trenne(); if( termThread ) { if( verbunden ) warteAufThread( 1000 ); if( verbunden ) { if( empfangen ) empfangen->trenne(); if( senden ) senden->trenne(); } if( empfangen ) empfangen->release(); if( senden ) senden->release(); DeleteCriticalSection( &cs ); ss->klientsMM( this ); ss->release(); ende(); // Eventuelles Ende des Aktuellen Threades } else { if( verbunden ) { if( empfangen ) empfangen->trenne(); if( senden ) senden->trenne(); } if( empfangen ) empfangen->release(); if( senden ) senden->release(); DeleteCriticalSection( &cs ); ss->klientsMM( this ); ss->release(); } } // nicht constant void SSKlient::lock() { EnterCriticalSection( &cs ); } void SSKlient::unlock() { LeaveCriticalSection( &cs ); } void SSKlient::absturz() { ende(); if( senden ) senden->trenne(); empfangen->trenne(); } void SSKlient::setSpielErstellt( SpielErstellt *zErstellt ) { this->zErstellt = zErstellt; } void SSKlient::setSpiel( Spiel *zSpiel ) { this->zSpiel = zSpiel; } void SSKlient::nichtTrennen() { verbunden = 0; } void SSKlient::spielGefunden( int karteId ) { if( !senden ) return; lock(); senden->sendeEncrypted( "\xB", 1 ); senden->sendeEncrypted( (char*)&karteId, 4 ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::zeitVerbleibend( char sekunden ) { if( !senden ) return; lock(); senden->sendeEncrypted( "\1", 1 ); senden->sendeEncrypted( &sekunden, 1 ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::erstellungAbgebrochen( char *grund ) { if( !senden ) return; char len = (char)textLength( grund ); lock(); senden->sendeEncrypted( "\2", 1 ); senden->sendeEncrypted( &len, 1 ); if( len ) senden->sendeEncrypted( grund, len ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::backInWarteschlange( char st, char min, char sec ) { if( !senden ) return; lock(); senden->sendeEncrypted( "\4", 1 ); senden->sendeEncrypted( &st, 1 ); senden->sendeEncrypted( &min, 1 ); senden->sendeEncrypted( &sec, 1 ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::erstellungFortsetzen() { if( !senden ) return; lock(); senden->sendeEncrypted( "\5", 1 ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::erstellungInitialisierung( SpielerTeamStruktur *sts ) { if( !senden ) return; lock(); senden->sendeEncrypted( "\6", 1 ); senden->sendeEncrypted( (char*)&sts->spielerAnzahl, 4 ); senden->sendeEncrypted( (char*)&sts->teamAnzahl, 4 ); for( int i = 0; i < sts->spielerAnzahl; i++ ) { int f = sts->spielerFarbe->hat( i ) ? sts->spielerFarbe->get( i ) : 0; senden->sendeEncrypted( (char*)&f, 4 ); } for( int i = 0; i < sts->teamAnzahl; i++ ) { int f = sts->teamFarbe->hat( i ) ? sts->teamFarbe->get( i ) : 0; senden->sendeEncrypted( (char*)&f, 4 ); } for( int i = 0; i < sts->teamAnzahl; i++ ) { Text *name = sts->teamName->z( i ); char len = (char)name->getLength(); senden->sendeEncrypted( &len, 1 ); if( len ) senden->sendeEncrypted( name->getText(), len ); } for( int i = 0; i < sts->teamAnzahl; i++ ) { int size = sts->teamSize->hat( i ) ? sts->teamSize->get( i ) : 0; senden->sendeEncrypted( (char*)&size, 4 ); } unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::erstellungAddSpieler( int accountId ) { if( !senden ) return; lock(); senden->sendeEncrypted( "\7", 1 ); senden->sendeEncrypted( (char*)&accountId, 4 ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::erstellungRemoveSpieler( int accountId ) { if( !senden ) return; lock(); senden->sendeEncrypted( "\x8", 1 ); senden->sendeEncrypted( (char*)&accountId, 4 ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::erstellungSpielerTeam( int accountId, int spielerNummer ) { if( !senden ) return; lock(); senden->sendeEncrypted( "\x9", 1 ); senden->sendeEncrypted( (char*)&accountId, 4 ); senden->sendeEncrypted( (char*)&spielerNummer, 4 ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::erstellungChatNachricht( char *nachricht ) { if( !senden ) return; char len = (char)textLength( nachricht ); if( !len ) return; lock(); senden->sendeEncrypted( "\xA", 1 ); senden->sendeEncrypted( &len, 1 ); senden->sendeEncrypted( nachricht, len ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::spielLadenBeginn() { if( !senden ) return; lock(); senden->sendeEncrypted( "\xC", 1 ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::spielLadenSpielerAdd( int accId, int spielerNumer ) { if( !senden ) return; lock(); senden->sendeEncrypted( "\xD", 1 ); senden->sendeEncrypted( (char*)&accId, 4 ); senden->sendeEncrypted( (char*)&spielerNumer, 4 ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::spielLadenSetSpielerProzent( int accId, int prozent ) { if( !senden ) return; lock(); senden->sendeEncrypted( "\xE", 1 ); senden->sendeEncrypted( (char*)&accId, 4 ); senden->sendeEncrypted( (char*)&prozent, 4 ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::spielLadenSetSpielerPing( int accId, int ping ) { if( !senden ) return; lock(); senden->sendeEncrypted( "\xF", 1 ); senden->sendeEncrypted( (char*)&accId, 4 ); senden->sendeEncrypted( (char*)&ping, 4 ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } double SSKlient::ping() { if( !senden ) return 0; ZeitMesser *zeit = new ZeitMesser(); char ret = 0; lock(); zeit->messungStart(); senden->sendeEncrypted( "\x10", 1 ); senden->getNachrichtEncrypted( &ret, 1 ); zeit->messungEnde(); unlock(); double retVal = zeit->getSekunden(); zeit->release(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); return retVal; } void SSKlient::spielLadenFertig() { if( !senden ) return; lock(); senden->sendeEncrypted( "\x11", 1 ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::spielNachricht( short len, char *bytes ) { if( !senden ) return; lock(); senden->sendeEncrypted( "\x12", 1 ); senden->sende( (char*)&len, 2 ); senden->sende( bytes, len ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::statistikNachricht( short len, char *bytes ) { if( !senden ) return; lock(); senden->sendeEncrypted( "\x13", 1 ); senden->sendeEncrypted( (char*)&len, 2 ); senden->sendeEncrypted( bytes, len ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } bool SSKlient::keepAlive() { if( !senden || !verbunden ) return 0; char res = 0; lock(); senden->sendeEncrypted( "\x14", 1 ); senden->getNachrichtEncrypted( &res, 1 ); unlock(); return res == 1; } void SSKlient::trenne() { if( !verbunden ) return; verbunden = 0; if( !senden ) return; lock(); senden->sendeEncrypted( "\0", 1 ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::setSenden( SSKlient *klient ) { senden = klient->getKlient(); Text *key = ss->zDB()->getKlientKey( klientNummer ); if( !key ) { senden->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Es konnte kein Key ermittelt werden." ); } else { senden->sendeEncrypted( "\1", 1 ); senden->setEmpfangKey( *key, key->getLength() ); senden->setSendeKey( *key, key->getLength() ); key->release(); } verbunden = 1; if( !ss->verteileKlient( this ) ) ss->unregisterKlient( this ); klient->nichtTrennen(); klient->release(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } void SSKlient::thread() { int unbekannt = 0; bool del = 0; while( 1 ) { bool br = 0; char message = 0; if( empfangen->getNachrichtEncrypted( &message, 1 ) ) { switch( message ) { case 1: // Klient Identifikation empfangen->getNachrichtEncrypted( (char*)&klientNummer, 4 ); if( !klientNummer ) errorZuKlientEmpfang( "Du besitzt noch keine Klient Nummer." ); else { accountId = ss->zDB()->getAccountId( klientNummer ); termThread = 0; if( ss->registerKlient( this ) ) return; termThread = 1; Text *key = ss->zDB()->getKlientKey( klientNummer ); if( !key ) errorZuKlientEmpfang( "Es konnte kein Key ermittelt werden." ); else { empfangen->sendeEncrypted( "\1", 1 ); empfangen->setEmpfangKey( *key, key->getLength() ); empfangen->setSendeKey( *key, key->getLength() ); key->release(); } } break; case 2: // Main / Erhaltung Server message if( 1 ) { char befehl = 0; empfangen->getNachrichtEncrypted( &befehl, 1 ); switch( befehl ) { case 2: // klient absturtz if( 1 ) { int klientId = 0; empfangen->getNachrichtEncrypted( (char*)&klientId, 4 ); if( klientId && ss->absturzKlient( klientId ) ) empfangen->sendeEncrypted( "\1", 1 ); else empfangen->sendeEncrypted( "\0", 1 ); } break; default: errorZuKlientEmpfang( "Befehl nicht bekannt!" ); break; } } break; case 3: // Verbindungsende trenne(); empfangen->sendeEncrypted( "\1", 1 ); br = 1; break; case 4: // SpielErstellt annehmen if( zErstellt ) { if( zErstellt->klientNimmtAn( accountId ) ) empfangen->sendeEncrypted( "\1", 1 ); else { empfangen->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." ); } } else { empfangen->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Dir wurde kein erstelltes Spiel zugeteilt." ); } break; case 5: // SpielErstellt ablehnen if( zErstellt ) { if( zErstellt->klientLehntAb( accountId ) ) empfangen->sendeEncrypted( "\1", 1 ); else { empfangen->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." ); } } else { empfangen->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Dir wurde kein erstelltes Spiel zugeteilt." ); } break; case 6: // SpielErstellt team wechseln if( zSpiel ) { empfangen->sendeEncrypted( "\1", 1 ); int team = 0; empfangen->getNachrichtEncrypted( (char*)&team, 4 ); if( zSpiel->klientWechseltTeam( accountId, team ) ) empfangen->sendeEncrypted( "\1", 1 ); else { empfangen->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Das Team Ist bereits voll." ); } } else { empfangen->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Dir wurde kein erstelltes Spiel zugeteilt." ); } break; case 7: // SpielErstellt chat Nachricht if( zSpiel ) { empfangen->sendeEncrypted( "\1", 1 ); char len = 0; empfangen->getNachrichtEncrypted( &len, 1 ); char *nachricht = new char[ len + 1 ]; nachricht[ (int)len ] = 0; if( len ) empfangen->getNachrichtEncrypted( nachricht, len ); Text *msg = ss->zDB()->getAccountRufName( accountId ); msg->append( ": " ); msg->append( nachricht ); delete[] nachricht; if( zSpiel->chatNachricht( msg->getText() ) ) empfangen->sendeEncrypted( "\1", 1 ); else { empfangen->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." ); } msg->release(); } else { empfangen->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Dir wurde kein erstelltes Spiel zugeteilt." ); } break; case 8: // Server Message if( 1 ) { char befehl = 0; empfangen->getNachrichtEncrypted( &befehl, 1 ); switch( befehl ) { case 0: // Verbindung Trennen empfangen->sendeEncrypted( "\1", 1 ); br = 1; del = 1; break; case 1: // Spiel Erstellen Abbrechen if( 1 ) { empfangen->sendeEncrypted( "\1", 1 ); int spielErstelltId = 0; empfangen->getNachrichtEncrypted( (char*)&spielErstelltId, 4 ); ss->SpielErstelltAbbruch( spielErstelltId ); empfangen->sendeEncrypted( "\1", 1 ); } break; default: empfangen->sendeEncrypted( "\0", 1 ); break; } } break; case 9: // Bereit zum Laden if( zSpiel && zSpiel->klientBereitZumLaden( accountId ) ) empfangen->sendeEncrypted( "\1", 1 ); else { empfangen->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." ); } break; case 0xA: // Bereit zum Spiel if( zSpiel && zSpiel->klientBereitZumSpiel( accountId ) ) empfangen->sendeEncrypted( "\1", 1 ); else { empfangen->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." ); } break; case 0xB: // Spiel Nachricht if( 1 ) { short len = 0; empfangen->getNachricht( (char*)&len, 2 ); char *bytes = new char[ len ]; empfangen->getNachricht( bytes, len ); if( !zSpiel || !zSpiel->spielNachricht( accountId, len, bytes ) ) errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." ); delete[] bytes; } break; case 0xC: // Spiel Laden Prozent if( 1 ) { empfangen->sendeEncrypted( "\1", 1 ); int prozent = 0; empfangen->getNachrichtEncrypted( (char*)&prozent, 4 ); if( zSpiel && zSpiel->klientSpielLadenProzent( accountId, prozent ) ) empfangen->sendeEncrypted( "\1", 1 ); else { empfangen->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." ); } } break; case 0xD: // Statistik Nachricht if( 1 ) { empfangen->sendeEncrypted( "\1", 1 ); short len = 0; empfangen->getNachrichtEncrypted( (char*)&len, 2 ); char *bytes = new char[ len ]; empfangen->getNachrichtEncrypted( bytes, len ); if( zSpiel && zSpiel->statistikNachricht( accountId, len, bytes ) ) empfangen->sendeEncrypted( "\1", 1 ); else { empfangen->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." ); } delete[] bytes; } break; case 0xE: // Team wählen Fertig if( 1 ) { if( zSpiel && zSpiel->klientTeamAuswahlFertig( accountId ) ) empfangen->sendeEncrypted( "\1", 1 ); else { empfangen->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Es ist ein unbekannter Fehler aufgetreten." ); } } break; case 0xF: // ping if( 1 ) { empfangen->sendeEncrypted( "\1", 1 ); keepAlive(); } break; default: empfangen->sendeEncrypted( "\0", 1 ); errorZuKlientSende( "Unbekannte Nachricht." ); unbekannt += 2; if( unbekannt > 10 ) { trenne(); br = 1; } break; } unbekannt--; if( unbekannt < 0 ) unbekannt = 0; } else { trenne(); br = 1; } if( br ) break; ss->addEmpfangen( empfangen->getDownloadBytes( 1 ) ); ss->addGesendet( empfangen->getUploadBytes( 1 ) ); } ss->addEmpfangen( empfangen->getDownloadBytes( 1 ) ); ss->addGesendet( empfangen->getUploadBytes( 1 ) ); if( del || !accountId ) { termThread = 0; delete this; } else { termThread = 0; ss->unregisterKlient( this ); } } void SSKlient::errorZuKlientEmpfang( const char *nachricht ) // sendet eine Fehlernachricht zum Klient { char len = (char)textLength( nachricht ); if( !len ) return; if( empfangen ) { empfangen->sendeEncrypted( "\3", 1 ); empfangen->sendeEncrypted( &len, 1 ); empfangen->sendeEncrypted( nachricht, len ); } ss->addEmpfangen( empfangen->getDownloadBytes( 1 ) ); ss->addGesendet( empfangen->getUploadBytes( 1 ) ); } void SSKlient::errorZuKlientSende( const char *nachricht ) { char len = (char)textLength( nachricht ); if( !len ) return; if( senden ) { lock(); senden->sendeEncrypted( "\3", 1 ); senden->sendeEncrypted( &len, 1 ); senden->sendeEncrypted( nachricht, len ); unlock(); ss->addEmpfangen( senden->getDownloadBytes( 1 ) ); ss->addGesendet( senden->getUploadBytes( 1 ) ); } } // const int SSKlient::getAccountId() const { return accountId; } int SSKlient::getKlientNummer() const { return klientNummer; } SKlient *SSKlient::getKlient() const { return empfangen->getThis(); } // Reference Counting SSKlientV *SSKlient::getThis() { ref++; return this; } SSKlientV *SSKlient::release() { ref--; if( !ref ) delete this; return 0; }