Пример #1
0
void WorldSocket::OnRead()
{
    TcpSocket::OnRead();
    if(!ibuf.GetLength())
    {
        this->CloseAndDelete();
        return;
    }
    while(ibuf.GetLength() > 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
        {
            ASSERT(_remaining > 0); // case pktsize==0 is handled below
            if(ibuf.GetLength() < _remaining)
            {
                DEBUG(logdebug("Delaying WorldPacket generation, bufsize is %u but should be >= %u",ibuf.GetLength(),_remaining));
                break;
            }
            _gothdr=false;
            WorldPacket *wp = new WorldPacket(_remaining);
            wp->resize(_remaining);
            ibuf.Read((char*)wp->contents(),_remaining);
            wp->SetOpcode(_opcode);
            GetSession()->AddToPktQueue(wp);
        }
        else // no pending header stored, so this packet must be a header
        {
            if(ibuf.GetLength() < sizeof(ServerPktHeader))
            {
                DEBUG(logdebug("Delaying header reading, bufsize is %u but should be >= %u",ibuf.GetLength(),sizeof(ServerPktHeader)));
                break;
            }

            if(GetSession()->GetInstance()->GetConf()->client > CLIENT_TBC)//Funny, old sources have this in TBC already...
            {
              // read first byte and check if size is 3 or 2 bytes
              uint8 firstSizeByte;
              ibuf.Read((char*)&firstSizeByte, 1);
              (_crypt.*pDecryptRecv)(&firstSizeByte, 1);
              if (firstSizeByte & 0x80) // got large packet
              {
                  ServerPktHeaderBig hdr;
                  ibuf.Read(((char*)&hdr) + 1, sizeof(ServerPktHeaderBig) - 1); // read *big* header, except first byte
                  (_crypt.*pDecryptRecv)(((uint8*)&hdr) + 1, sizeof(ServerPktHeaderBig) - 1); // decrypt 2 of 3 bytes (first one already decrypted above) of size, and cmd
                  hdr.size[0] = firstSizeByte; // assign missing first byte

                  uint32 realsize = ((hdr.size[0]&0x7F) << 16) | (hdr.size[1] << 8) | hdr.size[2];
                  _remaining = realsize - 2;
                  _opcode = hdr.cmd;
              }
              else // "normal" packet
              {
                  ServerPktHeader hdr;
                  ibuf.Read(((char*)&hdr) + 1, sizeof(ServerPktHeader) - 1); // read header, except first byte
                  (_crypt.*pDecryptRecv)(((uint8*)&hdr) + 1, sizeof(ServerPktHeader) - 1); // decrypt all except first
                  hdr.size |= firstSizeByte; // add already decrypted first byte

                  _remaining = ntohs(hdr.size) - 2;
                  _opcode = hdr.cmd;
              }
            }
            else
            {
              ServerPktHeader hdr;
              ibuf.Read(((char*)&hdr), sizeof(ServerPktHeader)); // read header
              (_crypt.*pDecryptRecv)(((uint8*)&hdr), sizeof(ServerPktHeader)); // decrypt all

              _remaining = ntohs(hdr.size) - 2;
              _opcode = hdr.cmd;

            }

            if(_opcode > MAX_OPCODE_ID)
            {
                logcritical("CRYPT ERROR: opcode=%u, remain=%u",_opcode,_remaining); // this should never be the case!
                GetSession()->GetInstance()->SetError(); // no way to recover the crypt, must exit
                // if the crypt gets messy its hardly possible to recover it, especially if we dont know
                // the length 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);
            }
            else // there is a data part to fetch
            {
                _gothdr=true; // only got the header, next packet will contain the data
            }
        }
    }
}
Пример #2
0
void _new_handler(void)
{
    logcritical("ERROR: Out of memory!");
    throw;
}