bool Buffer::DeserializeToMessage( ::google::protobuf::Message *message, uint32 length) { bool result = message->ParseFromArray(read_content(), length); ReadSkip(length); return result; }
bool WorldSocket::ProcessIncomingData() { ClientPktHeader header; if (m_useExistingHeader) { m_useExistingHeader = false; header = m_existingHeader; ReadSkip(sizeof(ClientPktHeader)); } else { if (!Read((char *)&header, sizeof(ClientPktHeader))) { errno = EBADMSG; return false; } m_crypt.DecryptRecv((uint8 *)&header, sizeof(ClientPktHeader)); EndianConvertReverse(header.size); EndianConvert(header.cmd); } // there must always be at least four bytes for the opcode, // and 0x2800 is the largest supported buffer in the client if ((header.size < 4) || (header.size > 0x2800) || (header.cmd >= NUM_MSG_TYPES)) { sLog.outError("WorldSocket::ProcessIncomingData: client sent malformed packet size = %u , cmd = %u", header.size, header.cmd); errno = EINVAL; return false; } // the minus four is because we've already read the four byte opcode value const uint16 validBytesRemaining = header.size - 4; // check if the client has told us that there is more data than there is if (validBytesRemaining > ReadLengthRemaining()) { // we must preserve the decrypted header so as not to corrupt the crypto state, and to prevent duplicating work m_useExistingHeader = true; m_existingHeader = header; // we move the read pointer backward because it will be skipped again later. this is a slight kludge, but to solve // it more elegantly would require introducing protocol awareness into the socket library, which we want to avoid ReadSkip(-static_cast<int>(sizeof(ClientPktHeader))); errno = EBADMSG; return false; } Opcodes x; const OpcodesList opcode = static_cast<OpcodesList>(header.cmd); if (IsClosed()) return false; std::unique_ptr<WorldPacket> pct(new WorldPacket(opcode, validBytesRemaining)); if (validBytesRemaining) { pct->append(InPeak(), validBytesRemaining); ReadSkip(validBytesRemaining); } sLog.outWorldPacketDump(GetRemoteEndpoint().c_str(), pct->GetOpcode(), pct->GetOpcodeName(), *pct, true); try { switch (opcode) { case CMSG_AUTH_SESSION: if (m_session) { sLog.outError("WorldSocket::ProcessIncomingData: Player send CMSG_AUTH_SESSION again"); return false; } return HandleAuthSession(*pct); case CMSG_PING: return HandlePing(*pct); case CMSG_KEEP_ALIVE: DEBUG_LOG("CMSG_KEEP_ALIVE ,size: " SIZEFMTD " ", pct->size()); return true; default: { if (!m_session) { sLog.outError("WorldSocket::ProcessIncomingData: Client not authed opcode = %u", uint32(opcode)); return false; } m_session->QueuePacket(std::move(pct)); return true; } } } catch (ByteBufferException&) { sLog.outError("WorldSocket::ProcessIncomingData ByteBufferException occured while parsing an instant handled packet (opcode: %u) from client %s, accountid=%i.", opcode, GetRemoteAddress().c_str(), m_session ? m_session->GetAccountId() : -1); if (sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG)) { DEBUG_LOG("Dumping error-causing packet:"); pct->hexlike(); } if (sWorld.getConfig(CONFIG_BOOL_KICK_PLAYER_ON_BAD_PACKET)) { DETAIL_LOG("Disconnecting session [account id %i / address %s] for badly formatted packet.", m_session ? m_session->GetAccountId() : -1, GetRemoteAddress().c_str()); return false; } } return true; }