1 /*
2  *  Copyright (C) 2011-2016  OpenDungeons Team
3  *
4  *  This program is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef ODPACKET_H
19 #define ODPACKET_H
20 
21 #include <OgreVector3.h>
22 #include <SFML/Network.hpp>
23 
24 #include <string>
25 #include <cstdint>
26 
27 /*! \brief This class is an utility class to transfer data through ODSocketClient.
28  * It should also override operators << and >> for each standard types.
29  * ODPacket should preserve integrity. That means that if an ODSocketClient
30  * sends an ODPacket, the server should receive exactly 1 similar ODPacket (same data,
31  * nothing less, nothing more)
32  * IMPORTANT : ODPacket can handle different types of data the same way. For that, when we receive
33  * data, we have to know its type (when an int is sent, we know an int will be received). The typical
34  * use of ODPacket is :
35  * Emission : int myInt;
36  *            ODPacket packet;
37  *            packet << myInt;
38  *            send(packet);
39  * Reception : ODPacket packet;
40  *             receive(packet);
41  *             int myInt;
42  *             packet >> myInt;
43  * As we can see in this example, we have to know the data type within the packet before reading it.
44  * But depending on architecture, default datatype can be different between the server and the client.
45  * For this reason, the data returned by a function should never be used directly as ODPacket data. Instead,
46  * a temporary variable should be used and sent to ODPacket (sized variables such as int32_t, int8_t, ...
47  * should be as used as possible for the same reason).
48  * For example : You should NOT do :
49  * packet << getName();
50  * You should do :
51  * std::string name = getName();
52  * packet << name;
53  * This way, if the function signature changes or if the data type is different (int vs long for example) on
54  * different platforms, there will be an error when compiling instead of a probable buggy behaviour at runtime.
55  * When dealing with class/structure, the best is to use directly the variables themselves, no getter/setter.
56  * For example, You should NOT do :
57  * Emission : packet << creature->getHp();
58  * Reception : double hp;
59  *             packet >> hp;
60  *             creature->setHp(hp);
61  * You should do :
62  * Emission : packet << creature->mHp;
63  * Reception : packet >> creature->mHp;
64  * This way, if mHp changes (from float to double for example), it will still work.
65  */
66 class ODPacket
67 {
68     friend class ODSocketClient;
69 
70     public:
ODPacket()71         ODPacket()
72         {}
~ODPacket()73         ~ODPacket()
74         {}
75 
76         /*! \brief Export data operators.
77          * The behaviour is the same as standard C++ streams
78          */
79         ODPacket& operator >>(bool&         data);
80         ODPacket& operator >>(int8_t&       data);
81         ODPacket& operator >>(uint8_t&      data);
82         ODPacket& operator >>(int16_t&      data);
83         ODPacket& operator >>(uint16_t&     data);
84         ODPacket& operator >>(int32_t&      data);
85         ODPacket& operator >>(uint32_t&     data);
86         ODPacket& operator >>(int64_t&      data);
87         ODPacket& operator >>(uint64_t&     data);
88         ODPacket& operator >>(float&        data);
89         ODPacket& operator >>(double&       data);
90         ODPacket& operator >>(char*         data);
91         ODPacket& operator >>(std::string&  data);
92         ODPacket& operator >>(wchar_t*      data);
93         ODPacket& operator >>(std::wstring& data);
94         ODPacket& operator >>(Ogre::Vector3& data);
95 
96         /*! \brief Import data operators
97          * The behaviour is the same as standard C++ streams
98          */
99         ODPacket& operator <<(bool                  data);
100         ODPacket& operator <<(int8_t                data);
101         ODPacket& operator <<(uint8_t               data);
102         ODPacket& operator <<(int16_t               data);
103         ODPacket& operator <<(uint16_t              data);
104         ODPacket& operator <<(int32_t               data);
105         ODPacket& operator <<(uint32_t              data);
106         ODPacket& operator <<(int64_t               data);
107         ODPacket& operator <<(uint64_t              data);
108         ODPacket& operator <<(float                 data);
109         ODPacket& operator <<(double                data);
110         ODPacket& operator <<(const char*           data);
111         ODPacket& operator <<(const std::string&    data);
112         ODPacket& operator <<(const wchar_t*        data);
113         ODPacket& operator <<(const std::wstring&   data);
114         ODPacket& operator <<(const Ogre::Vector3&   data);
115 
116         /*! \brief Return true if there were no error exporting data (operator >>).
117          * This behaviour is the same as standard C++ streams :
118          * If we try to export data while the packet is empty or from incompatible types,
119          * the data will be invalid and the function will return false
120          */
121         operator bool() const;
122 
123         /*! \brief Clears the packet. After calling Clear, the packet should
124          * be empty.
125          */
126         void clear();
127 
128         /*! \brief Writes the packet content to the given ofstream.
129          */
130         void writePacket(int32_t timestamp, std::ofstream& os);
131 
132         /*! \brief Reads the packet content from the given ifstream.
133          *         Returns the timestamp at which the packet has been sent.
134          *         If EOF has been reached, returns -1
135          */
136         int32_t readPacket(std::ifstream& is);
137 
138         /*! \brief Template function to put arguments in a packet, used for in-place construction.
139          */
140         template<typename FirstArg, typename ...Args>
putInPacket(ODPacket & packet,const FirstArg & arg,const Args &...args)141         static void putInPacket(ODPacket& packet, const FirstArg& arg, const Args&... args)
142         {
143             packet << arg;
144             putInPacket(packet, args...);
145         }
146 
147         template<typename Arg>
putInPacket(ODPacket & packet,const Arg & arg)148         static void putInPacket(ODPacket& packet, const Arg& arg)
149         {
150             packet << arg;
151         }
152 
153     private:
154         sf::Packet mPacket;
155 
156 };
157 
158 #endif // ODPACKET_H
159 
160