1 #ifndef MSP_NET_PROTOCOL_H_
2 #define MSP_NET_PROTOCOL_H_
7 #include <msp/core/inttypes.h>
13 class bad_packet: public std::runtime_error
16 bad_packet(const std::string &w): std::runtime_error(w) { }
17 virtual ~bad_packet() throw() { }
21 class buffer_error: public std::runtime_error
24 buffer_error(const std::string &w): std::runtime_error(w) { }
25 virtual ~buffer_error() throw() { }
32 template<typename T, UInt8 K>
39 struct CompoundTypeDef
41 virtual ~CompoundTypeDef() { }
43 virtual char *serialize(const C &, char *, char *) const = 0;
44 virtual const char *deserialize(C &, const char *, const char *) const = 0;
47 template<typename C, typename S>
48 struct CompoundDef: public CompoundTypeDef<C>
52 CompoundDef(const S &);
53 virtual ~CompoundDef();
55 virtual char *serialize(const C &, char *, char *) const;
56 virtual const char *deserialize(C &, const char *, const char *) const;
65 BasicSerializer(const Protocol &) { }
67 char *serialize(const T &, char *, char *) const;
68 const char *deserialize(T &, const char *, const char *) const;
71 class StringSerializer
74 typedef std::string ValueType;
77 BasicSerializer<UInt16> length_serializer;
80 StringSerializer(const Protocol &);
82 char *serialize(const std::string &, char *, char *) const;
83 const char *deserialize(std::string &, const char *, const char *) const;
93 BasicSerializer<UInt16> length_serializer;
94 typename Traits<typename A::value_type>::Serializer element_serializer;
97 ArraySerializer(const Protocol &);
99 char *serialize(const A &, char *, char *) const;
100 const char *deserialize(A &, const char *, const char *) const;
103 template<typename P, typename Head, typename S>
104 class Serializer: public Head
110 typedef Serializer<P, Serializer<P, Head, S>, typename Traits<N>::Serializer> Type;
114 typedef typename S::ValueType P::*Pointer;
120 Serializer(const Head &, Pointer, const Protocol &);
122 char *serialize(const P &, char *, char *) const;
123 const char *deserialize(P &, const char *, const char *) const;
133 typedef Serializer<P, NullSerializer, typename Traits<N>::Serializer> Type;
136 char *serialize(const P &, char *b, char *) const { return b; }
137 const char *deserialize(P &, const char *b, const char *) const { return b; }
145 static unsigned next_class_id;
147 PacketDefBase(unsigned);
149 virtual ~PacketDefBase() { }
150 virtual unsigned get_class_id() const = 0;
151 unsigned get_id() const { return id; }
152 virtual const char *dispatch(ReceiverBase &, const char *, const char *) const = 0;
156 class PacketTypeDef: public PacketDefBase
159 CompoundTypeDef<P> *compound;
161 static unsigned class_id;
164 PacketTypeDef(unsigned);
167 static unsigned get_static_class_id() { return class_id; }
168 virtual unsigned get_class_id() const { return class_id; }
171 void set_serializer(const S &);
173 const CompoundTypeDef<P> &get_compound() const { return *compound; }
175 char *serialize(const P &, char *, char *) const;
176 const char *deserialize(P &, const char *, const char *) const;
177 virtual const char *dispatch(ReceiverBase &, const char *, const char *) const;
180 template<typename P, typename S>
181 class PacketDefBuilder
184 const Protocol &protocol;
185 PacketTypeDef<P> &pktdef;
189 PacketDefBuilder(const Protocol &, PacketTypeDef<P> &, const S &);
192 PacketDefBuilder<P, typename S::template Next<T>::Type> operator()(T P::*);
201 PacketHeader(UInt16, UInt16);
204 typedef std::map<unsigned, PacketDefBase *> PacketMap;
206 PacketTypeDef<PacketHeader> header_def;
207 unsigned next_packet_id;
208 PacketMap packet_class_defs;
209 PacketMap packet_id_defs;
212 Protocol(unsigned = 1);
217 void add_packet(PacketDefBase *);
221 PacketDefBuilder<P, NullSerializer<P> > add();
223 const PacketDefBase &get_packet_by_class_id(unsigned) const;
224 const PacketDefBase &get_packet_by_id(unsigned) const;
227 const PacketTypeDef<P> &get_packet_by_class() const;
231 unsigned serialize(const P &, char *, unsigned) const;
233 unsigned get_packet_size(const char *, unsigned) const;
234 unsigned dispatch(ReceiverBase &, const char *, unsigned) const;
236 unsigned get_hash() const;
241 Protocol::PacketDefBuilder<P, Protocol::NullSerializer<P> > Protocol::add()
243 PacketTypeDef<P> *pdef = new PacketTypeDef<P>(next_packet_id++);
245 return PacketDefBuilder<P, NullSerializer<P> >(*this, *pdef, NullSerializer<P>());
249 const Protocol::PacketTypeDef<P> &Protocol::get_packet_by_class() const
251 const PacketDefBase &pdef = get_packet_by_class_id(PacketTypeDef<P>::get_static_class_id());
252 return static_cast<const PacketTypeDef<P> &>(pdef);
256 unsigned Protocol::serialize(const P &pkt, char *buf, unsigned size) const
258 const PacketTypeDef<P> &pdef = get_packet_by_class<P>();
259 char *ptr = pdef.serialize(pkt, buf+4, buf+size);
261 header_def.serialize(PacketHeader(pdef.get_id(), size), buf, buf+4);
266 template<typename T, UInt8 K>
267 struct Protocol::BasicTraits
269 typedef BasicSerializer<T> Serializer;
272 template<> struct Protocol::Traits<Int8>: BasicTraits<Int8> { };
273 template<> struct Protocol::Traits<UInt8>: BasicTraits<UInt8> { };
274 template<> struct Protocol::Traits<Int16>: BasicTraits<Int16> { };
275 template<> struct Protocol::Traits<UInt16>: BasicTraits<UInt16> { };
276 template<> struct Protocol::Traits<Int32>: BasicTraits<Int32> { };
277 template<> struct Protocol::Traits<UInt32>: BasicTraits<UInt32> { };
278 template<> struct Protocol::Traits<Int64>: BasicTraits<Int64> { };
279 template<> struct Protocol::Traits<UInt64>: BasicTraits<UInt64> { };
280 template<> struct Protocol::Traits<float>: BasicTraits<float> { };
281 template<> struct Protocol::Traits<double>: BasicTraits<double> { };
283 template<> struct Protocol::Traits<std::string>
285 typedef StringSerializer Serializer;
289 struct Protocol::Traits<std::vector<T> >
291 typedef ArraySerializer<std::vector<T> > Serializer;
296 template<typename C, typename S>
297 Protocol::CompoundDef<C, S>::CompoundDef(const S &s):
301 template<typename C, typename S>
302 Protocol::CompoundDef<C, S>::~CompoundDef()
307 template<typename C, typename S>
308 char *Protocol::CompoundDef<C, S>::serialize(const C &com, char *buf, char *end) const
310 return serializer->serialize(com, buf, end);
313 template<typename C, typename S>
314 const char *Protocol::CompoundDef<C, S>::deserialize(C &com, const char *buf, const char *end) const
316 return serializer->deserialize(com, buf, end);
321 Protocol::ArraySerializer<A>::ArraySerializer(const Protocol &proto):
322 length_serializer(proto),
323 element_serializer(proto)
327 char *Protocol::ArraySerializer<A>::serialize(const A &array, char *buf, char *end) const
329 buf = length_serializer.serialize(array.size(), buf, end);
330 for(typename A::const_iterator i=array.begin(); i!=array.end(); ++i)
331 buf = element_serializer.serialize(*i, buf, end);
336 const char *Protocol::ArraySerializer<A>::deserialize(A &array, const char *buf, const char *end) const
339 buf = length_serializer.deserialize(length, buf, end);
340 array.resize(length);
341 for(unsigned i=0; i<length; ++i)
342 buf = element_serializer.deserialize(array[i], buf, end);
347 template<typename P, typename Head, typename S>
348 Protocol::Serializer<P, Head, S>::Serializer(const Head &h, Pointer p, const Protocol &proto):
354 template<typename P, typename Head, typename S>
355 char * Protocol::Serializer<P, Head, S>::serialize(const P &pkt, char *buf, char *end) const
357 buf = Head::serialize(pkt, buf, end);
358 return ser.serialize(pkt.*ptr, buf, end);
361 template<typename P, typename Head, typename S>
362 const char * Protocol::Serializer<P, Head, S>::deserialize(P &pkt, const char *buf, const char *end) const
364 buf = Head::deserialize(pkt, buf, end);
365 return ser.deserialize(pkt.*ptr, buf, end);
370 unsigned Protocol::PacketTypeDef<P>::class_id = 0;
373 Protocol::PacketTypeDef<P>::PacketTypeDef(unsigned i):
375 compound(new CompoundDef<P, NullSerializer<P> >(NullSerializer<P>()))
378 class_id = next_class_id++;
382 Protocol::PacketTypeDef<P>::~PacketTypeDef()
389 void Protocol::PacketTypeDef<P>::set_serializer(const S &ser)
392 compound = new CompoundDef<P, S>(ser);
396 char *Protocol::PacketTypeDef<P>::serialize(const P &pkt, char *buf, char *end) const
398 return compound->serialize(pkt, buf, end);
402 const char *Protocol::PacketTypeDef<P>::deserialize(P &pkt, const char *buf, const char *end) const
404 return compound->deserialize(pkt, buf, end);
408 const char *Protocol::PacketTypeDef<P>::dispatch(ReceiverBase &rcv, const char *buf, const char *end) const
410 PacketReceiver<P> *prcv = dynamic_cast<PacketReceiver<P> *>(&rcv);
412 throw bad_packet("unsupported");
414 buf = deserialize(pkt, buf, end);
420 template<typename P, typename S>
421 Protocol::PacketDefBuilder<P, S>::PacketDefBuilder(const Protocol &p, PacketTypeDef<P> &k, const S &s):
427 template<typename P, typename S>
429 Protocol::PacketDefBuilder<P, typename S::template Next<T>::Type> Protocol::PacketDefBuilder<P, S>::operator()(T P::*ptr)
431 typename S::template Next<T>::Type next_ser(serializer, ptr, protocol);
432 pktdef.set_serializer(next_ser);
433 return PacketDefBuilder<P, typename S::template Next<T>::Type>(protocol, pktdef, next_ser);