diff options
Diffstat (limited to 'include/SFML/Network/Packet.hpp')
-rw-r--r-- | include/SFML/Network/Packet.hpp | 532 |
1 files changed, 532 insertions, 0 deletions
diff --git a/include/SFML/Network/Packet.hpp b/include/SFML/Network/Packet.hpp new file mode 100644 index 0000000..9f0edab --- /dev/null +++ b/include/SFML/Network/Packet.hpp @@ -0,0 +1,532 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_PACKET_HPP +#define SFML_PACKET_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include <SFML/Network/Export.hpp> +#include <string> +#include <vector> + + +namespace sf +{ +class String; +class TcpSocket; +class UdpSocket; + +//////////////////////////////////////////////////////////// +/// \brief Utility class to build blocks of data to transfer +/// over the network +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API Packet +{ + // A bool-like type that cannot be converted to integer or pointer types + typedef bool (Packet::*BoolType)(std::size_t); + +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty packet. + /// + //////////////////////////////////////////////////////////// + Packet(); + + //////////////////////////////////////////////////////////// + /// \brief Virtual destructor + /// + //////////////////////////////////////////////////////////// + virtual ~Packet(); + + //////////////////////////////////////////////////////////// + /// \brief Append data to the end of the packet + /// + /// \param data Pointer to the sequence of bytes to append + /// \param sizeInBytes Number of bytes to append + /// + /// \see clear + /// + //////////////////////////////////////////////////////////// + void append(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Clear the packet + /// + /// After calling Clear, the packet is empty. + /// + /// \see append + /// + //////////////////////////////////////////////////////////// + void clear(); + + //////////////////////////////////////////////////////////// + /// \brief Get a pointer to the data contained in the packet + /// + /// Warning: the returned pointer may become invalid after + /// you append data to the packet, therefore it should never + /// be stored. + /// The return pointer is NULL if the packet is empty. + /// + /// \return Pointer to the data + /// + /// \see getDataSize + /// + //////////////////////////////////////////////////////////// + const void* getData() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the size of the data contained in the packet + /// + /// This function returns the number of bytes pointed to by + /// what getData returns. + /// + /// \return Data size, in bytes + /// + /// \see getData + /// + //////////////////////////////////////////////////////////// + std::size_t getDataSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Tell if the reading position has reached the + /// end of the packet + /// + /// This function is useful to know if there is some data + /// left to be read, without actually reading it. + /// + /// \return True if all data was read, false otherwise + /// + /// \see operator bool + /// + //////////////////////////////////////////////////////////// + bool endOfPacket() const; + +public: + + //////////////////////////////////////////////////////////// + /// \brief Test the validity of the packet, for reading + /// + /// This operator allows to test the packet as a boolean + /// variable, to check if a reading operation was successful. + /// + /// A packet will be in an invalid state if it has no more + /// data to read. + /// + /// This behavior is the same as standard C++ streams. + /// + /// Usage example: + /// \code + /// float x; + /// packet >> x; + /// if (packet) + /// { + /// // ok, x was extracted successfully + /// } + /// + /// // -- or -- + /// + /// float x; + /// if (packet >> x) + /// { + /// // ok, x was extracted successfully + /// } + /// \endcode + /// + /// Don't focus on the return type, it's equivalent to bool but + /// it disallows unwanted implicit conversions to integer or + /// pointer types. + /// + /// \return True if last data extraction from packet was successful + /// + /// \see endOfPacket + /// + //////////////////////////////////////////////////////////// + operator BoolType() const; + + //////////////////////////////////////////////////////////// + /// Overload of operator >> to read data from the packet + /// + //////////////////////////////////////////////////////////// + Packet& operator >>(bool& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(Int8& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(Uint8& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(Int16& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(Uint16& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(Int32& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(Uint32& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(Int64& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(Uint64& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(float& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(double& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(char* data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(std::string& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(wchar_t* data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(std::wstring& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator >>(String& data); + + //////////////////////////////////////////////////////////// + /// Overload of operator << to write data into the packet + /// + //////////////////////////////////////////////////////////// + Packet& operator <<(bool data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(Int8 data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(Uint8 data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(Int16 data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(Uint16 data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(Int32 data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(Uint32 data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(Int64 data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(Uint64 data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(float data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(double data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(const char* data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(const std::string& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(const wchar_t* data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(const std::wstring& data); + + //////////////////////////////////////////////////////////// + /// \overload + //////////////////////////////////////////////////////////// + Packet& operator <<(const String& data); + +protected: + + friend class TcpSocket; + friend class UdpSocket; + + //////////////////////////////////////////////////////////// + /// \brief Called before the packet is sent over the network + /// + /// This function can be defined by derived classes to + /// transform the data before it is sent; this can be + /// used for compression, encryption, etc. + /// The function must return a pointer to the modified data, + /// as well as the number of bytes pointed. + /// The default implementation provides the packet's data + /// without transforming it. + /// + /// \param size Variable to fill with the size of data to send + /// + /// \return Pointer to the array of bytes to send + /// + /// \see onReceive + /// + //////////////////////////////////////////////////////////// + virtual const void* onSend(std::size_t& size); + + //////////////////////////////////////////////////////////// + /// \brief Called after the packet is received over the network + /// + /// This function can be defined by derived classes to + /// transform the data after it is received; this can be + /// used for decompression, decryption, etc. + /// The function receives a pointer to the received data, + /// and must fill the packet with the transformed bytes. + /// The default implementation fills the packet directly + /// without transforming the data. + /// + /// \param data Pointer to the received bytes + /// \param size Number of bytes + /// + /// \see onSend + /// + //////////////////////////////////////////////////////////// + virtual void onReceive(const void* data, std::size_t size); + +private: + + //////////////////////////////////////////////////////////// + /// Disallow comparisons between packets + /// + //////////////////////////////////////////////////////////// + bool operator ==(const Packet& right) const; + bool operator !=(const Packet& right) const; + + //////////////////////////////////////////////////////////// + /// \brief Check if the packet can extract a given number of bytes + /// + /// This function updates accordingly the state of the packet. + /// + /// \param size Size to check + /// + /// \return True if \a size bytes can be read from the packet + /// + //////////////////////////////////////////////////////////// + bool checkSize(std::size_t size); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::vector<char> m_data; ///< Data stored in the packet + std::size_t m_readPos; ///< Current reading position in the packet + std::size_t m_sendPos; ///< Current send position in the packet (for handling partial sends) + bool m_isValid; ///< Reading state of the packet +}; + +} // namespace sf + + +#endif // SFML_PACKET_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Packet +/// \ingroup network +/// +/// Packets provide a safe and easy way to serialize data, +/// in order to send it over the network using sockets +/// (sf::TcpSocket, sf::UdpSocket). +/// +/// Packets solve 2 fundamental problems that arise when +/// transferring data over the network: +/// \li data is interpreted correctly according to the endianness +/// \li the bounds of the packet are preserved (one send == one receive) +/// +/// The sf::Packet class provides both input and output modes. +/// It is designed to follow the behavior of standard C++ streams, +/// using operators >> and << to extract and insert data. +/// +/// It is recommended to use only fixed-size types (like sf::Int32, etc.), +/// to avoid possible differences between the sender and the receiver. +/// Indeed, the native C++ types may have different sizes on two platforms +/// and your data may be corrupted if that happens. +/// +/// Usage example: +/// \code +/// sf::Uint32 x = 24; +/// std::string s = "hello"; +/// double d = 5.89; +/// +/// // Group the variables to send into a packet +/// sf::Packet packet; +/// packet << x << s << d; +/// +/// // Send it over the network (socket is a valid sf::TcpSocket) +/// socket.send(packet); +/// +/// ----------------------------------------------------------------- +/// +/// // Receive the packet at the other end +/// sf::Packet packet; +/// socket.receive(packet); +/// +/// // Extract the variables contained in the packet +/// sf::Uint32 x; +/// std::string s; +/// double d; +/// if (packet >> x >> s >> d) +/// { +/// // Data extracted successfully... +/// } +/// \endcode +/// +/// Packets have built-in operator >> and << overloads for +/// standard types: +/// \li bool +/// \li fixed-size integer types (sf::Int8/16/32, sf::Uint8/16/32) +/// \li floating point numbers (float, double) +/// \li string types (char*, wchar_t*, std::string, std::wstring, sf::String) +/// +/// Like standard streams, it is also possible to define your own +/// overloads of operators >> and << in order to handle your +/// custom types. +/// +/// \code +/// struct MyStruct +/// { +/// float number; +/// sf::Int8 integer; +/// std::string str; +/// }; +/// +/// sf::Packet& operator <<(sf::Packet& packet, const MyStruct& m) +/// { +/// return packet << m.number << m.integer << m.str; +/// } +/// +/// sf::Packet& operator >>(sf::Packet& packet, MyStruct& m) +/// { +/// return packet >> m.number >> m.integer >> m.str; +/// } +/// \endcode +/// +/// Packets also provide an extra feature that allows to apply +/// custom transformations to the data before it is sent, +/// and after it is received. This is typically used to +/// handle automatic compression or encryption of the data. +/// This is achieved by inheriting from sf::Packet, and overriding +/// the onSend and onReceive functions. +/// +/// Here is an example: +/// \code +/// class ZipPacket : public sf::Packet +/// { +/// virtual const void* onSend(std::size_t& size) +/// { +/// const void* srcData = getData(); +/// std::size_t srcSize = getDataSize(); +/// +/// return MySuperZipFunction(srcData, srcSize, &size); +/// } +/// +/// virtual void onReceive(const void* data, std::size_t size) +/// { +/// std::size_t dstSize; +/// const void* dstData = MySuperUnzipFunction(data, size, &dstSize); +/// +/// append(dstData, dstSize); +/// } +/// }; +/// +/// // Use like regular packets: +/// ZipPacket packet; +/// packet << x << s << d; +/// ... +/// \endcode +/// +/// \see sf::TcpSocket, sf::UdpSocket +/// +//////////////////////////////////////////////////////////// |