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 std::string describe() const = 0;
44 virtual char *serialize(const C &, char *, char *) const = 0;
45 virtual const char *deserialize(C &, const char *, const char *) const = 0;
48 template<typename C, typename S>
49 struct CompoundDef: public CompoundTypeDef<C>
53 CompoundDef(const S &);
54 virtual ~CompoundDef();
56 virtual std::string describe() const;
57 virtual char *serialize(const C &, char *, char *) const;
58 virtual const char *deserialize(C &, const char *, const char *) const;
67 BasicSerializer(const Protocol &) { }
69 std::string describe() const { return get_type_signature<T>(); }
70 char *serialize(const T &, char *, char *) const;
71 const char *deserialize(T &, const char *, const char *) const;
74 class StringSerializer
77 typedef std::string ValueType;
80 BasicSerializer<UInt16> length_serializer;
83 StringSerializer(const Protocol &);
85 std::string describe() const { return get_type_signature<std::string>(); }
86 char *serialize(const std::string &, char *, char *) const;
87 const char *deserialize(std::string &, const char *, const char *) const;
97 BasicSerializer<UInt16> length_serializer;
98 typename Traits<typename A::value_type>::Serializer element_serializer;
101 ArraySerializer(const Protocol &);
103 std::string describe() const;
104 char *serialize(const A &, char *, char *) const;
105 const char *deserialize(A &, const char *, const char *) const;
108 template<typename P, typename Head, typename S>
109 class Serializer: public Head
115 typedef Serializer<P, Serializer<P, Head, S>, typename Traits<N>::Serializer> Type;
119 typedef typename S::ValueType P::*Pointer;
125 Serializer(const Head &, Pointer, const Protocol &);
127 std::string describe() const;
128 char *serialize(const P &, char *, char *) const;
129 const char *deserialize(P &, const char *, const char *) const;
139 typedef Serializer<P, NullSerializer, typename Traits<N>::Serializer> Type;
142 std::string describe() const { return std::string(); }
143 char *serialize(const P &, char *b, char *) const { return b; }
144 const char *deserialize(P &, const char *b, const char *) const { return b; }
152 static unsigned next_class_id;
154 PacketDefBase(unsigned);
156 virtual ~PacketDefBase() { }
157 virtual unsigned get_class_id() const = 0;
158 unsigned get_id() const { return id; }
159 virtual std::string describe() const = 0;
160 virtual const char *dispatch(ReceiverBase &, const char *, const char *) const = 0;
164 class PacketTypeDef: public PacketDefBase
167 CompoundTypeDef<P> *compound;
169 static unsigned class_id;
172 PacketTypeDef(unsigned);
175 static unsigned get_static_class_id() { return class_id; }
176 virtual unsigned get_class_id() const { return class_id; }
179 void set_serializer(const S &);
181 const CompoundTypeDef<P> &get_compound() const { return *compound; }
183 virtual std::string describe() const;
184 char *serialize(const P &, char *, char *) const;
185 const char *deserialize(P &, const char *, const char *) const;
186 virtual const char *dispatch(ReceiverBase &, const char *, const char *) const;
189 template<typename P, typename S>
190 class PacketDefBuilder
193 const Protocol &protocol;
194 PacketTypeDef<P> &pktdef;
198 PacketDefBuilder(const Protocol &, PacketTypeDef<P> &, const S &);
201 PacketDefBuilder<P, typename S::template Next<T>::Type> operator()(T P::*);
210 PacketHeader(UInt16, UInt16);
213 typedef std::map<unsigned, PacketDefBase *> PacketMap;
215 PacketTypeDef<PacketHeader> header_def;
216 unsigned next_packet_id;
217 PacketMap packet_class_defs;
218 PacketMap packet_id_defs;
221 Protocol(unsigned = 1);
226 void add_packet(PacketDefBase *);
230 PacketDefBuilder<P, NullSerializer<P> > add();
232 const PacketDefBase &get_packet_by_class_id(unsigned) const;
233 const PacketDefBase &get_packet_by_id(unsigned) const;
236 const PacketTypeDef<P> &get_packet_by_class() const;
240 unsigned serialize(const P &, char *, unsigned) const;
242 unsigned get_packet_size(const char *, unsigned) const;
243 unsigned dispatch(ReceiverBase &, const char *, unsigned) const;
245 UInt64 get_hash() const;
249 static std::string get_type_signature();
254 Protocol::PacketDefBuilder<P, Protocol::NullSerializer<P> > Protocol::add()
256 PacketTypeDef<P> *pdef = new PacketTypeDef<P>(next_packet_id++);
258 return PacketDefBuilder<P, NullSerializer<P> >(*this, *pdef, NullSerializer<P>());
262 const Protocol::PacketTypeDef<P> &Protocol::get_packet_by_class() const
264 const PacketDefBase &pdef = get_packet_by_class_id(PacketTypeDef<P>::get_static_class_id());
265 return static_cast<const PacketTypeDef<P> &>(pdef);
269 unsigned Protocol::serialize(const P &pkt, char *buf, unsigned size) const
271 const PacketTypeDef<P> &pdef = get_packet_by_class<P>();
272 char *ptr = pdef.serialize(pkt, buf+4, buf+size);
274 header_def.serialize(PacketHeader(pdef.get_id(), size), buf, buf+4);
279 std::string Protocol::get_type_signature()
281 const UInt16 sig = Traits<T>::signature;
285 result += '0'+(sig>>8);
290 template<typename T, UInt8 K>
291 struct Protocol::BasicTraits
293 static const UInt16 signature = K | (sizeof(T)<<8);
294 typedef BasicSerializer<T> Serializer;
297 template<> struct Protocol::Traits<Int8>: BasicTraits<Int8, 'I'> { };
298 template<> struct Protocol::Traits<UInt8>: BasicTraits<UInt8, 'U'> { };
299 template<> struct Protocol::Traits<Int16>: BasicTraits<Int16, 'I'> { };
300 template<> struct Protocol::Traits<UInt16>: BasicTraits<UInt16, 'U'> { };
301 template<> struct Protocol::Traits<Int32>: BasicTraits<Int32, 'I'> { };
302 template<> struct Protocol::Traits<UInt32>: BasicTraits<UInt32, 'U'> { };
303 template<> struct Protocol::Traits<Int64>: BasicTraits<Int64, 'I'> { };
304 template<> struct Protocol::Traits<UInt64>: BasicTraits<UInt64, 'U'> { };
305 template<> struct Protocol::Traits<float>: BasicTraits<float, 'F'> { };
306 template<> struct Protocol::Traits<double>: BasicTraits<double, 'F'> { };
308 template<> struct Protocol::Traits<std::string>
310 static const UInt16 signature = 'S';
311 typedef StringSerializer Serializer;
315 struct Protocol::Traits<std::vector<T> >
317 static const UInt16 signature = 'A';
318 typedef ArraySerializer<std::vector<T> > Serializer;
323 template<typename C, typename S>
324 Protocol::CompoundDef<C, S>::CompoundDef(const S &s):
328 template<typename C, typename S>
329 Protocol::CompoundDef<C, S>::~CompoundDef()
334 template<typename C, typename S>
335 std::string Protocol::CompoundDef<C, S>::describe() const
337 return "{"+serializer->describe()+"}";
340 template<typename C, typename S>
341 char *Protocol::CompoundDef<C, S>::serialize(const C &com, char *buf, char *end) const
343 return serializer->serialize(com, buf, end);
346 template<typename C, typename S>
347 const char *Protocol::CompoundDef<C, S>::deserialize(C &com, const char *buf, const char *end) const
349 return serializer->deserialize(com, buf, end);
354 Protocol::ArraySerializer<A>::ArraySerializer(const Protocol &proto):
355 length_serializer(proto),
356 element_serializer(proto)
360 std::string Protocol::ArraySerializer<A>::describe() const
362 return "["+element_serializer.describe()+"]";
366 char *Protocol::ArraySerializer<A>::serialize(const A &array, char *buf, char *end) const
368 buf = length_serializer.serialize(array.size(), buf, end);
369 for(typename A::const_iterator i=array.begin(); i!=array.end(); ++i)
370 buf = element_serializer.serialize(*i, buf, end);
375 const char *Protocol::ArraySerializer<A>::deserialize(A &array, const char *buf, const char *end) const
378 buf = length_serializer.deserialize(length, buf, end);
379 array.resize(length);
380 for(unsigned i=0; i<length; ++i)
381 buf = element_serializer.deserialize(array[i], buf, end);
386 template<typename P, typename Head, typename S>
387 Protocol::Serializer<P, Head, S>::Serializer(const Head &h, Pointer p, const Protocol &proto):
393 template<typename P, typename Head, typename S>
394 std::string Protocol::Serializer<P, Head, S>::describe() const
396 return Head::describe()+ser.describe();
399 template<typename P, typename Head, typename S>
400 char * Protocol::Serializer<P, Head, S>::serialize(const P &pkt, char *buf, char *end) const
402 buf = Head::serialize(pkt, buf, end);
403 return ser.serialize(pkt.*ptr, buf, end);
406 template<typename P, typename Head, typename S>
407 const char * Protocol::Serializer<P, Head, S>::deserialize(P &pkt, const char *buf, const char *end) const
409 buf = Head::deserialize(pkt, buf, end);
410 return ser.deserialize(pkt.*ptr, buf, end);
415 unsigned Protocol::PacketTypeDef<P>::class_id = 0;
418 Protocol::PacketTypeDef<P>::PacketTypeDef(unsigned i):
420 compound(new CompoundDef<P, NullSerializer<P> >(NullSerializer<P>()))
423 class_id = next_class_id++;
427 Protocol::PacketTypeDef<P>::~PacketTypeDef()
434 void Protocol::PacketTypeDef<P>::set_serializer(const S &ser)
437 compound = new CompoundDef<P, S>(ser);
441 std::string Protocol::PacketTypeDef<P>::describe() const
443 return compound->describe();
447 char *Protocol::PacketTypeDef<P>::serialize(const P &pkt, char *buf, char *end) const
449 return compound->serialize(pkt, buf, end);
453 const char *Protocol::PacketTypeDef<P>::deserialize(P &pkt, const char *buf, const char *end) const
455 return compound->deserialize(pkt, buf, end);
459 const char *Protocol::PacketTypeDef<P>::dispatch(ReceiverBase &rcv, const char *buf, const char *end) const
461 PacketReceiver<P> *prcv = dynamic_cast<PacketReceiver<P> *>(&rcv);
463 throw bad_packet("unsupported");
465 buf = deserialize(pkt, buf, end);
471 template<typename P, typename S>
472 Protocol::PacketDefBuilder<P, S>::PacketDefBuilder(const Protocol &p, PacketTypeDef<P> &k, const S &s):
478 template<typename P, typename S>
480 Protocol::PacketDefBuilder<P, typename S::template Next<T>::Type> Protocol::PacketDefBuilder<P, S>::operator()(T P::*ptr)
482 typename S::template Next<T>::Type next_ser(serializer, ptr, protocol);
483 pktdef.set_serializer(next_ser);
484 return PacketDefBuilder<P, typename S::template Next<T>::Type>(protocol, pktdef, next_ser);