644a220288a9ca2084c45251556b3ee77f1774c0
[invirt/third/libt4.git] / rpc / marshall.h
1 #ifndef marshall_h
2 #define marshall_h
3
4 #include <iostream>
5 #include <sstream>
6 #include <string>
7 #include <vector>
8 #include <map>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <cstddef>
12 #include <inttypes.h>
13 #include "lang/verify.h"
14
15 struct req_header {
16         req_header(int x=0, int p=0, int c = 0, int s = 0, int xi = 0):
17                 xid(x), proc(p), clt_nonce(c), srv_nonce(s), xid_rep(xi) {}
18         int xid;
19         int proc;
20         unsigned int clt_nonce;
21         unsigned int srv_nonce;
22         int xid_rep;
23 };
24
25 struct reply_header {
26         reply_header(int x=0, int r=0): xid(x), ret(r) {}
27         int xid;
28         int ret;
29 };
30
31 typedef uint64_t rpc_checksum_t;
32 typedef int rpc_sz_t;
33
34 //size of initial buffer allocation 
35 #define DEFAULT_RPC_SZ 1024
36 #define RPC_HEADER_SZ_NO_CHECKSUM (std::max(sizeof(req_header), sizeof(reply_header)) + sizeof(rpc_sz_t))
37 #if RPC_CHECKSUMMING
38 //size of rpc_header includes a 4-byte int to be filled by tcpchan and uint64_t checksum
39 #define RPC_HEADER_SZ (RPC_HEADER_SZ_NO_CHECKSUM + sizeof(rpc_checksum_t))
40 #else
41 #define RPC_HEADER_SZ (RPC_HEADER_SZ_NO_CHECKSUM)
42 #endif
43
44 class marshall {
45         private:
46                 char *_buf;     // Base of the raw bytes buffer (dynamically readjusted)
47                 int _capa;      // Capacity of the buffer
48                 int _ind;       // Read/write head position
49
50         public:
51                 marshall() {
52                         _buf = (char *) malloc(sizeof(char)*DEFAULT_RPC_SZ);
53                         VERIFY(_buf);
54                         _capa = DEFAULT_RPC_SZ;
55                         _ind = RPC_HEADER_SZ;
56                 }
57
58                 ~marshall() { 
59                         if (_buf) 
60                                 free(_buf); 
61                 }
62
63                 int size() { return _ind;}
64                 char *cstr() { return _buf;}
65
66                 void rawbyte(unsigned char);
67                 void rawbytes(const char *, int);
68
69                 // Return the current content (excluding header) as a string
70                 std::string get_content() { 
71                         return std::string(_buf+RPC_HEADER_SZ,_ind-RPC_HEADER_SZ);
72                 }
73
74                 // Return the current content (excluding header) as a string
75                 std::string str() {
76                         return get_content();
77                 }
78
79                 void pack(int i);
80
81                 void pack_req_header(const req_header &h) {
82                         int saved_sz = _ind;
83                         //leave the first 4-byte empty for channel to fill size of pdu
84                         _ind = sizeof(rpc_sz_t); 
85 #if RPC_CHECKSUMMING
86                         _ind += sizeof(rpc_checksum_t);
87 #endif
88                         pack(h.xid);
89                         pack(h.proc);
90                         pack((int)h.clt_nonce);
91                         pack((int)h.srv_nonce);
92                         pack(h.xid_rep);
93                         _ind = saved_sz;
94                 }
95
96                 void pack_reply_header(const reply_header &h) {
97                         int saved_sz = _ind;
98                         //leave the first 4-byte empty for channel to fill size of pdu
99                         _ind = sizeof(rpc_sz_t); 
100 #if RPC_CHECKSUMMING
101                         _ind += sizeof(rpc_checksum_t);
102 #endif
103                         pack(h.xid);
104                         pack(h.ret);
105                         _ind = saved_sz;
106                 }
107
108                 void take_buf(char **b, int *s) {
109                         *b = _buf;
110                         *s = _ind;
111                         _buf = NULL;
112                         _ind = 0;
113                         return;
114                 }
115 };
116 marshall& operator<<(marshall &, bool);
117 marshall& operator<<(marshall &, unsigned int);
118 marshall& operator<<(marshall &, int);
119 marshall& operator<<(marshall &, unsigned char);
120 marshall& operator<<(marshall &, char);
121 marshall& operator<<(marshall &, unsigned short);
122 marshall& operator<<(marshall &, short);
123 marshall& operator<<(marshall &, unsigned long long);
124 marshall& operator<<(marshall &, const std::string &);
125
126 class unmarshall {
127         private:
128                 char *_buf;
129                 int _sz;
130                 int _ind;
131                 bool _ok;
132         public:
133                 unmarshall(): _buf(NULL),_sz(0),_ind(0),_ok(false) {}
134                 unmarshall(char *b, int sz): _buf(b),_sz(sz),_ind(),_ok(true) {}
135                 unmarshall(const std::string &s) : _buf(NULL),_sz(0),_ind(0),_ok(false) 
136                 {
137                         //take the content which does not exclude a RPC header from a string
138                         take_content(s);
139                 }
140                 ~unmarshall() {
141                         if (_buf) free(_buf);
142                 }
143
144                 //take contents from another unmarshall object
145                 void take_in(unmarshall &another);
146
147                 //take the content which does not exclude a RPC header from a string
148                 void take_content(const std::string &s) {
149                         _sz = s.size()+RPC_HEADER_SZ;
150                         _buf = (char *)realloc(_buf,_sz);
151                         VERIFY(_buf);
152                         _ind = RPC_HEADER_SZ;
153                         memcpy(_buf+_ind, s.data(), s.size());
154                         _ok = true;
155                 }
156
157                 bool ok() { return _ok; }
158                 char *cstr() { return _buf;}
159                 bool okdone();
160                 unsigned int rawbyte();
161                 void rawbytes(std::string &s, unsigned int n);
162
163                 int ind() { return _ind;}
164                 int size() { return _sz;}
165                 void unpack(int *); //non-const ref
166                 void take_buf(char **b, int *sz) {
167                         *b = _buf;
168                         *sz = _sz;
169                         _sz = _ind = 0;
170                         _buf = NULL;
171                 }
172
173                 void unpack_req_header(req_header *h) {
174                         //the first 4-byte is for channel to fill size of pdu
175                         _ind = sizeof(rpc_sz_t); 
176 #if RPC_CHECKSUMMING
177                         _ind += sizeof(rpc_checksum_t);
178 #endif
179                         unpack(&h->xid);
180                         unpack(&h->proc);
181                         unpack((int *)&h->clt_nonce);
182                         unpack((int *)&h->srv_nonce);
183                         unpack(&h->xid_rep);
184                         _ind = RPC_HEADER_SZ;
185                 }
186
187                 void unpack_reply_header(reply_header *h) {
188                         //the first 4-byte is for channel to fill size of pdu
189                         _ind = sizeof(rpc_sz_t); 
190 #if RPC_CHECKSUMMING
191                         _ind += sizeof(rpc_checksum_t);
192 #endif
193                         unpack(&h->xid);
194                         unpack(&h->ret);
195                         _ind = RPC_HEADER_SZ;
196                 }
197 };
198
199 unmarshall& operator>>(unmarshall &, bool &);
200 unmarshall& operator>>(unmarshall &, unsigned char &);
201 unmarshall& operator>>(unmarshall &, char &);
202 unmarshall& operator>>(unmarshall &, unsigned short &);
203 unmarshall& operator>>(unmarshall &, short &);
204 unmarshall& operator>>(unmarshall &, unsigned int &);
205 unmarshall& operator>>(unmarshall &, int &);
206 unmarshall& operator>>(unmarshall &, unsigned long long &);
207 unmarshall& operator>>(unmarshall &, std::string &);
208
209 template <class C> marshall &
210 operator<<(marshall &m, std::vector<C> v)
211 {
212         m << (unsigned int) v.size();
213         for(unsigned i = 0; i < v.size(); i++)
214                 m << v[i];
215         return m;
216 }
217
218 template <class C> unmarshall &
219 operator>>(unmarshall &u, std::vector<C> &v)
220 {
221         unsigned n;
222         u >> n;
223         for(unsigned i = 0; i < n; i++){
224                 C z;
225                 u >> z;
226                 v.push_back(z);
227         }
228         return u;
229 }
230
231 template <class A, class B> marshall &
232 operator<<(marshall &m, const std::map<A,B> &d) {
233         typename std::map<A,B>::const_iterator i;
234
235         m << (unsigned int) d.size();
236
237         for (i = d.begin(); i != d.end(); i++) {
238                 m << i->first << i->second;
239         }
240         return m;
241 }
242
243 template <class A, class B> unmarshall &
244 operator>>(unmarshall &u, std::map<A,B> &d) {
245         unsigned int n;
246         u >> n;
247
248         d.clear();
249
250         for (unsigned int lcv = 0; lcv < n; lcv++) {
251                 A a;
252                 B b;
253                 u >> a >> b;
254                 d[a] = b;
255         }
256         return u;
257 }
258
259 #endif