4 #include <msp/core/maputils.h>
5 #include <msp/strings/format.h>
6 #include <msp/strings/lexicalcast.h>
16 PacketDefBuilder<PacketHeader, Serializer<PacketHeader>>(*this, header_def, Serializer<PacketHeader>())
17 .fields(&PacketHeader::type, &PacketHeader::length);
20 unsigned Protocol::get_next_packet_class_id()
22 static unsigned next_id = 1;
26 void Protocol::add_packet(unique_ptr<PacketDefBase> pdef)
28 unique_ptr<PacketDefBase> &ptr = packet_class_defs[pdef->get_class_id()];
30 packet_id_defs.erase(ptr->get_id());
32 if(unsigned id = ptr->get_id())
33 packet_id_defs[id] = ptr.get();
36 const Protocol::PacketDefBase &Protocol::get_packet_by_class_id(unsigned id) const
38 return *get_item(packet_class_defs, id);
41 const Protocol::PacketDefBase &Protocol::get_packet_by_id(unsigned id) const
43 return *get_item(packet_id_defs, id);
46 unsigned Protocol::get_max_packet_id() const
48 if(packet_id_defs.empty())
50 return prev(packet_id_defs.end())->first;
53 size_t Protocol::dispatch(ReceiverBase &rcv, const char *buf, size_t size, unsigned base_id) const
56 const char *ptr = header_def.deserialize(header, buf, buf+size);
57 if(header.length>size)
58 throw bad_packet("truncated");
59 const PacketDefBase &pdef = get_packet_by_id(header.type-base_id);
60 ptr = pdef.dispatch(rcv, ptr, ptr+header.length);
64 bool Protocol::get_packet_header(PacketHeader &header, const char *buf, size_t size) const
68 header_def.deserialize(header, buf, buf+size);
72 size_t Protocol::get_packet_size(const char *buf, size_t size) const
75 return (get_packet_header(header, buf, size) ? header.length : 0);
78 uint64_t Protocol::get_hash() const
80 uint64_t result = hash<64>(packet_id_defs.size());
81 for(auto &kvp: packet_id_defs)
83 hash_update<64>(result, kvp.first);
84 hash_update<64>(result, kvp.second->get_hash());
90 /* TODO These assumes the machine is little-endian; are there any relevant
91 big-endian platforms these days? */
93 char *Protocol::BasicSerializer<T>::serialize(const T &value, char *buf, char *end) const
95 if(end-buf<static_cast<int>(sizeof(T)))
96 throw buffer_error("overflow");
98 const char *ptr = reinterpret_cast<const char *>(&value)+sizeof(T);
99 for(size_t i=0; i<sizeof(T); ++i)
106 const char *Protocol::BasicSerializer<T>::deserialize(T &value, const char *buf, const char *end) const
108 if(end-buf<static_cast<int>(sizeof(T)))
109 throw buffer_error("underflow");
111 char *ptr = reinterpret_cast<char *>(&value)+sizeof(T);
112 for(size_t i=0; i<sizeof(T); ++i)
118 template char *Protocol::BasicSerializer<bool>::serialize(const bool &, char *, char *) const;
119 template char *Protocol::BasicSerializer<int8_t>::serialize(const int8_t &, char *, char *) const;
120 template char *Protocol::BasicSerializer<int16_t>::serialize(const int16_t &, char *, char *) const;
121 template char *Protocol::BasicSerializer<int32_t>::serialize(const int32_t &, char *, char *) const;
122 template char *Protocol::BasicSerializer<int64_t>::serialize(const int64_t &, char *, char *) const;
123 template char *Protocol::BasicSerializer<uint8_t>::serialize(const uint8_t &, char *, char *) const;
124 template char *Protocol::BasicSerializer<uint16_t>::serialize(const uint16_t &, char *, char *) const;
125 template char *Protocol::BasicSerializer<uint32_t>::serialize(const uint32_t &, char *, char *) const;
126 template char *Protocol::BasicSerializer<uint64_t>::serialize(const uint64_t &, char *, char *) const;
127 template char *Protocol::BasicSerializer<float>::serialize(const float &, char *, char *) const;
128 template char *Protocol::BasicSerializer<double>::serialize(const double &, char *, char *) const;
129 template const char *Protocol::BasicSerializer<bool>::deserialize(bool &, const char *, const char *) const;
130 template const char *Protocol::BasicSerializer<int8_t>::deserialize(int8_t &, const char *, const char *) const;
131 template const char *Protocol::BasicSerializer<int16_t>::deserialize(int16_t &, const char *, const char *) const;
132 template const char *Protocol::BasicSerializer<int32_t>::deserialize(int32_t &, const char *, const char *) const;
133 template const char *Protocol::BasicSerializer<int64_t>::deserialize(int64_t &, const char *, const char *) const;
134 template const char *Protocol::BasicSerializer<uint8_t>::deserialize(uint8_t &, const char *, const char *) const;
135 template const char *Protocol::BasicSerializer<uint16_t>::deserialize(uint16_t &, const char *, const char *) const;
136 template const char *Protocol::BasicSerializer<uint32_t>::deserialize(uint32_t &, const char *, const char *) const;
137 template const char *Protocol::BasicSerializer<uint64_t>::deserialize(uint64_t &, const char *, const char *) const;
138 template const char *Protocol::BasicSerializer<float>::deserialize(float &, const char *, const char *) const;
139 template const char *Protocol::BasicSerializer<double>::deserialize(double &, const char *, const char *) const;
142 Protocol::StringSerializer::StringSerializer(const Protocol &p):
146 char *Protocol::StringSerializer::serialize(const string &str, char *buf, char *end) const
148 buf = length_serializer.serialize(str.size(), buf, end);
149 if(end-buf<static_cast<int>(str.size()))
150 throw buffer_error("overflow");
151 copy(str.begin(), str.end(), buf);
152 return buf+str.size();
155 const char *Protocol::StringSerializer::deserialize(string &str, const char *buf, const char *end) const
158 buf = length_serializer.deserialize(length, buf, end);
159 if(end-buf<static_cast<int>(length))
160 throw buffer_error("underflow");
161 str.assign(buf, buf+length);
166 Protocol::PacketDefBase::PacketDefBase(unsigned i):
171 Protocol::PacketHeader::PacketHeader(uint16_t t, uint16_t l):