Browse Source

PatchClient Fertig

Kolja Strohm 6 years ago
parent
commit
d356610e91

+ 13 - 9
Include/KSGNetwork.h

@@ -27,7 +27,7 @@ namespace Network
 namespace KSGClient
 {
     // Enthält die Daten eines Spielers zu einem vergangenen Spiel
-    struct SpielHistorieSpielerDaten
+    class SpielHistorieSpielerDaten
     {
     protected:
         int ref; // Reference Counter
@@ -45,7 +45,7 @@ namespace KSGClient
     };
 
     // Enthält die Datein eines Teams zu einem vergangenen Spiel
-    struct SpielHistorieTeamDaten
+    class SpielHistorieTeamDaten
     {
     protected:
         int ref; // Reference Counter
@@ -64,7 +64,7 @@ namespace KSGClient
     };
 
     // Enthält Daten zu einem vergangenen Spiel
-    struct SpielHistorieDaten
+    class SpielHistorieDaten
     {
     protected:
         int ref; // Reference Counter
@@ -89,7 +89,7 @@ namespace KSGClient
     };
 
     // Enthält eine Liste von Spiel Daten aus vergangenen Spielen
-    struct SpielHistorieListe
+    class SpielHistorieListe
     {
     protected:
         int ref; // Reference Counter
@@ -104,7 +104,7 @@ namespace KSGClient
     };
 
     // Enthält Informationen zu einem Account
-    struct AccountInfo
+    class AccountInfo
     {
     protected:
         int ref; // Reference Counter
@@ -124,7 +124,7 @@ namespace KSGClient
     };
 
     // Enthält Informationen zur Aktivität eines Accounts an einem bestimmten Tag
-    struct AccountActivityInfo
+    class AccountActivityInfo
     {
     protected:
         int ref; // Reference Counter
@@ -143,7 +143,7 @@ namespace KSGClient
     };
 
     // Enthält eine Nachricht, die von Chat Server gesendet wurde
-    struct ChatServerNachricht
+    class ChatServerNachricht
     {
     protected:
         int ref; // Reference Counter
@@ -163,7 +163,7 @@ namespace KSGClient
     };
 
     // Enthält alle Daten zur Team - Spieler Konstalation einer Karte
-    struct SpielerTeamStruktur
+    class SpielerTeamStruktur
     {
     protected:
         int ref; // Reference Counter
@@ -183,7 +183,7 @@ namespace KSGClient
     };
 
     // Enthält eine Nachricht von dem Spiel Server
-    struct SpielServerNachricht
+    class SpielServerNachricht
     {
     protected:
         int ref; // Reference Counter
@@ -437,6 +437,10 @@ namespace KSGClient
         virtual LoginServerClient *release() = 0;
     };
 
+    class EditorServerClient;
+    class KartenServerClient;
+    class HistorieServerClient;
+
     // Wird verwendet um informationen über Accounts abzufragen
     //  Kann nur von eingeloggten Clients verwendet werden
     class InformationServerClient

+ 1 - 0
KSGNetwork/ErhaltungClient.cpp

@@ -144,6 +144,7 @@ void ErhaltungClient::abmelden()
 bool ErhaltungClient::trenne()
 {
     trenn = 1;
+    return 1;
 }
 
 // gibt den Letzten Fehlertext zuück

+ 1 - 1
KSGNetwork/ErhaltungClient.h

@@ -16,7 +16,7 @@ namespace KSGClient
         char *key;
         unsigned char keyLen;
         Framework::Critical cs;
-        Text err;
+        Framework::Text err;
         bool abmel;
         bool trenn;
 

+ 4 - 0
KSGNetwork/KSGNetwork.vcxproj

@@ -95,6 +95,7 @@
       <Optimization>Disabled</Optimization>
       <SDLCheck>true</SDLCheck>
       <ConformanceMode>true</ConformanceMode>
+      <PreprocessorDefinitions>_MBCS;_X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <CustomBuildStep>
       <Command>
@@ -132,6 +133,7 @@
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <SDLCheck>true</SDLCheck>
       <ConformanceMode>true</ConformanceMode>
+      <PreprocessorDefinitions>_MBCS;_X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <Link>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -150,11 +152,13 @@
     <ClInclude Include="Keys.h" />
     <ClInclude Include="Main.cpp" />
     <ClInclude Include="MainClient.h" />
+    <ClInclude Include="PatchClient.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="ErhaltungClient.cpp" />
     <ClCompile Include="Keys.cpp" />
     <ClCompile Include="MainClient.cpp" />
+    <ClCompile Include="PatchClient.cpp" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">

+ 6 - 0
KSGNetwork/KSGNetwork.vcxproj.filters

@@ -30,6 +30,9 @@
     <ClInclude Include="ErhaltungClient.h">
       <Filter>Headerdateien</Filter>
     </ClInclude>
+    <ClInclude Include="PatchClient.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="MainClient.cpp">
@@ -41,5 +44,8 @@
     <ClCompile Include="ErhaltungClient.cpp">
       <Filter>Quelldateien</Filter>
     </ClCompile>
+    <ClCompile Include="PatchClient.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 48 - 1
KSGNetwork/MainClient.cpp

@@ -2,6 +2,7 @@
 #include <Klient.h>
 #include "Keys.h"
 #include "ErhaltungClient.h"
+#include "PatchClient.h"
 
 using namespace KSGClient;
 
@@ -162,6 +163,7 @@ ErhaltungServerClient *MainClient::createErhaltungServerClient()
     if( !k )
     {
         err = "no connection to Main Server";
+        cs.unlock();
         return 0;
     }
     k->sendeEncrypted( "\6\x8", 2 );
@@ -206,7 +208,52 @@ ErhaltungServerClient *MainClient::createErhaltungServerClient()
 //  Gibt bei misserfolg 0 zurück
 PatchServerClient *MainClient::createPatchServerClient()
 {
-
+    cs.lock();
+    bool connected = k != 0;
+    if( !connected )
+        connect();
+    if( !k )
+    {
+        err = "no connection to Main Server";
+        cs.unlock();
+        return 0;
+    }
+    k->sendeEncrypted( "\6\2", 2 );
+    char byte = 0;
+    k->getNachrichtEncrypted( &byte, 1 );
+    if( byte == 2 )
+    {
+        unsigned char lsIp[ 4 ];
+        k->getNachrichtEncrypted( (char *)lsIp, 4 );
+        unsigned short lsPort = 0;
+        k->getNachrichtEncrypted( (char*)&lsPort, 2 );
+        Framework::Text ipT;
+        ipT += (int)lsIp[ 0 ];
+        ipT += ".";
+        ipT += (int)lsIp[ 1 ];
+        ipT += ".";
+        ipT += (int)lsIp[ 2 ];
+        ipT += ".";
+        ipT += (int)lsIp[ 3 ];
+        if( !connected )
+            disconnect();
+        cs.unlock();
+        return new PatchClient( cId, lsPort, ipT, key, keyLen );
+    }
+    else if( byte == 3 )
+    {
+        k->getNachrichtEncrypted( &byte, 1 );
+        char *f = new char[ byte + 1 ];
+        f[ byte ] = 0;
+        k->getNachrichtEncrypted( f, byte );
+        err = "error while requesting PatchServer server returned: ";
+        err += f;
+        delete[]f;
+    }
+    if( !connected )
+        disconnect();
+    cs.unlock();
+    return 0;
 }
 
 // Erzeugt einen News Server Client

+ 1 - 1
KSGNetwork/MainClient.h

@@ -16,7 +16,7 @@ namespace KSGClient
         char *key;
         unsigned char keyLen;
         Framework::Critical cs;
-        Text err;
+        Framework::Text err;
 
     public:
         // Konstruktor

+ 572 - 0
KSGNetwork/PatchClient.cpp

@@ -0,0 +1,572 @@
+#include "PatchClient.h"
+#include <Klient.h>
+#include <KSGTDatei.h>
+#include "Keys.h"
+#include <Datei.h>
+#include <Zeit.h>
+#include <Fortschritt.h>
+
+using namespace KSGClient;
+
+// Inhalt der PatchClient Klasse
+
+// Konstruktor
+PatchClient::PatchClient( int klientId, unsigned short port, char *ip, char *key, unsigned char keyLen )
+{
+    ref = 1;
+    this->ip = ip;
+    this->port = port;
+    cId = klientId;
+    k = 0;
+    this->key = new char[ keyLen ];
+    memcpy( this->key, key, keyLen );
+    this->keyLen = keyLen;
+}
+
+// Destruktor
+PatchClient::~PatchClient()
+{
+    if( k )
+        k->release();
+    delete[] key;
+}
+
+// verbindet ich mit dem Patch Server
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+bool PatchClient::verbinde()
+{
+    cs.lock();
+    if( k )
+    {
+        cs.unlock();
+        return 1;
+    }
+    k = new Network::Klient();
+    int l = 0;
+    char *key;
+    Keys::getServerKey( &key, l, Keys::PATCH, Keys::SENDEN );
+    k->setSendeKey( key, l );
+    delete[] key;
+    Keys::getServerKey( &key, l, Keys::PATCH, Keys::EMPFANGEN );
+    k->setEmpfangKey( key, l );
+    delete[] key;
+    if( k->verbinde( port, ip ) )
+    {
+        k->sende( "\0", 1 ); // Verschlüsselung Aktivieren
+        if( k->sendeEncrypted( "\1", 1 ) )
+        {
+            k->sendeEncrypted( (char*)&cId, 4 );
+#ifdef _X64
+            k->sendeEncrypted( "\2", 1 ); // 64 Bit Client
+#else
+            k->sendeEncrypted( "\1", 1 ); // 32 Bit Client
+#endif
+            char serverReturn = 0;
+            k->getNachrichtEncrypted( &serverReturn, 1 );
+            if( serverReturn == 3 )
+            {
+                char byte = 0;
+                k->getNachrichtEncrypted( &byte, 1 );
+                char *f = new char[ byte + 1 ];
+                f[ byte ] = 0;
+                k->getNachrichtEncrypted( f, byte );
+                err = "error while identifyin client Patch Server returned: ";
+                err += f;
+                delete[]f;
+                trenne( 0 );
+                cs.unlock();
+                return 0;
+            }
+            k->setSendeKey( (char*)key, keyLen );
+            k->setEmpfangKey( (char*)key, keyLen );
+        }
+        else
+        {
+            err = "network error while sending to Patch Server";
+            k = k->release();
+            cs.unlock();
+            return 0;
+        }
+    }
+    else
+    {
+        err = "network error while connecting to Patch Server";
+        k = k->release();
+        cs.unlock();
+        return 0;
+    }
+    cs.unlock();
+    return 1;
+}
+
+// Gibt eine Tabelle von Dateigruppen zurück.
+//  Gibt bei misserfolg 0 zurück
+Framework::KSGTDatei *PatchClient::getDateiGruppenListe()
+{
+    cs.lock();
+    if( !k )
+    {
+        err = "Der Client ist nicht verbunden.";
+        cs.unlock();
+        return 0;
+    }
+    k->sendeEncrypted( "\xC", 1 );
+    char ret = 0;
+    k->getNachrichtEncrypted( &ret, 1 );
+    if( ret == 3 )
+    { // error
+        k->getNachrichtEncrypted( &ret, 1 );
+        char *msg = new char[ ret + 1 ];
+        msg[ ret ] = 0;
+        if( ret )
+            k->getNachrichtEncrypted( msg, ret );
+        err = msg;
+        delete[] msg;
+        cs.unlock();
+        return 0;
+    }
+    Framework::KSGTDatei *dgtb = new Framework::KSGTDatei();
+    int id = 0;
+    k->getNachrichtEncrypted( (char*)&id, 4 );
+    while( id )
+    {
+        RCArray< Text > *zeile = new RCArray< Text >();
+        Text *idT = new Text();
+        idT->append( id );
+        zeile->set( idT, 0 );
+        int län = 0;
+        k->getNachrichtEncrypted( (char*)&län, 4 );
+        char *pfad = new char[ län + 1 ];
+        pfad[ län ] = 0;
+        if( län )
+            k->getNachrichtEncrypted( pfad, län );
+        zeile->set( new Text( pfad ), 1 );
+        delete[] pfad;
+        int vs = 0;
+        k->getNachrichtEncrypted( (char*)&vs, 4 );
+        Text *vsT = new Text();
+        vsT->append( vs );
+        zeile->set( vsT, 2 );
+        dgtb->addZeile( 3, zeile );
+        zeile->release();
+        k->getNachrichtEncrypted( (char*)&id, 4 );
+    }
+    k->sendeEncrypted( "\1", 1 );
+    cs.unlock();
+    return dgtb;
+}
+
+// Gibt eine Tabelle von Dateien zurück.
+//  gruppe: Die Id der Dateigruppe, zu der die Dateien gehöhren sollen
+//  Gibt bei misserfolg 0 zurück
+Framework::KSGTDatei *PatchClient::getDateiListe( int gruppe )
+{
+    cs.lock();
+    if( !k )
+    {
+        err = "Der Client ist nicht verbunden.";
+        cs.unlock();
+        return 0;
+    }
+    k->sendeEncrypted( "\x9", 1 );
+    char ret = 0;
+    k->getNachrichtEncrypted( &ret, 1 );
+    if( ret == 3 )
+    { // error
+        k->getNachrichtEncrypted( &ret, 1 );
+        char *msg = new char[ ret + 1 ];
+        msg[ ret ] = 0;
+        if( ret )
+            k->getNachrichtEncrypted( msg, ret );
+        err = msg;
+        delete[] msg;
+        cs.unlock();
+        return 0;
+    }
+    k->sendeEncrypted( (char*)&gruppe, 4 );
+    k->getNachrichtEncrypted( &ret, 1 );
+    if( ret == 3 )
+    { // error
+        k->getNachrichtEncrypted( &ret, 1 );
+        char *msg = new char[ ret + 1 ];
+        msg[ ret ] = 0;
+        if( ret )
+            k->getNachrichtEncrypted( msg, ret );
+        err = msg;
+        delete[] msg;
+        cs.unlock();
+        return 0;
+    }
+    KSGTDatei *dtb = new KSGTDatei();
+    int län = 0;
+    k->getNachrichtEncrypted( (char*)&län, 4 );
+    while( län )
+    {
+        RCArray< Text > *zeile = new RCArray< Text >();
+        zeile->set( new Text( "1" ), 0 );
+        char *pfad = new char[ län + 1 ];
+        pfad[ län ] = 0;
+        k->getNachrichtEncrypted( pfad, län );
+        zeile->set( new Text( pfad ), 1 );
+        delete[] pfad;
+        int vs = 0;
+        k->getNachrichtEncrypted( (char*)&vs, 4 );
+        Text *vsT = new Text();
+        vsT->append( vs );
+        zeile->set( vsT, 2 );
+        dtb->addZeile( 3, zeile );
+        zeile->release();
+        k->getNachrichtEncrypted( (char*)&län, 4 );
+    }
+    k->getNachrichtEncrypted( (char*)&län, 4 );
+    while( län )
+    {
+        RCArray< Text > *zeile = new RCArray< Text >();
+        zeile->set( new Text( "0" ), 0 );
+        char *pfad = new char[ län + 1 ];
+        pfad[ län ] = 0;
+        k->getNachrichtEncrypted( pfad, län );
+        zeile->set( new Text( pfad ), 1 );
+        delete[] pfad;
+        dtb->addZeile( 2, zeile );
+        zeile->release();
+        k->getNachrichtEncrypted( (char*)&län, 4 );
+    }
+    cs.unlock();
+    return dtb;
+}
+
+// Gibt die Größe einer Datei in bytes zurück
+//  gruppe: Die Id der Dateigruppe der Datei
+//  pfad: Der Pfad der Datei
+__int64 PatchClient::getDateiGröße( int gruppe, const char *pfad )
+{
+    cs.lock();
+    if( !k )
+    {
+        err = "Der Client ist nicht verbunden.";
+        cs.unlock();
+        return 0;
+    }
+    k->sendeEncrypted( "\xA", 1 );
+    char ret = 0;
+    k->getNachrichtEncrypted( &ret, 1 );
+    if( ret == 3 )
+    { // error
+        k->getNachrichtEncrypted( &ret, 1 );
+        char *msg = new char[ ret + 1 ];
+        msg[ ret ] = 0;
+        if( ret )
+            k->getNachrichtEncrypted( msg, ret );
+        err = msg;
+        delete[] msg;
+        cs.unlock();
+        return 0;
+    }
+    k->sendeEncrypted( (char*)&gruppe, 4 );
+    ret = 0;
+    k->getNachrichtEncrypted( &ret, 1 );
+    if( ret == 3 )
+    { // error
+        k->getNachrichtEncrypted( &ret, 1 );
+        char *msg = new char[ ret + 1 ];
+        msg[ ret ] = 0;
+        if( ret )
+            k->getNachrichtEncrypted( msg, ret );
+        err = msg;
+        delete[] msg;
+        cs.unlock();
+        return 0;
+    }
+    if( ret == 2 )
+    { // verweis auf anderen Server
+        int p = 0;
+        k->getNachrichtEncrypted( (char*)&p, 4 );
+        port = (unsigned short)p;
+        int län = 0;
+        k->getNachrichtEncrypted( (char*)&län, 4 );
+        delete[]ip;
+        ip = new char[ län + 1 ];
+        ip[ län ] = 0;
+        k->getNachrichtEncrypted( ip, län );
+        if( !trenne( 0 ) )
+        {
+            err = "Fehler beim wechseln des Servers: Die Verbindung konnte nicht getrennt werden.";
+            cs.unlock();
+            return 0;
+        }
+        if( !verbinde() )
+        {
+            err = "Fehler beim wechseln des Servers: Die Verbindung konnte nicht hergestellt werden.";
+            cs.unlock();
+            return 0;
+        }
+        cs.unlock();
+        return getDateiGröße( gruppe, pfad );
+    }
+    int län = textLength( pfad );
+    k->sendeEncrypted( (char*)&län, 4 );
+    k->sendeEncrypted( pfad, län );
+    __int64 größe = 0;
+    k->getNachrichtEncrypted( (char*)&größe, 8 );
+    cs.unlock();
+    return größe;
+}
+
+// Lädt eine Datei herunter
+//  gruppe: Die Dateigruppe der Datei
+//  start: Der Index des bytes, bei dem der download begonnen werden soll (Enthält im Falle eines Abbruchs die Position, von welcher aus als nächstes heruntergeladen werden muss)
+//  pfad: Der Pfad der Datei
+//  zielPfad: Der Pfad, an den die Datei gespeichert werden soll
+//  zFb: Ein Fortschrittsbalken, der automatisch aktualisiert wird
+//  abbruch: Wenn diese Variable während des Vorgangs auf 1 gesetzt wird, so wird das Herunterladen abgebrochen.
+//  maxbps: Die Anzahl der bytes pro Sekunde, die maximal übertragen werden sollen
+bool PatchClient::downloadDatei( int gruppe, __int64 *start, const char *pfad, const char *zielPfad, Framework::FBalken *zFb, bool *abbruch, int maxbps )
+{
+    cs.lock();
+    if( !k )
+    {
+        err = "Der Client ist nicht verbunden.";
+        cs.unlock();
+        return 0;
+    }
+    Datei *zielD = new Datei();
+    zielD->setDatei( zielPfad );
+    if( !zielD->existiert() )
+        zielD->erstellen();
+    bool ok = 0;
+    if( !( *start ) ) // datei neu erstellen
+        ok = zielD->open( Datei::Style::schreiben );
+    else // datei weiterschreiben
+        ok = zielD->open( Datei::Style::schreiben | Datei::Style::lesen );
+    if( !ok )
+    {
+        zielD->release();
+        err = "Die Datei konnte nicht zum schreiben geöffnet werden.";
+        cs.unlock();
+        return 0;
+    }
+    zielD->setSPosition( *start, 0 );
+    k->sendeEncrypted( "\xB", 1 );
+    char ret = 0;
+    k->getNachrichtEncrypted( &ret, 1 );
+    if( ret == 3 )
+    { // error
+        k->getNachrichtEncrypted( &ret, 1 );
+        char *msg = new char[ ret + 1 ];
+        msg[ ret ] = 0;
+        if( ret )
+            k->getNachrichtEncrypted( msg, ret );
+        err = msg;
+        delete[] msg;
+        zielD->close();
+        zielD->release();
+        cs.unlock();
+        return 0;
+    }
+    k->sendeEncrypted( (char*)&gruppe, 4 );
+    ret = 0;
+    k->getNachrichtEncrypted( &ret, 1 );
+    if( ret == 3 )
+    { // error
+        k->getNachrichtEncrypted( &ret, 1 );
+        char *msg = new char[ ret + 1 ];
+        msg[ ret ] = 0;
+        if( ret )
+            k->getNachrichtEncrypted( msg, ret );
+        err = msg;
+        delete[] msg;
+        zielD->close();
+        zielD->release();
+        cs.unlock();
+        return 0;
+    }
+    if( ret == 2 )
+    { // verweis auf anderen Server
+        int p = 0;
+        k->getNachrichtEncrypted( (char*)&p, 4 );
+        port = (unsigned short)p;
+        int län = 0;
+        k->getNachrichtEncrypted( (char*)&län, 4 );
+        delete[] ip;
+        ip = new char[ län + 1 ];
+        ip[ län ] = 0;
+        k->getNachrichtEncrypted( ip, län );
+        if( !trenne( 0 ) )
+        {
+            zielD->close();
+            zielD->release();
+            err = "Fehler beim wechseln des Servers: Die Verbindung konnte nicht getrennt werden.";
+            cs.unlock();
+            return 0;
+        }
+        if( !verbinde() )
+        {
+            zielD->close();
+            zielD->release();
+            err = "Fehler beim wechseln des Servers: Die Verbindung konnte nicht hergestellt werden.";
+            cs.unlock();
+            return 0;
+        }
+        zielD->close();
+        zielD->release();
+        cs.unlock();
+        return downloadDatei( gruppe, start, pfad, zielPfad, zFb, abbruch, maxbps );
+    }
+    int län = textLength( pfad );
+    k->sendeEncrypted( (char*)&län, 4 );
+    k->sendeEncrypted( pfad, län );
+    k->sendeEncrypted( (char*)start, 8 );
+    char *bytes = new char[ 2048 ];
+    unsigned short byteLän = 0;
+    k->getNachricht( (char*)&byteLän, 2 );
+    ZeitMesser *zMess = new ZeitMesser();
+    zMess->messungStart();
+    if( byteLän )
+    {
+        int bps = 0;
+        double sec = 0;
+        while( 1 )
+        {
+            k->getNachricht( bytes, byteLän );
+            zielD->schreibe( bytes, byteLän );
+            if( zFb )
+                zFb->aktionPlus( byteLän );
+            ( *start ) += byteLän;
+            bps += byteLän;
+            if( byteLän == 2048 )
+            {
+                if( ( *abbruch ) )
+                {
+                    zielD->close();
+                    zielD->release();
+                    k->trenne();
+                    k = k->release();
+                    delete[] bytes;
+                    zMess->release();
+                    cs.unlock();
+                    return 1;
+                }
+                k->getNachricht( (char*)&byteLän, 2 ); // sendelänge empfangen
+                if( !byteLän )
+                    break;
+            }
+            else
+                break;
+            if( maxbps )
+            {
+                zMess->messungEnde();
+                sec += zMess->getSekunden();
+                zMess->messungStart();
+                if( sec >= 1 )
+                {
+                    sec = 0;
+                    bps = 0;
+                }
+                while( bps >= maxbps )
+                {
+                    Sleep( 10 );
+                    zMess->messungEnde();
+                    sec += zMess->getSekunden();
+                    zMess->messungStart();
+                    if( sec >= 1 )
+                    {
+                        sec = 0;
+                        bps = 0;
+                    }
+                }
+            }
+        }
+    }
+    zMess->release();
+    delete[] bytes;
+    k->sendeEncrypted( "\1", 1 );
+    zielD->close();
+    zielD->release();
+    cs.unlock();
+    return 1;
+}
+
+// Trennt die Verbindung zum Server
+//  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+//  Sollte erst nach einem erfolgreichen Aufruf von verbinde aufgerufen werden
+bool PatchClient::trenne( bool abmelden )
+{
+    cs.lock();
+    verbinde();
+    if( !k )
+    {
+        cs.unlock();
+        return 1;
+    }
+    if( abmelden )
+    {
+        k->sendeEncrypted( "\4", 1 );
+        char ret = 0;
+        k->getNachrichtEncrypted( &ret, 1 );
+        if( ret == 3 )
+        { // error
+            k->getNachrichtEncrypted( &ret, 1 );
+            char *msg = new char[ ret + 1 ];
+            msg[ ret ] = 0;
+            if( ret )
+                k->getNachrichtEncrypted( msg, ret );
+            err = "error while unregister Client Patch Server returned: ";
+            err += msg;
+            delete[] msg;
+        }
+    }
+    k->sendeEncrypted( "\3", 1 );
+    char ret = 0;
+    k->getNachrichtEncrypted( &ret, 1 );
+    if( ret == 3 )
+    { // error
+        k->getNachrichtEncrypted( &ret, 1 );
+        char *msg = new char[ ret + 1 ];
+        msg[ ret ] = 0;
+        if( ret )
+            k->getNachrichtEncrypted( msg, ret );
+        err = "error while trenne Patch Server returned: ";
+        err += msg;
+        delete[] msg;
+    }
+    k->trenne();
+    k = k->release();
+    cs.unlock();
+    return 1;
+}
+
+// Gibt 1 zurück, falls der Client verbunden ist, 0 sonst
+bool PatchClient::istVerbunden() const
+{
+    return k != 0;
+}
+
+// Gibt die Anzahl von übertragenen Bytes seit dem letzten Aufruf zurück
+int PatchClient::getDownload() const
+{
+    return k ? k->getDownloadBytes( 1 ) : 0;
+}
+
+// gibt den Letzten Fehlertext zuück
+//  sollte erst aufgerufen werden, nachdem eine andere aufgerufene Methode fehlgeschlagen ist
+char *PatchClient::getLetzterFehler() const
+{
+    return err;
+}
+
+// Erhöht den Reference Counter um 1 un gibt this zurück
+PatchServerClient *PatchClient::getThis()
+{
+    ref++;
+    return this;
+}
+
+// Verringert den Reference Counter um 1 und gibt 0 zurück.
+//  Falls der Reference Counter nach dem Aufruf auf 0 ist löscht sich das Objekt selbst 
+PatchServerClient *PatchClient::release()
+{
+    if( !--ref )
+        delete this;
+    return 0;
+}

+ 66 - 0
KSGNetwork/PatchClient.h

@@ -0,0 +1,66 @@
+#pragma once
+
+#include "../Include/KSGNetwork.h"
+#include <Critical.h>
+
+namespace KSGClient
+{
+    class PatchClient : public PatchServerClient
+    {
+    private:
+        int ref;
+        Framework::Text ip;
+        unsigned short port;
+        int cId;
+        Network::Klient *k;
+        char *key;
+        unsigned char keyLen;
+        Framework::Critical cs;
+        Framework::Text err;
+
+    public:
+        // Konstruktor
+        PatchClient( int klientId, unsigned short port, char *ip, char *key, unsigned char keyLen );
+        // Destruktor
+        ~PatchClient();
+        // verbindet ich mit dem Patch Server
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        bool verbinde() override;
+        // Gibt eine Tabelle von Dateigruppen zurück.
+        //  Gibt bei misserfolg 0 zurück
+        Framework::KSGTDatei *getDateiGruppenListe() override;
+        // Gibt eine Tabelle von Dateien zurück.
+        //  gruppe: Die Id der Dateigruppe, zu der die Dateien gehöhren sollen
+        //  Gibt bei misserfolg 0 zurück
+        Framework::KSGTDatei *getDateiListe( int gruppe ) override;
+        // Gibt die Größe einer Datei in bytes zurück
+        //  gruppe: Die Id der Dateigruppe der Datei
+        //  pfad: Der Pfad der Datei
+        __int64 getDateiGröße( int gruppe, const char *pfad ) override;
+        // Lädt eine Datei herunter
+        //  gruppe: Die Dateigruppe der Datei
+        //  start: Der Index des bytes, bei dem der download begonnen werden soll (Enthält im Falle eines Abbruchs die Position, von welcher aus als nächstes heruntergeladen werden muss)
+        //  pfad: Der Pfad der Datei
+        //  zielPfad: Der Pfad, an den die Datei gespeichert werden soll
+        //  zFb: Ein Fortschrittsbalken, der automatisch aktualisiert wird
+        //  abbruch: Wenn diese Variable während des Vorgangs auf 1 gesetzt wird, so wird das Herunterladen abgebrochen.
+        //  maxbps: Die Anzahl der bytes pro Sekunde, die maximal übertragen werden sollen
+        bool downloadDatei( int gruppe, __int64 *start, const char *pfad, const char *zielPfad, Framework::FBalken *zFb, bool *abbruch, int maxbps ) override;
+        // Trennt die Verbindung zum Server
+        //  Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
+        //  Sollte erst nach einem erfolgreichen Aufruf von verbinde aufgerufen werden
+        bool trenne( bool abmelden ) override;
+        // Gibt 1 zurück, falls der Client verbunden ist, 0 sonst
+        bool istVerbunden() const override;
+        // Gibt die Anzahl von übertragenen Bytes seit dem letzten Aufruf zurück
+        int getDownload() const override;
+        // gibt den Letzten Fehlertext zuück
+        //  sollte erst aufgerufen werden, nachdem eine andere aufgerufene Methode fehlgeschlagen ist
+        char *getLetzterFehler() const override;
+        // Erhöht den Reference Counter um 1 un gibt this zurück
+        PatchServerClient *getThis() override;
+        // Verringert den Reference Counter um 1 und gibt 0 zurück.
+        //  Falls der Reference Counter nach dem Aufruf auf 0 ist löscht sich das Objekt selbst 
+        PatchServerClient *release() override;
+    };
+}