1 /***
2     This file is part of snapcast
3     Copyright (C) 2014-2021  Johannes Pohl
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 ***/
18 
19 #ifndef MESSAGE_HPP
20 #define MESSAGE_HPP
21 
22 #include "common/endian.hpp"
23 #include "common/time_defs.hpp"
24 #include <cstdlib>
25 #include <cstring>
26 #include <iostream>
27 #include <streambuf>
28 #ifndef WINDOWS
29 #include <sys/time.h>
30 #endif
31 #include <vector>
32 
33 /*
34 template<typename CharT, typename TraitsT = std::char_traits<CharT> >
35 class vectorwrapbuf : public std::basic_streambuf<CharT, TraitsT>
36 {
37 public:
38         vectorwrapbuf(std::vector<CharT> &vec)
39         {
40                 this->setg(vec.data(), vec.data(), vec.data() + vec.size());
41         }
42 };
43 */
44 
45 struct membuf : public std::basic_streambuf<char>
46 {
membufmembuf47     membuf(char* begin, char* end)
48     {
49         this->setg(begin, begin, end);
50     }
51 };
52 
53 
54 enum message_type
55 {
56     kBase = 0,
57     kCodecHeader = 1,
58     kWireChunk = 2,
59     kServerSettings = 3,
60     kTime = 4,
61     kHello = 5,
62     kStreamTags = 6,
63     kClientInfo = 7,
64 
65     kFirst = kBase,
66     kLast = kClientInfo
67 };
68 
69 
70 struct tv
71 {
tvtv72     tv()
73     {
74         timeval t;
75         chronos::steadytimeofday(&t);
76         sec = t.tv_sec;
77         usec = t.tv_usec;
78     }
tvtv79     tv(timeval tv) : sec(tv.tv_sec), usec(tv.tv_usec){};
tvtv80     tv(int32_t _sec, int32_t _usec) : sec(_sec), usec(_usec){};
81 
82     int32_t sec;
83     int32_t usec;
84 
operator +tv85     tv operator+(const tv& other) const
86     {
87         tv result(*this);
88         result.sec += other.sec;
89         result.usec += other.usec;
90         if (result.usec > 1000000)
91         {
92             result.sec += result.usec / 1000000;
93             result.usec %= 1000000;
94         }
95         return result;
96     }
97 
operator -tv98     tv operator-(const tv& other) const
99     {
100         tv result(*this);
101         result.sec -= other.sec;
102         result.usec -= other.usec;
103         while (result.usec < 0)
104         {
105             result.sec -= 1;
106             result.usec += 1000000;
107         }
108         return result;
109     }
110 };
111 
112 namespace msg
113 {
114 
115 const size_t max_size = 1000000;
116 
117 struct BaseMessage;
118 
119 using message_ptr = std::shared_ptr<msg::BaseMessage>;
120 
121 struct BaseMessage
122 {
BaseMessagemsg::BaseMessage123     BaseMessage() : type(kBase), id(0), refersTo(0)
124     {
125     }
126 
BaseMessagemsg::BaseMessage127     BaseMessage(message_type type_) : type(static_cast<uint16_t>(type_)), id(0), refersTo(0)
128     {
129     }
130 
131     virtual ~BaseMessage() = default;
132 
readmsg::BaseMessage133     virtual void read(std::istream& stream)
134     {
135         readVal(stream, type);
136         readVal(stream, id);
137         readVal(stream, refersTo);
138         readVal(stream, sent.sec);
139         readVal(stream, sent.usec);
140         readVal(stream, received.sec);
141         readVal(stream, received.usec);
142         readVal(stream, size);
143     }
144 
deserializemsg::BaseMessage145     void deserialize(char* payload)
146     {
147         membuf databuf(payload, payload + BaseMessage::getSize());
148         std::istream is(&databuf);
149         read(is);
150     }
151 
deserializemsg::BaseMessage152     void deserialize(const BaseMessage& baseMessage, char* payload)
153     {
154         type = baseMessage.type;
155         id = baseMessage.id;
156         refersTo = baseMessage.refersTo;
157         sent = baseMessage.sent;
158         received = baseMessage.received;
159         size = baseMessage.size;
160         membuf databuf(payload, payload + size);
161         std::istream is(&databuf);
162         read(is);
163     }
164 
serializemsg::BaseMessage165     virtual void serialize(std::ostream& stream) const
166     {
167         writeVal(stream, type);
168         writeVal(stream, id);
169         writeVal(stream, refersTo);
170         writeVal(stream, sent.sec);
171         writeVal(stream, sent.usec);
172         writeVal(stream, received.sec);
173         writeVal(stream, received.usec);
174         size = getSize();
175         writeVal(stream, size);
176         doserialize(stream);
177     }
178 
getSizemsg::BaseMessage179     virtual uint32_t getSize() const
180     {
181         return 3 * sizeof(uint16_t) + 2 * sizeof(tv) + sizeof(uint32_t);
182     };
183 
184     uint16_t type;
185     mutable uint16_t id;
186     uint16_t refersTo;
187     tv received;
188     mutable tv sent;
189     mutable uint32_t size;
190 
191 protected:
writeValmsg::BaseMessage192     void writeVal(std::ostream& stream, const bool& val) const
193     {
194         char c = val ? 1 : 0;
195         writeVal(stream, c);
196     }
197 
writeValmsg::BaseMessage198     void writeVal(std::ostream& stream, const char& val) const
199     {
200         stream.write(reinterpret_cast<const char*>(&val), sizeof(char));
201     }
202 
writeValmsg::BaseMessage203     void writeVal(std::ostream& stream, const uint16_t& val) const
204     {
205         uint16_t v = SWAP_16(val);
206         stream.write(reinterpret_cast<const char*>(&v), sizeof(uint16_t));
207     }
208 
writeValmsg::BaseMessage209     void writeVal(std::ostream& stream, const int16_t& val) const
210     {
211         uint16_t v = SWAP_16(val);
212         stream.write(reinterpret_cast<const char*>(&v), sizeof(int16_t));
213     }
214 
writeValmsg::BaseMessage215     void writeVal(std::ostream& stream, const uint32_t& val) const
216     {
217         uint32_t v = SWAP_32(val);
218         stream.write(reinterpret_cast<const char*>(&v), sizeof(uint32_t));
219     }
220 
writeValmsg::BaseMessage221     void writeVal(std::ostream& stream, const int32_t& val) const
222     {
223         uint32_t v = SWAP_32(val);
224         stream.write(reinterpret_cast<const char*>(&v), sizeof(int32_t));
225     }
226 
writeValmsg::BaseMessage227     void writeVal(std::ostream& stream, const char* payload, const uint32_t& size) const
228     {
229         writeVal(stream, size);
230         stream.write(payload, size);
231     }
232 
writeValmsg::BaseMessage233     void writeVal(std::ostream& stream, const std::string& val) const
234     {
235         auto size = static_cast<uint32_t>(val.size());
236         writeVal(stream, val.c_str(), size);
237     }
238 
239 
240 
readValmsg::BaseMessage241     void readVal(std::istream& stream, bool& val) const
242     {
243         char c;
244         readVal(stream, c);
245         val = (c != 0);
246     }
247 
readValmsg::BaseMessage248     void readVal(std::istream& stream, char& val) const
249     {
250         stream.read(reinterpret_cast<char*>(&val), sizeof(char));
251     }
252 
readValmsg::BaseMessage253     void readVal(std::istream& stream, uint16_t& val) const
254     {
255         stream.read(reinterpret_cast<char*>(&val), sizeof(uint16_t));
256         val = SWAP_16(val);
257     }
258 
readValmsg::BaseMessage259     void readVal(std::istream& stream, int16_t& val) const
260     {
261         stream.read(reinterpret_cast<char*>(&val), sizeof(int16_t));
262         val = SWAP_16(val);
263     }
264 
readValmsg::BaseMessage265     void readVal(std::istream& stream, uint32_t& val) const
266     {
267         stream.read(reinterpret_cast<char*>(&val), sizeof(uint32_t));
268         val = SWAP_32(val);
269     }
270 
readValmsg::BaseMessage271     void readVal(std::istream& stream, int32_t& val) const
272     {
273         stream.read(reinterpret_cast<char*>(&val), sizeof(int32_t));
274         val = SWAP_32(val);
275     }
276 
readValmsg::BaseMessage277     void readVal(std::istream& stream, char** payload, uint32_t& size) const
278     {
279         readVal(stream, size);
280         *payload = (char*)realloc(*payload, size);
281         stream.read(*payload, size);
282     }
283 
readValmsg::BaseMessage284     void readVal(std::istream& stream, std::string& val) const
285     {
286         uint32_t size;
287         readVal(stream, size);
288         val.resize(size);
289         stream.read(&val[0], size);
290     }
291 
292 
doserializemsg::BaseMessage293     virtual void doserialize(std::ostream& /*stream*/) const {};
294 };
295 
296 } // namespace msg
297 
298 #endif
299