client.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. /*
  2. EQ2Emulator: Everquest II Server Emulator
  3. Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
  4. This file is part of EQ2Emulator.
  5. */
  6. #include "../common/debug.h"
  7. #ifdef WIN32
  8. #define WIN32_LEAN_AND_MEAN
  9. #include <windows.h>
  10. #include <winsock.h>
  11. #include <process.h>
  12. #else
  13. #include <sys/socket.h>
  14. #include <netinet/in.h>
  15. #include <arpa/inet.h>
  16. #include <unistd.h>
  17. #endif
  18. #include <string.h>
  19. #include <iomanip>
  20. #include <stdlib.h>
  21. #include <assert.h>
  22. #include "net.h"
  23. #include "client.h"
  24. #include "../common/EQStream.h"
  25. #include "../common/packet_dump.h"
  26. #include "../common/packet_functions.h"
  27. #include "../common/emu_opcodes.h"
  28. #include "../common/MiscFunctions.h"
  29. #include "LWorld.h"
  30. #include "LoginDatabase.h"
  31. #include "../common/ConfigReader.h"
  32. #include "../common/Log.h"
  33. extern NetConnection net;
  34. extern LWorldList world_list;
  35. extern ClientList client_list;
  36. extern LoginDatabase database;
  37. extern map<int16,OpcodeManager*>EQOpcodeManager;
  38. extern ConfigReader configReader;
  39. using namespace std;
  40. Client::Client(EQStream* ieqnc) {
  41. eqnc = ieqnc;
  42. ip = eqnc->GetrIP();
  43. port = ntohs(eqnc->GetrPort());
  44. account_id = 0;
  45. lsadmin = 0;
  46. worldadmin = 0;
  47. lsstatus = 0;
  48. version = 0;
  49. kicked = false;
  50. verified = false;
  51. memset(bannedreason, 0, sizeof(bannedreason));
  52. //worldresponse_timer = new Timer(10000);
  53. //worldresponse_timer->Disable();
  54. memset(key,0,10);
  55. LoginMode = None;
  56. num_updates = 0;
  57. updatetimer = new Timer(500);
  58. updatelisttimer = new Timer(10000);
  59. //keepalive = new Timer(5000);
  60. //logintimer = new Timer(500); // Give time for the servers to send updates
  61. //keepalive->Start();
  62. //updatetimer->Start();
  63. //logintimer->Disable();
  64. disconnectTimer = 0;
  65. memset(ClientSession,0,25);
  66. request_num = 0;
  67. login_account = 0;
  68. createRequest = 0;
  69. playWaitTimer = NULL;
  70. start = false;
  71. update_position = 0;
  72. update_packets = 0;
  73. needs_world_list = true;
  74. sent_character_list = false;
  75. }
  76. Client::~Client() {
  77. //safe_delete(worldresponse_timer);
  78. //safe_delete(logintimer);
  79. safe_delete(login_account);
  80. eqnc->Close();
  81. safe_delete(playWaitTimer);
  82. safe_delete(createRequest);
  83. safe_delete(disconnectTimer);
  84. safe_delete(updatetimer);
  85. }
  86. bool Client::Process() {
  87. if(!start && !eqnc->CheckActive()){
  88. if(!playWaitTimer)
  89. playWaitTimer = new Timer(5000);
  90. else if(playWaitTimer->Check()){
  91. safe_delete(playWaitTimer);
  92. return false;
  93. }
  94. return true;
  95. }
  96. else if(!start){
  97. safe_delete(playWaitTimer);
  98. start = true;
  99. }
  100. if (disconnectTimer && disconnectTimer->Check())
  101. {
  102. safe_delete(disconnectTimer);
  103. getConnection()->SendDisconnect();
  104. }
  105. if (!kicked) {
  106. /************ Get all packets from packet manager out queue and process them ************/
  107. EQApplicationPacket *app = 0;
  108. /*if(logintimer && logintimer->Check())
  109. {
  110. database.LoadCharacters(GetLoginAccount());
  111. SendLoginAccepted();
  112. logintimer->Disable();
  113. }*/
  114. /*if(worldresponse_timer && worldresponse_timer->Check())
  115. {
  116. FatalError(WorldDownErrorMessage);
  117. worldresponse_timer->Disable();
  118. }*/
  119. if(playWaitTimer != NULL && playWaitTimer->Check ( ) )
  120. {
  121. SendPlayFailed(PLAY_ERROR_SERVER_TIMEOUT);
  122. safe_delete(playWaitTimer);
  123. }
  124. if(!needs_world_list && updatetimer && updatetimer->Check()){
  125. if(updatelisttimer && updatelisttimer->Check()){
  126. if(num_updates >= 180){ //30 minutes
  127. getConnection()->SendDisconnect();
  128. }
  129. else{
  130. vector<PacketStruct*>::iterator itr;
  131. if(update_packets){
  132. for(itr = update_packets->begin(); itr != update_packets->end(); itr++){
  133. safe_delete(*itr);
  134. }
  135. }
  136. safe_delete(update_packets);
  137. update_packets = world_list.GetServerListUpdate(version);
  138. }
  139. num_updates++;
  140. }
  141. else{
  142. if(!update_packets){
  143. update_packets = world_list.GetServerListUpdate(version);
  144. }
  145. else{
  146. if(update_position < update_packets->size()){
  147. QueuePacket(update_packets->at(update_position)->serialize());
  148. update_position++;
  149. }
  150. else
  151. update_position = 0;
  152. }
  153. }
  154. }
  155. while(app = eqnc->PopPacket())
  156. {
  157. switch(app->GetOpcode())
  158. {
  159. case OP_LoginRequestMsg:{
  160. DumpPacket(app);
  161. PacketStruct* packet = configReader.getStruct("LS_LoginRequest", 1);
  162. if(packet && packet->LoadPacketData(app->pBuffer,app->size)){
  163. version = packet->getType_int16_ByName("version");
  164. LogWrite(LOGIN__DEBUG, 0, "Login", "Classic Client Version Provided: %i", version);
  165. if (version == 0 || EQOpcodeManager.count(GetOpcodeVersion(version)) == 0)
  166. {
  167. safe_delete(packet);
  168. packet = configReader.getStruct("LS_LoginRequest", 1208);
  169. if (packet && packet->LoadPacketData(app->pBuffer, app->size)) {
  170. version = packet->getType_int16_ByName("version");
  171. }
  172. else
  173. break;
  174. }
  175. //[7:19 PM] Kirmmin: Well, I very quickly learned that unknown3 in LS_LoginRequest packet is the same value as cl_eqversion in the eq2_defaults.ini file.
  176. LogWrite(LOGIN__DEBUG, 0, "Login", "New Client Version Provided: %i", version);
  177. if (EQOpcodeManager.count(GetOpcodeVersion(version)) == 0) {
  178. LogWrite(LOGIN__ERROR, 0, "Login", "Incompatible client version provided: %i", version);
  179. SendLoginDenied();
  180. return false;
  181. }
  182. if(EQOpcodeManager.count(GetOpcodeVersion(version)) > 0 && getConnection()){
  183. getConnection()->SetClientVersion(GetVersion());
  184. EQ2_16BitString username = packet->getType_EQ2_16BitString_ByName("username");
  185. EQ2_16BitString password = packet->getType_EQ2_16BitString_ByName("password");
  186. LoginAccount* acct = database.LoadAccount(username.data.c_str(),password.data.c_str(), net.IsAllowingAccountCreation());
  187. if(acct){
  188. Client* otherclient = client_list.FindByLSID(acct->getLoginAccountID());
  189. if(otherclient)
  190. otherclient->getConnection()->SendDisconnect(); // This person is already logged in, we don't want them logged in twice, kick the previous client as it might be a ghost
  191. }
  192. if(acct){
  193. SetAccountName(username.data.c_str());
  194. database.UpdateAccountIPAddress(acct->getLoginAccountID(), getConnection()->GetrIP());
  195. database.UpdateAccountClientDataVersion(acct->getLoginAccountID(), version);
  196. LogWrite(LOGIN__INFO, 0, "Login", "%s successfully logged in.", (char*)username.data.c_str());
  197. }
  198. else
  199. {
  200. if (username.size > 0)
  201. LogWrite(LOGIN__ERROR, 0, "Login", "%s login failed!", (char*)username.data.c_str());
  202. else
  203. LogWrite(LOGIN__ERROR, 0, "Login", "[UNKNOWN USER] login failed!");
  204. }
  205. if(!acct)
  206. SendLoginDenied();
  207. else{
  208. needs_world_list = true;
  209. SetLoginAccount(acct);
  210. SendLoginAccepted();
  211. }
  212. }
  213. else{
  214. cout << "Error bad version: " << version << endl;
  215. SendLoginDeniedBadVersion();
  216. }
  217. }
  218. else{
  219. cout << "Error loading LS_LoginRequest packet: \n";
  220. //DumpPacket(app);
  221. }
  222. safe_delete(packet);
  223. break;
  224. }
  225. case OP_KeymapLoadMsg:{
  226. // cout << "Received OP_KeymapNoneMsg\n";
  227. //dunno what this is for
  228. break;
  229. }
  230. case OP_AllWSDescRequestMsg:{
  231. SendWorldList();
  232. needs_world_list = false;
  233. if(!sent_character_list) {
  234. database.LoadCharacters(GetLoginAccount(), GetVersion());
  235. sent_character_list = true;
  236. }
  237. SendCharList();
  238. break;
  239. }
  240. case OP_LsClientCrashlogReplyMsg:{
  241. // DumpPacket(app);
  242. SaveErrorsToDB(app, "Crash Log", GetVersion());
  243. break;
  244. }
  245. case OP_LsClientVerifylogReplyMsg:{
  246. // DumpPacket(app);
  247. SaveErrorsToDB(app, "Verify Log", GetVersion());
  248. break;
  249. }
  250. case OP_LsClientAlertlogReplyMsg:{
  251. // DumpPacket(app);
  252. SaveErrorsToDB(app, "Alert Log", GetVersion());
  253. break;
  254. }
  255. case OP_LsClientBaselogReplyMsg:{
  256. // DumpPacket(app);
  257. SaveErrorsToDB(app, "Base Log", GetVersion());
  258. break;
  259. }
  260. case OP_AllCharactersDescRequestMsg:{
  261. break;
  262. }
  263. case OP_CreateCharacterRequestMsg:{
  264. PacketStruct* packet = configReader.getStruct("CreateCharacter", GetVersion());
  265. DumpPacket(app);
  266. playWaitTimer = new Timer ( 15000 );
  267. playWaitTimer->Start ( );
  268. LogWrite(WORLD__INFO, 1, "World", "Character creation request from account %s", GetAccountName());
  269. if(packet->LoadPacketData(app->pBuffer,app->size, GetVersion() <= 561 ? false : true)){
  270. DumpPacket(app->pBuffer, app->size);
  271. packet->setDataByName("account_id",GetAccountID());
  272. LWorld* world_server = world_list.FindByID(packet->getType_int32_ByName("server_id"));
  273. if(!world_server)
  274. {
  275. DumpPacket(app->pBuffer, app->size);
  276. cout << GetAccountName() << " attempted creation of character with an invalid server id of: " << packet->getType_int32_ByName("server_id") << "\n";
  277. break;
  278. }
  279. else
  280. {
  281. createRequest = packet;
  282. ServerPacket* outpack = new ServerPacket(ServerOP_CharacterCreate, app->size+sizeof(int16));
  283. int16 out_version = GetVersion();
  284. memcpy(outpack->pBuffer, &out_version, sizeof(int16));
  285. memcpy(outpack->pBuffer + sizeof(int16), app->pBuffer, app->size);
  286. uchar* tmp = outpack->pBuffer;
  287. if(out_version<=283)
  288. tmp+=2;
  289. else if(out_version == 373) {
  290. tmp += 6;
  291. }
  292. else
  293. tmp += 7;
  294. int32 account_id = GetAccountID();
  295. memcpy(tmp, &account_id, sizeof(int32));
  296. world_server->SendPacket(outpack);
  297. safe_delete(outpack);
  298. }
  299. }
  300. else{
  301. LogWrite(WORLD__ERROR, 1, "World", "Error in character creation request from account %s!", GetAccountName());
  302. safe_delete(packet);
  303. }
  304. // world_list.SendWorldChanged(create.profile.server_id, false, this);
  305. break;
  306. }
  307. case OP_PlayCharacterRequestMsg:{
  308. int32 char_id = 0;
  309. int32 server_id = 0;
  310. PacketStruct* request = configReader.getStruct("LS_PlayRequest",GetVersion());
  311. if(request && request->LoadPacketData(app->pBuffer,app->size)){
  312. char_id = request->getType_int32_ByName("char_id");
  313. if (GetVersion() <= 283) {
  314. server_id = database.GetServer(GetAccountID(), char_id, request->getType_EQ2_16BitString_ByName("name").data);
  315. }
  316. else {
  317. server_id = request->getType_int32_ByName("server_id");
  318. }
  319. LWorld* world = world_list.FindByID(server_id);
  320. string name = database.GetCharacterName(char_id,server_id,GetAccountID());
  321. if(world && name.length() > 0){
  322. pending_play_char_id = char_id;
  323. ServerPacket* outpack = new ServerPacket(ServerOP_UsertoWorldReq, sizeof(UsertoWorldRequest_Struct));
  324. UsertoWorldRequest_Struct* req = (UsertoWorldRequest_Struct*)outpack->pBuffer;
  325. req->char_id = char_id;
  326. req->lsaccountid = GetAccountID();
  327. req->worldid = server_id;
  328. struct in_addr in;
  329. in.s_addr = GetIP();
  330. strcpy(req->ip_address, inet_ntoa(in));
  331. world->SendPacket(outpack);
  332. delete outpack;
  333. safe_delete(playWaitTimer);
  334. playWaitTimer = new Timer ( 5000 );
  335. playWaitTimer->Start ( );
  336. }
  337. else{
  338. cout << GetAccountName() << " sent invalid Play Request: \n";
  339. SendPlayFailed(PLAY_ERROR_PROBLEM);
  340. DumpPacket(app);
  341. }
  342. }
  343. safe_delete(request);
  344. break;
  345. }
  346. case OP_DeleteCharacterRequestMsg:{
  347. PacketStruct* request = configReader.getStruct("LS_DeleteCharacterRequest", GetVersion());
  348. PacketStruct* response = configReader.getStruct("LS_DeleteCharacterResponse", GetVersion());
  349. if(request && response && request->LoadPacketData(app->pBuffer,app->size)){
  350. EQ2_16BitString name = request->getType_EQ2_16BitString_ByName("name");
  351. int32 acct_id = GetAccountID();
  352. int32 char_id = request->getType_int32_ByName("char_id");
  353. int32 server_id = request->getType_int32_ByName("server_id");
  354. if(database.VerifyDelete(acct_id, char_id, name.data.c_str())){
  355. response->setDataByName("response", 1);
  356. GetLoginAccount()->removeCharacter((char*)name.data.c_str());
  357. LWorld* world_server = world_list.FindByID(server_id);
  358. if(world_server != NULL)
  359. world_server->SendDeleteCharacter ( char_id , acct_id );
  360. }
  361. else
  362. response->setDataByName("response", 0);
  363. response->setDataByName("server_id", server_id);
  364. response->setDataByName("char_id", char_id);
  365. response->setDataByName("account_id", account_id);
  366. response->setMediumStringByName("name", (char*)name.data.c_str());
  367. response->setDataByName("max_characters", 10);
  368. EQ2Packet* outapp = response->serialize();
  369. QueuePacket(outapp);
  370. this->SendCharList();
  371. }
  372. safe_delete(request);
  373. safe_delete(response);
  374. break;
  375. }
  376. default: {
  377. const char* name = app->GetOpcodeName();
  378. if (name)
  379. LogWrite(OPCODE__DEBUG, 1, "Opcode", "%s Received %04X (%i)", name, app->GetRawOpcode(), app->GetRawOpcode());
  380. else
  381. LogWrite(OPCODE__DEBUG, 1, "Opcode", "Received %04X (%i)", app->GetRawOpcode(), app->GetRawOpcode());
  382. }
  383. }
  384. delete app;
  385. }
  386. }
  387. if (!eqnc->CheckActive()) {
  388. return false;
  389. }
  390. return true;
  391. }
  392. void Client::SaveErrorsToDB(EQApplicationPacket* app, char* type, int32 version){
  393. int32 size = 0;
  394. z_stream zstream;
  395. if (version >= 546) {
  396. memcpy(&size, app->pBuffer + sizeof(int32), sizeof(int32));
  397. zstream.next_in = app->pBuffer + 8;
  398. zstream.avail_in = app->size - 8;
  399. }
  400. else { //box set
  401. size = 0xFFFF;
  402. zstream.next_in = app->pBuffer + 2;
  403. zstream.avail_in = app->size - 2;
  404. }
  405. size++;
  406. char* message = new char[size];
  407. memset(message, 0, size);
  408. int zerror = 0;
  409. zstream.next_out = (BYTE*)message;
  410. zstream.avail_out = size;
  411. zstream.zalloc = Z_NULL;
  412. zstream.zfree = Z_NULL;
  413. zstream.opaque = Z_NULL;
  414. zerror = inflateInit( &zstream);
  415. if(zerror != Z_OK) {
  416. safe_delete_array(message);
  417. return;
  418. }
  419. zerror = inflate( &zstream, 0 );
  420. if(message && strlen(message) > 0)
  421. database.SaveClientLog(type, message, GetLoginAccount()->getLoginName(), GetVersion());
  422. safe_delete_array(message);
  423. }
  424. void Client::CharacterApproved(int32 server_id,int32 char_id)
  425. {
  426. if(createRequest && server_id == createRequest->getType_int32_ByName("server_id")){
  427. LWorld* world_server = world_list.FindByID(server_id);
  428. if(!world_server)
  429. return;
  430. PacketStruct* packet = configReader.getStruct("LS_CreateCharacterReply", GetVersion());
  431. if(packet){
  432. packet->setDataByName("account_id", GetAccountID());
  433. packet->setDataByName("unknown", 0xFFFFFFFF);
  434. packet->setDataByName("response", CREATESUCCESS_REPLY);
  435. packet->setMediumStringByName("name", (char*)createRequest->getType_EQ2_16BitString_ByName("name").data.c_str());
  436. EQ2Packet* outapp = packet->serialize();
  437. QueuePacket(outapp);
  438. safe_delete(packet);
  439. database.SaveCharacter(createRequest, GetLoginAccount(),char_id, GetVersion());
  440. // refresh characters for this account
  441. database.LoadCharacters(GetLoginAccount(), GetVersion());
  442. SendCharList();
  443. if (GetVersion() <= 561)
  444. {
  445. pending_play_char_id = char_id;
  446. ServerPacket* outpack = new ServerPacket(ServerOP_UsertoWorldReq, sizeof(UsertoWorldRequest_Struct));
  447. UsertoWorldRequest_Struct* req = (UsertoWorldRequest_Struct*)outpack->pBuffer;
  448. req->char_id = char_id;
  449. req->lsaccountid = GetAccountID();
  450. req->worldid = server_id;
  451. struct in_addr in;
  452. in.s_addr = GetIP();
  453. strcpy(req->ip_address, inet_ntoa(in));
  454. world_server->SendPacket(outpack);
  455. delete outpack;
  456. }
  457. }
  458. }
  459. else{
  460. cout << GetAccountName() << " received invalid CharacterApproval from server: " << server_id << endl;
  461. }
  462. safe_delete(createRequest);
  463. }
  464. void Client::CharacterRejected(int8 reason_number)
  465. {
  466. PacketStruct* packet = configReader.getStruct("LS_CreateCharacterReply", GetVersion());
  467. if(createRequest && packet){
  468. packet->setDataByName("account_id", GetAccountID());
  469. int8 clientReasonNum = reason_number;
  470. // reason numbers change and instead of updating the world server
  471. // the login server will hold the up to date #'s
  472. /*
  473. switch(reason_number)
  474. {
  475. // these error codes seem to be removed now, they shutdown the client rather immediately
  476. // for now we are just going to play a joke on them and say they can't create a new character.
  477. case INVALIDRACE_REPLY:
  478. case INVALIDGENDER_REPLY:
  479. clientReasonNum = 8;
  480. break;
  481. case BADNAMELENGTH_REPLY:
  482. clientReasonNum = 9;
  483. break;
  484. case NAMEINVALID_REPLY:
  485. clientReasonNum = 10;
  486. break;
  487. case NAMEFILTER_REPLY:
  488. clientReasonNum = 11;
  489. break;
  490. case NAMETAKEN_REPLY:
  491. clientReasonNum = 12;
  492. break;
  493. case OVERLOADEDSERVER_REPLY:
  494. clientReasonNum = 13;
  495. break;
  496. }
  497. */
  498. packet->setDataByName("response", clientReasonNum);
  499. packet->setMediumStringByName("name", "");
  500. EQ2Packet* outapp = packet->serialize();
  501. QueuePacket(outapp);
  502. safe_delete(packet);
  503. }
  504. /*LS_CreateCharacterReply reply(GetAccountID(), reason_number, create.profile.name.data);
  505. EQ2Packet* outapp = reply.serialize();
  506. QueuePacket(outapp);
  507. create.Clear();*/
  508. }
  509. void Client::SendCharList(){
  510. /*PacketStruct* packet = configReader.getStruct("LS_CreateCharacterReply");
  511. packet->setDataByName("account_id", GetAccountID());
  512. packet->setDataByName("response", reason_number);
  513. packet->setDataByName("name", &create.profile.name);
  514. EQ2Packet* outapp = packet->serialize();
  515. QueuePacket(outapp);
  516. safe_delete(packet);*/
  517. LogWrite(LOGIN__INFO, 0, "Login", "[%s] sending character list.", GetAccountName());
  518. LS_CharSelectList list;
  519. list.loadData(GetAccountID(), GetLoginAccount()->charlist, GetVersion());
  520. EQ2Packet* outapp = list.serialize(GetVersion());
  521. DumpPacket(outapp->pBuffer, outapp->size);
  522. QueuePacket(outapp);
  523. }
  524. void Client::SendLoginDeniedBadVersion(){
  525. EQ2Packet* app = new EQ2Packet(OP_LoginReplyMsg, 0, sizeof(LS_LoginResponse));
  526. LS_LoginResponse* ls_response = (LS_LoginResponse*)app->pBuffer;
  527. ls_response->reply_code = 6;
  528. ls_response->unknown03 = 0xFFFFFFFF;
  529. ls_response->unknown04 = 0xFFFFFFFF;
  530. QueuePacket(app);
  531. StartDisconnectTimer();
  532. }
  533. void Client::SendLoginDenied(){
  534. EQ2Packet* app = new EQ2Packet(OP_LoginReplyMsg, 0, sizeof(LS_LoginResponse));
  535. LS_LoginResponse* ls_response = (LS_LoginResponse*)app->pBuffer;
  536. ls_response->reply_code = 1;
  537. // reply_codes for AoM:
  538. /* 1 = Login rejected: Invalid username or password. Please try again.
  539. 2 = Login rejected: Server thinks your account is currently playing; you may have to wait "
  540. "a few minutes for it to clear, then try again
  541. 6 = Login rejected: The client's version does not match the server's. Please re-run the patcher.
  542. 7 = Login rejected: You have no scheduled playtimes.
  543. 8 = Your account does not have the features required to play on this server.
  544. 11 = The client's build does not match the server's. Please re-run the patcher.
  545. 12 = You must update your password in order to log in. Pressing OK will op"
  546. "en your web browser to the SOE password management page
  547. Other Value > 1 = Login rejected for an unknown reason.
  548. */
  549. ls_response->unknown03 = 0xFFFFFFFF;
  550. ls_response->unknown04 = 0xFFFFFFFF;
  551. QueuePacket(app);
  552. StartDisconnectTimer();
  553. }
  554. void Client::SendLoginAccepted(int32 account_id, int8 login_response) {
  555. PacketStruct* packet = configReader.getStruct("LS_LoginReplyMsg", GetVersion());
  556. int i = 0;
  557. if (packet)
  558. {
  559. packet->setDataByName("account_id", account_id);
  560. packet->setDataByName("login_response", login_response);
  561. packet->setDataByName("do_not_force_soga", 1);
  562. // sub_level 0xFFFFFFFF = blacks out all portraits for class alignments, considered non membership
  563. // sub_level > 0 = class alignments still required, but portraits are viewable and race selectable
  564. // sub_level = 2 membership, you can 'create characters on time locked servers' vs standard
  565. // sub_level = 0 forces popup on close to web browser
  566. packet->setDataByName("sub_level", net.GetDefaultSubscriptionLevel());
  567. packet->setDataByName("race_flag", 0x1FFFFF);
  568. packet->setDataByName("class_flag", 0x7FFFFFE);
  569. packet->setMediumStringByName("username", GetAccountName());
  570. packet->setMediumStringByName("password", GetAccountName());
  571. // unknown5
  572. // full support = 0x7CFF
  573. // 1 << 12 (-4096) = missing echoes of faydwer, disables Fae and Arasai (black portraits) and kelethin as starting city
  574. // 1 << 13 (-8192) = disables sarnak (black portraits) and gorowyn as starting city
  575. packet->setDataByName("unknown5", net.GetExpansionFlag());
  576. packet->setDataByName("unknown6", 0xFF);
  577. packet->setDataByName("unknown6", 0xFF, 1);
  578. packet->setDataByName("unknown6", 0xFF, 2);
  579. // controls class access / playable characters
  580. packet->setDataByName("unknown10", 0xFF);
  581. // packet->setDataByName("unknown7a", 0x0101);
  582. // packet->setDataByName("race_unknown", 0x01);
  583. packet->setDataByName("unknown7", net.GetEnabledRaces()); // 0x01-0xFF disable extra races FAE(16) ARASAI (17) SARNAK (18) -- with 4096/8192 flags, no visibility of portraits
  584. packet->setDataByName("unknown7a", 0xEE);
  585. packet->setDataByName("unknown8", net.GetCitiesFlag(), 1); // dword_1ECBA18 operand for race flag packs (sublevel 0,1,2?) -- (sublevel -1) controls starting zones omission 0xEE vs 0xCF (CF misses halas)
  586. /*
  587. 1 = city of qeynos
  588. 2 = city of freeport
  589. 4 = city of kelethin
  590. 8 = city of neriak
  591. 16 = gorowyn
  592. 32 = new halas
  593. 64 = queens colony
  594. 128 = outpost overlord
  595. */
  596. EQ2Packet* outapp = packet->serialize();
  597. QueuePacket(outapp);
  598. safe_delete(packet);
  599. }
  600. }
  601. void Client::SendWorldList(){
  602. EQ2Packet* pack = world_list.MakeServerListPacket(lsadmin, version);
  603. EQ2Packet* dupe = pack->Copy();
  604. DumpPacket(dupe->pBuffer,dupe->size);
  605. QueuePacket(dupe);
  606. SendLoginAccepted(0, 10); // triggers a different code path in the client to set certain flags
  607. return;
  608. }
  609. void Client::QueuePacket(EQ2Packet* app){
  610. eqnc->EQ2QueuePacket(app);
  611. }
  612. void Client::WorldResponse(int32 worldid, int8 response, char* ip_address, int32 port, int32 access_key)
  613. {
  614. LWorld* world = world_list.FindByID(worldid);
  615. if(world == 0) {
  616. FatalError(0);
  617. return;
  618. }
  619. if(response != 1){
  620. if(response == PLAY_ERROR_CHAR_NOT_LOADED){
  621. string pending_play_char_name = database.GetCharacterName(pending_play_char_id, worldid, GetAccountID());
  622. if(database.VerifyDelete(GetAccountID(), pending_play_char_id, pending_play_char_name.c_str())){
  623. GetLoginAccount()->removeCharacter((char*)pending_play_char_name.c_str());
  624. }
  625. }
  626. FatalError(response);
  627. return;
  628. }
  629. PacketStruct* response_packet = configReader.getStruct("LS_PlayResponse", GetVersion());
  630. if(response_packet){
  631. safe_delete(playWaitTimer);
  632. response_packet->setDataByName("response", 1);
  633. response_packet->setSmallStringByName("server", ip_address);
  634. response_packet->setDataByName("port", port);
  635. response_packet->setDataByName("account_id", GetAccountID());
  636. response_packet->setDataByName("access_code", access_key);
  637. EQ2Packet* outapp = response_packet->serialize();
  638. QueuePacket(outapp);
  639. safe_delete(response_packet);
  640. }
  641. return;
  642. }
  643. void Client::FatalError(int8 response) {
  644. safe_delete(playWaitTimer);
  645. SendPlayFailed(response);
  646. }
  647. void Client::SendPlayFailed(int8 response){
  648. PacketStruct* response_packet = configReader.getStruct("LS_PlayResponse", GetVersion());
  649. if(response_packet){
  650. response_packet->setDataByName("response", response);
  651. response_packet->setSmallStringByName("server", "");
  652. response_packet->setDataByName("port", 0);
  653. response_packet->setDataByName("account_id", GetAccountID());
  654. response_packet->setDataByName("access_code", 0);
  655. EQ2Packet* outapp = response_packet->serialize();
  656. QueuePacket(outapp);
  657. safe_delete(response_packet);
  658. }
  659. }
  660. void ClientList::Add(Client* client) {
  661. MClientList.writelock();
  662. client_list[client] = true;
  663. MClientList.releasewritelock();
  664. }
  665. Client* ClientList::Get(int32 ip, int16 port) {
  666. Client* ret = 0;
  667. map<Client*, bool>::iterator itr;
  668. MClientList.readlock();
  669. for(itr = client_list.begin(); itr != client_list.end(); itr++){
  670. if(itr->first->GetIP() == ip && itr->first->GetPort() == port){
  671. ret = itr->first;
  672. break;
  673. }
  674. }
  675. MClientList.releasereadlock();
  676. return ret;
  677. }
  678. void ClientList::FindByCreateRequest(){
  679. Client* client = 0;
  680. map<Client*, bool>::iterator itr;
  681. MClientList.readlock();
  682. for(itr = client_list.begin(); itr != client_list.end(); itr++){
  683. if(itr->first->AwaitingCharCreationRequest()){
  684. if(!client)
  685. client = itr->first;
  686. else{
  687. client = 0;//more than 1 character waiting, dont want to send rejection to wrong one
  688. break;
  689. }
  690. }
  691. }
  692. MClientList.releasereadlock();
  693. if(client)
  694. client->CharacterRejected(UNKNOWNERROR_REPLY);
  695. }
  696. Client* ClientList::FindByLSID(int32 lsaccountid) {
  697. Client* client = 0;
  698. map<Client*, bool>::iterator itr;
  699. MClientList.readlock();
  700. for(itr = client_list.begin(); itr != client_list.end(); itr++){
  701. if(itr->first->GetAccountID() == lsaccountid){
  702. client = itr->first;
  703. break;
  704. }
  705. }
  706. MClientList.releasereadlock();
  707. return client;
  708. }
  709. void ClientList::SendPacketToAllClients(EQ2Packet* app){
  710. Client* client = 0;
  711. map<Client*, bool>::iterator itr;
  712. MClientList.readlock();
  713. if(client_list.size() > 0){
  714. for(itr = client_list.begin(); itr != client_list.end(); itr++){
  715. itr->first->QueuePacket(app->Copy());
  716. }
  717. }
  718. safe_delete(app);
  719. MClientList.releasereadlock();
  720. }
  721. void ClientList::Process() {
  722. Client* client = 0;
  723. vector<Client*> erase_list;
  724. map<Client*, bool>::iterator itr;
  725. MClientList.readlock();
  726. for(itr = client_list.begin(); itr != client_list.end(); itr++){
  727. client = itr->first;
  728. if(!client->Process())
  729. erase_list.push_back(client);
  730. }
  731. MClientList.releasereadlock();
  732. if(erase_list.size() > 0){
  733. vector<Client*>::iterator erase_itr;
  734. MClientList.writelock();
  735. for(erase_itr = erase_list.begin(); erase_itr != erase_list.end(); erase_itr++){
  736. client = *erase_itr;
  737. struct in_addr in;
  738. in.s_addr = client->getConnection()->GetRemoteIP();
  739. net.numclients--;
  740. LogWrite(LOGIN__INFO, 0, "Login", "Removing client from ip: %s on port %i, Account Name: %s", inet_ntoa(in), ntohs(client->getConnection()->GetRemotePort()), client->GetAccountName());
  741. client->getConnection()->Close();
  742. net.UpdateWindowTitle();
  743. client_list.erase(client);
  744. }
  745. MClientList.releasewritelock();
  746. }
  747. }
  748. void Client::StartDisconnectTimer() {
  749. if (!disconnectTimer)
  750. {
  751. disconnectTimer = new Timer(1000);
  752. disconnectTimer->Start();
  753. }
  754. }