partially fixed: handle disconnected from world server; added a new config option: reconnect=1/0

This commit is contained in:
False.Genesis 2007-01-10 01:16:49 +00:00
parent 5004629d12
commit 0b1ae6f9ca
8 changed files with 138 additions and 69 deletions

View File

@ -12,12 +12,6 @@
#include "Realm/RealmSocket.h" #include "Realm/RealmSocket.h"
#include "World/WorldSession.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 ####### //###### Start of program code #######
@ -52,6 +46,7 @@ PseuInstance::PseuInstance(PseuInstanceRunnable *run)
_conf=NULL; _conf=NULL;
_stop=false; _stop=false;
_fastquit=false; _fastquit=false;
_startrealm=true;
createWorldSession=false; createWorldSession=false;
@ -83,7 +78,6 @@ bool PseuInstance::Init(void) {
_scp=new DefScriptPackage(); _scp=new DefScriptPackage();
_scp->SetParentMethod((void*)this); _scp->SetParentMethod((void*)this);
_conf=new PseuInstanceConf(); _conf=new PseuInstanceConf();
_rsession=new RealmSocket(_sh);
if(!_scp->variables.ReadVarsFromFile(_confdir + "PseuWoW.conf")) if(!_scp->variables.ReadVarsFromFile(_confdir + "PseuWoW.conf"))
{ {
@ -132,36 +126,40 @@ bool PseuInstance::Init(void) {
void PseuInstance::Run(void) void PseuInstance::Run(void)
{ {
if(!_initialized) do
return;
_rsession->SetDeleteByHandler();
_rsession->SetHost(GetConf()->realmlist);
_rsession->SetPort(GetConf()->realmport);
_rsession->SetInstance(this);
_rsession->Start();
if(_rsession->IsValid())
{ {
_sh.Add(_rsession); if(!_initialized)
_sh.Select(1,0); return;
}
while(!_stop) _rsession=new RealmSocket(_sh);
{ _rsession->SetDeleteByHandler();
Update(); _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) if(_fastquit)
{ {
printf("Aborting Instance...\n"); printf("Aborting Instance...\n");
return; return;
} }
printf("Shutting down instance...\n"); printf("Shutting down instance...\n");
SaveAllCache();
// save all data here
} }
@ -169,9 +167,8 @@ void PseuInstance::Update()
{ {
if(_sh.GetCount()) if(_sh.GetCount())
_sh.Select(0,0); // update the realmsocket _sh.Select(0,0); // update the realmsocket
//else
// socket invalid? if(createWorldSession && (!_wsession))
if(createWorldSession)
{ {
createWorldSession=false; createWorldSession=false;
_wsession=new WorldSession(this); _wsession=new WorldSession(this);
@ -184,6 +181,14 @@ void PseuInstance::Update()
{ {
_wsession->Update(); // update the worldSESSION, which will update the worldsocket itself _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); this->Sleep(GetConf()->networksleeptime);
} }
@ -306,6 +311,7 @@ void PseuInstanceConf::ApplyFromVarSet(VarSet &v)
accname=v.Get("ACCNAME"); accname=v.Get("ACCNAME");
accpass=v.Get("ACCPASS"); accpass=v.Get("ACCPASS");
exitonerror=(bool)atoi(v.Get("EXITONERROR").c_str()); exitonerror=(bool)atoi(v.Get("EXITONERROR").c_str());
reconnect=(bool)atoi(v.Get("RECONNECT").c_str());
realmport=atoi(v.Get("REALMPORT").c_str()); realmport=atoi(v.Get("REALMPORT").c_str());
clientversion_string=v.Get("CLIENTVERSION"); clientversion_string=v.Get("CLIENTVERSION");
clientbuild=atoi(v.Get("CLIENTBUILD").c_str()); clientbuild=atoi(v.Get("CLIENTBUILD").c_str());

View File

@ -26,6 +26,7 @@ class PseuInstanceConf
std::string accname; std::string accname;
std::string accpass; std::string accpass;
bool exitonerror; bool exitonerror;
bool reconnect;
uint16 realmport; uint16 realmport;
uint16 worldport; uint16 worldport;
uint8 clientversion[3]; uint8 clientversion[3];
@ -84,6 +85,7 @@ class PseuInstance
std::string _confdir,_scpdir; std::string _confdir,_scpdir;
bool _initialized; bool _initialized;
bool _stop,_fastquit; bool _stop,_fastquit;
bool _startrealm;
BigNumber _sessionkey; BigNumber _sessionkey;
char *_ver,*_ver_short; char *_ver,*_ver_short;
SocketHandler _sh; SocketHandler _sh;

View File

@ -5,6 +5,7 @@
#define _REALMSOCKET_H #define _REALMSOCKET_H
#include "Network/ResolvSocket.h" #include "Network/ResolvSocket.h"
#include "PseuWoW.h"
class RealmSocket : public TcpSocket class RealmSocket : public TcpSocket
{ {

View File

@ -44,7 +44,7 @@ bool PlayerNameCache::SaveToFile(void){
fh.open(fn, std::ios_base::out | std::ios_base::binary); fh.open(fn, std::ios_base::out | std::ios_base::binary);
if(!fh) if(!fh)
{ {
printf("ERROR: could not open file '%s'!\n",fn); printf("ERROR: could not write to file '%s'!\n",fn);
return false; return false;
} }
uint32 size=_cache.size(); uint32 size=_cache.size();

View File

@ -6,10 +6,11 @@
#include "Opcodes.h" #include "Opcodes.h"
#include "WorldPacket.h" #include "WorldPacket.h"
#include "WorldSocket.h" #include "WorldSocket.h"
#include "WorldSession.h"
#include "NameTables.h" #include "NameTables.h"
#include "RealmSocket.h" #include "RealmSocket.h"
#include "WorldSession.h"
WorldSession::WorldSession(PseuInstance *in) WorldSession::WorldSession(PseuInstance *in)
{ {
@ -20,6 +21,7 @@ WorldSession::WorldSession(PseuInstance *in)
_followGUID=0; // dont follow anything _followGUID=0; // dont follow anything
_myGUID=0; // i dont have a guid yet _myGUID=0; // i dont have a guid yet
plrNameCache.ReadFromFile(); // load names/guids of known players plrNameCache.ReadFromFile(); // load names/guids of known players
_deleteme = false;
//... //...
} }
@ -32,6 +34,8 @@ WorldSession::~WorldSession()
packet = pktQueue.next(); packet = pktQueue.next();
delete packet; delete packet;
} }
_OnLeaveWorld();
//delete _socket; the socket will be deleted by its handler!! //delete _socket; the socket will be deleted by its handler!!
} }
@ -46,10 +50,19 @@ void WorldSession::Start(void)
_sh.Select(1,0); _sh.Select(1,0);
} }
bool WorldSession::DeleteMe(void)
{
return _deleteme;
}
void WorldSession::SetSocket(WorldSocket *sock)
{
_socket = sock;
}
void WorldSession::AddToPktQueue(WorldPacket *pkt) void WorldSession::AddToPktQueue(WorldPacket *pkt)
{ {
pktQueue.add(pkt); pktQueue.add(pkt);
printf("-- Added Packet to queue, size is now %u\n",pktQueue.size());
} }
void WorldSession::SendWorldPacket(WorldPacket &pkt) void WorldSession::SendWorldPacket(WorldPacket &pkt)
@ -61,15 +74,26 @@ void WorldSession::Update(void)
{ {
if (!IsValid()) if (!IsValid())
return; return;
if(_sh.GetCount())
if( _socket && _sh.GetCount() )
_sh.Select(0,0); _sh.Select(0,0);
if(!_socket)
{
if(_valid)
{
_deleteme = true;
}
_logged=_authed=_valid=false;
return;
}
OpcodeHandler *table = _GetOpcodeHandlerTable(); OpcodeHandler *table = _GetOpcodeHandlerTable();
bool known=false; bool known=false;
while(!pktQueue.empty()) while(!pktQueue.empty())
{ {
WorldPacket *packet = pktQueue.next(); WorldPacket *packet = pktQueue.next();
printf("QUEUE: %u packets left\n",pktQueue.size());
printf(">> Opcode %u [%s]\n",packet->GetOpcode(),LookupName(packet->GetOpcode(),g_worldOpcodeNames)); printf(">> Opcode %u [%s]\n",packet->GetOpcode(),LookupName(packet->GetOpcode(),g_worldOpcodeNames));
for (uint16 i = 0; table[i].handler != NULL; i++) for (uint16 i = 0; table[i].handler != NULL; i++)
@ -86,7 +110,9 @@ void WorldSession::Update(void)
delete packet; delete packet;
} }
// do more stuff here
_DoTimedActions();
} }
@ -139,12 +165,36 @@ void WorldSession::SetFollowTarget(uint64 guid)
_followGUID=guid; _followGUID=guid;
} }
void WorldSession::OnEnterWorld(void) void WorldSession::_OnEnterWorld(void)
{ {
if(!_logged) if(!_logged)
{ {
_logged=true; _logged=true;
//GetInstance()->GetScripts()->RunScriptByName("_enterworld",NULL,255); //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) void WorldSession::_HandleSetProficiencyOpcode(WorldPacket& recvPacket)
{ {
OnEnterWorld(); _OnEnterWorld();
} }
void WorldSession::_HandleAccountDataMD5Opcode(WorldPacket& recvPacket) void WorldSession::_HandleAccountDataMD5Opcode(WorldPacket& recvPacket)
{ {
OnEnterWorld(); _OnEnterWorld();
} }
void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket) void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)

View File

@ -6,11 +6,12 @@
#include "Network/SocketHandler.h" #include "Network/SocketHandler.h"
#include "common.h" #include "common.h"
#include "Player.h" #include "Player.h"
#include "../Auth/AuthCrypt.h" #include "Auth/AuthCrypt.h"
#include "SharedDefines.h" #include "SharedDefines.h"
class WorldSocket; class WorldSocket;
class WorldPacket; class WorldPacket;
class PingerThread;
struct OpcodeHandler struct OpcodeHandler
{ {
@ -30,11 +31,14 @@ public:
OpcodeHandler *_GetOpcodeHandlerTable(void) const; OpcodeHandler *_GetOpcodeHandlerTable(void) const;
void SetSocket(WorldSocket *sock);
void AddToPktQueue(WorldPacket *pkt); void AddToPktQueue(WorldPacket *pkt);
void Connect(std::string addr,uint16 port); void Connect(std::string addr,uint16 port);
void Update(void); void Update(void);
void Start(void); void Start(void);
bool IsValid(void) { return _valid; } bool IsValid(void) { return _valid; }
bool DeleteMe(void);
void SendWorldPacket(WorldPacket&); void SendWorldPacket(WorldPacket&);
void SetTarget(uint64 guid); void SetTarget(uint64 guid);
@ -55,7 +59,9 @@ public:
private: private:
// Helpers // Helpers
void OnEnterWorld(void); void _OnEnterWorld(void); // = login
void _OnLeaveWorld(void); // = logout
void _DoTimedActions(void);
// Opcode Handlers // Opcode Handlers
void _HandleAuthChallengeOpcode(WorldPacket& recvPacket); void _HandleAuthChallengeOpcode(WorldPacket& recvPacket);
@ -74,7 +80,7 @@ private:
PseuInstance *_instance; PseuInstance *_instance;
WorldSocket *_socket; WorldSocket *_socket;
ZThread::LockedQueue<WorldPacket*,ZThread::FastMutex> pktQueue; ZThread::LockedQueue<WorldPacket*,ZThread::FastMutex> pktQueue;
bool _valid,_authed,_logged; // world status bool _valid,_authed,_logged,_deleteme; // world status
SocketHandler _sh; // handles the WorldSocket SocketHandler _sh; // handles the WorldSocket
uint64 _targetGUID,_followGUID,_myGUID; uint64 _targetGUID,_followGUID,_myGUID;

View File

@ -20,75 +20,79 @@ void WorldSocket::OnConnectFailed()
printf("WorldSocket::OnConnectFailed()\n"); printf("WorldSocket::OnConnectFailed()\n");
} }
void WorldSocket::OnDelete()
{
printf("Connection to world server has been closed.\n");
if(_session)
_session->SetSocket(NULL);
}
void WorldSocket::OnRead() void WorldSocket::OnRead()
{ {
TcpSocket::OnRead(); TcpSocket::OnRead();
uint32 len = ibuf.GetLength(); uint32 len = ibuf.GetLength();
printf("WorldSocket::OnRead() %u bytes\n",len); //printf("WorldSocket::OnRead() %u bytes\n",len);
if(!len) if(!len)
{
this->CloseAndDelete();
return; return;
}
uint8 *buf=new uint8[len]; uint8 *buf=new uint8[len];
ibuf.Read((char*)buf,len); ibuf.Read((char*)buf,len);
ByteBuffer bb; uint32 offset=0; // to skip data already read
bb.append(buf,len);
// bb.hexlike();
uint32 offset=0;
while(len > 0) // when all packets from the current ibuf are transformed into WorldPackets the remaining len will be zero
// 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)
{ {
if(_gothdr) // already got header, this packet has to be the data part if(_gothdr) // already got header, this packet has to be the data part
{ {
_gothdr=false; _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; WorldPacket *wp = new WorldPacket;
wp->append(buf+offset,_remaining); wp->append(buf+offset,_remaining);
wp->SetOpcode(_opcode); wp->SetOpcode(_opcode);
GetSession()->AddToPktQueue(wp); GetSession()->AddToPktQueue(wp);
offset += _remaining; // skip the data already used 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 else // no pending header stored, so this packet must be a header
{ {
printf("WP: Fetched header (%u bytes)\n",len);
ServerPktHeader hdr; ServerPktHeader hdr;
memcpy(&hdr,buf+offset,sizeof(ServerPktHeader)); memcpy(&hdr,buf+offset,sizeof(ServerPktHeader));
_crypt.DecryptRecv((uint8*)&hdr,sizeof(ServerPktHeader)); _crypt.DecryptRecv((uint8*)&hdr,sizeof(ServerPktHeader));
_remaining = ntohs(hdr.size)-2; _remaining = ntohs(hdr.size)-2;
_opcode = hdr.cmd; _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 // 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; WorldPacket *wp = new WorldPacket;
wp->SetOpcode(_opcode); wp->SetOpcode(_opcode);
GetSession()->AddToPktQueue(wp); GetSession()->AddToPktQueue(wp);
offset += 4 ; // skip the data already used 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 _gothdr=true; // only got the header, next packet wil contain the data
offset += 4 ; // skip the data already used 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) void WorldSocket::SendWorldPacket(WorldPacket &pkt)

View File

@ -28,6 +28,7 @@ public:
void OnRead(); void OnRead();
void OnConnect(); void OnConnect();
void OnConnectFailed(); void OnConnectFailed();
void OnDelete();
void SendWorldPacket(WorldPacket &pkt); void SendWorldPacket(WorldPacket &pkt);
void InitCrypt(uint8*,uint32); void InitCrypt(uint8*,uint32);
@ -36,9 +37,8 @@ private:
WorldSession *_session; WorldSession *_session;
AuthCrypt _crypt; AuthCrypt _crypt;
bool _gothdr; // true if only the header was recieved yet bool _gothdr; // true if only the header was recieved yet
ByteBuffer _hdr; uint16 _opcode; // stores the last recieved opcode
uint16 _opcode; uint16 _remaining; // bytes amount of the next data packet
uint16 _remaining;
}; };