fixed logging to world + experimental pkt decrypt
This commit is contained in:
parent
1cfddad5b6
commit
8add84b129
@ -31,7 +31,6 @@ public:
|
|||||||
void _HandleLogonChallenge(void);
|
void _HandleLogonChallenge(void);
|
||||||
|
|
||||||
void OnRead(void);
|
void OnRead(void);
|
||||||
//void OnAccept(void);
|
|
||||||
void OnConnect(void);
|
void OnConnect(void);
|
||||||
void OnConnectFailed(void);
|
void OnConnectFailed(void);
|
||||||
|
|
||||||
|
|||||||
@ -11,27 +11,11 @@
|
|||||||
#include "RealmSocket.h"
|
#include "RealmSocket.h"
|
||||||
|
|
||||||
|
|
||||||
struct ClientPktHeader
|
|
||||||
{
|
|
||||||
uint16 size;
|
|
||||||
uint16 cmd;
|
|
||||||
uint16 nil;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ServerPktHeader
|
|
||||||
{
|
|
||||||
uint16 size;
|
|
||||||
uint16 cmd;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
WorldSession::WorldSession(PseuInstance *in)
|
WorldSession::WorldSession(PseuInstance *in)
|
||||||
{
|
{
|
||||||
_instance = in;
|
_instance = in;
|
||||||
_valid=_authed=_logged=false;
|
_valid=_authed=_logged=false;
|
||||||
_socket=new WorldSocket(_sh,this);
|
_socket=new WorldSocket(_sh,this);
|
||||||
_socket->SetDeleteByHandler();
|
|
||||||
_sh.Add(_socket);
|
|
||||||
_targetGUID=0; // no target
|
_targetGUID=0; // no target
|
||||||
_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
|
||||||
@ -41,33 +25,36 @@ WorldSession::WorldSession(PseuInstance *in)
|
|||||||
|
|
||||||
WorldSession::~WorldSession()
|
WorldSession::~WorldSession()
|
||||||
{
|
{
|
||||||
|
WorldPacket *packet;
|
||||||
|
// clear the queue
|
||||||
|
while(!pktQueue.empty())
|
||||||
|
{
|
||||||
|
packet = pktQueue.next();
|
||||||
|
delete packet;
|
||||||
|
}
|
||||||
//delete _socket; the socket will be deleted by its handler!!
|
//delete _socket; the socket will be deleted by its handler!!
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::Start(void)
|
void WorldSession::Start(void)
|
||||||
{
|
{
|
||||||
|
printf("Connecting to '%s' on port %u\n",GetInstance()->GetConf()->worldhost.c_str(),GetInstance()->GetConf()->worldport);
|
||||||
_socket->Open(GetInstance()->GetConf()->worldhost,GetInstance()->GetConf()->worldport);
|
_socket->Open(GetInstance()->GetConf()->worldhost,GetInstance()->GetConf()->worldport);
|
||||||
GetInstance()->GetRSession()->SetCloseAndDelete(); // realm socket is no longer needed
|
GetInstance()->GetRSession()->SetCloseAndDelete(); // realm socket is no longer needed
|
||||||
_valid=true;
|
_valid=true;
|
||||||
|
_sh.Add(_socket);
|
||||||
|
_socket->SetDeleteByHandler();
|
||||||
|
_sh.Select(1,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::AddToDataQueue(uint8 *data, uint32 len)
|
void WorldSession::AddToPktQueue(WorldPacket *pkt)
|
||||||
{
|
{
|
||||||
for (uint32 i=0;i<len;i++)
|
pktQueue.add(pkt);
|
||||||
pktQueue.push_back(data[i]);
|
printf("-- Added Packet to queue, size is now %u\n",pktQueue.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::SendWorldPacket(WorldPacket &pkt)
|
void WorldSession::SendWorldPacket(WorldPacket &pkt)
|
||||||
{
|
{
|
||||||
ClientPktHeader hdr;
|
_socket->SendWorldPacket(pkt);
|
||||||
memset(&hdr,0,sizeof(ClientPktHeader));
|
|
||||||
hdr.size = ntohs(pkt.size()+4);
|
|
||||||
hdr.cmd = pkt.GetOpcode();
|
|
||||||
_crypt.EncryptSend((uint8*)&hdr, 6);
|
|
||||||
ByteBuffer final(pkt.size()+6);
|
|
||||||
final.append((uint8*)&hdr,sizeof(ClientPktHeader));
|
|
||||||
final.append(pkt.contents(),pkt.size());
|
|
||||||
_socket->SendBuf((char*)final.contents(),final.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::Update(void)
|
void WorldSession::Update(void)
|
||||||
@ -76,42 +63,32 @@ void WorldSession::Update(void)
|
|||||||
return;
|
return;
|
||||||
if(_sh.GetCount())
|
if(_sh.GetCount())
|
||||||
_sh.Select(0,0);
|
_sh.Select(0,0);
|
||||||
WorldPacket packet;
|
|
||||||
OpcodeHandler *table = _GetOpcodeHandlerTable();
|
OpcodeHandler *table = _GetOpcodeHandlerTable();
|
||||||
while(pktQueue.size()>5)
|
bool known=false;
|
||||||
|
while(!pktQueue.empty())
|
||||||
{
|
{
|
||||||
packet = BuildWorldPacket();
|
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++)
|
for (uint16 i = 0; table[i].handler != NULL; i++)
|
||||||
if (table[i].opcode == packet.GetOpcode())
|
{
|
||||||
(this->*table[i].handler)(packet);
|
if (table[i].opcode == packet->GetOpcode())
|
||||||
|
{
|
||||||
|
(this->*table[i].handler)(*packet);
|
||||||
|
known=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if(!known)
|
||||||
|
|
||||||
packet.clear();
|
|
||||||
|
delete packet;
|
||||||
}
|
}
|
||||||
// do more stuff here
|
// do more stuff here
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldPacket WorldSession::BuildWorldPacket(void)
|
|
||||||
{
|
|
||||||
ServerPktHeader hdr;
|
|
||||||
WorldPacket wp;
|
|
||||||
uint16 _remaining;
|
|
||||||
for (uint8 i=0;i<sizeof(ServerPktHeader);i++)
|
|
||||||
{
|
|
||||||
((uint8*)&hdr)[i] = pktQueue.front();
|
|
||||||
pktQueue.pop_front();
|
|
||||||
}
|
|
||||||
_crypt.DecryptRecv((uint8*)&hdr,sizeof(ServerPktHeader));
|
|
||||||
_remaining = ntohs(hdr.size)-2;
|
|
||||||
wp.SetOpcode(hdr.cmd);
|
|
||||||
for (uint16 i=0;i<_remaining;i++)
|
|
||||||
{
|
|
||||||
wp << pktQueue.front();
|
|
||||||
pktQueue.pop_front();
|
|
||||||
}
|
|
||||||
return wp;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
OpcodeHandler *WorldSession::_GetOpcodeHandlerTable() const
|
OpcodeHandler *WorldSession::_GetOpcodeHandlerTable() const
|
||||||
{
|
{
|
||||||
@ -167,7 +144,7 @@ void WorldSession::OnEnterWorld(void)
|
|||||||
if(!_logged)
|
if(!_logged)
|
||||||
{
|
{
|
||||||
_logged=true;
|
_logged=true;
|
||||||
GetInstance()->GetScripts()->RunScriptByName("_enterworld",NULL,255);
|
//GetInstance()->GetScripts()->RunScriptByName("_enterworld",NULL,255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +159,7 @@ void WorldSession::_HandleAuthChallengeOpcode(WorldPacket& recvPacket)
|
|||||||
std::string acc = stringToUpper(GetInstance()->GetConf()->accname);
|
std::string acc = stringToUpper(GetInstance()->GetConf()->accname);
|
||||||
uint32 serverseed;
|
uint32 serverseed;
|
||||||
recvPacket >> serverseed;
|
recvPacket >> serverseed;
|
||||||
//DEBUG3(printf("W:auth: serverseed=0x%X\n",serverseed);)
|
printf("W:auth: serverseed=0x%X\n",serverseed);
|
||||||
Sha1Hash digest;
|
Sha1Hash digest;
|
||||||
digest.UpdateData(acc);
|
digest.UpdateData(acc);
|
||||||
uint32 unk=0;
|
uint32 unk=0;
|
||||||
@ -207,10 +184,13 @@ void WorldSession::_HandleAuthChallengeOpcode(WorldPacket& recvPacket)
|
|||||||
// printf("CMSG_AUTH_SESSION=");
|
// printf("CMSG_AUTH_SESSION=");
|
||||||
// printchex((char*)outpkt.contents(),outpkt.size(),true);
|
// printchex((char*)outpkt.contents(),outpkt.size(),true);
|
||||||
//)
|
//)
|
||||||
SendWorldPacket(auth);
|
SendWorldPacket(auth);
|
||||||
_crypt.SetKey(GetInstance()->GetSessionKey().AsByteArray(), 40);
|
|
||||||
_crypt.Init();
|
// note that if the sessionkey/auth is wrong or failed, the server sends the following packet UNENCRYPTED!
|
||||||
_authed=true;
|
// so its not 100% correct to init the crypt here, but it should do the job if authing was correct
|
||||||
|
_socket->InitCrypt(GetInstance()->GetSessionKey().AsByteArray(), 40);
|
||||||
|
|
||||||
|
_authed=true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,9 +30,8 @@ public:
|
|||||||
|
|
||||||
OpcodeHandler *_GetOpcodeHandlerTable(void) const;
|
OpcodeHandler *_GetOpcodeHandlerTable(void) const;
|
||||||
|
|
||||||
void AddToDataQueue(uint8*, uint32);
|
void AddToPktQueue(WorldPacket *pkt);
|
||||||
void Connect(std::string addr,uint16 port);
|
void Connect(std::string addr,uint16 port);
|
||||||
WorldPacket BuildWorldPacket(void);
|
|
||||||
void Update(void);
|
void Update(void);
|
||||||
void Start(void);
|
void Start(void);
|
||||||
bool IsValid(void) { return _valid; }
|
bool IsValid(void) { return _valid; }
|
||||||
@ -73,9 +72,8 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
PseuInstance *_instance;
|
PseuInstance *_instance;
|
||||||
AuthCrypt _crypt;
|
|
||||||
WorldSocket *_socket;
|
WorldSocket *_socket;
|
||||||
std::deque<uint8> pktQueue;
|
ZThread::LockedQueue<WorldPacket*,ZThread::FastMutex> pktQueue;
|
||||||
bool _valid,_authed,_logged; // world status
|
bool _valid,_authed,_logged; // world status
|
||||||
SocketHandler _sh; // handles the WorldSocket
|
SocketHandler _sh; // handles the WorldSocket
|
||||||
uint64 _targetGUID,_followGUID,_myGUID;
|
uint64 _targetGUID,_followGUID,_myGUID;
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
WorldSocket::WorldSocket(SocketHandler &h, WorldSession *s) : TcpSocket(h)
|
WorldSocket::WorldSocket(SocketHandler &h, WorldSession *s) : TcpSocket(h)
|
||||||
{
|
{
|
||||||
_session = s;
|
_session = s;
|
||||||
|
_gothdr = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -22,11 +23,120 @@ void WorldSocket::OnConnectFailed()
|
|||||||
void WorldSocket::OnRead()
|
void WorldSocket::OnRead()
|
||||||
{
|
{
|
||||||
TcpSocket::OnRead();
|
TcpSocket::OnRead();
|
||||||
printf("WorldSocket::OnRead() %u bytes\n",ibuf.GetLength());
|
uint32 len = ibuf.GetLength();
|
||||||
if(!ibuf.GetLength())
|
printf("WorldSocket::OnRead() %u bytes\n",len);
|
||||||
|
if(!len)
|
||||||
return;
|
return;
|
||||||
uint8 *buf=new uint8[ibuf.GetLength()];
|
|
||||||
ibuf.Read((char*)buf,ibuf.GetLength());
|
uint8 *buf=new uint8[len];
|
||||||
GetSession()->AddToDataQueue(buf,ibuf.GetLength());
|
ibuf.Read((char*)buf,len);
|
||||||
|
|
||||||
|
ByteBuffer bb;
|
||||||
|
bb.append(buf,len);
|
||||||
|
bb.hexlike();
|
||||||
|
|
||||||
|
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(true)
|
||||||
|
{
|
||||||
|
|
||||||
|
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: Building complete WorldPacket with opcode %u\n",_opcode);
|
||||||
|
WorldPacket *wp = new WorldPacket;
|
||||||
|
wp->append(buf+offset,len);
|
||||||
|
wp->SetOpcode(_opcode);
|
||||||
|
GetSession()->AddToPktQueue(wp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else // no pending header stored, so this packet must be a header
|
||||||
|
{
|
||||||
|
printf("WP: Got 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);
|
||||||
|
|
||||||
|
// the header is fine, now check if there are more data
|
||||||
|
if(_remaining == 0)
|
||||||
|
{
|
||||||
|
printf("WP: Got header-only Packet, building WorldPacket\n");
|
||||||
|
WorldPacket *wp = new WorldPacket;
|
||||||
|
wp->SetOpcode(_opcode);
|
||||||
|
GetSession()->AddToPktQueue(wp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if( _remaining && len-4==0 )
|
||||||
|
{
|
||||||
|
printf("WP: Got ONLY a header, waiting for data...\n");
|
||||||
|
_gothdr=true; // only got the header, next packet wil contain the data
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else // if the packet is bigger then 4 bytes, header & packet are merged
|
||||||
|
{
|
||||||
|
if( (len - sizeof(ServerPktHeader)) == _remaining )
|
||||||
|
{
|
||||||
|
printf("WP: Got merged Packet, building WorldPacket\n");
|
||||||
|
WorldPacket *wp = new WorldPacket;
|
||||||
|
wp->append(buf+4+offset,_remaining); // skip first 4 bytes (header)
|
||||||
|
wp->SetOpcode(_opcode);
|
||||||
|
GetSession()->AddToPktQueue(wp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if ( (len - sizeof(ServerPktHeader)) < _remaining )
|
||||||
|
{
|
||||||
|
printf("WP: Got too small merged packet (total=%u, data=%u)\n",len,_remaining);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if( (len - sizeof(ServerPktHeader)) > _remaining)
|
||||||
|
{
|
||||||
|
WorldPacket *wp = new WorldPacket;
|
||||||
|
wp->append(buf+4+offset,_remaining); // skip first 4 bytes (header)
|
||||||
|
wp->SetOpcode(_opcode);
|
||||||
|
GetSession()->AddToPktQueue(wp);
|
||||||
|
|
||||||
|
offset += (4 + _remaining); // skip the header & the data already used
|
||||||
|
len -= (4 + _remaining);
|
||||||
|
printf("WP: Got too big merged packet, new offset=%u, new len=%u, reading more data..\n",offset,len);
|
||||||
|
|
||||||
|
if(len <= 0)
|
||||||
|
break; // all data done
|
||||||
|
else
|
||||||
|
continue; // read next part
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delete buf; // UNSURE: delete or delete[]
|
delete buf; // UNSURE: delete or delete[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldSocket::SendWorldPacket(WorldPacket &pkt)
|
||||||
|
{
|
||||||
|
ClientPktHeader hdr;
|
||||||
|
memset(&hdr,0,sizeof(ClientPktHeader));
|
||||||
|
hdr.size = ntohs(pkt.size()+4);
|
||||||
|
hdr.cmd = pkt.GetOpcode();
|
||||||
|
_crypt.EncryptSend((uint8*)&hdr, 6);
|
||||||
|
ByteBuffer final(pkt.size()+6);
|
||||||
|
final.append((uint8*)&hdr,sizeof(ClientPktHeader));
|
||||||
|
final.append(pkt.contents(),pkt.size());
|
||||||
|
SendBuf((char*)final.contents(),final.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldSocket::InitCrypt(uint8 *key,uint32 len)
|
||||||
|
{
|
||||||
|
_crypt.SetKey(key,len);
|
||||||
|
_crypt.Init();
|
||||||
|
}
|
||||||
|
|||||||
@ -6,6 +6,19 @@
|
|||||||
|
|
||||||
class WorldSession;
|
class WorldSession;
|
||||||
|
|
||||||
|
struct ClientPktHeader
|
||||||
|
{
|
||||||
|
uint16 size;
|
||||||
|
uint16 cmd;
|
||||||
|
uint16 nil;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerPktHeader
|
||||||
|
{
|
||||||
|
uint16 size;
|
||||||
|
uint16 cmd;
|
||||||
|
};
|
||||||
|
|
||||||
class WorldSocket : public TcpSocket
|
class WorldSocket : public TcpSocket
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -16,8 +29,16 @@ public:
|
|||||||
void OnConnect();
|
void OnConnect();
|
||||||
void OnConnectFailed();
|
void OnConnectFailed();
|
||||||
|
|
||||||
|
void SendWorldPacket(WorldPacket &pkt);
|
||||||
|
void InitCrypt(uint8*,uint32);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WorldSession *_session;
|
WorldSession *_session;
|
||||||
|
AuthCrypt _crypt;
|
||||||
|
bool _gothdr; // true if only the header was recieved yet
|
||||||
|
ByteBuffer _hdr;
|
||||||
|
uint16 _opcode;
|
||||||
|
uint16 _remaining;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user