// // Packet.h // libraries/networking/src // // Created by Clement on 7/2/15. // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #ifndef hifi_Packet_h #define hifi_Packet_h #include #include #include "HifiSockAddr.h" #include "PacketHeaders.h" class Packet : public QIODevice { Q_OBJECT public: using SequenceNumber = uint16_t; static std::unique_ptr create(PacketType::Value type, qint64 size = -1); static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); // Provided for convenience, try to limit use static std::unique_ptr createCopy(const Packet& other); static qint64 localHeaderSize(PacketType::Value type); static qint64 maxPayloadSize(PacketType::Value type); virtual qint64 totalHeadersSize() const; // Cumulated size of all the headers virtual qint64 localHeaderSize() const; // Current level's header size // Payload direct access to the payload, use responsibly! char* getPayload() { return _payloadStart; } const char* getPayload() const { return _payloadStart; } // Return direct access to the entire packet, use responsibly! char* getData() { return _packet.get(); } const char* getData() const { return _packet.get(); } PacketType::Value getType() const { return _type; } void setType(PacketType::Value type); PacketVersion getVersion() const { return _version; } qint64 getSizeWithHeader() const { return localHeaderSize() + getSizeUsed(); } qint64 getSizeUsed() const { return _sizeUsed; } void setSizeUsed(qint64 sizeUsed) { _sizeUsed = sizeUsed; } HifiSockAddr& getSenderSockAddr() { return _senderSockAddr; } const HifiSockAddr& getSenderSockAddr() const { return _senderSockAddr; } SequenceNumber readSequenceNumber() const; bool readIsControlPacket() const; // QIODevice virtual functions // WARNING: Those methods all refer to the payload ONLY and NOT the entire packet virtual bool isSequential() const { return false; } virtual bool reset() { setSizeUsed(0); return QIODevice::reset(); } virtual qint64 size() const { return _capacity; } template qint64 peekPrimitive(T* data); template qint64 readPrimitive(T* data); template qint64 writePrimitive(const T& data); protected: Packet(PacketType::Value type, int64_t size); Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); Packet(const Packet& other); Packet& operator=(const Packet& other); Packet(Packet&& other); Packet& operator=(Packet&& other); // Header readers PacketType::Value readType() const; PacketVersion readVersion() const; // QIODevice virtual functions virtual qint64 writeData(const char* data, qint64 maxSize); virtual qint64 readData(char* data, qint64 maxSize); // Header writers void writePacketTypeAndVersion(PacketType::Value type); void writeSequenceNumber(SequenceNumber seqNum); PacketType::Value _type; // Packet type PacketVersion _version; // Packet version qint64 _packetSize = 0; // Total size of the allocated memory std::unique_ptr _packet; // Allocated memory char* _payloadStart = nullptr; // Start of the payload qint64 _capacity = 0; // Total capacity of the payload qint64 _sizeUsed = 0; // How much of the payload is actually used HifiSockAddr _senderSockAddr; // sender address for packet (only used on receiving end) }; template qint64 Packet::peekPrimitive(T* data) { return QIODevice::peek(reinterpret_cast(data), sizeof(T)); } template qint64 Packet::readPrimitive(T* data) { return QIODevice::read(reinterpret_cast(data), sizeof(T)); } template qint64 Packet::writePrimitive(const T& data) { static_assert(!std::is_pointer::value, "T must not be a pointer"); return QIODevice::write(reinterpret_cast(&data), sizeof(T)); } #endif // hifi_Packet_h