#include "MainServer.h"
#include "Datenbank.h"
#include <Text.h>
#include <iostream>
#include <Klient.h>
#include <Globals.h>

// Inhalt der MainServer Klasse aus MainServer.h
// Konstruktor 
MainServer::MainServer( InitDatei *zDat )
    : Thread()
{
    Network::Start( 100 );
    std::cout << "MS: Verbindung mit Datenbank wird hergestellt...\n";
    db = new MSDatenbank( zDat );
    clients = 0;
    empfangen = 0;
    gesendet = 0;
    dat = dynamic_cast<InitDatei *>( zDat->getThis() );
    serverSSL = new SSLServer();
    serverSSL->setPrivateKeyPassword( zDat->zWert( "SSLPasswort" )->getText() );
    serverSSL->setCertificateFile( zDat->zWert( "SSLCert" )->getText() );
    serverSSL->setPrivateKeyFile( zDat->zWert( "SSLKey" )->getText() );
    server = new Server();
    aServer = new SSLServer();
    aServer->setPrivateKeyPassword( zDat->zWert( "SSLPasswort" )->getText() );
    aServer->setCertificateFile( zDat->zWert( "SSLCert" )->getText() );
    std::cout << "using cert file " << zDat->zWert( "SSLCert" )->getText() << "\n";
    aServer->setPrivateKeyFile( zDat->zWert( "SSLKey" )->getText() );
    std::cout << "using private key " << zDat->zWert( "SSLKey" )->getText() << "\n";
    std::cout << "MS: Starten des Admin Servers...\n";
    if( !aServer->verbinde( (unsigned short)TextZuInt( zDat->zWert( "AdminServerPort" )->getText(), 10 ), 10 ) )
    {
        std::cout << "MS: Der Admin Server konnte nicht gestartet werden. Das Programm wird beendet.\n";
        exit( 1 );
    }
    else
    {
        std::cout << "Admin Server Port: " << zDat->zWert( "AdminServerPort" )->getText() << "\n";
        std::cout.flush();
    }
    end = 0;
    InitializeCriticalSection( &cs );
    if( zDat->zWert( "Aktiv" )->istGleich( "TRUE" ) )
        serverStarten();
}

// Destruktor 
MainServer::~MainServer()
{
    ende();
    serverSSL->trenne();
    serverSSL->release();
    server->trenne();
    server->release();
    aServer->trenne();
    aServer->release();
    dat->release();
    db->release();
    Network::Exit();
    DeleteCriticalSection( &cs );
}

// nicht constant 
void MainServer::runn()
{
    while( !end && aServer->isConnected() )
    {
        SSLSKlient *klient;
        klient = aServer->getKlient();
        if( klient )
            std::cout << "Neuer Admin Client verbunden.\n";
        if( end && klient )
        {
            klient->trenne();
            klient = (SSLSKlient *)klient->release();
            Sleep( 1000 );
            return;
        }
        if( !klient )
            continue;
        MSAKlient *clHandle = new MSAKlient( klient, dynamic_cast<MainServer *>( getThis() ) );
        clHandle->start();
    }
}

void MainServer::thread()
{
    MainServer *ms = this;
    new AsynchronCall( [ms]()
    {
        while( ms->serverSSL->isConnected() )
        {
            SSLSKlient *klient = ms->serverSSL->getKlient();
            if( ms->end && klient )
            {
                klient->trenne();
                klient = (SSLSKlient *)klient->release();
                Sleep( 1000 );
                return;
            }
            if( !klient )
                continue;
            Framework::getThreadRegister()->cleanUpClosedThreads();
            MSKlientSSL *clHandle = new MSKlientSSL( klient, dynamic_cast<MainServer *>( ms->getThis() ) );
            clHandle->start();
            ms->clients++;
        }
    } );
    while( server->isConnected() )
    {
        SKlient *klient;
        klient = server->getKlient();
        if( !klient )
            continue;
        Framework::getThreadRegister()->cleanUpClosedThreads();
        MSKlient *clHandle = new MSKlient( klient, dynamic_cast<MainServer *>( getThis() ) );
        clHandle->start();
        clients++;
    }
    run = 0;
}

void MainServer::close()
{
    serverSSL->trenne();
    server->trenne();
#ifdef WIN32
    warteAufThread( 1000 );
#endif
    ende();
    run = 0;
    end = 1;
    Klient *klient = new Klient();
    klient->verbinde( aServer->getPort(), "127.0.0.1" );
    Sleep( 500 );
    aServer->trenne();
    klient->release();
}

bool MainServer::serverStarten()
{
    if( run )
        return 1;
    bool ret = server->verbinde( (unsigned short)TextZuInt( dat->zWert( "ServerPort" )->getText(), 10 ), 10 );
    ret &= serverSSL->verbinde( (unsigned short)TextZuInt( dat->zWert( "SSLPort" )->getText(), 10 ), 10 );
    start();
    return ret;
}

void MainServer::serverBeenden()
{
    if( !run )
        return;
    server->trenne();
    serverSSL->trenne();
#ifdef WIN32
    warteAufThread( 1000 );
#endif
    ende();
    server->release();
    server = new Server();
    run = 0;
}

void MainServer::addGesendet( int bytes )
{
    gesendet += bytes;
}

void MainServer::addEmpfangen( int bytes )
{
    empfangen += empfangen;
}

void MainServer::clientTrennung()
{
    clients--;
}

// constant 
Server *MainServer::zServer() const
{
    return server;
}

MSDatenbank *MainServer::zDB() const
{
    return db;
}

bool MainServer::hatClients() const
{
    return clients > 0;
}

InitDatei *MainServer::zInit() const
{
    return dat;
}


// Inhalt der MSKlient Klasse aus MainServer.h
// Konstruktor 
MSAKlient::MSAKlient( SSLSKlient *klient, MainServer *ms )
    : Thread()
{
    this->klient = klient;
    name = new Text( "" );
    passwort = new Text( "" );
    adminId = 0;
    this->ms = ms;
}

// Destruktor 
MSAKlient::~MSAKlient()
{
    klient->trenne();
    klient->release();
    ms->release();
    name->release();
    passwort->release();
}

// nicht constant 
void MSAKlient::thread()
{
    while( 1 )
    {
        char c = 0;
        if( !klient->getNachricht( &c, 1 ) )
            break;
        else
        {
            bool br = 0;
            switch( c )
            {
            case 1: // Login
                if( 1 )
                {
                    klient->sende( "\1", 1 );
                    unsigned char nLen = 0;
                    klient->getNachricht( (char *)&nLen, 1 );
                    char *n = new char[ nLen + 1 ];
                    n[ (int)nLen ] = 0;
                    if( nLen )
                        klient->getNachricht( n, nLen );
                    unsigned char pLen = 0;
                    klient->getNachricht( (char *)&pLen, 1 );
                    char *p = new char[ pLen + 1 ];
                    p[ (int)pLen ] = 0;
                    if( pLen )
                        klient->getNachricht( p, pLen );
                    int adminId = ms->zDB()->istAdministrator( n, p );
                    if( adminId )
                    {
                        klient->sende( "\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->sende( "\1", 1 );
                break;
            case 3: // Trennen
                br = 1;
                klient->sende( "\1", 1 );
                break;
            case 4: // Server starten
                if( !adminId )
                    errorZuKlient( "Du musst dich einloggen." );
                else
                {
                    if( ms->zDB()->adminHatRecht( adminId, Admin_Recht::MSStarten ) )
                    {
                        if( !ms->serverStarten() )
                            errorZuKlient( "Beim starten des Servers ist ein Fehler aufgetreten." );
                        else
                            klient->sende( "\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( ms->zDB()->adminHatRecht( adminId, Admin_Recht::MSBeenden ) )
                    {
                        ms->serverBeenden();
                        klient->sende( "\1", 1 );
                    }
                    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( ms->isRunning() )
                    {
                        if( ms->zDB()->adminHatRecht( adminId, Admin_Recht::MSBeenden ) )
                        {
                            ms->serverBeenden();
                            ok = 1;
                        }
                        else
                            errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
                    }
                    else
                        ok = 1;
                    if( ok && ms->hatClients() )
                    {
                        errorZuKlient( "Es sind noch Klients Online. Bitte versuche es später erneut." );
                        break;
                    }
                    if( ok )
                    {
                        klient->sende( "\1", 1 );
                        std::cout << "MS: Der Server wird von Benutzer " << adminId << " heruntergefahren.\n";
                        ms->close();
                        br = 1;
                    }
                }
                break;
            case 7: // Progtamm abstürzen
                if( !adminId )
                    errorZuKlient( "Du musst dich einloggen." );
                else
                {
                    bool ok = 0;
                    if( ms->isRunning() )
                    {
                        if( ms->zDB()->adminHatRecht( adminId, Admin_Recht::MSBeenden ) )
                        {
                            ms->serverBeenden();
                            ok = 1;
                        }
                        else
                            errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
                    }
                    else
                        ok = 1;
                    if( ok )
                    {
                        klient->sende( "\1", 1 );
                        std::cout << "MS: Der Server wurde von Benutzer " << adminId << " terminiert.\n";
                        ms->close();
                        br = 1;
                    }
                }
                break;
            case 8: // Status Frage
                if( 1 )
                {
                    klient->sende( "\1", 1 );
                    char status = (int)ms->isRunning();
                    klient->sende( &status, 1 );
                }
                break;
            case 9: // Patch Server Liste
                if( adminId )
                {
                    Array< ServerData * > d;
                    if( ms->zDB()->getPatchServerList( &d ) )
                        klient->sende( "\1", 1 );
                    else
                        errorZuKlient( "Fehler beim Abruf der Patch Server Tabelle." );
                    int anz = d.getEintragAnzahl();
                    klient->sende( (char *)&anz, 4 );
                    for( int i = 0; i < anz; i++ )
                    {
                        ServerData *s = d.get( i );
                        klient->sende( (char *)&s->id, 4 );
                        klient->sende( (char *)&s->port, 2 );
                        klient->sende( (char *)&s->adminPort, 2 );
                        unsigned char len = (unsigned char)s->name.getLength();
                        klient->sende( (char *)&len, 1 );
                        klient->sende( s->name, len );
                        len = (unsigned char)s->ip.getLength();
                        klient->sende( (char *)&len, 1 );
                        klient->sende( s->ip, len );
                        len = (unsigned char)s->status.getLength();
                        klient->sende( (char *)&len, 1 );
                        klient->sende( s->status, len );
                        delete s;
                    }
                }
                else
                    errorZuKlient( "Du musst dich einloggen." );
                break;
            case 10: // get Patch Server Details
            {
                if( adminId )
                {
                    klient->sende( "\1", 1 );
                    int id = 0;
                    klient->getNachricht( (char *)&id, 4 );
                    ServerDetails d;
                    if( ms->zDB()->getPatchServerDetails( id, &d ) )
                    {
                        klient->sende( "\1", 1 );
                        unsigned char len = (unsigned char)d.name.getLength();
                        klient->sende( (char *)&len, 1 );
                        klient->sende( d.name, len );
                        len = (unsigned char)d.ip.getLength();
                        klient->sende( (char *)&len, 1 );
                        klient->sende( d.ip, len );
                        klient->sende( (char *)&d.port, 2 );
                        klient->sende( (char *)&d.adminPort, 2 );
                        klient->sende( (char *)&d.tasks, 4 );
                        klient->sende( (char *)&d.maxTasks, 4 );
                    }
                    else
                        errorZuKlient( "Fehler beim abrufen der Server Details." );
                }
                else
                    errorZuKlient( "Du musst dich einloggen." );
                break;
            }
            default:
                errorZuKlient( "Unbekannte Nachricht!" );
                break;
            }
            if( br )
                break;
            ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
            ms->addGesendet( klient->getUploadBytes( 1 ) );
        }
    }
    ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
    ms->addGesendet( klient->getUploadBytes( 1 ) );
    delete this;
}

void MSAKlient::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient
{
    klient->sende( "\3", 1 );
    char len = (char)textLength( nachricht );
    klient->sende( &len, 1 );
    klient->sende( nachricht, len );
}


// Konstruktor 
MSKlientSSL::MSKlientSSL( SSLSKlient *klient, MainServer *ms )
{
    this->klient = klient;
    klientNummer = 0;
    this->ms = ms;
}

// Destruktor 
MSKlientSSL::~MSKlientSSL()
{
    ms->clientTrennung();
    ms->release();
    klient->release();
}

// nicht constant 
void MSKlientSSL::thread()
{
    while( 1 )
    {
        char c = 0;
        if( !klient->getNachricht( &c, 1 ) )
            break;
        else
        {
            bool br = 0;
            switch( c )
            {
            case 1: // Client Identifikation
                if( !klientNummer )
                {
                    klientNummer = ms->zDB()->getNextClientId();
                    Text *key = ms->zDB()->getKlientKey( klientNummer );
                    if( key )
                    {
                        int port = TextZuInt( ms->zInit()->zWert( "ServerPort" )->getText(), 10 );
                        klient->sende( "\1", 1 );
                        klient->sende( (char *)&port, 4 );
                        klient->sende( (char *)&klientNummer, 4 );
                        char len = (char)key->getLength();
                        klient->sende( &len, 1 );
                        if( len )
                            klient->sende( key->getText(), len );
                        key->release();
                    }
                    else
                        errorZuKlient( "Es konnte kein Schlüssel ermittelt werden." );
                }
                else
                    errorZuKlient( "Du besitzt bereits eine Klient Nummer." );
                break;
            case 3: // Verbindungsende
                br = 1;
                klient->sende( "\1", 1 );
                break;
            default:
                errorZuKlient( "Unbekannte Nachricht!\0" );
                break;
            }
            if( br )
                break;
            ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
            ms->addGesendet( klient->getUploadBytes( 1 ) );
        }
    }
    ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
    ms->addGesendet( klient->getUploadBytes( 1 ) );
    delete this;
}

void MSKlientSSL::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient
{
    klient->sende( "\3", 1 );
    char len = (char)textLength( nachricht );
    klient->sende( &len, 1 );
    klient->sende( nachricht, len );
}


// Inhalt der MSKlient Klasse aus MainServer.h
// Konstruktor 
MSKlient::MSKlient( SKlient *klient, MainServer *ms )
    : Thread()
{
    this->klient = klient;
    unsigned char key[ 20 ] = { 199, 164, 172, 55, 246, 16, 155, 8, 151, 176, 250, 181, 227, 133, 30, 41, 200, 26, 7, 151 };
    klient->setSendeKey( (char *)key, 20 );
    klient->setEmpfangKey( (char *)key, 20 );
    klientNummer = 0;
    this->ms = ms;
    encrypted = 0;
}

// Destruktor 
MSKlient::~MSKlient()
{
    ms->clientTrennung();
    ms->release();
    klient->release();
}

// nicht constant 
void MSKlient::thread()
{
    while( 1 )
    {
        char c = 0;
        if( ( !encrypted && !klient->getNachricht( &c, 1 ) ) || ( encrypted && !klient->getNachrichtEncrypted( &c, 1 ) ) )
            break;
        else
        {
            bool br = 0;
            switch( c )
            {
            case 0:
                encrypted = 1;
                break;
            case 1: // Client Identifikation
                if( 1 )
                {
                    if( encrypted )
                        klient->getNachrichtEncrypted( (char *)&klientNummer, 4 );
                    else
                        klient->getNachricht( (char *)&klientNummer, 4 );
                    bool ret1 = 0;
                    if( !klientNummer )
                    {
                        klientNummer = ms->zDB()->getNextClientId();
                        if( encrypted )
                        {
                            Text *key = ms->zDB()->getKlientKey( klientNummer );
                            if( key )
                            {
                                klient->sendeEncrypted( "\1", 1 );
                                klient->sendeEncrypted( (char *)&klientNummer, 4 );
                                char len = (char)key->getLength();
                                klient->sendeEncrypted( &len, 1 );
                                if( len )
                                    klient->sendeEncrypted( key->getText(), len );
                                klient->setEmpfangKey( *key, len );
                                klient->setSendeKey( *key, len );
                                key->release();
                            }
                            else
                                errorZuKlient( "Es konnte kein Schlüssel ermittelt werden." );
                        }
                        else
                        {
                            klient->sende( "\1", 1 );
                            klient->sende( (char *)&klientNummer, 4 );
                        }
                        ret1 = 1;
                    }
                    if( !ms->zDB()->proveRegisteredClient( klientNummer ) )
                        errorZuKlient( "Deine Client Nummer ist nicht aktiv!" );
                    else if( !ret1 )
                    {
                        if( encrypted )
                        {
                            Text *key = ms->zDB()->getKlientKey( klientNummer );
                            if( !key )
                                errorZuKlient( "Es konnte kein Schlüssel ermittelt werden." );
                            else
                            {
                                klient->sendeEncrypted( "\1", 1 );
                                klient->setEmpfangKey( *key, key->getLength() );
                                klient->setSendeKey( *key, key->getLength() );
                                key->release();
                            }
                        }
                        else
                            klient->sende( "\1", 1 );
                    }
                }
                break;
            case 3: // Verbindungsende
                br = 1;
                if( encrypted )
                    klient->sendeEncrypted( "\1", 1 );
                else
                    klient->sende( "\1", 1 );
                break;
            case 6: // frage nach Server
                if( 1 )
                {
                    char serverTyp = 0;
                    if( encrypted )
                        klient->getNachrichtEncrypted( &serverTyp, 1 );
                    else
                        klient->getNachricht( &serverTyp, 1 );
                    switch( serverTyp )
                    {
                    case 1: // Register Server
                        if( klientNummer )
                        {
                            int sNum = ms->zDB()->suchRegisterServer( klientNummer );
                            if( sNum )
                            {
                                unsigned char *msg = ms->zDB()->getServerPortIp( sNum );
                                if( msg )
                                {
                                    if( encrypted )
                                    {
                                        klient->sendeEncrypted( "\2", 1 );
                                        klient->sendeEncrypted( (char *)msg, 6 );
                                    }
                                    else
                                    {
                                        klient->sende( "\2", 1 );
                                        klient->sende( (char *)msg, 6 );
                                    }
                                }
                                else
                                    errorZuKlient( "Aufgrund eines unerwarteten Fehlers konnte dir kein\nRegistrierungsserver zugewiesen werden!" );
                                delete[]msg;
                            }
                            else
                                errorZuKlient( "Der Server ist derzeit ausgelastet!" );
                        }
                        else
                            errorZuKlient( "Du besitzt noch keine Client Nummer!" );
                        break;
                    case 2: // Patch Server
                        if( klientNummer )
                        {
                            int sNum = ms->zDB()->suchPatchServer( klientNummer );
                            if( sNum )
                            {
                                unsigned char *msg = ms->zDB()->getServerPortIp( sNum );
                                if( msg )
                                {
                                    if( encrypted )
                                    {
                                        klient->sendeEncrypted( "\2", 1 );
                                        klient->sendeEncrypted( (char *)msg, 6 );
                                    }
                                    else
                                    {
                                        klient->sende( "\2", 1 );
                                        klient->sende( (char *)msg, 6 );
                                    }
                                }
                                else
                                    errorZuKlient( "Aufgrund eines unerwarteten Fehlers konnte dir kein\nPatchserver zugewiesen werden!" );
                                delete[]msg;
                            }
                            else
                                errorZuKlient( "Der Server ist derzeit ausgelastet!" );
                        }
                        else
                            errorZuKlient( "Du besitzt noch keine Client Nummer!" );
                        break;
                    case 3: // Login Server
                        if( klientNummer )
                        {
                            int sNum = ms->zDB()->suchLoginServer( klientNummer );
                            if( sNum )
                            {
                                unsigned char *msg = ms->zDB()->getServerPortIp( sNum );
                                if( msg )
                                {
                                    if( encrypted )
                                    {
                                        klient->sendeEncrypted( "\2", 1 );
                                        klient->sendeEncrypted( (char *)msg, 6 );
                                    }
                                    else
                                    {
                                        klient->sende( "\2", 1 );
                                        klient->sende( (char *)msg, 6 );
                                    }
                                }
                                else
                                    errorZuKlient( "Aufgrund eines unerwarteten Fehlers konnte dir kein\nLoginserver zugewiesen werden!" );
                                delete[]msg;
                            }
                            else
                                errorZuKlient( "Der Server ist derzeit ausgelastet!" );
                        }
                        else
                            errorZuKlient( "Du besitzt noch keine Client Nummer!" );
                        break;
                    case 4: // Informations Server
                        if( klientNummer )
                        {
                            int sNum = ms->zDB()->suchInformationServer( klientNummer );
                            if( sNum )
                            {
                                unsigned char *msg = ms->zDB()->getServerPortIp( sNum );
                                if( msg )
                                {
                                    if( encrypted )
                                    {
                                        klient->sendeEncrypted( "\2", 1 );
                                        klient->sendeEncrypted( (char *)msg, 6 );
                                    }
                                    else
                                    {
                                        klient->sende( "\2", 1 );
                                        klient->sende( (char *)msg, 6 );
                                    }
                                }
                                else
                                    errorZuKlient( "Aufgrund eines unerwarteten Fehlers konnte dir kein\nInformationserver zugewiesen werden!" );
                                delete[]msg;
                            }
                            else
                                errorZuKlient( "Der Server ist derzeit ausgelastet!" );
                        }
                        else
                            errorZuKlient( "Du besitzt noch keine Client Nummer!" );
                        break;
                    case 5: // Chat Server
                        if( klientNummer )
                        {
                            int sNum = ms->zDB()->suchChatServer( klientNummer );
                            if( sNum )
                            {
                                unsigned char *msg = ms->zDB()->getServerPortIp( sNum );
                                if( msg )
                                {
                                    if( encrypted )
                                    {
                                        klient->sendeEncrypted( "\2", 1 );
                                        klient->sendeEncrypted( (char *)msg, 6 );
                                    }
                                    else
                                    {
                                        klient->sende( "\2", 1 );
                                        klient->sende( (char *)msg, 6 );
                                    }
                                }
                                else
                                    errorZuKlient( "Aufgrund eines unerwarteten Fehlers konnte dir kein\nChatserver zugewiesen werden!" );
                                delete[]msg;
                            }
                            else
                                errorZuKlient( "Der Server ist derzeit ausgelastet!" );
                        }
                        else
                            errorZuKlient( "Du besitzt noch keine Client Nummer!" );
                        break;
                    case 6: // Anmeldung Server
                        if( klientNummer )
                        {
                            int sNum = ms->zDB()->suchAnmeldungServer( klientNummer );
                            if( sNum )
                            {
                                unsigned char *msg = ms->zDB()->getServerPortIp( sNum );
                                if( msg )
                                {
                                    if( encrypted )
                                    {
                                        klient->sendeEncrypted( "\2", 1 );
                                        klient->sendeEncrypted( (char *)msg, 6 );
                                    }
                                    else
                                    {
                                        klient->sende( "\2", 1 );
                                        klient->sende( (char *)msg, 6 );
                                    }
                                }
                                else
                                    errorZuKlient( "Aufgrund eines unerwarteten Fehlers konnte dir kein\nAnmeldungserver zugewiesen werden!" );
                                delete[]msg;
                            }
                            else
                                errorZuKlient( "Der Server ist derzeit ausgelastet!" );
                        }
                        else
                            errorZuKlient( "Du besitzt noch keine Client Nummer!" );
                        break;
                    case 7: // Shop Server
                        if( klientNummer )
                        {
                            int sNum = ms->zDB()->suchShopServer( klientNummer );
                            if( sNum )
                            {
                                unsigned char *msg = ms->zDB()->getServerPortIp( sNum );
                                if( msg )
                                {
                                    if( encrypted )
                                    {
                                        klient->sendeEncrypted( "\2", 1 );
                                        klient->sendeEncrypted( (char *)msg, 6 );
                                    }
                                    else
                                    {
                                        klient->sende( "\2", 1 );
                                        klient->sende( (char *)msg, 6 );
                                    }
                                }
                                else
                                    errorZuKlient( "Aufgrund eines unerwarteten Fehlers konnte dir kein\nShopserver zugewiesen werden!" );
                                delete[]msg;
                            }
                            else
                                errorZuKlient( "Der Server ist derzeit ausgelastet!" );
                        }
                        else
                            errorZuKlient( "Du besitzt noch keine Client Nummer!" );
                        break;
                    case 8: // Erhaltung Server
                        if( klientNummer )
                        {
                            int sNum = ms->zDB()->suchErhaltungServer( klientNummer );
                            if( sNum )
                            {
                                unsigned char *msg = ms->zDB()->getServerPortIp( sNum );
                                if( msg )
                                {
                                    if( encrypted )
                                    {
                                        klient->sendeEncrypted( "\2", 1 );
                                        klient->sendeEncrypted( (char *)msg, 6 );
                                    }
                                    else
                                    {
                                        klient->sende( "\2", 1 );
                                        klient->sende( (char *)msg, 6 );
                                    }
                                }
                                else
                                    errorZuKlient( "Aufgrund eines unerwarteten Fehlers konnte dir kein\nPatchserver zugewiesen werden!" );
                                delete[]msg;
                            }
                            else
                                errorZuKlient( "Der Server ist derzeit ausgelastet!" );
                        }
                        else
                            errorZuKlient( "Du besitzt noch keine Client Nummer!" );
                        break;
                    case 9: // News Server
                        if( klientNummer )
                        {
                            int sNum = ms->zDB()->suchNewsServer( klientNummer );
                            if( sNum )
                            {
                                unsigned char *msg = ms->zDB()->getServerPortIp( sNum );
                                if( msg )
                                {
                                    if( encrypted )
                                    {
                                        klient->sendeEncrypted( "\2", 1 );
                                        klient->sendeEncrypted( (char *)msg, 6 );
                                    }
                                    else
                                    {
                                        klient->sende( "\2", 1 );
                                        klient->sende( (char *)msg, 6 );
                                    }
                                }
                                else
                                    errorZuKlient( "Aufgrund eines unerwarteten Fehlers konnte dir kein\nNewsserver zugewiesen werden!" );
                                delete[]msg;
                            }
                            else
                                errorZuKlient( "Der Server ist derzeit ausgelastet!" );
                        }
                        else
                            errorZuKlient( "Du besitzt noch keine Client Nummer!" );
                        break;
                    case 0xA: // Minigame Server
                        if( klientNummer )
                        {
                            int sNum = ms->zDB()->suchMinigameServer( klientNummer );
                            if( sNum )
                            {
                                unsigned char *msg = ms->zDB()->getServerPortIp( sNum );
                                if( msg )
                                {
                                    if( encrypted )
                                    {
                                        klient->sendeEncrypted( "\2", 1 );
                                        klient->sendeEncrypted( (char *)msg, 6 );
                                    }
                                    else
                                    {
                                        klient->sende( "\2", 1 );
                                        klient->sende( (char *)msg, 6 );
                                    }
                                }
                                else
                                    errorZuKlient( "Aufgrund eines unerwarteten Fehlers konnte dir kein\nMinigameserver zugewiesen werden!" );
                                delete[]msg;
                            }
                            else
                                errorZuKlient( "Der Server ist derzeit ausgelastet!" );
                        }
                        else
                            errorZuKlient( "Du besitzt noch keine Client Nummer!" );
                        break;
                    default:
                        errorZuKlient( "Die Art des Servers ist nicht bekannt!\0" );
                        break;
                    }
                }
                break;
            case 7: // client unregistrierung
                if( klientNummer )
                {
                    int accountId = ms->zDB()->clientistEingeloggt( klientNummer );
                    if( accountId )
                    {
                        Array< int > *ret = new Array< int >();
                        int anzahl = ms->zDB()->logoutKlient( klientNummer, ret );
                        if( anzahl > 0 )
                        {
                            int jetzt = 0;
                            int chAnz = ret->get( jetzt );
                            jetzt++;
                            for( int i = 0; i < chAnz; i++ )
                            {
                                int chatroomId = ret->get( jetzt );
                                jetzt++;
                                if( chatroomId )
                                {
                                    MSGWeiterleitung *weiter = new MSGWeiterleitung( dynamic_cast<MainServer *>( ms->getThis() ) );
                                    weiter->spielerLeavesChatroom( chatroomId, accountId );
                                    weiter->release();
                                    if( ret->get( jetzt ) )
                                    {
                                        MSGWeiterleitung *weiter = new MSGWeiterleitung( dynamic_cast<MainServer *>( ms->getThis() ) );
                                        weiter->setChatroomAdmin( chatroomId, ms->zDB()->getChatroomAdmin( chatroomId ) );
                                        weiter->release();
                                    }
                                    jetzt++;
                                }
                            }
                            if( ret->get( jetzt ) == 1 )
                            {
                                jetzt++;
                                MSGWeiterleitung *weiter = new MSGWeiterleitung( dynamic_cast<MainServer *>( ms->getThis() ) );
                                weiter->spielErstelltAbbrechen( ret->get( jetzt ) );
                                weiter->release();
                            }
                            jetzt++;
                            if( ret->get( jetzt ) == 1 )
                            {
                                jetzt++;
                                int gruppeId = ret->get( jetzt );
                                MSGWeiterleitung *weiter = new MSGWeiterleitung( dynamic_cast<MainServer *>( ms->getThis() ) );
                                weiter->spielerLeavesGruppe( gruppeId, accountId );
                                weiter->release();
                                jetzt++;
                                if( ret->get( jetzt ) )
                                {
                                    MSGWeiterleitung *weiter = new MSGWeiterleitung( dynamic_cast<MainServer *>( ms->getThis() ) );
                                    weiter->setGruppeAdmin( gruppeId, ms->zDB()->getGruppeAdmin( gruppeId ) );
                                    weiter->release();
                                }
                            }
                            else if( ret->get( jetzt ) == 2 )
                            {
                                jetzt++;
                                int gruppeId = ret->get( jetzt );
                                MSGWeiterleitung *weiter = new MSGWeiterleitung( dynamic_cast<MainServer *>( ms->getThis() ) );
                                weiter->kickSpielerAusGruppe( gruppeId );
                                weiter->release();
                            }
                        }
                    }
                    MSGWeiterleitung *weiter = new MSGWeiterleitung( dynamic_cast<MainServer *>( ms->getThis() ) );
                    weiter->patchServerKlientAbsturz( klientNummer );
                    weiter->registerServerKlientAbsturz( klientNummer );
                    weiter->loginServerKlientAbsturz( klientNummer );
                    weiter->informationServerKlientAbsturz( klientNummer );
                    weiter->chatServerKlientAbsturz( klientNummer );
                    weiter->anmeldungServerKlientAbsturz( klientNummer );
                    weiter->spielServerKlientAbsturz( klientNummer );
                    weiter->shopServerKlientAbsturz( klientNummer );
                    weiter->newsServerKlientAbsturz( klientNummer );
                    weiter->historieServerKlientAbsturz( klientNummer );
                    weiter->kartenServerKlientAbsturz( klientNummer );
                    weiter->editorServerKlientAbsturz( klientNummer );
                    weiter->minigameServerKlientAbsturz( klientNummer );
                    weiter->release();
                    int *treffer = ms->zDB()->unregisterClient( klientNummer, 0 );
                    if( !treffer )
                        errorZuKlient( "Der Klient konnte nicht entfernt werden." );
                    else
                    {
                        if( encrypted )
                            klient->sendeEncrypted( "\1", 1 );
                        else
                            klient->sende( "\1", 1 );
                    }
                    delete[]treffer;
                }
                else
                    errorZuKlient( "Du besitzt noch keine Client Nummer!" );
                break;
            default:
                errorZuKlient( "Unbekannte Nachricht!" );
                break;
            }
            if( br )
                break;
            ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
            ms->addGesendet( klient->getUploadBytes( 1 ) );
        }
    }
    ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
    ms->addGesendet( klient->getUploadBytes( 1 ) );
    delete this;
}

void MSKlient::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient
{
    if( encrypted )
    {
        klient->sendeEncrypted( "\3", 1 );
        char len = (char)textLength( nachricht );
        klient->sendeEncrypted( &len, 1 );
        klient->sendeEncrypted( nachricht, len );
    }
    else
    {
        klient->sende( "\3", 1 );
        char len = (char)textLength( nachricht );
        klient->sende( &len, 1 );
        klient->sende( nachricht, len );
    }
}


// Inhalt der MSGWeiterleitung Klasse aus LoginServer.h
// Konstruktor
MSGWeiterleitung::MSGWeiterleitung( MainServer *ms )
    : ReferenceCounter()
{
    this->ms = ms;
}

// Destruktor
MSGWeiterleitung::~MSGWeiterleitung()
{
    ms->release();
}

// nicht constant
bool MSGWeiterleitung::patchServerKlientAbsturz( int klientId )
{
    Text *ip = new Text();
    int port = 0;
    if( !ms->zDB()->getPatchServer( klientId, ip, &port ) )
    {
        ip->release();
        return 0;
    }
    Klient *k = new Klient();
    unsigned char key[ 20 ] = { 102, 139, 140, 143, 52, 52, 194, 167, 97, 106, 23, 72, 170, 121, 213, 178, 28, 28, 124, 185 };
    k->setSendeKey( (char *)key, 20 );
    k->setEmpfangKey( (char *)key, 20 );
    k->verbinde( (unsigned short)port, ip->getText() );
    ip->release();
    char ret = 0;
    k->sende( "\0", 1 ); // Verkeyung aktivieren
    k->sendeEncrypted( "\2\2", 2 );
    k->sendeEncrypted( (char *)&klientId, 4 );
    k->getNachrichtEncrypted( &ret, 1 );
    bool erf = ret == 1;
    k->sendeEncrypted( "\3", 1 );
    k->getNachrichtEncrypted( &ret, 1 );
    ms->addEmpfangen( k->getDownloadBytes( 1 ) );
    ms->addGesendet( k->getUploadBytes( 1 ) );
    k->trenne();
    k->release();
    return erf;
}

bool MSGWeiterleitung::registerServerKlientAbsturz( int klientId )
{
    Text *ip = new Text();
    int port = 0;
    if( !ms->zDB()->getRegisterServer( klientId, ip, &port ) )
    {
        ip->release();
        return 0;
    }
    Klient *k = new Klient();
    unsigned char key[ 20 ] = { 186, 186, 179, 126, 216, 207, 123, 154, 168, 149, 51, 221, 6, 193, 160, 141, 164, 126, 44, 242 };
    k->setSendeKey( (char *)key, 20 );
    k->setEmpfangKey( (char *)key, 20 );
    k->verbinde( (unsigned short)port, ip->getText() );
    ip->release();
    char ret = 0;
    k->sendeEncrypted( "\2\2", 2 );
    k->sendeEncrypted( (char *)&klientId, 4 );
    k->getNachrichtEncrypted( &ret, 1 );
    bool erf = ret == 1;
    k->sendeEncrypted( "\3", 1 );
    k->getNachrichtEncrypted( &ret, 1 );
    ms->addEmpfangen( k->getDownloadBytes( 1 ) );
    ms->addGesendet( k->getUploadBytes( 1 ) );
    k->trenne();
    k->release();
    return erf;
}

bool MSGWeiterleitung::loginServerKlientAbsturz( int klientId )
{
    Text *ip = new Text();
    int port = 0;
    if( !ms->zDB()->getLoginServer( klientId, ip, &port ) )
    {
        ip->release();
        return 0;
    }
    Klient *k = new Klient();
    unsigned char key[ 20 ] = { 143, 166, 245, 235, 76, 75, 116, 80, 26, 178, 142, 176, 109, 53, 106, 222, 223, 55, 139, 111 };
    k->setSendeKey( (char *)key, 20 );
    k->setEmpfangKey( (char *)key, 20 );
    k->verbinde( (unsigned short)port, ip->getText() );
    ip->release();
    char ret = 0;
    k->sendeEncrypted( "\2\2", 2 );
    k->sendeEncrypted( (char *)&klientId, 4 );
    k->getNachrichtEncrypted( &ret, 1 );
    bool erf = ret == 1;
    k->sendeEncrypted( "\3", 1 );
    k->getNachrichtEncrypted( &ret, 1 );
    ms->addEmpfangen( k->getDownloadBytes( 1 ) );
    ms->addGesendet( k->getUploadBytes( 1 ) );
    k->trenne();
    k->release();
    return erf;
}

bool MSGWeiterleitung::informationServerKlientAbsturz( int klientId )
{
    Text *ip = new Text();
    int port = 0;
    if( !ms->zDB()->getInformationServer( klientId, ip, &port ) )
    {
        ip->release();
        return 0;
    }
    Klient *k = new Klient();
    unsigned char key[ 20 ] = { 231, 246, 125, 32, 88, 172, 229, 223, 246, 138, 74, 64, 142, 245, 217, 218, 162, 62, 103, 50 };
    k->setSendeKey( (char *)key, 20 );
    k->setEmpfangKey( (char *)key, 20 );
    k->verbinde( (unsigned short)port, ip->getText() );
    ip->release();
    char ret = 0;
    k->sendeEncrypted( "\2\2", 2 );
    k->sendeEncrypted( (char *)&klientId, 4 );
    k->getNachrichtEncrypted( &ret, 1 );
    bool erf = ret == 1;
    k->sendeEncrypted( "\3", 1 );
    k->getNachrichtEncrypted( &ret, 1 );
    ms->addEmpfangen( k->getDownloadBytes( 1 ) );
    ms->addGesendet( k->getUploadBytes( 1 ) );
    k->trenne();
    k->release();
    return erf;
}

bool MSGWeiterleitung::chatServerKlientAbsturz( int klientId )
{
    Text *ip = new Text();
    int port = 0;
    if( !ms->zDB()->getChatServer( klientId, ip, &port ) )
    {
        ip->release();
        return 0;
    }
    Klient *k = new Klient();
    unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
    k->setSendeKey( (char *)key, 20 );
    k->setEmpfangKey( (char *)key, 20 );
    k->verbinde( (unsigned short)port, ip->getText() );
    ip->release();
    char ret = 0;
    k->sendeEncrypted( "\2\2", 2 );
    k->sendeEncrypted( (char *)&klientId, 4 );
    k->getNachrichtEncrypted( &ret, 1 );
    bool erf = ret == 1;
    k->sendeEncrypted( "\3", 1 );
    k->getNachrichtEncrypted( &ret, 1 );
    ms->addEmpfangen( k->getDownloadBytes( 1 ) );
    ms->addGesendet( k->getUploadBytes( 1 ) );
    k->trenne();
    k->release();
    return erf;
}

bool MSGWeiterleitung::anmeldungServerKlientAbsturz( int klientId )
{
    Text *ip = new Text();
    int port = 0;
    if( !ms->zDB()->getAnmeldungServer( klientId, ip, &port ) )
    {
        ip->release();
        return 0;
    }
    Klient *k = new Klient();
    unsigned char key[ 20 ] = { 158, 10, 37, 155, 117, 58, 28, 197, 132, 76, 252, 83, 84, 222, 11, 125, 240, 218, 25, 201 };
    k->setSendeKey( (char *)key, 20 );
    k->setEmpfangKey( (char *)key, 20 );
    k->verbinde( (unsigned short)port, ip->getText() );
    ip->release();
    char ret = 0;
    k->sendeEncrypted( "\2\2", 2 );
    k->sendeEncrypted( (char *)&klientId, 4 );
    k->getNachrichtEncrypted( &ret, 1 );
    bool erf = ret == 1;
    k->sendeEncrypted( "\3", 1 );
    k->getNachrichtEncrypted( &ret, 1 );
    ms->addEmpfangen( k->getDownloadBytes( 1 ) );
    ms->addGesendet( k->getUploadBytes( 1 ) );
    k->trenne();
    k->release();
    return erf;
}

bool MSGWeiterleitung::spielServerKlientAbsturz( int klientId )
{
    Text *ip = new Text();
    int port = 0;
    if( !ms->zDB()->getSpielServer( klientId, ip, &port ) )
    {
        ip->release();
        return 0;
    }
    Klient *k = new 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 };
    k->setSendeKey( (char *)key, 20 );
    k->setEmpfangKey( (char *)key, 20 );
    k->verbinde( (unsigned short)port, ip->getText() );
    ip->release();
    char ret = 0;
    k->sendeEncrypted( "\2\2", 2 );
    k->sendeEncrypted( (char *)&klientId, 4 );
    k->getNachrichtEncrypted( &ret, 1 );
    bool erf = ret == 1;
    k->sendeEncrypted( "\3", 1 );
    k->getNachrichtEncrypted( &ret, 1 );
    ms->addEmpfangen( k->getDownloadBytes( 1 ) );
    ms->addGesendet( k->getUploadBytes( 1 ) );
    k->trenne();
    k->release();
    return erf;
}

bool MSGWeiterleitung::shopServerKlientAbsturz( int klientId )
{
    Text *ip = new Text();
    int port = 0;
    if( !ms->zDB()->getShopServer( klientId, ip, &port ) )
    {
        ip->release();
        return 0;
    }
    Klient *k = new Klient();
    unsigned char key[ 20 ] = { 218, 226, 231, 216, 68, 63, 132, 155, 49, 235, 239, 0, 19, 23, 116, 244, 235, 21, 189, 53 };
    k->setSendeKey( (char *)key, 20 );
    k->setEmpfangKey( (char *)key, 20 );
    k->verbinde( (unsigned short)port, ip->getText() );
    ip->release();
    char ret = 0;
    k->sendeEncrypted( "\2\2", 2 );
    k->sendeEncrypted( (char *)&klientId, 4 );
    k->getNachrichtEncrypted( &ret, 1 );
    bool erf = ret == 1;
    k->sendeEncrypted( "\3", 1 );
    k->getNachrichtEncrypted( &ret, 1 );
    ms->addEmpfangen( k->getDownloadBytes( 1 ) );
    ms->addGesendet( k->getUploadBytes( 1 ) );
    k->trenne();
    k->release();
    return erf;
}

bool MSGWeiterleitung::newsServerKlientAbsturz( int klientId )
{
    Text *ip = new Text();
    int port = 0;
    if( !ms->zDB()->getNewsServer( klientId, ip, &port ) )
    {
        ip->release();
        return 0;
    }
    Klient *k = new Klient();
    unsigned char key[ 20 ] = { 4, 150, 243, 145, 204, 71, 253, 88, 4, 51, 189, 207, 189, 248, 231, 40, 106, 7, 182, 5 };
    k->setSendeKey( (char *)key, 20 );
    k->setEmpfangKey( (char *)key, 20 );
    k->verbinde( (unsigned short)port, ip->getText() );
    ip->release();
    char ret = 0;
    k->sendeEncrypted( "\2\2", 2 );
    k->sendeEncrypted( (char *)&klientId, 4 );
    k->getNachrichtEncrypted( &ret, 1 );
    bool erf = ret == 1;
    k->sendeEncrypted( "\3", 1 );
    k->getNachrichtEncrypted( &ret, 1 );
    ms->addEmpfangen( k->getDownloadBytes( 1 ) );
    ms->addGesendet( k->getUploadBytes( 1 ) );
    k->trenne();
    k->release();
    return erf;
}

bool MSGWeiterleitung::historieServerKlientAbsturz( int klientId )
{
    Text *ip = new Text();
    int port = 0;
    if( !ms->zDB()->getHistorieServer( klientId, ip, &port ) )
    {
        ip->release();
        return 0;
    }
    Klient *k = new Klient();
    unsigned char key[ 20 ] = { 207, 30, 72, 46, 30, 50, 56, 213, 82, 107, 14, 201, 149, 58, 110, 138, 228, 241, 52, 54 };
    k->setSendeKey( (char *)key, 20 );
    k->setEmpfangKey( (char *)key, 20 );
    k->verbinde( (unsigned short)port, ip->getText() );
    ip->release();
    char ret = 0;
    k->sendeEncrypted( "\2\2", 2 );
    k->sendeEncrypted( (char *)&klientId, 4 );
    k->getNachrichtEncrypted( &ret, 1 );
    bool erf = ret == 1;
    k->sendeEncrypted( "\3", 1 );
    k->getNachrichtEncrypted( &ret, 1 );
    ms->addEmpfangen( k->getDownloadBytes( 1 ) );
    ms->addGesendet( k->getUploadBytes( 1 ) );
    k->trenne();
    k->release();
    return erf;
}

bool MSGWeiterleitung::kartenServerKlientAbsturz( int klientId )
{
    Text *ip = new Text();
    int port = 0;
    if( !ms->zDB()->getKartenServer( klientId, ip, &port ) )
    {
        ip->release();
        return 0;
    }
    Klient *k = new Klient();
    unsigned char key[ 20 ] = { 24, 15, 53, 87, 38, 73, 154, 38, 246, 90, 39, 133, 11, 199, 22, 80, 26, 132, 95, 54 };
    k->setSendeKey( (char *)key, 20 );
    k->setEmpfangKey( (char *)key, 20 );
    k->verbinde( (unsigned short)port, ip->getText() );
    ip->release();
    char ret = 0;
    k->sendeEncrypted( "\2\2", 2 );
    k->sendeEncrypted( (char *)&klientId, 4 );
    k->getNachrichtEncrypted( &ret, 1 );
    bool erf = ret == 1;
    k->sendeEncrypted( "\3", 1 );
    k->getNachrichtEncrypted( &ret, 1 );
    ms->addEmpfangen( k->getDownloadBytes( 1 ) );
    ms->addGesendet( k->getUploadBytes( 1 ) );
    k->trenne();
    k->release();
    return erf;
}

bool MSGWeiterleitung::editorServerKlientAbsturz( int klientId )
{
    Text *ip = new Text();
    int port = 0;
    if( !ms->zDB()->getEditorServer( klientId, ip, &port ) )
    {
        ip->release();
        return 0;
    }
    Klient *k = new Klient();
    unsigned char key[ 20 ] = { 55, 124, 19, 204, 23, 5, 59, 75, 247, 138, 119, 111, 57, 250, 206, 187, 165, 6, 247, 151 };
    k->setSendeKey( (char *)key, 20 );
    k->setEmpfangKey( (char *)key, 20 );
    k->verbinde( (unsigned short)port, ip->getText() );
    ip->release();
    char ret = 0;
    k->sendeEncrypted( "\2\2", 2 );
    k->sendeEncrypted( (char *)&klientId, 4 );
    k->getNachrichtEncrypted( &ret, 1 );
    bool erf = ret == 1;
    k->sendeEncrypted( "\3", 1 );
    k->getNachrichtEncrypted( &ret, 1 );
    ms->addEmpfangen( k->getDownloadBytes( 1 ) );
    ms->addGesendet( k->getUploadBytes( 1 ) );
    k->trenne();
    k->release();
    return erf;
}

bool MSGWeiterleitung::minigameServerKlientAbsturz( int klientId )
{
    Text *ip = new Text();
    int port = 0;
    if( !ms->zDB()->getMinigameServer( klientId, ip, &port ) )
    {
        ip->release();
        return 0;
    }
    Klient *k = new Klient();
    unsigned char key[ 20 ] = { 88, 103, 192, 232, 69, 54, 57, 3, 239, 138, 234, 172, 126, 72, 81, 55, 205, 97, 59, 255 };
    k->setSendeKey( (char *)key, 20 );
    k->setEmpfangKey( (char *)key, 20 );
    k->verbinde( (unsigned short)port, ip->getText() );
    ip->release();
    char ret = 0;
    k->sendeEncrypted( "\2\2", 2 );
    k->sendeEncrypted( (char *)&klientId, 4 );
    k->getNachrichtEncrypted( &ret, 1 );
    bool erf = ret == 1;
    k->sendeEncrypted( "\3", 1 );
    k->getNachrichtEncrypted( &ret, 1 );
    ms->addEmpfangen( k->getDownloadBytes( 1 ) );
    ms->addGesendet( k->getUploadBytes( 1 ) );
    k->trenne();
    k->release();
    return erf;
}

bool MSGWeiterleitung::spielErstelltAbbrechen( int spielErstelltId )
{
    bool ret = 1;
    Text *ip = new Text( "" );
    unsigned short port = 0;
    ret = ret & ms->zDB()->getSpielServerPortIp( spielErstelltId, &port, ip );
    if( ip->getLength() )
    {
        Klient *klient = new 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 );
        ret = ret & klient->verbinde( port, ip->getText() );
        ret = ret & klient->sendeEncrypted( "\x8\x1", 2 );
        char res = 0;
        ret = ret & klient->getNachrichtEncrypted( &res, 1 );
        if( res )
        {
            ret = ret & klient->sendeEncrypted( (char *)&spielErstelltId, 4 );
            ret = ret & klient->getNachrichtEncrypted( &res, 1 );
        }
        ret = (char)ret & res;
        ret = ret & klient->sendeEncrypted( "\x8\x0", 2 );
        ret = ret & klient->getNachrichtEncrypted( &res, 1 );
        ret = (char)ret & res;
        ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
        ms->addGesendet( klient->getUploadBytes( 1 ) );
        klient->trenne();
        klient = (Klient *)klient->release();
        ip->release();
    }
    return ret;
}

bool MSGWeiterleitung::spielerLeavesGruppe( int gruppeId, int accountId )
{
    bool ret = 1;
    Array< int > *accId = new Array< int >();
    int anzahl = ms->zDB()->getSpielerAusGruppe( gruppeId, accId );
    for( int i = 0; i < anzahl; i++ )
    {
        int account = accId->get( i );
        if( account == accountId )
            continue;
        Text *ip = new Text( "" );
        unsigned short port = 0;
        ret = ret & ms->zDB()->getChatServerPortIp( account, &port, ip );
        if( ip->getLength() )
        {
            Klient *klient = new Klient();
            unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
            klient->setSendeKey( (char *)key, 20 );
            klient->setEmpfangKey( (char *)key, 20 );
            ret = ret & klient->verbinde( port, ip->getText() );
            ret = ret & klient->sendeEncrypted( "\5\x15", 2 );
            char res = 0;
            ret = ret & klient->getNachrichtEncrypted( &res, 1 );
            if( res )
            {
                ret = ret & klient->sendeEncrypted( (char *)&account, 4 );
                ret = ret & klient->sendeEncrypted( (char *)&accountId, 4 );
                ret = ret & klient->sendeEncrypted( (char *)&gruppeId, 4 );
                ret = ret & klient->getNachrichtEncrypted( &res, 1 );
            }
            ret = (char)ret & res;
            ret = ret & klient->sendeEncrypted( "\5\x18", 2 );
            res = 0;
            ret = ret & klient->getNachrichtEncrypted( &res, 1 );
            if( res )
            {
                ret = ret & klient->sendeEncrypted( (char *)&account, 4 );
                ret = ret & klient->sendeEncrypted( (char *)&gruppeId, 4 );
                ret = ret & klient->getNachrichtEncrypted( &res, 1 );
            }
            ret = (char)ret & res;
            ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
            ms->addGesendet( klient->getUploadBytes( 1 ) );
            klient->trenne();
            klient = (Klient *)klient->release();
        }
        ip->release();
    }
    accId->release();
    return ret;
}

bool MSGWeiterleitung::setGruppeAdmin( int gruppeId, int adminId )
{
    if( !adminId || !gruppeId )
        return 0;
    bool ret = 1;
    Array< int > *accId = new Array< int >();
    int anzahl = ms->zDB()->getSpielerAusGruppe( gruppeId, accId );
    for( int i = 0; i < anzahl; i++ )
    {
        int account = accId->get( i );
        Text *ip = new Text( "" );
        unsigned short port = 0;
        ret = ret & ms->zDB()->getChatServerPortIp( account, &port, ip );
        if( ip->getLength() )
        {
            Klient *klient = new Klient();
            unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
            klient->setSendeKey( (char *)key, 20 );
            klient->setEmpfangKey( (char *)key, 20 );
            ret = ret & klient->verbinde( port, ip->getText() );
            ret = ret & klient->sendeEncrypted( "\5\x1B", 2 );
            char res = 0;
            ret = ret & klient->getNachrichtEncrypted( &res, 1 );
            if( res )
            {
                ret = ret & klient->sendeEncrypted( (char *)&account, 4 );
                ret = ret & klient->sendeEncrypted( (char *)&adminId, 4 );
                ret = ret & klient->sendeEncrypted( (char *)&gruppeId, 4 );
                ret = ret & klient->getNachrichtEncrypted( &res, 1 );
            }
            ret = (char)ret & res;
            ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
            ms->addGesendet( klient->getUploadBytes( 1 ) );
            klient->trenne();
            klient = (Klient *)klient->release();
        }
        ip->release();
    }
    accId->release();
    return ret;
}

bool MSGWeiterleitung::spielerLeavesChatroom( int chatroomId, int accountId )
{
    bool ret = 1;
    Array< int > *accId = new Array< int >();
    int anzahl = ms->zDB()->getSpielerAusChatroom( chatroomId, accId );
    for( int i = 0; i < anzahl; i++ )
    {
        int account = accId->get( i );
        if( account == accountId )
            continue;
        Text *ip = new Text( "" );
        unsigned short port = 0;
        ret = ret & ms->zDB()->getChatServerPortIp( account, &port, ip );
        if( ip->getLength() )
        {
            Klient *klient = new Klient();
            unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
            klient->setSendeKey( (char *)key, 20 );
            klient->setEmpfangKey( (char *)key, 20 );
            ret = ret & klient->verbinde( port, ip->getText() );
            ret = ret & klient->sendeEncrypted( "\5\xE", 2 );
            char res = 0;
            ret = ret & klient->getNachrichtEncrypted( &res, 1 );
            if( res )
            {
                ret = ret & klient->sendeEncrypted( (char *)&accountId, 4 );
                ret = ret & klient->sendeEncrypted( (char *)&account, 4 );
                ret = ret & klient->sendeEncrypted( (char *)&chatroomId, 4 );
                ret = ret & klient->getNachrichtEncrypted( &res, 1 );
            }
            ret = (char)ret & res;
            ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
            ms->addGesendet( klient->getUploadBytes( 1 ) );
            klient->trenne();
            klient = (Klient *)klient->release();
        }
        ip->release();
    }
    accId->release();
    return ret;
}

bool MSGWeiterleitung::setChatroomAdmin( int chatroomId, int adminId )
{
    if( !adminId || !chatroomId )
        return 0;
    bool ret = 1;
    Text *ip = new Text( "" );
    unsigned short port = 0;
    ret = ret & ms->zDB()->getChatServerPortIp( adminId, &port, ip );
    if( ip->getLength() )
    {
        Klient *klient = new Klient();
        unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
        klient->setSendeKey( (char *)key, 20 );
        klient->setEmpfangKey( (char *)key, 20 );
        ret = ret & klient->verbinde( port, ip->getText() );
        ret = ret & klient->sendeEncrypted( "\5\x12", 2 );
        char res = 0;
        ret = ret & klient->getNachrichtEncrypted( &res, 1 );
        if( res )
        {
            ret = ret & klient->sendeEncrypted( (char *)&adminId, 4 );
            ret = ret & klient->sendeEncrypted( (char *)&chatroomId, 4 );
            ret = ret & klient->getNachrichtEncrypted( &res, 1 );
        }
        ret = (char)ret & res;
        ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
        ms->addGesendet( klient->getUploadBytes( 1 ) );
        klient->trenne();
        klient = (Klient *)klient->release();
    }
    ip->release();
    return ret;
}

bool MSGWeiterleitung::kickSpielerAusGruppe( int gruppeId )
{
    if( !gruppeId )
        return 0;
    bool ret = 1;
    Array< int > *accId = new Array< int >();
    int anzahl = ms->zDB()->getSpielerAusGruppe( gruppeId, accId );
    for( int i = 0; i < anzahl; i++ )
    {
        int account = accId->get( i );
        Text *ip = new Text( "" );
        unsigned short port = 0;
        ret = ret & ms->zDB()->getChatServerPortIp( account, &port, ip );
        if( ip->getLength() )
        {
            Klient *klient = new Klient();
            unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
            klient->setSendeKey( (char *)key, 20 );
            klient->setEmpfangKey( (char *)key, 20 );
            ret = ret & klient->verbinde( port, ip->getText() );
            ret = ret & klient->sendeEncrypted( "\5\x16", 2 );
            char res = 0;
            ret = ret & klient->getNachrichtEncrypted( &res, 1 );
            if( res )
            {
                ret = ret & klient->sendeEncrypted( (char *)&account, 4 );
                ret = ret & klient->sendeEncrypted( (char *)&gruppeId, 4 );
                ret = ret & klient->getNachrichtEncrypted( &res, 1 );
            }
            ret = (char)ret & res;
            ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
            ms->addGesendet( klient->getUploadBytes( 1 ) );
            klient->trenne();
            klient = (Klient *)klient->release();
        }
        ms->zDB()->kickSpielerAusGruppe( gruppeId, account );
        ip->release();
    }
    accId->release();
    return ret;
}