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