void FifoReadCallback::forwardMessage(const PacketHeader& header, std::unique_ptr<folly::IOBuf>&& buf) { auto data = buf->coalesce(); CHECK(data.size() == header.packetSize()) << "Invalid header buffer size!"; messageReady_(header.connectionId(), header.packetId(), std::move(from_), std::move(to_), data); }
void FifoReadCallback::feedParser(const PacketHeader& header, std::unique_ptr<folly::IOBuf>&& buf) { auto bodyBuf = buf->coalesce(); CHECK(bodyBuf.size() == header.packetSize()) << "Invalid header buffer size!"; auto& parser = parserMap_.fetch(header.msgId()).parser(); if (header.packetId() == 0) { parser.reset(); } parser.parse(bodyBuf); }
void FifoReadCallback::forwardMessage(const PacketHeader& header, std::unique_ptr<folly::IOBuf> buf) { auto data = buf->coalesce(); CHECK(data.size() == header.packetSize()) << "Invalid header buffer size!"; if (typeId_ != 0) { messageReady_(header.connectionId(), header.packetId(), std::move(from_), std::move(to_), typeId_, msgStartTime_, data); typeId_ = 0; } else { VLOG(2) << "Type id is 0. Skipping message."; } }
Status ConnectionOut::sendPacketWithHeader(Packet& p, PacketHeader h){ assert(&p != &buffer); do { size_t n = std::min(p.remaining(), NRG_MAX_PACKET_SIZE - PacketHeader::size); if(p.remaining() > NRG_MAX_PACKET_SIZE - PacketHeader::size){ h.flags |= PKTFLAG_CONTINUED; } h.write(buffer.reset()); buffer.writeArray(p.getPointer(), n); if(cc.transform) cc.transform->apply(buffer, buffer2.reset()); Packet& sendme = cc.transform ? buffer2 : buffer; last_status = sock.sendPacket(sendme, remote_addr); if(!last_status){ return last_status; } p.seek(n, SEEK_CUR); ++h.frag_index; } while(p.remaining()); return last_status = StatusOK(); }
void Battlenet::Session::ReadHandler() { BitStream stream(std::move(GetReadBuffer())); _crypt.DecryptRecv(stream.GetBuffer(), stream.GetSize()); while (!stream.IsRead()) { try { PacketHeader header; header.Opcode = stream.Read<uint32>(6); if (stream.Read<bool>(1)) header.Channel = stream.Read<int32>(4); if (header.Channel != AUTHENTICATION && (header.Channel != CONNECTION || header.Opcode != Connection::CMSG_PING) && !_authed) { TC_LOG_DEBUG("session.packets", "%s Received not allowed %s. Client has not authed yet.", GetClientInfo().c_str(), header.ToString().c_str()); CloseSocket(); return; } if (ClientPacket* packet = sPacketManager.CreateClientPacket(header, stream)) { if (sPacketManager.IsHandled(header)) TC_LOG_DEBUG("session.packets", "%s Received %s", GetClientInfo().c_str(), PacketToStringHelper(packet).c_str()); packet->CallHandler(this); delete packet; } else if (sPacketManager.GetClientPacketName(header)) { LogUnhandledPacket(header); break; } else { TC_LOG_DEBUG("session.packets", "%s Received unknown %s", GetClientInfo().c_str(), header.ToString().c_str()); break; } stream.AlignToNextByte(); } catch (BitStreamPositionException const& e) { TC_LOG_ERROR("session.packets", "%s Exception thrown during packet processing %s", GetClientInfo().c_str(), e.what()); CloseSocket(); return; } } GetReadBuffer().Resize(size_t(BufferSizes::Read)); AsyncRead(); }
// Reads a key data from a stream PIStream &Key::operator<<(PIStream &in) { // Read packet header PacketHeader header; in >> header; if (!header.valid()) { throw "Invalid packet header"; } if (header.type() != PacketHeader::TYPE_SECRET_KEY) { throw Utils::strprintf("Invalid packet type %d (not a secret key)", header.type()); } uint32_t headerOff = in.pos(); // Read public key in >> m_version; if (m_version < 2 || 4 < m_version) { throw Utils::strprintf("Unspported key version %d", m_version); } in >> m_time; if (m_version < 4) { in >> m_expire; }
bool ConnectionIn::addPacket(Packet& p){ PacketHeader h; if(cc.transform){ if(!cc.transform->remove(p, buffer.reset())){ return false; // removal of packet transformation failed. } } Packet& input = cc.transform ? buffer : p; if(!h.read(input) || h.version != 0){ return false; // packet has invalid header / unknown version. } int packet_age = 0; if(packet_history.none()){ // first packet recieved cc.seq_num = h.seq_num; packet_history[0] = 1; } else { int16_t seq_dist = static_cast<int16_t>(h.seq_num - cc.seq_num); if(abs(seq_dist) >= NRG_CONN_PACKET_HISTORY){ return true; // packet is out of history range. } // states need to know about retransmissons of the newest packet if(seq_dist < 0 && (h.flags & PKTFLAG_RETRANSMISSION)){ return true; } if(seq_dist > 0){ // new packet packet_history <<= seq_dist; packet_history[0] = 1; cc.seq_num = h.seq_num; // update ages of reassembly fragments and remove them if they're too old. for(auto& i : reassembly_buf){ if(i.age >= 0) i.age += seq_dist; if(i.age > (int)NRG_CONN_PACKET_HISTORY){ i.age = -1; i.data.reset(); } } } else { if(packet_history[-seq_dist]){ // already recieved this packet. return true; } else { packet_history[-seq_dist] = 1; packet_age = -seq_dist; } } } if((h.flags & PKTFLAG_FINISHED) && (cc.seq_num != h.seq_num)){ return false; // packet claims end of stream, but there is a newer one... } new_packet = true; // reconstruct packets that were split into multiple fragments. if(h.frag_index > 0 || (h.flags & PKTFLAG_CONTINUED)){ if(h.frag_index >= reassembly_buf.size()){ return false; } ReassemblyInfo& frag = reassembly_buf[h.frag_index]; if(frag.age >= 0 && packet_age > frag.age){ new_packet = false; } else { frag.data.writeArray(input.getPointer(), input.remaining()); frag.age = packet_age; frag.continued = h.flags & PKTFLAG_CONTINUED; // check if the newly added fragment completes a full packet. for(size_t i = 0; i < reassembly_buf.size(); ++i){ NRG_DEBUG("Age calc: [%d, %d]\n", (int)i, reassembly_buf[i].age); if(reassembly_buf[i].age == -1 || (i > 0 && reassembly_buf[i].age != reassembly_buf[i-1].age - 1)){ new_packet = false; } if(!reassembly_buf[i].continued) break; } NRG_DEBUG("Got fragment, idx: %d, continued?: %d, age: %d full?: %d\n", h.frag_index, h.flags & PKTFLAG_CONTINUED, packet_age, new_packet ); // write all the fragments out if they do form a full packet. if(new_packet){ latest.reset(); int age_counter = reassembly_buf[0].age; for(auto& i : reassembly_buf){ if(i.age != age_counter--) break; latest.writeArray(i.data.getBasePointer(), i.data.size()); i.data.reset(); i.age = -1; } } } } else { latest.reset().writeArray(input.getPointer(), input.remaining()); } if(cc.seq_num > h.seq_num) h.flags |= PKTFLAG_OUT_OF_ORDER; latest_flags = static_cast<PacketFlags>(h.flags); return true; }