533 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			533 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| ////////////////////////////////////////////////////////////
 | |
| //
 | |
| // 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
 | |
| ///
 | |
| ////////////////////////////////////////////////////////////
 |