3 This file is part of libmspnet
4 Copyright © 2009 Mikkosoft Productions, Mikko Rasa
5 Distributed under the LGPL
8 #ifndef MSP_NET_PROTOCOL_H_
9 #define MSP_NET_PROTOCOL_H_
13 #include <msp/core/except.h>
27 PacketDefBase(unsigned i): id(i) { }
29 virtual ~PacketDefBase() { }
30 virtual unsigned get_class_id() const =0;
31 unsigned get_id() const { return id; }
32 virtual const char *disassemble(ReceiverBase &, const char *, const char *) const =0;
34 static unsigned next_class_id;
43 virtual ~FieldBase() { }
44 virtual char *assemble(const P &, char *, char *) const =0;
45 virtual const char *disassemble(P &, const char *, const char *) const =0;
48 template<typename P, typename T>
49 class Field: public FieldBase<P>
55 Field(T P::*p): ptr(p) { }
57 virtual char *assemble(const P &p, char *d, char *e) const
58 { return assemble_field(p.*ptr, d, e); }
60 virtual const char *disassemble(P &p, const char *d, const char *e) const
61 { return disassemble_field(p.*ptr, d, e); }
66 class PacketDef: public PacketDefBase
69 std::vector<FieldBase<P> *> fields;
72 PacketDef(unsigned i): PacketDefBase(i)
73 { if(!class_id) class_id=next_class_id++; }
77 for(typename std::vector<FieldBase<P> *>::const_iterator i=fields.begin(); i!=fields.end(); ++i)
81 virtual unsigned get_class_id() const { return class_id; }
84 PacketDef &operator()(T P::*p)
85 { fields.push_back(new Field<P, T>(p)); return *this; }
87 char *assemble(const P &p, char *d, char *e) const
89 for(typename std::vector<FieldBase<P> *>::const_iterator i=fields.begin(); i!=fields.end(); ++i)
90 d=(*i)->assemble(p, d, e);
94 const char *disassemble(ReceiverBase &r, const char *d, const char *e) const
96 PacketReceiver<P> *prcv=dynamic_cast<PacketReceiver<P> *>(&r);
98 throw Exception("Packet type not supported by receiver");
100 for(typename std::vector<FieldBase<P> *>::const_iterator i=fields.begin(); i!=fields.end(); ++i)
101 d=(*i)->disassemble(pkt, d, e);
106 static unsigned class_id;
109 typedef std::map<unsigned, PacketDefBase *> PacketMap;
111 unsigned next_packet_id;
112 PacketMap packet_class_defs;
113 PacketMap packet_id_defs;
115 Protocol(unsigned =1);
120 void add_packet(PacketDefBase &);
126 PacketDef<P> *pdef=new PacketDef<P>(next_packet_id++);
131 const PacketDefBase &get_packet_by_class(unsigned) const;
132 const PacketDefBase &get_packet_by_id(unsigned) const;
136 unsigned assemble(const P &pkt, char *buf, unsigned size) const
138 unsigned id=PacketDef<P>::class_id;
139 const PacketDef<P> &pdef=static_cast<const PacketDef<P> &>(get_packet_by_class(id));
140 char *ptr=pdef.assemble(pkt, buf+4, buf+size);
141 assemble_header(buf, pdef.get_id(), (size=ptr-buf));
145 unsigned disassemble(ReceiverBase &, const char *, unsigned) const;
147 unsigned get_packet_size(const char *, unsigned) const;
149 unsigned get_hash() const;
152 static void assemble_header(char *, unsigned, unsigned);
155 static char *assemble_field(const T &, char *, char *);
158 static const char *disassemble_field(T &, const char *, const char *);
162 unsigned Protocol::PacketDef<P>::class_id=0;