PatchClient.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. #include "PatchClient.h"
  2. #include <Klient.h>
  3. #include <KSGTDatei.h>
  4. #include "Keys.h"
  5. #include <Datei.h>
  6. #include <Zeit.h>
  7. #include <Fortschritt.h>
  8. using namespace KSGClient;
  9. // Inhalt der PatchClient Klasse
  10. // Konstruktor
  11. PatchClient::PatchClient( int klientId, unsigned short port, char *ip, char *key, unsigned char keyLen )
  12. {
  13. ref = 1;
  14. this->ip = ip;
  15. this->port = port;
  16. cId = klientId;
  17. k = 0;
  18. this->key = new char[ keyLen ];
  19. memcpy( this->key, key, keyLen );
  20. this->keyLen = keyLen;
  21. }
  22. // Destruktor
  23. PatchClient::~PatchClient()
  24. {
  25. trenne( 1 );
  26. delete[] key;
  27. }
  28. // verbindet ich mit dem Patch Server
  29. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  30. bool PatchClient::verbinde()
  31. {
  32. cs.lock();
  33. if( k )
  34. {
  35. cs.unlock();
  36. return 1;
  37. }
  38. k = new Network::Klient();
  39. int l = 0;
  40. char *key;
  41. Keys::getServerKey( &key, l, Keys::PATCH, Keys::SENDEN );
  42. k->setSendeKey( key, l );
  43. delete[] key;
  44. Keys::getServerKey( &key, l, Keys::PATCH, Keys::EMPFANGEN );
  45. k->setEmpfangKey( key, l );
  46. delete[] key;
  47. if( k->verbinde( port, ip ) )
  48. {
  49. k->sende( "\0", 1 ); // Verschlüsselung Aktivieren
  50. if( k->sendeEncrypted( "\1", 1 ) )
  51. {
  52. k->sendeEncrypted( (char*)&cId, 4 );
  53. #ifdef _X64
  54. k->sendeEncrypted( "\2", 1 ); // 64 Bit Client
  55. #else
  56. k->sendeEncrypted( "\1", 1 ); // 32 Bit Client
  57. #endif
  58. char serverReturn = 0;
  59. k->getNachrichtEncrypted( &serverReturn, 1 );
  60. if( serverReturn == 3 )
  61. {
  62. char byte = 0;
  63. k->getNachrichtEncrypted( &byte, 1 );
  64. char *f = new char[ byte + 1 ];
  65. f[ byte ] = 0;
  66. k->getNachrichtEncrypted( f, byte );
  67. err = "error while identifying client Patch Server returned: ";
  68. err += f;
  69. delete[]f;
  70. trenne( 0 );
  71. cs.unlock();
  72. return 0;
  73. }
  74. k->setSendeKey( this->key, this->keyLen );
  75. k->setEmpfangKey( this->key, this->keyLen );
  76. }
  77. else
  78. {
  79. err = "network error while sending to Patch Server";
  80. k = k->release();
  81. cs.unlock();
  82. return 0;
  83. }
  84. }
  85. else
  86. {
  87. err = "network error while connecting to Patch Server";
  88. k = k->release();
  89. cs.unlock();
  90. return 0;
  91. }
  92. cs.unlock();
  93. return 1;
  94. }
  95. // Gibt eine Tabelle von Dateigruppen zurück.
  96. // Gibt bei misserfolg 0 zurück
  97. Framework::KSGTDatei *PatchClient::getDateiGruppenListe()
  98. {
  99. cs.lock();
  100. if( !k )
  101. {
  102. err = "Der Client ist nicht verbunden.";
  103. cs.unlock();
  104. return 0;
  105. }
  106. k->sendeEncrypted( "\xC", 1 );
  107. char ret = 0;
  108. k->getNachrichtEncrypted( &ret, 1 );
  109. if( ret == 3 )
  110. { // error
  111. k->getNachrichtEncrypted( &ret, 1 );
  112. char *msg = new char[ ret + 1 ];
  113. msg[ ret ] = 0;
  114. if( ret )
  115. k->getNachrichtEncrypted( msg, ret );
  116. err = msg;
  117. delete[] msg;
  118. cs.unlock();
  119. return 0;
  120. }
  121. Framework::KSGTDatei *dgtb = new Framework::KSGTDatei();
  122. int id = 0;
  123. k->getNachrichtEncrypted( (char*)&id, 4 );
  124. while( id )
  125. {
  126. RCArray< Text > *zeile = new RCArray< Text >();
  127. Text *idT = new Text();
  128. idT->append( id );
  129. zeile->set( idT, 0 );
  130. int län = 0;
  131. k->getNachrichtEncrypted( (char*)&län, 4 );
  132. char *pfad = new char[ län + 1 ];
  133. pfad[ län ] = 0;
  134. if( län )
  135. k->getNachrichtEncrypted( pfad, län );
  136. zeile->set( new Text( pfad ), 1 );
  137. delete[] pfad;
  138. int vs = 0;
  139. k->getNachrichtEncrypted( (char*)&vs, 4 );
  140. Text *vsT = new Text();
  141. vsT->append( vs );
  142. zeile->set( vsT, 2 );
  143. dgtb->addZeile( 3, zeile );
  144. zeile->release();
  145. k->getNachrichtEncrypted( (char*)&id, 4 );
  146. }
  147. k->sendeEncrypted( "\1", 1 );
  148. cs.unlock();
  149. return dgtb;
  150. }
  151. // Gibt eine Tabelle von Dateien zurück.
  152. // gruppe: Die Id der Dateigruppe, zu der die Dateien gehöhren sollen
  153. // Gibt bei misserfolg 0 zurück
  154. Framework::KSGTDatei *PatchClient::getDateiListe( int gruppe )
  155. {
  156. cs.lock();
  157. if( !k )
  158. {
  159. err = "Der Client ist nicht verbunden.";
  160. cs.unlock();
  161. return 0;
  162. }
  163. k->sendeEncrypted( "\x9", 1 );
  164. char ret = 0;
  165. k->getNachrichtEncrypted( &ret, 1 );
  166. if( ret == 3 )
  167. { // error
  168. k->getNachrichtEncrypted( &ret, 1 );
  169. char *msg = new char[ ret + 1 ];
  170. msg[ ret ] = 0;
  171. if( ret )
  172. k->getNachrichtEncrypted( msg, ret );
  173. err = msg;
  174. delete[] msg;
  175. cs.unlock();
  176. return 0;
  177. }
  178. k->sendeEncrypted( (char*)&gruppe, 4 );
  179. k->getNachrichtEncrypted( &ret, 1 );
  180. if( ret == 3 )
  181. { // error
  182. k->getNachrichtEncrypted( &ret, 1 );
  183. char *msg = new char[ ret + 1 ];
  184. msg[ ret ] = 0;
  185. if( ret )
  186. k->getNachrichtEncrypted( msg, ret );
  187. err = msg;
  188. delete[] msg;
  189. cs.unlock();
  190. return 0;
  191. }
  192. KSGTDatei *dtb = new KSGTDatei();
  193. int län = 0;
  194. k->getNachrichtEncrypted( (char*)&län, 4 );
  195. while( län )
  196. {
  197. RCArray< Text > *zeile = new RCArray< Text >();
  198. zeile->set( new Text( "1" ), 0 );
  199. char *pfad = new char[ län + 1 ];
  200. pfad[ län ] = 0;
  201. k->getNachrichtEncrypted( pfad, län );
  202. zeile->set( new Text( pfad ), 1 );
  203. delete[] pfad;
  204. int vs = 0;
  205. k->getNachrichtEncrypted( (char*)&vs, 4 );
  206. Text *vsT = new Text();
  207. vsT->append( vs );
  208. zeile->set( vsT, 2 );
  209. dtb->addZeile( 3, zeile );
  210. zeile->release();
  211. k->getNachrichtEncrypted( (char*)&län, 4 );
  212. }
  213. k->getNachrichtEncrypted( (char*)&län, 4 );
  214. while( län )
  215. {
  216. RCArray< Text > *zeile = new RCArray< Text >();
  217. zeile->set( new Text( "0" ), 0 );
  218. char *pfad = new char[ län + 1 ];
  219. pfad[ län ] = 0;
  220. k->getNachrichtEncrypted( pfad, län );
  221. zeile->set( new Text( pfad ), 1 );
  222. delete[] pfad;
  223. dtb->addZeile( 2, zeile );
  224. zeile->release();
  225. k->getNachrichtEncrypted( (char*)&län, 4 );
  226. }
  227. cs.unlock();
  228. return dtb;
  229. }
  230. // Gibt die Größe einer Datei in bytes zurück
  231. // gruppe: Die Id der Dateigruppe der Datei
  232. // pfad: Der Pfad der Datei
  233. __int64 PatchClient::getDateiGröße( int gruppe, const char *pfad )
  234. {
  235. cs.lock();
  236. if( !k )
  237. {
  238. err = "Der Client ist nicht verbunden.";
  239. cs.unlock();
  240. return 0;
  241. }
  242. k->sendeEncrypted( "\xA", 1 );
  243. char ret = 0;
  244. k->getNachrichtEncrypted( &ret, 1 );
  245. if( ret == 3 )
  246. { // error
  247. k->getNachrichtEncrypted( &ret, 1 );
  248. char *msg = new char[ ret + 1 ];
  249. msg[ ret ] = 0;
  250. if( ret )
  251. k->getNachrichtEncrypted( msg, ret );
  252. err = msg;
  253. delete[] msg;
  254. cs.unlock();
  255. return 0;
  256. }
  257. k->sendeEncrypted( (char*)&gruppe, 4 );
  258. ret = 0;
  259. k->getNachrichtEncrypted( &ret, 1 );
  260. if( ret == 3 )
  261. { // error
  262. k->getNachrichtEncrypted( &ret, 1 );
  263. char *msg = new char[ ret + 1 ];
  264. msg[ ret ] = 0;
  265. if( ret )
  266. k->getNachrichtEncrypted( msg, ret );
  267. err = msg;
  268. delete[] msg;
  269. cs.unlock();
  270. return 0;
  271. }
  272. if( ret == 2 )
  273. { // verweis auf anderen Server
  274. int p = 0;
  275. k->getNachrichtEncrypted( (char*)&p, 4 );
  276. port = (unsigned short)p;
  277. int län = 0;
  278. k->getNachrichtEncrypted( (char*)&län, 4 );
  279. delete[]ip;
  280. ip = new char[ län + 1 ];
  281. ip[ län ] = 0;
  282. k->getNachrichtEncrypted( ip, län );
  283. if( !trenne( 0 ) )
  284. {
  285. err = "Fehler beim wechseln des Servers: Die Verbindung konnte nicht getrennt werden.";
  286. cs.unlock();
  287. return 0;
  288. }
  289. if( !verbinde() )
  290. {
  291. err = "Fehler beim wechseln des Servers: Die Verbindung konnte nicht hergestellt werden.";
  292. cs.unlock();
  293. return 0;
  294. }
  295. cs.unlock();
  296. return getDateiGröße( gruppe, pfad );
  297. }
  298. int län = textLength( pfad );
  299. k->sendeEncrypted( (char*)&län, 4 );
  300. k->sendeEncrypted( pfad, län );
  301. __int64 größe = 0;
  302. k->getNachrichtEncrypted( (char*)&größe, 8 );
  303. cs.unlock();
  304. return größe;
  305. }
  306. // Lädt eine Datei herunter
  307. // gruppe: Die Dateigruppe der Datei
  308. // 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)
  309. // pfad: Der Pfad der Datei
  310. // zielPfad: Der Pfad, an den die Datei gespeichert werden soll
  311. // zFb: Ein Fortschrittsbalken, der automatisch aktualisiert wird
  312. // abbruch: Wenn diese Variable während des Vorgangs auf 1 gesetzt wird, so wird das Herunterladen abgebrochen.
  313. // maxbps: Die Anzahl der bytes pro Sekunde, die maximal übertragen werden sollen
  314. bool PatchClient::downloadDatei( int gruppe, __int64 *start, const char *pfad, const char *zielPfad, Framework::FBalken *zFb, bool *abbruch, int maxbps )
  315. {
  316. cs.lock();
  317. if( !k )
  318. {
  319. err = "Der Client ist nicht verbunden.";
  320. cs.unlock();
  321. return 0;
  322. }
  323. Datei *zielD = new Datei();
  324. zielD->setDatei( zielPfad );
  325. if( !zielD->existiert() )
  326. zielD->erstellen();
  327. bool ok = 0;
  328. if( !( *start ) ) // datei neu erstellen
  329. ok = zielD->open( Datei::Style::schreiben );
  330. else // datei weiterschreiben
  331. ok = zielD->open( Datei::Style::schreiben | Datei::Style::lesen );
  332. if( !ok )
  333. {
  334. zielD->release();
  335. err = "Die Datei konnte nicht zum schreiben geöffnet werden.";
  336. cs.unlock();
  337. return 0;
  338. }
  339. zielD->setSPosition( *start, 0 );
  340. k->sendeEncrypted( "\xB", 1 );
  341. char ret = 0;
  342. k->getNachrichtEncrypted( &ret, 1 );
  343. if( ret == 3 )
  344. { // error
  345. k->getNachrichtEncrypted( &ret, 1 );
  346. char *msg = new char[ ret + 1 ];
  347. msg[ ret ] = 0;
  348. if( ret )
  349. k->getNachrichtEncrypted( msg, ret );
  350. err = msg;
  351. delete[] msg;
  352. zielD->close();
  353. zielD->release();
  354. cs.unlock();
  355. return 0;
  356. }
  357. k->sendeEncrypted( (char*)&gruppe, 4 );
  358. ret = 0;
  359. k->getNachrichtEncrypted( &ret, 1 );
  360. if( ret == 3 )
  361. { // error
  362. k->getNachrichtEncrypted( &ret, 1 );
  363. char *msg = new char[ ret + 1 ];
  364. msg[ ret ] = 0;
  365. if( ret )
  366. k->getNachrichtEncrypted( msg, ret );
  367. err = msg;
  368. delete[] msg;
  369. zielD->close();
  370. zielD->release();
  371. cs.unlock();
  372. return 0;
  373. }
  374. if( ret == 2 )
  375. { // verweis auf anderen Server
  376. int p = 0;
  377. k->getNachrichtEncrypted( (char*)&p, 4 );
  378. port = (unsigned short)p;
  379. int län = 0;
  380. k->getNachrichtEncrypted( (char*)&län, 4 );
  381. delete[] ip;
  382. ip = new char[ län + 1 ];
  383. ip[ län ] = 0;
  384. k->getNachrichtEncrypted( ip, län );
  385. if( !trenne( 0 ) )
  386. {
  387. zielD->close();
  388. zielD->release();
  389. err = "Fehler beim wechseln des Servers: Die Verbindung konnte nicht getrennt werden.";
  390. cs.unlock();
  391. return 0;
  392. }
  393. if( !verbinde() )
  394. {
  395. zielD->close();
  396. zielD->release();
  397. err = "Fehler beim wechseln des Servers: Die Verbindung konnte nicht hergestellt werden.";
  398. cs.unlock();
  399. return 0;
  400. }
  401. zielD->close();
  402. zielD->release();
  403. cs.unlock();
  404. return downloadDatei( gruppe, start, pfad, zielPfad, zFb, abbruch, maxbps );
  405. }
  406. int län = textLength( pfad );
  407. k->sendeEncrypted( (char*)&län, 4 );
  408. k->sendeEncrypted( pfad, län );
  409. k->sendeEncrypted( (char*)start, 8 );
  410. char *bytes = new char[ 2048 ];
  411. unsigned short byteLän = 0;
  412. k->getNachricht( (char*)&byteLän, 2 );
  413. ZeitMesser *zMess = new ZeitMesser();
  414. zMess->messungStart();
  415. if( byteLän )
  416. {
  417. int bps = 0;
  418. double sec = 0;
  419. while( 1 )
  420. {
  421. k->getNachricht( bytes, byteLän );
  422. zielD->schreibe( bytes, byteLän );
  423. if( zFb )
  424. zFb->aktionPlus( byteLän );
  425. ( *start ) += byteLän;
  426. bps += byteLän;
  427. if( byteLän == 2048 )
  428. {
  429. if( ( *abbruch ) )
  430. {
  431. zielD->close();
  432. zielD->release();
  433. k->trenne();
  434. k = k->release();
  435. delete[] bytes;
  436. zMess->release();
  437. cs.unlock();
  438. return 1;
  439. }
  440. k->getNachricht( (char*)&byteLän, 2 ); // sendelänge empfangen
  441. if( !byteLän )
  442. break;
  443. }
  444. else
  445. break;
  446. if( maxbps )
  447. {
  448. zMess->messungEnde();
  449. sec += zMess->getSekunden();
  450. zMess->messungStart();
  451. if( sec >= 1 )
  452. {
  453. sec = 0;
  454. bps = 0;
  455. }
  456. while( bps >= maxbps )
  457. {
  458. Sleep( 10 );
  459. zMess->messungEnde();
  460. sec += zMess->getSekunden();
  461. zMess->messungStart();
  462. if( sec >= 1 )
  463. {
  464. sec = 0;
  465. bps = 0;
  466. }
  467. }
  468. }
  469. }
  470. }
  471. zMess->release();
  472. delete[] bytes;
  473. k->sendeEncrypted( "\1", 1 );
  474. zielD->close();
  475. zielD->release();
  476. cs.unlock();
  477. return 1;
  478. }
  479. // Trennt die Verbindung zum Server
  480. // Gibt 1 zurück, falls der Vorgang erfolgreich ist, 0 sonnst
  481. // Sollte erst nach einem erfolgreichen Aufruf von verbinde aufgerufen werden
  482. bool PatchClient::trenne( bool abmelden )
  483. {
  484. cs.lock();
  485. verbinde();
  486. if( !k )
  487. {
  488. cs.unlock();
  489. return 1;
  490. }
  491. if( abmelden )
  492. {
  493. k->sendeEncrypted( "\4", 1 );
  494. char ret = 0;
  495. k->getNachrichtEncrypted( &ret, 1 );
  496. if( ret == 3 )
  497. { // error
  498. k->getNachrichtEncrypted( &ret, 1 );
  499. char *msg = new char[ ret + 1 ];
  500. msg[ ret ] = 0;
  501. if( ret )
  502. k->getNachrichtEncrypted( msg, ret );
  503. err = "error while unregister Client Patch Server returned: ";
  504. err += msg;
  505. delete[] msg;
  506. }
  507. }
  508. k->sendeEncrypted( "\3", 1 );
  509. char ret = 0;
  510. k->getNachrichtEncrypted( &ret, 1 );
  511. if( ret == 3 )
  512. { // error
  513. k->getNachrichtEncrypted( &ret, 1 );
  514. char *msg = new char[ ret + 1 ];
  515. msg[ ret ] = 0;
  516. if( ret )
  517. k->getNachrichtEncrypted( msg, ret );
  518. err = "error while trenne Patch Server returned: ";
  519. err += msg;
  520. delete[] msg;
  521. }
  522. k->trenne();
  523. k = k->release();
  524. cs.unlock();
  525. return 1;
  526. }
  527. // Gibt 1 zurück, falls der Client verbunden ist, 0 sonst
  528. bool PatchClient::istVerbunden() const
  529. {
  530. return k != 0;
  531. }
  532. // Gibt die Anzahl von übertragenen Bytes seit dem letzten Aufruf zurück
  533. int PatchClient::getDownload() const
  534. {
  535. return k ? k->getDownloadBytes( 1 ) : 0;
  536. }
  537. // gibt den Letzten Fehlertext zuück
  538. // sollte erst aufgerufen werden, nachdem eine andere aufgerufene Methode fehlgeschlagen ist
  539. char *PatchClient::getLetzterFehler() const
  540. {
  541. return err;
  542. }
  543. // Erhöht den Reference Counter um 1 un gibt this zurück
  544. PatchServerClient *PatchClient::getThis()
  545. {
  546. ref++;
  547. return this;
  548. }
  549. // Verringert den Reference Counter um 1 und gibt 0 zurück.
  550. // Falls der Reference Counter nach dem Aufruf auf 0 ist löscht sich das Objekt selbst
  551. PatchServerClient *PatchClient::release()
  552. {
  553. if( !--ref )
  554. delete this;
  555. return 0;
  556. }