RealmListSrv.cpp
上传用户:jxpjxmjjw
上传日期:2009-12-07
资源大小:5877k
文件大小:16k
源码类别:

模拟服务器

开发平台:

Visual C++

  1. // Copyright (C) 2004 Team Python
  2. //  
  3. // This program is free software; you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation; either version 2 of the License, or
  6. // (at your option) any later version.
  7. // 
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. // GNU General Public License for more details.
  12. // 
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software 
  15. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  16. // RealmListSrv.cpp: implementation of the RealmListSrv class.
  17. //
  18. //////////////////////////////////////////////////////////////////////
  19. #include "RealmListSrv.h"
  20. #include "Log.h"
  21. #include "Singleton.h"
  22. #include "Database.h"
  23. #include "Sockets.h"
  24. #include <sys/stat.h>
  25. #include <string>
  26. using namespace::std;
  27. #include "WorldServer.h"
  28. #define world WorldServer::getSingleton()
  29. //////////////////////////////////////////////////////////////////////
  30. // Construction/Destruction
  31. //////////////////////////////////////////////////////////////////////
  32. createFileSingleton( RealmListSrv );
  33. RealmListSrv::RealmListSrv( ) {
  34.     FILE * patchini = fopen( "patch.ini", "r" );
  35.     if( !patchini ) {
  36.         printf( "WARNING: patch.ini not found -- no client patching will be performed!" );
  37.     } else {
  38.         char redline[256];
  39.         uint32 buildnum; char * offset;
  40.         uint8 counter; char tempbyte[3]; tempbyte[2]=0;
  41.         while( fgets( redline, 256, patchini ) ) {
  42.             if( offset = strchr( redline, '=' ) ) {
  43.                 buildnum = atoi( redline );
  44.                 mPatches[ buildnum ] = new Patch();//uint8[ 16 ];
  45.                 strncpy( mPatches[ buildnum ]->Platform, offset - 3, 3 );
  46.                 mPatches[ buildnum ]->Platform[ 3 ] = 0;
  47.                 offset++;
  48.                 for( counter = 0; counter < 16; counter ++, offset += 2 ) {
  49.                     strncpy( tempbyte, offset, 2 );
  50.                     mPatches[ buildnum ]->Hash[ counter ] = (uint8)strtoul( tempbyte, NULL, 16 );
  51.                 }
  52.             }
  53.         }
  54.         fclose( patchini );
  55.     }
  56. }
  57. RealmListSrv::~RealmListSrv( ) {
  58.     for( RealmMap::iterator i = mRealms.begin( ); i != mRealms.end( ); ++ i ) {
  59.         delete i->second;
  60.     }
  61.     mRealms.clear( );
  62.     for( PatchMap::iterator i = mPatches.begin( ); i != mPatches.end( ); ++ i ) {
  63.         delete i->second;
  64.     }
  65.     mPatches.clear( );
  66. }
  67. void RealmListSrv::addRealm( char * name, char * address, uint8 icon, uint8 color, uint32 players ) {
  68.     removeRealm( name );
  69.     mRealms[ name ] = new Realm( );
  70.     mRealms[ name ]->address = address;
  71.     mRealms[ name ]->players = players;
  72. mRealms[ name ]->icon = icon;
  73. mRealms[ name ]->color = color;
  74. }
  75. void RealmListSrv::setRealm( char * name, uint8 icon, uint8 color, uint32 players ) {
  76.     if( mRealms.find( name ) != mRealms.end( ) )
  77.         mRealms[ name ]->players = players;
  78. if (icon!=2) mRealms[ name ]->icon = icon;
  79. if (color!=2) mRealms[ name ]->color = color;
  80. }
  81. void RealmListSrv::removeRealm( char * name ) {
  82.     if( mRealms.find( name ) != mRealms.end( ) ) {
  83.         delete mRealms[ name ];
  84.         mRealms.erase( name );
  85.     }
  86. }
  87. /* method to print realmlist */
  88. void RealmListSrv::printRealms()
  89. {
  90. RealmMap::iterator i;
  91. for( i = mRealms.begin( ); i != mRealms.end( ); ++ i )
  92. {
  93. printf("%s %dn",i->first.c_str(),i->second->players );
  94. }
  95. }
  96. enum opcode {
  97.     LOGON_CHALLENGE = 0x00, 
  98.     LOGON_PROOF = 0x01, 
  99.     RECONNECT_CHALLENGE = 0x02, 
  100.     RECONNECT_PROOF = 0x03, 
  101.     REALMLIST = 0x10,
  102. UPDATESRV = 0x04
  103. };
  104. void RealmListSrv::server_sockevent( nlink_server *cptr, uint16 revents, void *myNet ) {
  105. NetworkInterface * client;
  106. struct nlink_client *ncptr;
  107. if(revents & PF_READ)
  108. {
  109. client = ( ( NetworkInterface * ) myNet )->getConnection( );
  110. if (!client) 
  111. return;
  112. uint32 nonblockingstate = true;
  113. IOCTL_SOCKET( client->getSocketID(), IOCTL_NOBLOCK, &nonblockingstate );
  114. ncptr = new nlink_client;
  115. if(ncptr == NULL)
  116. return;
  117. memset(ncptr, 0, sizeof(*ncptr));
  118. ncptr->hdr.type = RCLIENT;
  119. ncptr->hdr.fd = client->getSocketID();
  120. nlink_insert((struct nlink *)ncptr);
  121. Client *pClient = new Client();
  122. pClient->BindNI(client);
  123. ncptr->pClient = pClient;
  124. }
  125. }
  126. void RealmListSrv::client_sockevent(struct nlink_client *cptr, unsigned short revents){
  127. if(revents & PF_READ)
  128. {
  129. RealmClient *pClient = static_cast < RealmClient * > ( cptr->pClient );
  130. NetworkInterface *net = pClient->getNetwork();
  131. uint8 opcode; 
  132. if (!net->isConnected()) {
  133. disconnect_client(cptr);
  134. return;
  135. }
  136. net->getData( 1, &opcode );
  137. if (!net->isConnected()) {
  138. disconnect_client(cptr);
  139. return;
  140. }
  141. switch( opcode ) {
  142. case LOGON_CHALLENGE:
  143. {
  144. Log::getSingleton( ).outString( "REALMLIST: Recieved LOGON_CHALLENGE" );
  145. uint8 unknown; uint16 length;
  146. char WoW[5]; uint8 byte1, byte2, byte3; uint16 client_version;
  147. char x86[5]; char Win[5]; char enUS[5];
  148. WoW[4] = x86[4] = Win[4] = enUS[4] = 0;
  149. uint8 wb1, wb2;
  150. int16 int1; uint32 int2; uint8 name_length; char name[256];
  151.                     
  152. net->getData( 1, &unknown );
  153. net->getData( 2, &length );
  154. net->getData( 4, WoW );
  155. net->getData( 1, &byte1 ); net->getData( 1, &byte2 ); net->getData( 1, &byte3 );
  156. net->getData( 2, &client_version );
  157. net->getData( 4, x86 ); net->getData( 4, Win ); net->getData( 4, enUS );
  158. net->getData( 1, &wb1 ); net->getData( 1, &wb2 );
  159. net->getData( 2, &int1 ); net->getData( 4, &int2 ); net->getData( 1, &name_length );
  160. if (!net->isConnected())
  161. break;
  162. net->getData( name_length, name );
  163. name[ name_length ] = 0;
  164. std::string cib;
  165. //printf( "Username: %sn", name );
  166. cib = WoW; std::reverse( cib.begin( ), cib.end( ) );
  167. //printf( "Game ID: %sn", cib.c_str( ) );
  168. //printf( "Version: %in", client_version );
  169. cib = x86; std::reverse( cib.begin( ), cib.end( ) );
  170. //printf( "Architecture: %sn", cib.c_str( ) );
  171. cib = Win; std::reverse( cib.begin( ), cib.end( ) );
  172. //printf( "Platform: %sn", cib.c_str( ) );
  173. cib = enUS; std::reverse( cib.begin( ), cib.end( ) );
  174. //printf( "Language: %sn", cib.c_str( ) );
  175. //printf( "Unknown Start Byte: %i n", unknown );
  176. //printf( "Unknown 3 Game Bytes: %i %i %i n", byte1, byte2, byte3 );
  177. //printf( "Unknown 2 Bytes: %i %in", wb1, wb2 );
  178. //printf( "Unknown 16bit Int: %in", int1 );
  179. //printf( "Unknown 32bit Int: %in", int2 );
  180.                     
  181. if( client_version != EXPECTED_WOW_CLIENT_BUILD ) {
  182. if( client_version < EXPECTED_WOW_CLIENT_BUILD ) {
  183. if( mPatches.find( client_version ) != mPatches.end( ) ) {
  184. char filnam[64]; 
  185. sprintf( filnam, "%i%s.mpq", client_version, mPatches[ client_version ]->Platform );
  186. FILE * patchfil = fopen( filnam, "rb" );
  187. if( patchfil ) {
  188. {
  189. uint8 newopcode = LOGON_PROOF;
  190. uint8 data[2] = { newopcode, 0x0a };
  191. net->sendData( 2, data );
  192. Log::getSingleton( ).outString( "REALMLIST: Sent LOGON_PROOF" );
  193. }
  194. {
  195. uint8 newopcode = '0';
  196. char * stringy = "Patch";
  197. uint8 stringling = strlen( stringy );
  198. //uint8 hash[] = { 0x7e, 0xf1, 0x34, 0x33, 0xf8, 0xd6, 0xe6, 0xc5, 0x58, 0x92, 0x72, 0x01, 0xae, 0xe8, 0x82, 0x39 };
  199. //uint8 hash[] = { 0x5b, 0x75, 0x24, 0x2d, 0x24, 0x5b, 0x0b, 0xa2, 0x74, 0xac, 0x92, 0xc5, 0xb3, 0xcc, 0x97, 0xfc };
  200. struct stat filestats;
  201. fstat( fileno( patchfil ), &filestats );
  202. uint64 filesize = filestats.st_size;
  203. net->sendData( 1, &newopcode );
  204. net->sendData( 1, &stringling );
  205. net->sendData( stringling, stringy );
  206. net->sendData( 8, &filesize );
  207. net->sendData( 16, mPatches[ client_version ]->Hash );
  208. Log::getSingleton( ).outString( "REALMLIST: Sent patch initialization" );
  209. }
  210. {
  211. uint8 newopcode;
  212. net->getData( 1, &newopcode );
  213. if( newopcode == '2' )
  214. Log::getSingleton( ).outString( "REALMLIST: Got patch acknowledgement" );
  215. else
  216. printf( "WEIRD PATCH RESPOnSE: '%c'n", newopcode );
  217. }
  218. {
  219. uint8 datablock[1500];
  220. uint16 datalen;
  221. uint8 newopcode = '1';
  222. Log::getSingleton( ).outString( "REALMLIST: Sending patch data...." );
  223. while( !feof( patchfil ) && net->isConnected( ) ) {
  224. datalen = fread( datablock, 1, 1500, patchfil );
  225. net->sendData( 1, &newopcode );
  226. net->sendData( 2, &datalen );
  227. net->sendData( datalen, datablock );
  228. }
  229. Log::getSingleton( ).outString( "REALMLIST: Done sending patch data." );
  230. }
  231. fclose( patchfil );
  232. } else {
  233. Log::getSingleton( ).outString( "REALMLIST: Error -- Failed to load patch mpq!" );
  234. }
  235. } else {
  236. Log::getSingleton( ).outString( "REALMLIST: Error -- No patch found to satisfy client version!" );
  237. }
  238. }
  239. uint8 tdata[] = { 0x01, 0x09 };
  240. net->sendData( sizeof( tdata ) , tdata );
  241. Log::getSingleton( ).outString( "REALMLIST: Sent LOGON_PROOF with rejection 'bad client version'" );
  242. break;
  243. // check if username and password exist
  244. DatabaseInterface *dbi = Database::getSingleton( ).createDatabaseInterface( );
  245. switch( dbi->Login( name, "BETA2", net->getIP() ) ) {
  246. case -1:   // bad password
  247. {
  248. uint8 tdata[] = { 0x01, 0x07 };
  249. net->sendData( sizeof( tdata ) , tdata );
  250. Log::getSingleton( ).outString( "REALMLIST: Sent LOGON_PROOF with rejection 'prepaid time used up'" );
  251. }break;
  252. case -2:   // general failure
  253. {
  254. uint8 tdata[] = { 0x01, 0x08 };
  255. net->sendData( sizeof( tdata ) , tdata );
  256. Log::getSingleton( ).outString( "REALMLIST: Sent LOGON_PROOF with rejection 'could not log in'" );
  257. }break;
  258. case -3:   // bad username
  259. {
  260. uint8 tdata[] = { 0x01, 0x03 };
  261. net->sendData( sizeof( tdata ) , tdata );
  262. Log::getSingleton( ).outString( "REALMLIST: Sent LOGON_PROOF with rejection 'account closed'" );
  263. }break;
  264. default:
  265. {
  266. uint8 newopcode = RECONNECT_PROOF;
  267. uint8 newdata = 0;
  268. uint8 data[2] = { newopcode, newdata };
  269. net->sendData(2, data);
  270. Log::getSingleton( ).outString( "REALMLIST: Sent RECONNECT_PROOF" );
  271. }break;
  272. }
  273. Database::getSingleton( ).removeDatabaseInterface( dbi );
  274. }break;
  275. case LOGON_PROOF:
  276. {
  277. Log::getSingleton( ).outString( "REALMLIST: Recieved LOGON_PROOF" );
  278. uint8 databuf[ 16*6+7 ];
  279. net->getData( 16*6+7, databuf );
  280. for( int i = 0; i < 16*6+7; i ++ ) {
  281. if( i % 16 == 0 )
  282. printf( "n" );
  283. printf( "%.2X ", databuf[i] );
  284. }
  285. printf ("n");
  286.                     
  287. uint8 newopcode = RECONNECT_PROOF;
  288. uint8 newdata = 0;
  289. uint8 data[2] = { newopcode, newdata };
  290. net->sendData(2, data);
  291. Log::getSingleton( ).outString( "REALMLIST: Sent RECONNECT_PROOF" );
  292. }break;
  293. case RECONNECT_CHALLENGE:
  294. {
  295. Log::getSingleton( ).outString( "REALMLIST: Recieved RECONNECT_CHALLENGE" );
  296. uint8 unknownbyte; uint16 datalen; 
  297. char WoW[5];  uint8 byte1, byte2, byte3; uint16 clientversion; char x86[5];
  298. char Win[5]; char enUS[5]; 
  299. uint8 ubyte1, ubyte2; int16 int1; uint32 int2;
  300. uint8 namelen; char name[256];
  301. net->getData( 1, &unknownbyte );
  302. net->getData( 2, &datalen );
  303. net->getData( 4, WoW ); WoW[4]=0;
  304. net->getData( 1, &byte1 ); net->getData( 1, &byte2 ); net->getData( 1, &byte3 );
  305. net->getData( 2, &clientversion );
  306. net->getData( 4, x86 ); x86[4]=0;
  307. net->getData( 4, Win ); Win[4]=0;
  308. net->getData( 4, enUS ); enUS[4]=0;
  309. //net->getData( 13, preuserdata );// ARGH
  310. net->getData( 1, &ubyte1 ); net->getData( 1, &ubyte2 ); net->getData( 2, &int1 );
  311. net->getData( 4, &int2 );
  312. net->getData( 1, &namelen );
  313. net->getData( namelen, name );
  314. name[ namelen ] = 0;
  315. //printf( "Username: %sn", name );
  316. std::string cib = WoW; std::reverse( cib.begin( ), cib.end( ) );
  317. //printf( "Game ID: %sn", cib.c_str( ) );
  318. //printf( "Version: %in", clientversion );
  319. cib = x86; std::reverse( cib.begin( ), cib.end( ) );
  320. //printf( "Architecture: %sn", cib.c_str( ) );
  321. cib = Win; std::reverse( cib.begin( ), cib.end( ) );
  322. //printf( "Platform: %sn", cib.c_str( ) );
  323. cib = enUS; std::reverse( cib.begin( ), cib.end( ) );
  324. //printf( "Language: %sn", cib.c_str( ) );
  325. //printf( "Unknown start byte: %in", unknownbyte );
  326. //printf( "3 game bytes: %i %i %in", byte1, byte2, byte3 );
  327. //printf( "Unknown 2 bytes: %i %in", ubyte1, ubyte2 );
  328. //printf( "Unknown 16bit int: %in", int1 );
  329. //printf( "Unknown 32bit int: %in", int2 );
  330. /*
  331. net->sendData( 1, &opcode );
  332. uint8 zerobyte = 0;
  333. for( int a = 0; a < 0x21; a ++ )
  334. net->sendData( 1, &zerobyte );
  335. */
  336. uint8 newopcode = RECONNECT_PROOF;
  337. uint8 newdata = 0;
  338. uint8 data[2] = { newopcode, newdata };
  339. net->sendData(2, data);
  340. Log::getSingleton( ).outString( "REALMLIST: Sent RECONNECT_CHALLENGE" );
  341. }break;
  342. case RECONNECT_PROOF:
  343. {
  344. Log::getSingleton( ).outString( "REALMLIST: Recieved RECONNECT_PROOF" );
  345. uint8 buf[5*16+7];
  346. net->getData( sizeof( buf), buf );
  347. uint8 newopcode = RECONNECT_PROOF;
  348. uint8 newdata = 0;
  349. uint8 data[2] = { newopcode, newdata };
  350. net->sendData(2, data);
  351. //                    net->sendData( 1, &newopcode );
  352. //                    net->sendData( 1, &newdata );
  353. Log::getSingleton( ).outString( "REALMLIST: Sent RECONNECT_PROOF" );
  354. }break;
  355. case REALMLIST:
  356. {
  357. Log::getSingleton( ).outString( "REALMLIST: Recieved REALMLIST request" );
  358. uint32 request; net->getData(4, &request );
  359. //format: uint16 datalen, uint32 request, uint8 numrealms
  360. //eachrealm: string name, string address, uint32 numplayers
  361. uint16 datalen = 7;
  362. RealmMap::iterator i;
  363. uint8 totalrealms = 0;
  364. for( i = mRealms.begin( ); i != mRealms.end( ); ++ i, ++totalrealms )
  365. datalen += i->first.length( ) + 1 + i->second->address.length( ) + 13;
  366. uint8 *data = new uint8[ datalen + 3 ];
  367. data[ 0 ] = REALMLIST;
  368. memcpy( data+1, &datalen, 2 );
  369. memcpy( data+3, &request, 4 );
  370. data[7]=totalrealms;
  371. int doo = 8;
  372. for( i = mRealms.begin( ); i != mRealms.end( ); ++ i ) {
  373. data[ doo++ ] = i->second->icon; 
  374. data[ doo++ ] = 0x00;
  375. data[ doo++ ] = 0x00;
  376. data[ doo++ ] = 0x00;
  377. data[ doo++ ] = i->second->color; 
  378. strcpy( (char *)data+doo, i->first.c_str( ) );
  379. doo+=i->first.length( )+1;
  380. strcpy( (char *)data+doo, i->second->address.c_str( ) );
  381. doo+=i->second->address.length( )+1;
  382. data[ doo++ ] = (uint8)(i->second->players & 255);
  383. data[ doo++ ] = (uint8)((i->second->players >> 8) & 255);
  384. data[ doo++ ] = (uint8)((i->second->players >> 16)& 255);
  385. data[ doo++ ] = (uint8)((i->second->players >> 24)& 255);
  386. data[ doo++ ] = (uint32)world.GetClientsConnected();
  387. // data[ doo++ ] = 0x64; // ping time (fake)
  388. data[ doo++ ] = 0x01;
  389. data[ doo++ ] = 0x02;
  390. }
  391. data[ doo++ ] = 0x00;
  392. data[ doo++ ] = 0x00;
  393. net->sendData( datalen + 3, data );
  394. Log::getSingleton( ).outString( "REALMLIST: Sent REALMLIST" );
  395. delete [] data;
  396. }break;
  397. case UPDATESRV:
  398. {
  399. char buf[256];
  400. char *realm;
  401. char *count;
  402. string rTemp = "";
  403. Log::getSingleton( ).outString( "REALMLIST: Recieved UPDATESRV request" );
  404. net->getData( 256, buf );
  405. realm = strtok(buf,";");
  406. count = strtok(0,";");
  407. rTemp="";
  408. rTemp.append(realm);
  409. // 2, 2 stands for unchanged icon and color
  410. this->setRealm( const_cast<char *>(rTemp.c_str()), 2, 2, atoi(count) );
  411. }break;
  412. default:
  413. {
  414. char debugchararray[256];
  415. sprintf( debugchararray, "REALMLIST: Recieved unknown opcode %i", opcode );
  416. Log::getSingleton( ).outString( debugchararray );
  417. }break;
  418. }
  419. }
  420. }
  421. void RealmListSrv::disconnect_client( struct nlink_client *cptr )
  422. {
  423. RealmClient * pClient = static_cast < RealmClient * > ( cptr->pClient );
  424. mClients.erase( pClient );
  425. delete pClient;
  426. Log::getSingleton( ).outString( "REALM: Socket Closed!" );
  427. Server::disconnect_client( cptr );
  428. }