/*** This file is part of snapcast Copyright (C) 2015 Johannes Pohl This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ***/ #ifndef MESSAGE_H #define MESSAGE_H #include #include #include #include #include template > class vectorwrapbuf : public std::basic_streambuf { public: vectorwrapbuf(std::vector &vec) { this->setg(vec.data(), vec.data(), vec.data() + vec.size()); } }; struct membuf : public std::basic_streambuf { membuf(char* begin, char* end) { this->setg(begin, begin, end); } }; enum message_type { kBase = 0, kHeader = 1, kWireChunk = 2, kSampleFormat = 3, kServerSettings = 4, kTime = 5, kRequest = 6, kAck = 7, kCommand = 8, kHello = 9, kMap = 10, kString = 11 }; struct tv { tv() { timeval t; gettimeofday(&t, NULL); sec = t.tv_sec; usec = t.tv_usec; } tv(timeval tv) : sec(tv.tv_sec), usec(tv.tv_usec) {}; tv(int32_t _sec, int32_t _usec) : sec(_sec), usec(_usec) {}; int32_t sec; int32_t usec; tv operator+(const tv& other) { tv result(*this); result.sec += other.sec; result.usec += other.usec; if (result.usec > 1000000) { result.sec += result.usec / 1000000; result.usec %= 1000000; } return result; } tv operator-(const tv& other) { tv result(*this); result.sec -= other.sec; result.usec -= other.usec; while (result.usec < 0) { result.sec -= 1; result.usec += 1000000; } return result; } }; namespace msg { struct BaseMessage { BaseMessage() : type(kBase), id(0), refersTo(0) { } BaseMessage(message_type type_) : type(type_), id(0), refersTo(0) { } virtual ~BaseMessage() { } virtual void read(std::istream& stream) { stream.read(reinterpret_cast(&type), sizeof(uint16_t)); stream.read(reinterpret_cast(&id), sizeof(uint16_t)); stream.read(reinterpret_cast(&refersTo), sizeof(uint16_t)); stream.read(reinterpret_cast(&sent.sec), sizeof(int32_t)); stream.read(reinterpret_cast(&sent.usec), sizeof(int32_t)); stream.read(reinterpret_cast(&received.sec), sizeof(int32_t)); stream.read(reinterpret_cast(&received.usec), sizeof(int32_t)); stream.read(reinterpret_cast(&size), sizeof(uint32_t)); } void deserialize(char* payload) { membuf databuf(payload, payload + BaseMessage::getSize()); std::istream is(&databuf); read(is); } void deserialize(const BaseMessage& baseMessage, char* payload) { type = baseMessage.type; id = baseMessage.id; refersTo = baseMessage.refersTo; sent = baseMessage.sent; received = baseMessage.received; size = baseMessage.size; membuf databuf(payload, payload + size); std::istream is(&databuf); read(is); } virtual void serialize(std::ostream& stream) const { stream.write(reinterpret_cast(&type), sizeof(uint16_t)); stream.write(reinterpret_cast(&id), sizeof(uint16_t)); stream.write(reinterpret_cast(&refersTo), sizeof(uint16_t)); stream.write(reinterpret_cast(&sent.sec), sizeof(int32_t)); stream.write(reinterpret_cast(&sent.usec), sizeof(int32_t)); stream.write(reinterpret_cast(&received.sec), sizeof(int32_t)); stream.write(reinterpret_cast(&received.usec), sizeof(int32_t)); size = getSize(); stream.write(reinterpret_cast(&size), sizeof(uint32_t)); doserialize(stream); } virtual uint32_t getSize() const { return 3*sizeof(uint16_t) + 2*sizeof(tv) + sizeof(uint32_t); }; uint16_t type; mutable uint16_t id; uint16_t refersTo; tv received; mutable tv sent; mutable uint32_t size; protected: virtual void doserialize(std::ostream& stream) const { }; }; struct SerializedMessage { ~SerializedMessage() { free(buffer); } BaseMessage message; char* buffer; }; } #endif