]> git.tdb.fi Git - libs/net.git/blob - source/protocol.h
Add function to check if handshake is done
[libs/net.git] / source / protocol.h
1 /* $Id$
2
3 This file is part of libmspnet
4 Copyright © 2009  Mikkosoft Productions, Mikko Rasa
5 Distributed under the LGPL
6 */
7
8 #ifndef MSP_NET_PROTOCOL_H_
9 #define MSP_NET_PROTOCOL_H_
10
11 #include <map>
12 #include <vector>
13 #include <msp/core/except.h>
14 #include "receiver.h"
15
16 namespace Msp {
17 namespace Net {
18
19 class Protocol
20 {
21 private:
22         class PacketDefBase
23         {
24         protected:
25                 unsigned id;
26
27                 PacketDefBase(unsigned i): id(i) { }
28         public:
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;
33
34                 static unsigned next_class_id;
35         };
36
37         template<typename P>
38         class FieldBase
39         {
40         protected:
41                 FieldBase() { }
42         public:
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;
46         };
47
48         template<typename P, typename T>
49         class Field: public FieldBase<P>
50         {
51         private:
52                 T P::*ptr;
53
54         public:
55                 Field(T P::*p): ptr(p) { }
56
57                 virtual char *assemble(const P &p, char *d, char *e) const
58                 { return assemble_field(p.*ptr, d, e); }
59
60                 virtual const char *disassemble(P &p, const char *d, const char *e) const
61                 { return disassemble_field(p.*ptr, d, e); }
62         };
63
64 protected:
65         template<typename P>
66         class PacketDef: public PacketDefBase
67         {
68         private:
69                 std::vector<FieldBase<P> *> fields;
70
71         public:
72                 PacketDef(unsigned i): PacketDefBase(i)
73                 { if(!class_id) class_id=next_class_id++; }
74
75                 ~PacketDef()
76                 {
77                         for(typename std::vector<FieldBase<P> *>::const_iterator i=fields.begin(); i!=fields.end(); ++i)
78                                 delete *i;
79                 }
80
81                 virtual unsigned get_class_id() const { return class_id; }
82
83                 template<typename T>
84                 PacketDef &operator()(T P::*p)
85                 { fields.push_back(new Field<P, T>(p)); return *this; }
86
87                 char *assemble(const P &p, char *d, char *e) const
88                 {
89                         for(typename std::vector<FieldBase<P> *>::const_iterator i=fields.begin(); i!=fields.end(); ++i)
90                                 d=(*i)->assemble(p, d, e);
91                         return d;
92                 }
93
94                 const char *disassemble(ReceiverBase &r, const char *d, const char *e) const
95                 {
96                         PacketReceiver<P> *prcv=dynamic_cast<PacketReceiver<P> *>(&r);
97                         if(!prcv)
98                                 throw Exception("Packet type not supported by receiver");
99                         P pkt;
100                         for(typename std::vector<FieldBase<P> *>::const_iterator i=fields.begin(); i!=fields.end(); ++i)
101                                 d=(*i)->disassemble(pkt, d, e);
102                         prcv->receive(pkt);
103                         return d;
104                 }
105
106                 static unsigned class_id;
107         };
108
109         typedef std::map<unsigned, PacketDefBase *> PacketMap;
110
111         unsigned next_packet_id;
112         PacketMap packet_class_defs;
113         PacketMap packet_id_defs;
114
115         Protocol(unsigned =1);
116 public:
117         ~Protocol();
118
119 private:
120         void add_packet(PacketDefBase &);
121
122 protected:
123         template<typename P>
124         PacketDef<P> &add()
125         {
126                 PacketDef<P> *pdef=new PacketDef<P>(next_packet_id++);
127                 add_packet(*pdef);
128                 return *pdef;
129         }
130
131         const PacketDefBase &get_packet_by_class(unsigned) const;
132         const PacketDefBase &get_packet_by_id(unsigned) const;
133
134 public:
135         template<typename P>
136         unsigned assemble(const P &pkt, char *buf, unsigned size) const
137         {
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));
142                 return size;
143         }
144
145         unsigned disassemble(ReceiverBase &, const char *, unsigned) const;
146
147         unsigned get_packet_size(const char *, unsigned) const;
148
149         unsigned get_hash() const;
150
151 private:
152         static void assemble_header(char *, unsigned, unsigned);
153
154         template<typename T>
155         static char *assemble_field(const T &, char *, char *);
156
157         template<typename T>
158         static const char *disassemble_field(T &, const char *, const char *);
159 };
160
161 template<typename P>
162 unsigned Protocol::PacketDef<P>::class_id=0;
163
164 } // namespace Net
165 } // namespace Msp
166
167 #endif