]> git.tdb.fi Git - libs/net.git/blob - source/net/protocol.h
f6c382c9f1ca003e2dbb982e0d7f59867c3a5ae3
[libs/net.git] / source / net / protocol.h
1 #ifndef MSP_NET_PROTOCOL_H_
2 #define MSP_NET_PROTOCOL_H_
3
4 #include <map>
5 #include <stdexcept>
6 #include <vector>
7 #include <msp/core/inttypes.h>
8 #include "receiver.h"
9
10 namespace Msp {
11 namespace Net {
12
13 class bad_packet: public std::runtime_error
14 {
15 public:
16         bad_packet(const std::string &w): std::runtime_error(w) { }
17         virtual ~bad_packet() throw() { }
18 };
19
20
21 class buffer_error: public std::runtime_error
22 {
23 public:
24         buffer_error(const std::string &w): std::runtime_error(w) { }
25         virtual ~buffer_error() throw() { }
26 };
27
28
29 class Protocol
30 {
31 private:
32         template<typename T, UInt8 K>
33         struct BasicTraits;
34
35         template<typename T>
36         struct Traits;
37
38         template<typename C>
39         struct CompoundTypeDef
40         {
41                 virtual ~CompoundTypeDef() { }
42
43                 virtual char *serialize(const C &, char *, char *) const = 0;
44                 virtual const char *deserialize(C &, const char *, const char *) const = 0;
45         };
46
47         template<typename C, typename S>
48         struct CompoundDef: public CompoundTypeDef<C>
49         {
50                 S *serializer;
51
52                 CompoundDef(const S &);
53                 virtual ~CompoundDef();
54
55                 virtual char *serialize(const C &, char *, char *) const;
56                 virtual const char *deserialize(C &, const char *, const char *) const;
57         };
58
59         template<typename T>
60         class BasicSerializer
61         {
62         public:
63                 typedef T ValueType;
64
65                 BasicSerializer(const Protocol &) { }
66
67                 char *serialize(const T &, char *, char *) const;
68                 const char *deserialize(T &, const char *, const char *) const;
69         };
70
71         class StringSerializer
72         {
73         public:
74                 typedef std::string ValueType;
75
76         private:
77                 BasicSerializer<UInt16> length_serializer;
78
79         public:
80                 StringSerializer(const Protocol &);
81
82                 char *serialize(const std::string &, char *, char *) const;
83                 const char *deserialize(std::string &, const char *, const char *) const;
84         };
85
86         template<typename A>
87         class ArraySerializer
88         {
89         public:
90                 typedef A ValueType;
91
92         private:
93                 BasicSerializer<UInt16> length_serializer;
94                 typename Traits<typename A::value_type>::Serializer element_serializer;
95
96         public:
97                 ArraySerializer(const Protocol &);
98
99                 char *serialize(const A &, char *, char *) const;
100                 const char *deserialize(A &, const char *, const char *) const;
101         };
102
103         template<typename P, typename Head, typename S>
104         class Serializer: public Head
105         {
106         public:
107                 template<typename N>
108                 struct Next
109                 {
110                         typedef Serializer<P, Serializer<P, Head, S>, typename Traits<N>::Serializer> Type;
111                 };
112
113         private:
114                 typedef typename S::ValueType P::*Pointer;
115
116                 Pointer ptr;
117                 S ser;
118
119         public:
120                 Serializer(const Head &, Pointer, const Protocol &);
121
122                 char *serialize(const P &, char *, char *) const;
123                 const char *deserialize(P &, const char *, const char *) const;
124         };
125
126         template<typename P>
127         class NullSerializer
128         {
129         public:
130                 template<typename N>
131                 struct Next
132                 {
133                         typedef Serializer<P, NullSerializer, typename Traits<N>::Serializer> Type;
134                 };
135
136                 char *serialize(const P &, char *b, char *) const { return b; }
137                 const char *deserialize(P &, const char *b, const char *) const { return b; }
138         };
139
140         class PacketDefBase
141         {
142         protected:
143                 unsigned id;
144
145                 static unsigned next_class_id;
146
147                 PacketDefBase(unsigned);
148         public:
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;
153         };
154
155         template<typename P>
156         class PacketTypeDef: public PacketDefBase
157         {
158         private:
159                 CompoundTypeDef<P> *compound;
160
161                 static unsigned class_id;
162
163         public:
164                 PacketTypeDef(unsigned);
165                 ~PacketTypeDef();
166
167                 static unsigned get_static_class_id() { return class_id; }
168                 virtual unsigned get_class_id() const { return class_id; }
169
170                 template<typename S>
171                 void set_serializer(const S &);
172
173                 const CompoundTypeDef<P> &get_compound() const { return *compound; }
174
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;
178         };
179
180         template<typename P, typename S>
181         class PacketDefBuilder
182         {
183         private:
184                 const Protocol &protocol;
185                 PacketTypeDef<P> &pktdef;
186                 S serializer;
187
188         public:
189                 PacketDefBuilder(const Protocol &, PacketTypeDef<P> &, const S &);
190                 
191                 template<typename T>
192                 PacketDefBuilder<P, typename S::template Next<T>::Type> operator()(T P::*);
193         };
194
195         struct PacketHeader
196         {
197                 UInt16 type;
198                 UInt16 length;
199
200                 PacketHeader();
201                 PacketHeader(UInt16, UInt16);
202         };
203
204         typedef std::map<unsigned, PacketDefBase *> PacketMap;
205
206         PacketTypeDef<PacketHeader> header_def;
207         unsigned next_packet_id;
208         PacketMap packet_class_defs;
209         PacketMap packet_id_defs;
210
211 protected:
212         Protocol(unsigned = 1);
213 public:
214         ~Protocol();
215
216 private:
217         void add_packet(PacketDefBase *);
218
219 protected:
220         template<typename P>
221         PacketDefBuilder<P, NullSerializer<P> > add();
222
223         const PacketDefBase &get_packet_by_class_id(unsigned) const;
224         const PacketDefBase &get_packet_by_id(unsigned) const;
225
226         template<typename P>
227         const PacketTypeDef<P> &get_packet_by_class() const;
228
229 public:
230         template<typename P>
231         unsigned serialize(const P &, char *, unsigned) const;
232
233         unsigned get_packet_size(const char *, unsigned) const;
234         unsigned dispatch(ReceiverBase &, const char *, unsigned) const;
235
236         unsigned get_hash() const;
237 };
238
239
240 template<typename P>
241 Protocol::PacketDefBuilder<P, Protocol::NullSerializer<P> > Protocol::add()
242 {
243         PacketTypeDef<P> *pdef = new PacketTypeDef<P>(next_packet_id++);
244         add_packet(pdef);
245         return PacketDefBuilder<P, NullSerializer<P> >(*this, *pdef, NullSerializer<P>());
246 }
247
248 template<typename P>
249 const Protocol::PacketTypeDef<P> &Protocol::get_packet_by_class() const
250 {
251         const PacketDefBase &pdef = get_packet_by_class_id(PacketTypeDef<P>::get_static_class_id());
252         return static_cast<const PacketTypeDef<P> &>(pdef);
253 }
254
255 template<typename P>
256 unsigned Protocol::serialize(const P &pkt, char *buf, unsigned size) const
257 {
258         const PacketTypeDef<P> &pdef = get_packet_by_class<P>();
259         char *ptr = pdef.serialize(pkt, buf+4, buf+size);
260         size = ptr-buf;
261         header_def.serialize(PacketHeader(pdef.get_id(), size), buf, buf+4);
262         return size;
263 }
264
265
266 template<typename T, UInt8 K>
267 struct Protocol::BasicTraits
268 {
269         typedef BasicSerializer<T> Serializer;
270 };
271
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> { };
282
283 template<> struct Protocol::Traits<std::string>
284 {
285         typedef StringSerializer Serializer;
286 };
287
288 template<typename T>
289 struct Protocol::Traits<std::vector<T> >
290 {
291         typedef ArraySerializer<std::vector<T> > Serializer;
292 };
293
294
295
296 template<typename C, typename S>
297 Protocol::CompoundDef<C, S>::CompoundDef(const S &s):
298         serializer(new S(s))
299 { }
300
301 template<typename C, typename S>
302 Protocol::CompoundDef<C, S>::~CompoundDef()
303 {
304         delete serializer;
305 }
306
307 template<typename C, typename S>
308 char *Protocol::CompoundDef<C, S>::serialize(const C &com, char *buf, char *end) const
309 {
310         return serializer->serialize(com, buf, end);
311 }
312
313 template<typename C, typename S>
314 const char *Protocol::CompoundDef<C, S>::deserialize(C &com, const char *buf, const char *end) const
315 {
316         return serializer->deserialize(com, buf, end);
317 }
318
319
320 template<typename A>
321 Protocol::ArraySerializer<A>::ArraySerializer(const Protocol &proto):
322         length_serializer(proto),
323         element_serializer(proto)
324 { }
325
326 template<typename A>
327 char *Protocol::ArraySerializer<A>::serialize(const A &array, char *buf, char *end) const
328 {
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);
332         return buf;
333 }
334
335 template<typename A>
336 const char *Protocol::ArraySerializer<A>::deserialize(A &array, const char *buf, const char *end) const
337 {
338         UInt16 length;
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);
343         return buf;
344 }
345
346
347 template<typename P, typename Head, typename S>
348 Protocol::Serializer<P, Head, S>::Serializer(const Head &h, Pointer p, const Protocol &proto):
349         Head(h),
350         ptr(p),
351         ser(proto)
352 { }
353
354 template<typename P, typename Head, typename S>
355 char * Protocol::Serializer<P, Head, S>::serialize(const P &pkt, char *buf, char *end) const
356 {
357         buf = Head::serialize(pkt, buf, end);
358         return ser.serialize(pkt.*ptr, buf, end);
359 }
360
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
363 {
364         buf = Head::deserialize(pkt, buf, end);
365         return ser.deserialize(pkt.*ptr, buf, end);
366 }
367
368
369 template<typename P>
370 unsigned Protocol::PacketTypeDef<P>::class_id = 0;
371
372 template<typename P>
373 Protocol::PacketTypeDef<P>::PacketTypeDef(unsigned i):
374         PacketDefBase(i),
375         compound(new CompoundDef<P, NullSerializer<P> >(NullSerializer<P>()))
376 {
377         if(!class_id)
378                 class_id = next_class_id++;
379 }
380
381 template<typename P>
382 Protocol::PacketTypeDef<P>::~PacketTypeDef()
383 {
384         delete compound;
385 }
386
387 template<typename P>
388 template<typename S>
389 void Protocol::PacketTypeDef<P>::set_serializer(const S &ser)
390 {
391         delete compound;
392         compound = new CompoundDef<P, S>(ser);
393 }
394
395 template<typename P>
396 char *Protocol::PacketTypeDef<P>::serialize(const P &pkt, char *buf, char *end) const
397 {
398         return compound->serialize(pkt, buf, end);
399 }
400
401 template<typename P>
402 const char *Protocol::PacketTypeDef<P>::deserialize(P &pkt, const char *buf, const char *end) const
403 {
404         return compound->deserialize(pkt, buf, end);
405 }
406
407 template<typename P>
408 const char *Protocol::PacketTypeDef<P>::dispatch(ReceiverBase &rcv, const char *buf, const char *end) const
409 {
410         PacketReceiver<P> *prcv = dynamic_cast<PacketReceiver<P> *>(&rcv);
411         if(!prcv)
412                 throw bad_packet("unsupported");
413         P pkt;
414         buf = deserialize(pkt, buf, end);
415         prcv->receive(pkt);
416         return buf;
417 }
418
419
420 template<typename P, typename S>
421 Protocol::PacketDefBuilder<P, S>::PacketDefBuilder(const Protocol &p, PacketTypeDef<P> &k, const S &s):
422         protocol(p),
423         pktdef(k),
424         serializer(s)
425 { }
426
427 template<typename P, typename S>
428 template<typename T>
429 Protocol::PacketDefBuilder<P, typename S::template Next<T>::Type> Protocol::PacketDefBuilder<P, S>::operator()(T P::*ptr)
430 {
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);
434 }
435
436 } // namespace Net
437 } // namespace Msp
438
439 #endif