mojo_client/src/Client/World/WorldSocket.cpp
False.Genesis 01761191e1 misc stuff
2007-01-12 20:07:18 +00:00

121 lines
3.6 KiB
C++

#include "WorldPacket.h"
#include "WorldSession.h"
#include "WorldSocket.h"
WorldSocket::WorldSocket(SocketHandler &h, WorldSession *s) : TcpSocket(h)
{
_session = s;
_gothdr = false;
}
void WorldSocket::OnConnect()
{
printf("Connected to world server.\r\n");
}
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::OnException()
{
this->SetCloseAndDelete();
}
void WorldSocket::OnRead()
{
TcpSocket::OnRead();
uint32 len = ibuf.GetLength();
//printf("WorldSocket::OnRead() %u bytes\n",len);
if(!len)
{
this->CloseAndDelete();
return;
}
uint8 *buf=new uint8[len];
ibuf.Read((char*)buf,len);
uint32 offset=0; // to skip data already read
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;
WorldPacket *wp = new WorldPacket;
wp->append(buf+offset,_remaining);
wp->SetOpcode(_opcode);
GetSession()->AddToPktQueue(wp);
offset += _remaining; // skip the data already used
len -= _remaining; // and adjust the length
}
else // no pending header stored, so this packet must be a header
{
ServerPktHeader hdr;
memcpy(&hdr,buf+offset,sizeof(ServerPktHeader));
_crypt.DecryptRecv((uint8*)&hdr,sizeof(ServerPktHeader));
_remaining = ntohs(hdr.size)-2;
_opcode = hdr.cmd;
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) // this is a packet with no data (like CMSG_NULL_ACTION)
{
WorldPacket *wp = new WorldPacket;
wp->SetOpcode(_opcode);
GetSession()->AddToPktQueue(wp);
offset += 4 ; // skip the data already used
len -= 4; // and adjust the lentgh
}
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; // and adjust the lentgh
}
}
}
delete buf;
}
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();
}