diff --git a/src/Client/PseuWoW.cpp b/src/Client/PseuWoW.cpp index ae5c2df..2622a38 100644 --- a/src/Client/PseuWoW.cpp +++ b/src/Client/PseuWoW.cpp @@ -12,12 +12,6 @@ #include "Realm/RealmSocket.h" #include "World/WorldSession.h" -/* TODO: -defscriptpackage fix, xchgresult einbauen, CmdSet.caller einbauen, permissionmap einbauen -WorldSesssion::Update() rein -opcode handler table vervollstädigen + funktionen dafür umschreiben - -*/ //###### Start of program code ####### @@ -52,6 +46,7 @@ PseuInstance::PseuInstance(PseuInstanceRunnable *run) _conf=NULL; _stop=false; _fastquit=false; + _startrealm=true; createWorldSession=false; @@ -83,7 +78,6 @@ bool PseuInstance::Init(void) { _scp=new DefScriptPackage(); _scp->SetParentMethod((void*)this); _conf=new PseuInstanceConf(); - _rsession=new RealmSocket(_sh); if(!_scp->variables.ReadVarsFromFile(_confdir + "PseuWoW.conf")) { @@ -132,36 +126,40 @@ bool PseuInstance::Init(void) { void PseuInstance::Run(void) { - if(!_initialized) - return; - - _rsession->SetDeleteByHandler(); - _rsession->SetHost(GetConf()->realmlist); - _rsession->SetPort(GetConf()->realmport); - _rsession->SetInstance(this); - _rsession->Start(); - - if(_rsession->IsValid()) + do { - _sh.Add(_rsession); - _sh.Select(1,0); - } + if(!_initialized) + return; - while(!_stop) - { - Update(); + _rsession=new RealmSocket(_sh); + _rsession->SetDeleteByHandler(); + _rsession->SetHost(GetConf()->realmlist); + _rsession->SetPort(GetConf()->realmport); + _rsession->SetInstance(this); + _rsession->Start(); + + if(_rsession->IsValid()) + { + _sh.Add(_rsession); + _sh.Select(1,0); + } + _startrealm=false; // the realm is started now + + while((!_stop) && (!_startrealm)) + { + Update(); + } } + while(GetConf()->reconnect && (!_stop)); if(_fastquit) { printf("Aborting Instance...\n"); return; } - printf("Shutting down instance...\n"); - - // save all data here + SaveAllCache(); } @@ -169,9 +167,8 @@ void PseuInstance::Update() { if(_sh.GetCount()) _sh.Select(0,0); // update the realmsocket - //else - // socket invalid? - if(createWorldSession) + + if(createWorldSession && (!_wsession)) { createWorldSession=false; _wsession=new WorldSession(this); @@ -184,6 +181,14 @@ void PseuInstance::Update() { _wsession->Update(); // update the worldSESSION, which will update the worldsocket itself } + if(_wsession && _wsession->DeleteMe()) + { + delete _wsession; + _wsession=NULL; + _startrealm=true; + this->Sleep(1000); // wait 1 sec before reconnecting + return; + } this->Sleep(GetConf()->networksleeptime); } @@ -306,6 +311,7 @@ void PseuInstanceConf::ApplyFromVarSet(VarSet &v) accname=v.Get("ACCNAME"); accpass=v.Get("ACCPASS"); exitonerror=(bool)atoi(v.Get("EXITONERROR").c_str()); + reconnect=(bool)atoi(v.Get("RECONNECT").c_str()); realmport=atoi(v.Get("REALMPORT").c_str()); clientversion_string=v.Get("CLIENTVERSION"); clientbuild=atoi(v.Get("CLIENTBUILD").c_str()); diff --git a/src/Client/PseuWoW.h b/src/Client/PseuWoW.h index b4f148a..2051faa 100644 --- a/src/Client/PseuWoW.h +++ b/src/Client/PseuWoW.h @@ -26,6 +26,7 @@ class PseuInstanceConf std::string accname; std::string accpass; bool exitonerror; + bool reconnect; uint16 realmport; uint16 worldport; uint8 clientversion[3]; @@ -84,6 +85,7 @@ class PseuInstance std::string _confdir,_scpdir; bool _initialized; bool _stop,_fastquit; + bool _startrealm; BigNumber _sessionkey; char *_ver,*_ver_short; SocketHandler _sh; diff --git a/src/Client/Realm/RealmSocket.h b/src/Client/Realm/RealmSocket.h index 39ea07c..e4ea332 100644 --- a/src/Client/Realm/RealmSocket.h +++ b/src/Client/Realm/RealmSocket.h @@ -5,6 +5,7 @@ #define _REALMSOCKET_H #include "Network/ResolvSocket.h" +#include "PseuWoW.h" class RealmSocket : public TcpSocket { diff --git a/src/Client/World/Player.cpp b/src/Client/World/Player.cpp index e0d40e6..1915b8a 100644 --- a/src/Client/World/Player.cpp +++ b/src/Client/World/Player.cpp @@ -44,7 +44,7 @@ bool PlayerNameCache::SaveToFile(void){ fh.open(fn, std::ios_base::out | std::ios_base::binary); if(!fh) { - printf("ERROR: could not open file '%s'!\n",fn); + printf("ERROR: could not write to file '%s'!\n",fn); return false; } uint32 size=_cache.size(); diff --git a/src/Client/World/WorldSession.cpp b/src/Client/World/WorldSession.cpp index f03e4d3..9a6af35 100644 --- a/src/Client/World/WorldSession.cpp +++ b/src/Client/World/WorldSession.cpp @@ -6,10 +6,11 @@ #include "Opcodes.h" #include "WorldPacket.h" #include "WorldSocket.h" -#include "WorldSession.h" #include "NameTables.h" #include "RealmSocket.h" +#include "WorldSession.h" + WorldSession::WorldSession(PseuInstance *in) { @@ -20,6 +21,7 @@ WorldSession::WorldSession(PseuInstance *in) _followGUID=0; // dont follow anything _myGUID=0; // i dont have a guid yet plrNameCache.ReadFromFile(); // load names/guids of known players + _deleteme = false; //... } @@ -32,6 +34,8 @@ WorldSession::~WorldSession() packet = pktQueue.next(); delete packet; } + _OnLeaveWorld(); + //delete _socket; the socket will be deleted by its handler!! } @@ -46,10 +50,19 @@ void WorldSession::Start(void) _sh.Select(1,0); } +bool WorldSession::DeleteMe(void) +{ + return _deleteme; +} + +void WorldSession::SetSocket(WorldSocket *sock) +{ + _socket = sock; +} + void WorldSession::AddToPktQueue(WorldPacket *pkt) { pktQueue.add(pkt); - printf("-- Added Packet to queue, size is now %u\n",pktQueue.size()); } void WorldSession::SendWorldPacket(WorldPacket &pkt) @@ -61,15 +74,26 @@ void WorldSession::Update(void) { if (!IsValid()) return; - if(_sh.GetCount()) + + if( _socket && _sh.GetCount() ) _sh.Select(0,0); + if(!_socket) + { + if(_valid) + { + _deleteme = true; + } + _logged=_authed=_valid=false; + return; + } + + OpcodeHandler *table = _GetOpcodeHandlerTable(); bool known=false; while(!pktQueue.empty()) { WorldPacket *packet = pktQueue.next(); - printf("QUEUE: %u packets left\n",pktQueue.size()); printf(">> Opcode %u [%s]\n",packet->GetOpcode(),LookupName(packet->GetOpcode(),g_worldOpcodeNames)); for (uint16 i = 0; table[i].handler != NULL; i++) @@ -86,7 +110,9 @@ void WorldSession::Update(void) delete packet; } - // do more stuff here + + _DoTimedActions(); + } @@ -139,12 +165,36 @@ void WorldSession::SetFollowTarget(uint64 guid) _followGUID=guid; } -void WorldSession::OnEnterWorld(void) +void WorldSession::_OnEnterWorld(void) { if(!_logged) { _logged=true; //GetInstance()->GetScripts()->RunScriptByName("_enterworld",NULL,255); + + } +} + +void WorldSession::_OnLeaveWorld(void) +{ + if(_logged) + { + _logged=false; + + } +} + +void WorldSession::_DoTimedActions(void) +{ + static clock_t pingtime=0; + if(_logged) + { + if(pingtime < clock()) + { + pingtime=clock() + 30*CLOCKS_PER_SEC; + SendPing(clock()); + } + //... } } @@ -281,12 +331,12 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket) void WorldSession::_HandleSetProficiencyOpcode(WorldPacket& recvPacket) { - OnEnterWorld(); + _OnEnterWorld(); } void WorldSession::_HandleAccountDataMD5Opcode(WorldPacket& recvPacket) { - OnEnterWorld(); + _OnEnterWorld(); } void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket) diff --git a/src/Client/World/WorldSession.h b/src/Client/World/WorldSession.h index cd44815..9378379 100644 --- a/src/Client/World/WorldSession.h +++ b/src/Client/World/WorldSession.h @@ -6,11 +6,12 @@ #include "Network/SocketHandler.h" #include "common.h" #include "Player.h" -#include "../Auth/AuthCrypt.h" +#include "Auth/AuthCrypt.h" #include "SharedDefines.h" class WorldSocket; class WorldPacket; +class PingerThread; struct OpcodeHandler { @@ -30,11 +31,14 @@ public: OpcodeHandler *_GetOpcodeHandlerTable(void) const; + void SetSocket(WorldSocket *sock); + void AddToPktQueue(WorldPacket *pkt); void Connect(std::string addr,uint16 port); void Update(void); void Start(void); bool IsValid(void) { return _valid; } + bool DeleteMe(void); void SendWorldPacket(WorldPacket&); void SetTarget(uint64 guid); @@ -55,7 +59,9 @@ public: private: // Helpers - void OnEnterWorld(void); + void _OnEnterWorld(void); // = login + void _OnLeaveWorld(void); // = logout + void _DoTimedActions(void); // Opcode Handlers void _HandleAuthChallengeOpcode(WorldPacket& recvPacket); @@ -74,7 +80,7 @@ private: PseuInstance *_instance; WorldSocket *_socket; ZThread::LockedQueue pktQueue; - bool _valid,_authed,_logged; // world status + bool _valid,_authed,_logged,_deleteme; // world status SocketHandler _sh; // handles the WorldSocket uint64 _targetGUID,_followGUID,_myGUID; diff --git a/src/Client/World/WorldSocket.cpp b/src/Client/World/WorldSocket.cpp index f568b88..4a87f0d 100644 --- a/src/Client/World/WorldSocket.cpp +++ b/src/Client/World/WorldSocket.cpp @@ -20,75 +20,79 @@ void WorldSocket::OnConnectFailed() printf("WorldSocket::OnConnectFailed()\n"); } +void WorldSocket::OnDelete() +{ + printf("Connection to world server has been closed.\n"); + if(_session) + _session->SetSocket(NULL); +} + void WorldSocket::OnRead() { TcpSocket::OnRead(); uint32 len = ibuf.GetLength(); - printf("WorldSocket::OnRead() %u bytes\n",len); + //printf("WorldSocket::OnRead() %u bytes\n",len); if(!len) + { + this->CloseAndDelete(); return; + } uint8 *buf=new uint8[len]; ibuf.Read((char*)buf,len); - ByteBuffer bb; - bb.append(buf,len); - // bb.hexlike(); + uint32 offset=0; // to skip data already read - uint32 offset=0; - - // this is a bit tricky, but needed, because sometimes packets come over as [[hdr][data][hdr]] - // and the 2nd header needs to be extracted too - while(len > 0) + + while(len > 0) // when all packets from the current ibuf are transformed into WorldPackets the remaining len will be zero { if(_gothdr) // already got header, this packet has to be the data part { _gothdr=false; - /*if( len != _remaining ) - { - printf("WP: Recieved packet is not correct (%u of %u)\n",len,_remaining); - break; - }*/ - - printf("WP: Fetched DATA part, building complete WorldPacket with opcode %u\n",_opcode); WorldPacket *wp = new WorldPacket; wp->append(buf+offset,_remaining); wp->SetOpcode(_opcode); GetSession()->AddToPktQueue(wp); offset += _remaining; // skip the data already used - len -= _remaining; + len -= _remaining; // and adjust the length } else // no pending header stored, so this packet must be a header { - printf("WP: Fetched header (%u bytes)\n",len); ServerPktHeader hdr; memcpy(&hdr,buf+offset,sizeof(ServerPktHeader)); _crypt.DecryptRecv((uint8*)&hdr,sizeof(ServerPktHeader)); _remaining = ntohs(hdr.size)-2; _opcode = hdr.cmd; - printf("WP: Opcode=%u, remains=%u\n",_opcode,_remaining); + if(_opcode > 800) // no opcode has yet a number over 800 + { + printf("CRYPT ERROR: opcode=%u, remain=%u\n",_opcode,_remaining); + GetSession()->GetInstance()->Stop(); + // if the crypt gets messy its hardly possible to recover it, especially if we dont know + // the lentgh of the following data part + // TODO: invent some way how to recover the crypt (reconnect?) + return; + } // the header is fine, now check if there are more data - if(_remaining == 0) + if(_remaining == 0) // this is a packet with no data (like CMSG_NULL_ACTION) { - printf("WP: Packet has no body, building WorldPacket\n"); WorldPacket *wp = new WorldPacket; wp->SetOpcode(_opcode); GetSession()->AddToPktQueue(wp); offset += 4 ; // skip the data already used - len -= 4; + len -= 4; // and adjust the lentgh } - else + else // there is a data part to fetch { _gothdr=true; // only got the header, next packet wil contain the data offset += 4 ; // skip the data already used - len -= 4; + len -= 4; // and adjust the lentgh } } } - delete buf; // UNSURE: delete or delete[] + delete buf; } void WorldSocket::SendWorldPacket(WorldPacket &pkt) diff --git a/src/Client/World/WorldSocket.h b/src/Client/World/WorldSocket.h index 7984740..68f0a87 100644 --- a/src/Client/World/WorldSocket.h +++ b/src/Client/World/WorldSocket.h @@ -28,6 +28,7 @@ public: void OnRead(); void OnConnect(); void OnConnectFailed(); + void OnDelete(); void SendWorldPacket(WorldPacket &pkt); void InitCrypt(uint8*,uint32); @@ -36,9 +37,8 @@ private: WorldSession *_session; AuthCrypt _crypt; bool _gothdr; // true if only the header was recieved yet - ByteBuffer _hdr; - uint16 _opcode; - uint16 _remaining; + uint16 _opcode; // stores the last recieved opcode + uint16 _remaining; // bytes amount of the next data packet };