3 #include <msp/core/hash.h>
4 #include <msp/core/maputils.h>
5 #include <msp/strings/format.h>
6 #include <msp/strings/lexicalcast.h>
8 #include "protocol_impl.h"
15 Protocol::Protocol(unsigned npi):
19 PacketDefBuilder<PacketHeader, NullSerializer<PacketHeader> >(*this, header_def, NullSerializer<PacketHeader>())
20 (&PacketHeader::type)(&PacketHeader::length);
25 for(map<unsigned, PacketDefBase *>::iterator i=packet_class_defs.begin(); i!=packet_class_defs.end(); ++i)
29 void Protocol::add_packet(PacketDefBase *pdef)
31 PacketDefBase *&ptr = packet_class_defs[pdef->get_class_id()];
34 packet_id_defs.erase(ptr->get_id());
38 if(unsigned id = pdef->get_id())
39 packet_id_defs[id] = pdef;
42 const Protocol::PacketDefBase &Protocol::get_packet_by_class_id(unsigned id) const
44 return *get_item(packet_class_defs, id);
47 const Protocol::PacketDefBase &Protocol::get_packet_by_id(unsigned id) const
49 return *get_item(packet_id_defs, id);
52 size_t Protocol::dispatch(ReceiverBase &rcv, const char *buf, size_t size) const
55 buf = header_def.deserialize(header, buf, buf+size);
56 if(header.length>size)
57 throw bad_packet("truncated");
58 const PacketDefBase &pdef = get_packet_by_id(header.type);
59 const char *ptr = pdef.dispatch(rcv, buf, buf+header.length);
63 size_t Protocol::get_packet_size(const char *buf, size_t size) const
68 header_def.deserialize(header, buf, buf+size);
72 uint64_t Protocol::get_hash() const
75 for(PacketMap::const_iterator i=packet_id_defs.begin(); i!=packet_id_defs.end(); ++i)
76 description += format("%d:%s\n", i->first, i->second->describe());
77 return hash<64>(description);
81 /* TODO These assumes the machine is little-endian; are there any relevant
82 big-endian platforms these days? */
84 char *Protocol::BasicSerializer<T>::serialize(const T &value, char *buf, char *end) const
86 if(end-buf<static_cast<int>(sizeof(T)))
87 throw buffer_error("overflow");
89 const char *ptr = reinterpret_cast<const char *>(&value)+sizeof(T);
90 for(size_t i=0; i<sizeof(T); ++i)
97 const char *Protocol::BasicSerializer<T>::deserialize(T &value, const char *buf, const char *end) const
99 if(end-buf<static_cast<int>(sizeof(T)))
100 throw buffer_error("underflow");
102 char *ptr = reinterpret_cast<char *>(&value)+sizeof(T);
103 for(size_t i=0; i<sizeof(T); ++i)
109 template char *Protocol::BasicSerializer<bool>::serialize(const bool &, char *, char *) const;
110 template char *Protocol::BasicSerializer<int8_t>::serialize(const int8_t &, char *, char *) const;
111 template char *Protocol::BasicSerializer<int16_t>::serialize(const int16_t &, char *, char *) const;
112 template char *Protocol::BasicSerializer<int32_t>::serialize(const int32_t &, char *, char *) const;
113 template char *Protocol::BasicSerializer<int64_t>::serialize(const int64_t &, char *, char *) const;
114 template char *Protocol::BasicSerializer<uint8_t>::serialize(const uint8_t &, char *, char *) const;
115 template char *Protocol::BasicSerializer<uint16_t>::serialize(const uint16_t &, char *, char *) const;
116 template char *Protocol::BasicSerializer<uint32_t>::serialize(const uint32_t &, char *, char *) const;
117 template char *Protocol::BasicSerializer<uint64_t>::serialize(const uint64_t &, char *, char *) const;
118 template char *Protocol::BasicSerializer<float>::serialize(const float &, char *, char *) const;
119 template char *Protocol::BasicSerializer<double>::serialize(const double &, char *, char *) const;
120 template const char *Protocol::BasicSerializer<bool>::deserialize(bool &, const char *, const char *) const;
121 template const char *Protocol::BasicSerializer<int8_t>::deserialize(int8_t &, const char *, const char *) const;
122 template const char *Protocol::BasicSerializer<int16_t>::deserialize(int16_t &, const char *, const char *) const;
123 template const char *Protocol::BasicSerializer<int32_t>::deserialize(int32_t &, const char *, const char *) const;
124 template const char *Protocol::BasicSerializer<int64_t>::deserialize(int64_t &, const char *, const char *) const;
125 template const char *Protocol::BasicSerializer<uint8_t>::deserialize(uint8_t &, const char *, const char *) const;
126 template const char *Protocol::BasicSerializer<uint16_t>::deserialize(uint16_t &, const char *, const char *) const;
127 template const char *Protocol::BasicSerializer<uint32_t>::deserialize(uint32_t &, const char *, const char *) const;
128 template const char *Protocol::BasicSerializer<uint64_t>::deserialize(uint64_t &, const char *, const char *) const;
129 template const char *Protocol::BasicSerializer<float>::deserialize(float &, const char *, const char *) const;
130 template const char *Protocol::BasicSerializer<double>::deserialize(double &, const char *, const char *) const;
133 Protocol::StringSerializer::StringSerializer(const Protocol &p):
137 char *Protocol::StringSerializer::serialize(const string &str, char *buf, char *end) const
139 buf = length_serializer.serialize(str.size(), buf, end);
140 if(end-buf<static_cast<int>(str.size()))
141 throw buffer_error("overflow");
142 copy(str.begin(), str.end(), buf);
143 return buf+str.size();
146 const char *Protocol::StringSerializer::deserialize(string &str, const char *buf, const char *end) const
149 buf = length_serializer.deserialize(length, buf, end);
150 if(end-buf<static_cast<int>(length))
151 throw buffer_error("underflow");
152 str.assign(buf, buf+length);
157 unsigned Protocol::PacketDefBase::next_class_id = 1;
159 Protocol::PacketDefBase::PacketDefBase(unsigned i):
164 Protocol::PacketHeader::PacketHeader():
169 Protocol::PacketHeader::PacketHeader(uint16_t t, uint16_t l):