MinigameK.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. #include "../KSGKlient.h"
  2. #include "../KSGServer.h"
  3. #include "../Keys.h"
  4. // Inhalt der MinigameClient Klasse
  5. // Konstruktor
  6. MinigameClient::MinigameClient()
  7. {
  8. verbunden = 0;
  9. fehler = 0;
  10. klient = 0;
  11. needCapture = 0;
  12. klientId = getKlientId();
  13. ref = 1;
  14. }
  15. // Destruktor
  16. MinigameClient::~MinigameClient()
  17. {
  18. cs.lock();
  19. if( klient )
  20. {
  21. char serverReturn = 0;
  22. if( verbunden )
  23. {
  24. if( needCapture )
  25. klient->sendeEncrypted( "\0\0\0\0", 4 );
  26. needCapture = 0;
  27. klient->sendeEncrypted( "\4", 1 );
  28. klient->getNachrichtEncrypted( &serverReturn, 1 );
  29. if( serverReturn == 3 )
  30. {
  31. char län = 0;
  32. klient->getNachrichtEncrypted( &län, 1 );
  33. char *nachricht = new char[ län + 1 ];
  34. nachricht[ län ] = 0;
  35. klient->getNachrichtEncrypted( nachricht, län );
  36. delete[]nachricht;
  37. }
  38. klient->sendeEncrypted( "\3", 1 );
  39. klient->getNachrichtEncrypted( &serverReturn, 1 );
  40. klient->trenne();
  41. }
  42. else
  43. {
  44. int keyLen = 0;
  45. char *key = 0;
  46. Keys::getServerKey( &key, keyLen, Keys::MINIGAME, Keys::SENDEN );
  47. klient->setSendeKey( key, keyLen );
  48. delete[] key;
  49. Keys::getServerKey( &key, keyLen, Keys::MINIGAME, Keys::EMPFANGEN );
  50. klient->setEmpfangKey( key, keyLen );
  51. delete[] key;
  52. klient->verbinde( klient->getServerPort(), klient->getServerIp() );
  53. klient->sendeEncrypted( "\1", 1 );
  54. klient->sendeEncrypted( (char*)&klientId, 4 );
  55. klient->getNachrichtEncrypted( &serverReturn, 1 );
  56. if( serverReturn == 3 )
  57. {
  58. char län = 0;
  59. klient->getNachrichtEncrypted( &län, 1 );
  60. char *nachricht = new char[ län + 1 ];
  61. nachricht[ län ] = 0;
  62. klient->getNachrichtEncrypted( nachricht, län );
  63. delete[]nachricht;
  64. }
  65. else
  66. {
  67. char *sl = 0;
  68. char slLän = getSchlüssel( &sl );
  69. klient->setSendeKey( sl, slLän );
  70. klient->setEmpfangKey( sl, slLän );
  71. delete[] sl;
  72. klient->sendeEncrypted( "\4", 1 );
  73. klient->getNachrichtEncrypted( &serverReturn, 1 );
  74. if( serverReturn == 3 )
  75. {
  76. char län = 0;
  77. klient->getNachrichtEncrypted( &län, 1 );
  78. char *nachricht = new char[ län + 1 ];
  79. nachricht[ län ] = 0;
  80. klient->getNachrichtEncrypted( nachricht, län );
  81. delete[]nachricht;
  82. }
  83. }
  84. klient->sendeEncrypted( "\3", 1 );
  85. klient->getNachrichtEncrypted( &serverReturn, 1 );
  86. klient->trenne();
  87. }
  88. klient = klient->release();
  89. }
  90. delete[]fehler;
  91. cs.unlock();
  92. }
  93. // verbindet ich mit dem Minigame Server
  94. bool MinigameClient::verbinde()
  95. {
  96. cs.lock();
  97. if( verbunden )
  98. {
  99. cs.unlock();
  100. return 1;
  101. }
  102. if( !klient )
  103. {
  104. char *msIp = getMainServerIp();
  105. unsigned short msPort = getMainServerPort();
  106. klient = new Klient();
  107. int keyLen = 0;
  108. char *key = 0;
  109. Keys::getServerKey( &key, keyLen, Keys::MAIN, Keys::SENDEN );
  110. klient->setSendeKey( key, keyLen );
  111. delete[] key;
  112. Keys::getServerKey( &key, keyLen, Keys::MAIN, Keys::EMPFANGEN );
  113. klient->setEmpfangKey( key, keyLen );
  114. delete[] key;
  115. if( !klient->verbinde( msPort, msIp ) )
  116. {
  117. char *err = "Fehler beim verbinden mit dem Main Server. Bitte versuche es Später erneut.";
  118. delete[]fehler;
  119. fehler = new char[ textLength( err ) + 1 ];
  120. fehler[ textLength( err ) ] = 0;
  121. memcpy( fehler, err, textLength( err ) );
  122. klient = klient->release();
  123. delete[]msIp;
  124. cs.unlock();
  125. return 0;
  126. }
  127. delete[]msIp;
  128. klient->sende( "\0", 1 ); // verschlüsselung aktivieren
  129. klient->sendeEncrypted( "\1", 1 );
  130. klient->sendeEncrypted( (char*)&klientId, 4 );
  131. char serverReturn = 0;
  132. klient->getNachrichtEncrypted( &serverReturn, 1 );
  133. if( serverReturn == 3 )
  134. {
  135. char byte = 0;
  136. klient->getNachrichtEncrypted( &byte, 1 );
  137. delete[]fehler;
  138. fehler = new char[ byte + 1 ];
  139. fehler[ byte ] = 0;
  140. klient->getNachrichtEncrypted( fehler, byte );
  141. klient->sendeEncrypted( "\3", 1 );
  142. klient->getNachrichtEncrypted( &serverReturn, 1 );
  143. klient->trenne();
  144. klient = klient->release();
  145. cs.unlock();
  146. return 0;
  147. }
  148. char *sl = 0;
  149. char slLän = getSchlüssel( &sl );
  150. klient->setSendeKey( sl, slLän );
  151. klient->setEmpfangKey( sl, slLän );
  152. delete[] sl;
  153. klient->sendeEncrypted( "\6\xA", 2 );
  154. char byte = 0;
  155. klient->getNachrichtEncrypted( &byte, 1 );
  156. if( byte == 2 )
  157. {
  158. unsigned char lsIp[ 4 ];
  159. klient->getNachrichtEncrypted( (char *)lsIp, 4 );
  160. unsigned short lsPort = 0;
  161. klient->getNachrichtEncrypted( (char*)&lsPort, 2 );
  162. klient->sendeEncrypted( "\3", 1 );
  163. klient->getNachrichtEncrypted( &serverReturn, 1 );
  164. klient->trenne();
  165. Text *lsIpT = new Text( "" );
  166. lsIpT->append( (int)lsIp[ 0 ] );
  167. lsIpT->append( "." );
  168. lsIpT->append( (int)lsIp[ 1 ] );
  169. lsIpT->append( "." );
  170. lsIpT->append( (int)lsIp[ 2 ] );
  171. lsIpT->append( "." );
  172. lsIpT->append( (int)lsIp[ 3 ] );
  173. int keyLen = 0;
  174. char *key = 0;
  175. Keys::getServerKey( &key, keyLen, Keys::MINIGAME, Keys::SENDEN );
  176. klient->setSendeKey( key, keyLen );
  177. delete[] key;
  178. Keys::getServerKey( &key, keyLen, Keys::MINIGAME, Keys::EMPFANGEN );
  179. klient->setEmpfangKey( key, keyLen );
  180. delete[] key;
  181. klient->verbinde( lsPort, lsIpT->getText() );
  182. lsIpT = lsIpT->release();
  183. klient->sendeEncrypted( "\3", 1 );
  184. klient->getNachrichtEncrypted( &serverReturn, 1 );
  185. klient->trenne();
  186. }
  187. if( byte == 3 )
  188. {
  189. klient->getNachrichtEncrypted( &byte, 1 );
  190. delete[]fehler;
  191. fehler = new char[ byte + 1 ];
  192. fehler[ byte ] = 0;
  193. klient->getNachrichtEncrypted( fehler, byte );
  194. klient->sendeEncrypted( "\3", 1 );
  195. klient->getNachrichtEncrypted( &serverReturn, 1 );
  196. klient->trenne();
  197. klient = klient->release();
  198. cs.unlock();
  199. return 0;
  200. }
  201. }
  202. int keyLen = 0;
  203. char *key = 0;
  204. Keys::getServerKey( &key, keyLen, Keys::MINIGAME, Keys::SENDEN );
  205. klient->setSendeKey( key, keyLen );
  206. delete[] key;
  207. Keys::getServerKey( &key, keyLen, Keys::MINIGAME, Keys::EMPFANGEN );
  208. klient->setEmpfangKey( key, keyLen );
  209. delete[] key;
  210. if( klient->verbinde( klient->getServerPort(), klient->getServerIp() ) )
  211. {
  212. if( klient->sendeEncrypted( "\1", 1 ) )
  213. {
  214. klient->sendeEncrypted( (char*)&klientId, 4 );
  215. char serverReturn = 0;
  216. klient->getNachrichtEncrypted( &serverReturn, 1 );
  217. if( serverReturn == 3 )
  218. {
  219. char byte = 0;
  220. klient->getNachrichtEncrypted( &byte, 1 );
  221. delete[]fehler;
  222. fehler = new char[ byte + 1 ];
  223. fehler[ byte ] = 0;
  224. klient->getNachrichtEncrypted( fehler, byte );
  225. klient->sendeEncrypted( "\3", 1 );
  226. klient->getNachrichtEncrypted( &serverReturn, 1 );
  227. klient->trenne();
  228. cs.unlock();
  229. return 0;
  230. }
  231. char *sl = 0;
  232. char slLän = getSchlüssel( &sl );
  233. klient->setSendeKey( sl, slLän );
  234. klient->setEmpfangKey( sl, slLän );
  235. delete[] sl;
  236. verbunden = 1;
  237. cs.unlock();
  238. return 1;
  239. }
  240. else
  241. {
  242. char *err = "Der dir zugewiesene Minigame Server hat die Verbindung abgebrochen. Bitte versuche es Später erneut.";
  243. delete[]fehler;
  244. fehler = new char[ textLength( err ) + 1 ];
  245. fehler[ textLength( err ) ] = 0;
  246. memcpy( fehler, err, textLength( err ) );
  247. klient = klient->release();
  248. }
  249. }
  250. else
  251. {
  252. char *err = "Der dir zugewiesene Minigame Server antwortet nicht. Bitte versuche es Später erneut.";
  253. delete[]fehler;
  254. fehler = new char[ textLength( err ) + 1 ];
  255. fehler[ textLength( err ) ] = 0;
  256. memcpy( fehler, err, textLength( err ) );
  257. klient = klient->release();
  258. }
  259. cs.unlock();
  260. return 0;
  261. }
  262. // Gibt die liste mit allen Optionen zu einem Minigame zurück, zu denen es Welt beste Scores gibt
  263. // mName: Der Name des Minigames
  264. // zOptionList: Ein Zeiger auf ein Array von Texten, in denen die Optionen gespeichert werden
  265. // return: Anzahl der Optionen
  266. int MinigameClient::getMinigameOptionList( char *mName, RCArray< Text > *zOptionList )
  267. {
  268. if( !verbunden )
  269. verbinde();
  270. if( !verbunden )
  271. return 0;
  272. if( needCapture )
  273. return 0;
  274. cs.lock();
  275. klient->sendeEncrypted( "\x6", 1 );
  276. char ret = 0;
  277. klient->getNachrichtEncrypted( &ret, 1 );
  278. if( ret == 1 )
  279. {
  280. char l = (char)textLength( mName );
  281. klient->sendeEncrypted( &l, 1 );
  282. klient->sendeEncrypted( mName, l );
  283. int anz = 0;
  284. klient->getNachrichtEncrypted( (char*)&anz, 4 );
  285. for( int i = 0; i < anz; i++ )
  286. {
  287. klient->getNachrichtEncrypted( &l, 1 );
  288. char *option = new char[ l + 1 ];
  289. option[ l ] = 0;
  290. klient->getNachrichtEncrypted( option, l );
  291. zOptionList->add( new Text( option ) );
  292. delete[] option;
  293. }
  294. cs.unlock();
  295. return anz;
  296. }
  297. if( ret == 3 )
  298. {
  299. char l = 0;
  300. klient->getNachrichtEncrypted( &l, 1 );
  301. delete[] fehler;
  302. fehler = new char[ l + 1 ];
  303. fehler[ l ] = 0;
  304. klient->getNachrichtEncrypted( fehler, l );
  305. }
  306. cs.unlock();
  307. return 0;
  308. }
  309. // Gibt eine Liste mit den Weltbesten Scores zurück
  310. // mName: Der Name des Minigames
  311. // zScore: (rückgabe) Ein Array von Scores
  312. // zPlayerList: (rückgabe) Ein Array von Spielernamen, die die Scores erreicht haben.
  313. // zOptionList: (rückgabe) Ein Array von Optionen, die beim erreichen der Scores aktiv waren.
  314. // return: Anzahl der Scores
  315. int MinigameClient::getMinigameBestscoreList( char *mName, Array< int > *zScore, RCArray< Text > *zPlayerList, RCArray< Text > *zOptionList )
  316. {
  317. if( !verbunden )
  318. verbinde();
  319. if( !verbunden )
  320. return 0;
  321. if( needCapture )
  322. return 0;
  323. cs.lock();
  324. klient->sendeEncrypted( "\x7", 1 );
  325. char ret = 0;
  326. klient->getNachrichtEncrypted( &ret, 1 );
  327. if( ret == 1 )
  328. {
  329. char l = (char)textLength( mName );
  330. klient->sendeEncrypted( &l, 1 );
  331. klient->sendeEncrypted( mName, l );
  332. int anz = 0;
  333. klient->getNachrichtEncrypted( (char*)&anz, 4 );
  334. for( int i = 0; i < anz; i++ )
  335. {
  336. int score = 0;
  337. klient->getNachrichtEncrypted( (char*)&score, 4 );
  338. zScore->add( score );
  339. klient->getNachrichtEncrypted( &l, 1 );
  340. char *player = new char[ l + 1 ];
  341. player[ l ] = 0;
  342. klient->getNachrichtEncrypted( player, l );
  343. zPlayerList->add( new Text( player ) );
  344. delete[] player;
  345. klient->getNachrichtEncrypted( &l, 1 );
  346. char *option = new char[ l + 1 ];
  347. option[ l ] = 0;
  348. klient->getNachrichtEncrypted( option, l );
  349. zOptionList->add( new Text( option ) );
  350. delete[] option;
  351. }
  352. cs.unlock();
  353. return anz;
  354. }
  355. if( ret == 3 )
  356. {
  357. char l = 0;
  358. klient->getNachrichtEncrypted( &l, 1 );
  359. delete[] fehler;
  360. fehler = new char[ l + 1 ];
  361. fehler[ l ] = 0;
  362. klient->getNachrichtEncrypted( fehler, l );
  363. }
  364. cs.unlock();
  365. return 0;
  366. }
  367. // Gibt den Welt bestscore zu einem Bestimmten Minigame mit bestimmten Optionen zurück.
  368. // mName: Der Name des Minigames
  369. // oName: Die Optionen
  370. // zPlayer: (rückgabe) Der Spielername, der den Score erreicht hat
  371. // return: Der Score der erreicht wurde
  372. int MinigameClient::getMinigameOptionBestscore( char *mName, char *oName, Text *zPlayer )
  373. {
  374. if( !verbunden )
  375. verbinde();
  376. if( !verbunden )
  377. return 0;
  378. if( needCapture )
  379. return 0;
  380. cs.lock();
  381. klient->sendeEncrypted( "\x8", 1 );
  382. char ret = 0;
  383. klient->getNachrichtEncrypted( &ret, 1 );
  384. if( ret == 1 )
  385. {
  386. char l = (char)textLength( mName );
  387. klient->sendeEncrypted( &l, 1 );
  388. klient->sendeEncrypted( mName, l );
  389. l = (char)textLength( oName );
  390. klient->sendeEncrypted( &l, 1 );
  391. klient->sendeEncrypted( oName, l );
  392. int score = 0;
  393. klient->getNachrichtEncrypted( (char*)&score, 4 );
  394. klient->getNachrichtEncrypted( &l, 1 );
  395. char *player = new char[ l + 1 ];
  396. player[ l ] = 0;
  397. klient->getNachrichtEncrypted( player, l );
  398. zPlayer->setText( player );
  399. delete[] player;
  400. cs.unlock();
  401. return score;
  402. }
  403. if( ret == 3 )
  404. {
  405. char l = 0;
  406. klient->getNachrichtEncrypted( &l, 1 );
  407. delete[] fehler;
  408. fehler = new char[ l + 1 ];
  409. fehler[ l ] = 0;
  410. klient->getNachrichtEncrypted( fehler, l );
  411. }
  412. cs.unlock();
  413. return 0;
  414. }
  415. // Meldet die Beendigung eines Minigames
  416. // mName: Der Name des Minigames
  417. // oName: Die Optionen mit denen gespielt wurde
  418. // score: Der Erreichte Score
  419. // return: 0: Im Falle eines Fehlers, 1: Im Falle eines Erfolgs, 2: Falls ein Game Capture hochgeladen werden muss
  420. int MinigameClient::reportEndOfGame( char *mName, char *oName, int score )
  421. {
  422. if( !verbunden )
  423. verbinde();
  424. if( !verbunden )
  425. return 0;
  426. if( needCapture )
  427. return 0;
  428. cs.lock();
  429. klient->sendeEncrypted( "\x9", 1 );
  430. char ret = 0;
  431. klient->getNachrichtEncrypted( &ret, 1 );
  432. if( ret == 1 )
  433. {
  434. char l = (char)textLength( mName );
  435. klient->sendeEncrypted( &l, 1 );
  436. klient->sendeEncrypted( mName, l );
  437. l = (char)textLength( oName );
  438. klient->sendeEncrypted( &l, 1 );
  439. klient->sendeEncrypted( oName, l );
  440. klient->sendeEncrypted( (char*)&score, 4 );
  441. klient->getNachrichtEncrypted( &ret, 1 );
  442. if( ret == 1 )
  443. {
  444. cs.unlock();
  445. needCapture = 1;
  446. return 2;
  447. }
  448. cs.unlock();
  449. return 1;
  450. }
  451. if( ret == 3 )
  452. {
  453. char l = 0;
  454. klient->getNachrichtEncrypted( &l, 1 );
  455. delete[] fehler;
  456. fehler = new char[ l + 1 ];
  457. fehler[ l ] = 0;
  458. klient->getNachrichtEncrypted( fehler, l );
  459. }
  460. cs.unlock();
  461. return 0;
  462. }
  463. // Lädt ein Game Capture hoch
  464. // zCapture: Ein Zeiger auf die Capture Datei
  465. // return: 1, falls erfolgreich
  466. bool MinigameClient::uploadGameCapture( Datei *zCapture )
  467. {
  468. if( !verbunden )
  469. verbinde();
  470. if( !verbunden )
  471. return 0;
  472. if( !needCapture )
  473. return 0;
  474. cs.lock();
  475. int size = (int)zCapture->getSize();
  476. if( !zCapture->istOffen() )
  477. zCapture->open( Datei::Style::lesen );
  478. klient->sendeEncrypted( (char*)&size, 4 );
  479. char *buffer = new char[ 2048 ];
  480. while( size > 0 )
  481. {
  482. int l = size > 2048 ? 2048 : size;
  483. zCapture->lese( buffer, l );
  484. klient->sendeEncrypted( buffer, l );
  485. size -= l;
  486. }
  487. delete[] buffer;
  488. zCapture->close();
  489. needCapture = 0;
  490. cs.unlock();
  491. return 1;
  492. }
  493. // Lädt ein Game Capture herunter
  494. // mName: Der Name des Minigames
  495. // oName: Die Optionen
  496. // return: Ein Zeiger auf die Datei mit dem Capture
  497. Datei *MinigameClient::downloadGameCapture( char *mName, char *oName )
  498. {
  499. if( !verbunden )
  500. verbinde();
  501. if( !verbunden )
  502. return 0;
  503. if( needCapture )
  504. return 0;
  505. cs.lock();
  506. klient->sendeEncrypted( "\xA", 1 );
  507. char ret = 0;
  508. klient->getNachrichtEncrypted( &ret, 1 );
  509. if( ret == 1 )
  510. {
  511. char l = (char)textLength( mName );
  512. klient->sendeEncrypted( &l, 1 );
  513. klient->sendeEncrypted( mName, l );
  514. l = (char)textLength( oName );
  515. klient->sendeEncrypted( &l, 1 );
  516. klient->sendeEncrypted( oName, l );
  517. klient->getNachrichtEncrypted( &ret, 1 );
  518. if( ret == 1 )
  519. {
  520. Datei *capture = new Datei();
  521. capture->setDatei( "data/tmp/minigames/wb.mgc" );
  522. capture->erstellen();
  523. capture->open( Datei::Style::schreiben );
  524. int size = 0;
  525. klient->getNachrichtEncrypted( (char*)&size, 4 );
  526. char *buffer = new char[ 2048 ];
  527. while( size > 0 )
  528. {
  529. int l = size > 2048 ? 2048 : size;
  530. klient->getNachrichtEncrypted( buffer, l );
  531. capture->schreibe( buffer, l );
  532. size -= l;
  533. }
  534. delete[] buffer;
  535. capture->close();
  536. cs.unlock();
  537. return capture;
  538. }
  539. cs.unlock();
  540. return 0;
  541. }
  542. if( ret == 3 )
  543. {
  544. char l = 0;
  545. klient->getNachrichtEncrypted( &l, 1 );
  546. delete[] fehler;
  547. fehler = new char[ l + 1 ];
  548. fehler[ l ] = 0;
  549. klient->getNachrichtEncrypted( fehler, l );
  550. }
  551. cs.unlock();
  552. return 0;
  553. }
  554. bool MinigameClient::keepAlive()
  555. {
  556. if( needCapture )
  557. return 1;
  558. if( !verbunden )
  559. return 0;
  560. char res = 0;
  561. if( !cs.tryLock() )
  562. return 1;
  563. klient->sendeEncrypted( "\x5", 1 );
  564. klient->getNachrichtEncrypted( &res, 1 );
  565. cs.unlock();
  566. if( res != 1 )
  567. trenne();
  568. return res == 1;
  569. }
  570. // Erhält die Verbindung aufrecht
  571. bool MinigameClient::trenne()
  572. {
  573. if( verbunden )
  574. {
  575. cs.lock();
  576. if( needCapture )
  577. klient->sendeEncrypted( "\0\0\0\0", 4 );
  578. needCapture = 0;
  579. klient->sendeEncrypted( "\3", 1 );
  580. char serverReturn = 0;
  581. klient->getNachrichtEncrypted( &serverReturn, 1 );
  582. klient->trenne();
  583. verbunden = 0;
  584. cs.unlock();
  585. }
  586. return 1;
  587. }
  588. // trennt sich von dem Minigame Server
  589. bool MinigameClient::istVerbunden() const
  590. {
  591. return verbunden;
  592. }
  593. // prüft, ob mit Editor Server verbunden
  594. char *MinigameClient::getLetzterFehler() const
  595. {
  596. return fehler;
  597. }
  598. // gibt den Letzten Fehlertext zuück
  599. // Reference Counting
  600. MinigameKlientV *MinigameClient::getThis()
  601. {
  602. ref++;
  603. return this;
  604. }
  605. MinigameKlientV *MinigameClient::release()
  606. {
  607. if( !--ref )
  608. delete this;
  609. return 0;
  610. }