#include "EditorServer.h"
#include <iostream>
#include <Klient.h>
#include <Globals.h>

// Inhalt der EditorServer Klasse aus EditorServer.h
// Konstruktor 
EditorServer::EditorServer( InitDatei *zIni )
    : Thread()
{
    Network::Start( 100 );
    std::cout << "EdS: Verbindung mit Datenbank wird hergestellt...\n";
    db = new EdSDatenbank( zIni );
    klientAnzahl = 0;
    klients = new RCArray< EdSKlient >();
    empfangen = 0;
    gesendet = 0;
    fehler = new Text();
    ini = zIni->getThis();
    id = *zIni->zWert( "ServerId" );
    server = new Server();
    aServer = new Server();
    std::cout << "EdS: Starten des Admin Servers...\n";
    if( !aServer->verbinde( (unsigned short)TextZuInt( ini->zWert( "AdminServerPort" )->getText(), 10 ), 10 ) )
    {
        std::cout << "EdS: 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;
    if( zIni->zWert( "Aktiv" )->istGleich( "TRUE" ) )
    {
        serverStarten();
        serverFortsetzen();
    }
}

// Destruktor 
EditorServer::~EditorServer()
{
    fehler->release();
    server->trenne();
    server->release();
    aServer->trenne();
    aServer->release();
    if( klients )
        klients->release();
    ini->release();
    db->release();
    DeleteCriticalSection( &cs );
}

// nicht constant 
void EditorServer::runn()
{
    while( !end )
    {
        SKlient *klient;
        klient = aServer->getKlient();
        if( end && klient )
        {
            klient->trenne();
            klient = klient->release();
            Sleep( 1000 );
            return;
        }
        if( !klient )
            return;
        EdSAKlient *clHandle = new EdSAKlient( klient, getThis() );
        clHandle->start();
    }
}

void EditorServer::thread()
{
    while( 1 )
    {
        SKlient *klient;
        klient = server->getKlient();
        if( !klient )
            break;
		Framework::getThreadRegister()->cleanUpClosedThreads();
        EdSKlient *clHandle = new EdSKlient( klient, getThis() );
        EnterCriticalSection( &cs );
        klients->set( clHandle, klientAnzahl );
        klientAnzahl++;
        LeaveCriticalSection( &cs );
        clHandle->start();
    }
}

void EditorServer::close()
{
    db->setServerStatus( id, 1 );
    server->trenne();
#ifdef WIN32
    warteAufThread( 1000 );
#endif
    EnterCriticalSection( &cs );
    for( int i = 0; i < klientAnzahl; i++ )
        klients->z( i )->absturz();
    klients = klients->release();
    klientAnzahl = 0;
    LeaveCriticalSection( &cs );
    ende();
    run = 0;
    end = 1;
    Klient *klient = new Klient();
    klient->verbinde( aServer->getPort(), "127.0.0.1" );
    Sleep( 500 );
    aServer->trenne();
    klient->release();
}

bool EditorServer::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();
        return 1;
    }
    else
    {
        serverBeenden();
        fehler->setText( "Der Server konnte nicht gestartet werden: Eventuell ist der Port in benutzung." );
        return 0;
    }
}

bool EditorServer::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 EditorServer::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 EditorServer::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;
    }
    nichtPausiert = 0;
    ende();
    if( server )
        server->trenne();
    return 1;
}

bool EditorServer::setMaxKarten( int mk )
{
    if( !db->setMaxKarten( id, mk ) )
    {
        fehler->setText( "Die maximale Anzahl der Karten konnte nicht gesetzt werden:\n" );
        fehler->append( db->getLetzterFehler() );
        return 0;
    }
    ini->setWert( "MaxKarten", Text() += mk );
    return 1;
}

bool EditorServer::absturzKlient( int klientId )
{
    bool gefunden = 0;
    EnterCriticalSection( &cs );
    for( int i = 0; i < klientAnzahl; i++ )
    {
        if( klients->z( i )->getKlientNummer() == klientId )
        {
            klients->z( i )->absturz();
            klients->remove( i );
            klientAnzahl--;
            gefunden = 1;
            break;
        }
    }
    LeaveCriticalSection( &cs );
    return gefunden;
}

bool EditorServer::removeKlient( EdSKlient *zKlient )
{
    bool gefunden = 0;
    EnterCriticalSection( &cs );
    for( int i = 0; i < klientAnzahl; i++ )
    {
        if( klients->z( i ) == zKlient )
        {
            klients->remove( i );
            klientAnzahl--;
            gefunden = 1;
            break;
        }
    }
    LeaveCriticalSection( &cs );
    return gefunden;
}

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

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

// constant 
bool EditorServer::istAn() const
{
    return db->serverIstNichtPausiert( id );
}

Server *EditorServer::zServer() const
{
    return server;
}

EdSDatenbank *EditorServer::zDB() const
{
    return db;
}

InitDatei *EditorServer::zIni() const
{
    return ini;
}

bool EditorServer::hatClients() const
{
    return klientAnzahl > 0;
}

int EditorServer::getId() const
{
    return id;
}

char *EditorServer::getLetzterFehler() const
{
    return fehler->getText();
}

// Reference Counting
EditorServer *EditorServer::getThis()
{
    ref++;
    return this;
}

EditorServer *EditorServer::release()
{
    ref--;
    if( !ref )
        delete this;
    return 0;
}


// Inhalt der EdSAKlient Klasse aus EditorServer.h
// Konstruktor 
EdSAKlient::EdSAKlient( SKlient *klient, EditorServer *eds )
    : Thread()
{
    this->klient = klient;
    unsigned char key[ 20 ] = { 102, 98, 8, 248, 114, 86, 30, 28, 18, 142, 113, 108, 129, 101, 196, 53, 37, 184, 73, 108 };
    klient->setSendeKey( (char*)key, 20 );
    klient->setEmpfangKey( (char*)key, 20 );
    name = new Text( "" );
    passwort = new Text( "" );
    adminId = 0;
    this->eds = eds;
}

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

// nicht constant 
void EdSAKlient::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 );
                    unsigned char nLen = 0;
                    klient->getNachrichtEncrypted( (char*)&nLen, 1 );
                    char *n = new char[ nLen + 1 ];
                    n[ (int)nLen ] = 0;
                    if( nLen )
                        klient->getNachrichtEncrypted( n, nLen );
                    unsigned char pLen = 0;
                    klient->getNachrichtEncrypted( (char*)&pLen, 1 );
                    char *p = new char[ pLen + 1 ];
                    p[ (int)pLen ] = 0;
                    if( pLen )
                        klient->getNachrichtEncrypted( p, pLen );
                    int adminId = eds->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( eds->zDB()->adminHatRecht( adminId, Admin_Recht::EdSStarten ) )
                    {
                        if( !eds->serverStarten() )
                        {
                            Text *err = new Text();
                            err->append( eds->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( eds->zDB()->adminHatRecht( adminId, Admin_Recht::EdSBeenden ) )
                    {
                        if( eds->serverBeenden() )
                            klient->sendeEncrypted( "\1", 1 );
                        else
                        {
                            Text *err = new Text();
                            err->append( eds->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( eds->isRunning() )
                    {
                        if( eds->zDB()->adminHatRecht( adminId, Admin_Recht::EdSBeenden ) )
                        {
                            if( eds->serverBeenden() )
                                ok = 1;
                            else
                            {
                                Text *err = new Text();
                                err->append( eds->getLetzterFehler() );
                                errorZuKlient( err->getText() );
                                err->release();
                            }
                        }
                        else
                            errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
                    }
                    else
                        ok = 1;
                    if( ok && eds->hatClients() )
                    {
                        errorZuKlient( "Es sind noch Klients Online. Bitte versuche es später erneut." );
                        break;
                    }
                    if( ok )
                    {
                        klient->sendeEncrypted( "\1", 1 );
                        std::cout << "EdS: Der Server wird von Benutzer " << adminId << " heruntergefahren.\n";
                        eds->close();
                        br = 1;
                    }
                }
                break;
            case 7: // Progtamm abstürzen
                if( !adminId )
                    errorZuKlient( "Du musst dich einloggen." );
                else
                {
                    bool ok = 0;
                    if( eds->isRunning() )
                    {
                        if( eds->zDB()->adminHatRecht( adminId, Admin_Recht::EdSBeenden ) )
                        {
                            eds->serverBeenden();
                            ok = 1;
                        }
                        else
                            errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
                    }
                    else
                        ok = 1;
                    if( ok )
                    {
                        klient->sendeEncrypted( "\1", 1 );
                        std::cout << "EdS: Der Server wurde von Benutzer " << adminId << " terminiert.\n";
                        eds->close();
                        br = 1;
                    }
                }
                break;
            case 8: // Status Frage
                if( 1 )
                {
                    char status = 0;
                    if( eds->isRunning() )
                    {
                        status = 1;
                        if( eds->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( eds->zDB()->adminHatRecht( adminId, Admin_Recht::EdSPausieren ) )
                    {
                        bool ok = 0;
                        if( pause )
                            ok = eds->serverPause();
                        else
                            ok = eds->serverFortsetzen();
                        if( ok )
                            klient->sendeEncrypted( "\1", 1 );
                        else
                        {
                            Text *err = new Text();
                            err->append( eds->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 Clients setzen
                if( !adminId )
                    errorZuKlient( "Du musst dich einloggen." );
                else
                {
                    klient->sendeEncrypted( "\1", 1 );
                    int maxK = 0;
                    klient->getNachrichtEncrypted( (char*)&maxK, 4 );
                    if( eds->zDB()->adminHatRecht( adminId, Admin_Recht::EdSMKChange ) )
                    {
                        if( eds->setMaxKarten( maxK ) )
                            klient->sendeEncrypted( "\1", 1 );
                        else
                        {
                            Text *err = new Text();
                            err->append( eds->getLetzterFehler() );
                            errorZuKlient( err->getText() );
                            err->release();
                        }
                    }
                    else
                        errorZuKlient( "Du bist nicht berechtigt die maximale Anzahl der Karten zu verändern." );
                }
                break;
            case 0xC: // klient absturtz
                if( 1 )
                {
                    klient->sendeEncrypted( "\1", 1 );
                    int klientId = 0;
                    klient->getNachrichtEncrypted( (char*)&klientId, 4 );
                    if( klientId && eds->absturzKlient( klientId ) )
                        klient->sendeEncrypted( "\1", 1 );
                    else
                        klient->sendeEncrypted( "\0", 1 );
                }
                break;
            default:
                errorZuKlient( "Unbekannte Nachricht!" );
                break;
            }
            if( br )
                break;
            eds->addEmpfangen( klient->getDownloadBytes( 1 ) );
            eds->addGesendet( klient->getUploadBytes( 1 ) );
        }
    }
    eds->addEmpfangen( klient->getDownloadBytes( 1 ) );
    eds->addGesendet( klient->getUploadBytes( 1 ) );
    delete this;
}

void EdSAKlient::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 EdSKlient aus EditorServer.h
// Konstruktor 
EdSKlient::EdSKlient( SKlient *klient, EditorServer *eds )
    : Thread()
{
    this->klient = 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 };
    klient->setSendeKey( (char*)key, 20 );
    klient->setEmpfangKey( (char*)key, 20 );
    klientNummer = 0;
    this->eds = eds;
    ked = 0;
    ref = 1;
}

// Destruktor 
EdSKlient::~EdSKlient()
{
    if( ked )
        ked->release();
    klient->release();
    eds->release();
}

// nicht constant
void EdSKlient::absturz()
{
    ende();
    klient->trenne();
    eds->zDB()->unregisterKlient( klientNummer, eds->getId() );
}

void EdSKlient::thread()
{
    while( 1 )
    {
        char c = 0;
        if( !klient->getNachrichtEncrypted( &c, 1 ) )
            break;
        else
        {
            bool br = 0;
            switch( c )
            {
            case 1: // Klient identifikation
                klient->getNachrichtEncrypted( (char*)&klientNummer, 4 );
                if( !eds->zDB()->proveKlient( klientNummer, eds->getId() ) )
                {
                    klientNummer = 0;
                    errorZuKlient( "Du bist nicht für diesen Server eingetragen" );
                }
                else
                {
                    Text *key = eds->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();
                    }
                }
                break;
            case 2: // Main / Erhaltung Server message
                if( 1 )
                {
                    char befehl = 0;
                    klient->getNachrichtEncrypted( &befehl, 1 );
                    switch( befehl )
                    {
                    case 2: // klient absturtz
                        if( 1 )
                        {
                            int klientId = 0;
                            klient->getNachrichtEncrypted( (char*)&klientId, 4 );
                            if( klientId && eds->absturzKlient( klientId ) )
                                klient->sendeEncrypted( "\1", 1 );
                            else
                                klient->sendeEncrypted( "\0", 1 );
                        }
                        break;
                    default:
                        errorZuKlient( "Befehl nicht bekannt!" );
                        break;
                    }
                }
                break;
            case 3: // Verbindungsende
                br = 1;
                klient->sendeEncrypted( "\1", 1 );
                break;
            case 4: // unregister Klient
                if( !klientNummer )
                {
                    errorZuKlient( "Du bist nicht Identifiziert." );
                    break;
                }
                eds->zDB()->unregisterKlient( klientNummer, eds->getId() );
                klient->sendeEncrypted( "\1", 1 );
                break;
            case 5: // keep alive
                if( !klientNummer )
                {
                    errorZuKlient( "Du bist nicht Identifiziert." );
                    break;
                }
                klient->sendeEncrypted( "\1", 1 );
                break;
            case 6: // lade Karte
                if( !klientNummer )
                {
                    errorZuKlient( "Du bist nicht Identifiziert." );
                    break;
                }
                else
                {
                    klient->sendeEncrypted( "\1", 1 );
                    int karteId = 0;
                    klient->getNachrichtEncrypted( (char*)&karteId, 4 );
                    if( eds->zDB()->proveKarte( karteId, klientNummer, eds->getId() ) )
                    {
                        if( ked )
                            ked->release();
                        ked = new KarteEditor( karteId, eds->zDB()->getThis(), eds->zIni()->zWert( "KartenPfad" )->getText(), eds->zIni() );
                        if( ked->istOk() )
                            klient->sendeEncrypted( "\1", 1 );
                        else
                        {
                            errorZuKlient( ked->getLetzterFehler() );
                            ked = ked->release();
                        }
                    }
                    else
                        errorZuKlient( "Du kannst diese Karte nicht bearbeiten." );
                }
                break;
            case 7: // Nachricht
                if( !klientNummer )
                {
                    errorZuKlient( "Du bist nicht Identifiziert." );
                    break;
                }
                else
                {
                    if( !ked || !ked->istOk() )
                        errorZuKlient( "Es wurde keine Karte geladen." );
                    else
                    {
                        klient->sendeEncrypted( "\1", 1 );
                        if( !ked->prozessMessage( klient ) )
                            errorZuKlient( ked->getLetzterFehler() );
                        ked->removeError();
                    }
                }
                break;
            case 8: // Shop Seite herunterladen (Vom Shop Server)
                if( klientNummer )
                {
                    errorZuKlient( "Du bist nicht berechtigt." );
                    break;
                }
                else
                {
                    klient->sendeEncrypted( "\1", 1 );
                    int id = 0;
                    klient->getNachrichtEncrypted( (char*)&id, 4 );
                    if( ked )
                        ked->release();
                    ked = new KarteEditor( id, eds->zDB()->getThis(), eds->zIni()->zWert( "KartenPfad" )->getText(), eds->zIni() );
                    if( !ked->istOk() )
                    {
                        errorZuKlient( "Die Karte konnte nicht geladen werden." );
                        ked = ked->release();
                        break;
                    }
                    klient->sendeEncrypted( "\1", 1 );
                    RCArray< Text > *list = new RCArray< Text >();
                    int anz = ked->getDateiUpdateListe( ( char* )"shop", list );
                    klient->sendeEncrypted( (char*)&anz, 4 );
                    for( int i = 0; i < anz; i++ )
                    {
                        Text p = list->z( i )->getText();
                        char l = (char)p.getLength();
                        klient->sendeEncrypted( &l, 1 );
                        klient->sendeEncrypted( p, l );
                        Text tmp = ked->getPfad();
                        tmp += "/live/shop";
                        p.insert( 0, (char*)tmp );
                        Datei d;
                        d.setDatei( p );
                        __int64 size = d.getSize();
                        klient->sendeEncrypted( (char*)&size, 8 );
                        d.open( Datei::Style::lesen );
                        char *buffer = new char[ 2048 ];
                        while( size )
                        {
                            int l = size > 2048 ? 2048 : (int)size;
                            d.lese( buffer, l );
                            klient->sende( buffer, l );
                            size -= l;
                        }
                        delete[] buffer;
                        d.close();
                    }
                    list->release();
                    if( ked )
                        ked = ked->release();
                }
                break;
            case 9: // Karte Update herunterladen (Vom Karten Server)
                if( klientNummer )
                {
                    errorZuKlient( "Du bist nicht berechtigt." );
                    break;
                }
                else
                {
                    klient->sendeEncrypted( "\1", 1 );
                    int id = 0;
                    klient->getNachrichtEncrypted( (char*)&id, 4 );
                    if( ked )
                        ked->release();
                    ked = new KarteEditor( id, eds->zDB()->getThis(), eds->zIni()->zWert( "KartenPfad" )->getText(), eds->zIni() );
                    if( !ked->istOk() )
                    {
                        errorZuKlient( "Die Karte konnte nicht geladen werden." );
                        ked = ked->release();
                        break;
                    }
                    klient->sendeEncrypted( "\1", 1 );
                    RCArray< Text > *list = new RCArray< Text >();
                    int anz = ked->getDateiUpdateListe( ( char* )"map", list );
                    klient->sendeEncrypted( (char*)&anz, 4 );
                    for( int i = 0; i < anz; i++ )
                    {
                        Text p = list->z( i )->getText();
                        char l = (char)p.getLength();
                        klient->sendeEncrypted( &l, 1 );
                        klient->sendeEncrypted( p, l );
                        Text tmp = ked->getPfad();
                        tmp += "/live/map";
                        p.insert( 0, (char*)tmp );
                        Datei d;
                        d.setDatei( p );
                        __int64 size = d.getSize();
                        klient->sendeEncrypted( (char*)&size, 8 );
                        d.open( Datei::Style::lesen );
                        char *buffer = new char[ 2048 ];
                        while( size )
                        {
                            int l = size > 2048 ? 2048 : (int)size;
                            d.lese( buffer, l );
                            klient->sende( buffer, l );
                            size -= l;
                        }
                        delete[] buffer;
                        d.close();
                    }
                    list->release();
                    if( ked )
                        ked = ked->release();
                }
                break;
            case 10: // Neue Karte erstellen
            {
                if( !klientNummer )
                {
                    errorZuKlient( "Du bist nicht Identifiziert." );
                    break;
                }
                else
                {
                    klient->sendeEncrypted( "\1", 1 );
                    unsigned char l = 0;
                    klient->getNachrichtEncrypted( (char*)&l, 1 );
                    char *n = new char[ l + 1 ];
                    n[ (int)l ] = 0;
                    klient->getNachrichtEncrypted( n, l );
                    int spielArt = 0;
                    klient->getNachrichtEncrypted( (char*)&spielArt, 4 );
                    if( eds->zDB()->karteErstellen( n, spielArt, klientNummer ) )
                        klient->sendeEncrypted( "\1", 1 );
                    else
                        errorZuKlient( "Für dieses Spiel kann momentan keine Karte erstellt werden." );
                    delete[] n;
                }
                break;
            }
            default:
                errorZuKlient( "Unbekannte Nachricht!" );
                break;
            }
            if( br )
                break;
            eds->addEmpfangen( klient->getDownloadBytes( 1 ) );
            eds->addGesendet( klient->getUploadBytes( 1 ) );
        }
    }
    eds->addEmpfangen( klient->getDownloadBytes( 1 ) );
    eds->addGesendet( klient->getUploadBytes( 1 ) );
    eds->removeKlient( this ); // delete this
}

// constant
void EdSKlient::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 );
}

int EdSKlient::getKlientNummer() const // gibt die KlientId zurück
{
    return klientNummer;
}

// Reference Counting
EdSKlient *EdSKlient::getThis()
{
    ref++;
    return this;
}

EdSKlient *EdSKlient::release()
{
    ref--;
    if( !ref )
        delete this;
    return 0;
}