d7f1dff838924c1e7b8ef74e714e9b02794bffb7
[invirt/third/libt4.git] / rpc / marshall.h
1 #ifndef marshall_h
2 #define marshall_h
3
4 #include "types.h"
5
6 // for structs or classes containing a MEMBERS declaration
7 class marshall;
8 class unmarshall;
9 #define FORWARD_MARSHALLABLE(_c_) \
10 extern unmarshall & operator>>(unmarshall &u, typename remove_reference<_c_>::type &a); \
11 extern marshall & operator<<(marshall &m, const _c_ a);
12 #define MARSHALLABLE(_c_) \
13 inline unmarshall & operator>>(unmarshall &u, _c_ &a) { return u >> a._tuple_(); } \
14 inline marshall & operator<<(marshall &m, const _c_ a) { return m << a._tuple_(); }
15
16 // for plain old data
17 #define MARSHALL_RAW_NETWORK_ORDER_AS(_c_, _d_) \
18 marshall & operator<<(marshall &m, _c_ x) { _d_ y = hton((_d_)x); m.rawbytes(&y, sizeof(_d_)); return m; } \
19 unmarshall & operator>>(unmarshall &u, _c_ &x) { _d_ y; u.rawbytes(&y, sizeof(_d_)); x = (_c_)ntoh(y); return u; }
20
21 #define MARSHALL_RAW_NETWORK_ORDER(_c_) MARSHALL_RAW_NETWORK_ORDER_AS(_c_, _c_)
22
23 using proc_t = uint32_t;
24 using status_t = int32_t;
25
26 struct request_header {
27     int xid;
28     proc_t proc;
29     unsigned int clt_nonce;
30     unsigned int srv_nonce;
31     int xid_rep;
32
33     MEMBERS(xid, proc, clt_nonce, srv_nonce, xid_rep)
34 };
35
36 FORWARD_MARSHALLABLE(request_header)
37 ENDIAN_SWAPPABLE(request_header)
38
39 struct reply_header {
40     int xid;
41     int ret;
42
43     MEMBERS(xid, ret)
44 };
45
46 FORWARD_MARSHALLABLE(reply_header)
47 ENDIAN_SWAPPABLE(reply_header)
48
49 typedef int rpc_sz_t;
50
51 const size_t RPC_HEADER_SZ = max(sizeof(request_header), sizeof(reply_header)) + sizeof(rpc_sz_t);
52 const size_t DEFAULT_RPC_SZ = 1024; // size of initial buffer allocation
53
54 // Template parameter pack expansion is not allowed in certain contexts, but
55 // brace initializers (for instance, calls to constructors of empty structs)
56 // are fair game.  
57 struct pass { template <typename... Args> inline pass(Args&&...) {} };
58
59 class marshall {
60     private:
61         string buf_ = string(DEFAULT_RPC_SZ, 0); // Raw bytes buffer
62         size_t index_ = RPC_HEADER_SZ; // Read/write head position
63
64         inline void reserve(size_t n) {
65             if (index_+n > buf_.size())
66                 buf_.resize(index_+n);
67         }
68     public:
69         template <typename... Args>
70         marshall(const Args&... args) {
71             (void)pass{(*this << args)...};
72         }
73
74         void rawbytes(const void *p, size_t n) {
75             reserve(n);
76             copy((char *)p, (char *)p+n, &buf_[index_]);
77             index_ += n;
78         }
79
80         // with header
81         operator string () const { return buf_.substr(0,index_); }
82         // without header
83         string content() { return buf_.substr(RPC_HEADER_SZ,index_-RPC_HEADER_SZ); }
84
85         template <class T>
86         void pack_header(const T &h) {
87             VERIFY(sizeof(T)+sizeof(rpc_sz_t) <= RPC_HEADER_SZ);
88             size_t saved_sz = index_;
89             index_ = sizeof(rpc_sz_t); // first 4 bytes hold length field
90             *this << h;
91             index_ = saved_sz;
92         }
93 };
94
95 FORWARD_MARSHALLABLE(bool);
96 FORWARD_MARSHALLABLE(uint8_t);
97 FORWARD_MARSHALLABLE(int8_t);
98 FORWARD_MARSHALLABLE(uint16_t);
99 FORWARD_MARSHALLABLE(int16_t);
100 FORWARD_MARSHALLABLE(uint32_t);
101 FORWARD_MARSHALLABLE(int32_t);
102 FORWARD_MARSHALLABLE(size_t);
103 FORWARD_MARSHALLABLE(uint64_t);
104 FORWARD_MARSHALLABLE(int64_t);
105 FORWARD_MARSHALLABLE(string &);
106
107 template <class A> typename enable_if<is_iterable<A>::value, marshall>::type &
108 operator<<(marshall &m, const A &x) {
109     m << (unsigned int)x.size();
110     for (const auto &a : x)
111         m << a;
112     return m;
113 }
114
115 template <class A, class B> marshall &
116 operator<<(marshall &m, const pair<A,B> &d) {
117     return m << d.first << d.second;
118 }
119
120 template<typename E>
121 using enum_type_t = typename enable_if<is_enum<E>::value, typename underlying_type<E>::type>::type;
122 template<typename E> constexpr inline enum_type_t<E> from_enum(E e) noexcept { return (enum_type_t<E>)e; }
123 template<typename E> constexpr inline E to_enum(enum_type_t<E> value) noexcept { return (E)value; }
124
125 template <class E> typename enable_if<is_enum<E>::value, marshall>::type &
126 operator<<(marshall &m, E e) {
127     return m << from_enum(e);
128 }
129
130 template <class E> typename enable_if<is_enum<E>::value, unmarshall>::type &
131 operator>>(unmarshall &u, E &e);
132
133 class unmarshall {
134     private:
135         string buf_;
136         size_t index_ = 0;
137         bool ok_ = false;
138
139         inline bool ensure(size_t n) {
140             if (index_+n > buf_.size())
141                 ok_ = false;
142             return ok_;
143         }
144     public:
145         unmarshall() {}
146         unmarshall(const string &s, bool has_header)
147             : buf_(s),index_(RPC_HEADER_SZ) {
148             if (!has_header)
149                 buf_.insert(0, RPC_HEADER_SZ, 0);
150             ok_ = (buf_.size() >= RPC_HEADER_SZ);
151         }
152
153         bool ok() const { return ok_; }
154         bool okdone() const { return ok_ && index_ == buf_.size(); }
155
156         void rawbytes(void * t, size_t n) {
157             VERIFY(ensure(n));
158             copy(&buf_[index_], &buf_[index_+n], (char *)t);
159             index_ += n;
160         }
161
162         template <class T>
163         void unpack_header(T & h) {
164             // first 4 bytes hold length field
165             VERIFY(sizeof(T)+sizeof(rpc_sz_t) <= RPC_HEADER_SZ);
166             index_ = sizeof(rpc_sz_t);
167             *this >> h;
168             index_ = RPC_HEADER_SZ;
169         }
170
171         template <class T> inline T grab() { T t; *this >> t; return t; }
172 };
173
174 template <class A> typename enable_if<is_iterable<A>::value, unmarshall>::type &
175 operator>>(unmarshall &u, A &x) {
176     unsigned n = u.grab<unsigned>();
177     x.clear();
178     while (n--)
179         x.emplace_back(u.grab<typename A::value_type>());
180     return u;
181 }
182
183 template <class A, class B> unmarshall &
184 operator>>(unmarshall &u, map<A,B> &x) {
185     unsigned n = u.grab<unsigned>();
186     x.clear();
187     while (n--)
188         x.emplace(u.grab<pair<A,B>>());
189     return u;
190 }
191
192 template <class A, class B> unmarshall &
193 operator>>(unmarshall &u, pair<A,B> &d) {
194     return u >> d.first >> d.second;
195 }
196
197 template <class E> typename enable_if<is_enum<E>::value, unmarshall>::type &
198 operator>>(unmarshall &u, E &e) {
199     e = to_enum<E>(u.grab<enum_type_t<E>>());
200     return u;
201 }
202
203 typedef function<int(unmarshall &, marshall &)> handler;
204
205 //
206 // Automatic marshalling wrappers for RPC handlers
207 //
208
209 // PAI 2013/09/19
210 // C++11 does neither of these two things for us:
211 // 1) Declare variables using a parameter pack expansion, like so
212 //      Args... args;
213 // 2) Call a function with a tuple of the arguments it expects
214 //
215 // We implement an 'invoke' function for functions of the RPC handler
216 // signature, i.e. int(R & r, const Args...)
217 //
218 // One thing we need in order to accomplish this is a way to cause the compiler
219 // to specialize 'invoke' with a parameter pack containing a list of indices
220 // for the elements of the tuple.  This will allow us to call the underlying
221 // function with the exploded contents of the tuple.  The empty type
222 // tuple_indices<size_t...> accomplishes this.  It will be passed in to
223 // 'invoke' as a parameter which will be ignored, but its type will force the
224 // compiler to specialize 'invoke' appropriately.
225
226 // This class encapsulates the default response to runtime unmarshalling
227 // failures.  The templated wrappers below may optionally use a different
228 // class.
229
230 struct VerifyOnFailure {
231     static inline int unmarshall_args_failure() {
232         VERIFY(0);
233         return 0;
234     }
235 };
236
237 // Here's the implementation of 'invoke'.  It could be more general, but this
238 // meets our needs.
239
240 // One for function pointers...
241
242 template <class F, class R, class RV, class args_type, size_t... Indices>
243 typename enable_if<!is_member_function_pointer<F>::value, RV>::type
244 invoke(RV, F f, void *, R & r, args_type & t, tuple_indices<Indices...>) {
245     return f(r, move(get<Indices>(t))...);
246 }
247
248 // And one for pointers to member functions...
249
250 template <class F, class C, class RV, class R, class args_type, size_t... Indices>
251 typename enable_if<is_member_function_pointer<F>::value, RV>::type
252 invoke(RV, F f, C *c, R & r, args_type & t, tuple_indices<Indices...>) {
253     return (c->*f)(r, move(get<Indices>(t))...);
254 }
255
256 // The class marshalled_func_imp uses partial template specialization to
257 // implement the ::wrap static function.  ::wrap takes a function pointer or a
258 // pointer to a member function and returns a handler * object which
259 // unmarshalls arguments, verifies successful unmarshalling, calls the supplied
260 // function, and marshalls the response.
261
262 template <class Functor, class Instance, class Signature,
263           class ErrorHandler=VerifyOnFailure> struct marshalled_func_imp;
264
265 // Here we specialize on the Signature template parameter to obtain the list of
266 // argument types.  Note that we do not assume that the Functor parameter has
267 // the same pattern as Signature; this allows us to ignore the distinctions
268 // between various types of callable objects at this level of abstraction.
269
270 template <class F, class C, class ErrorHandler, class R, class RV, class... Args>
271 struct marshalled_func_imp<F, C, RV(R&, Args...), ErrorHandler> {
272     static inline handler *wrap(F f, C *c=nullptr) {
273         // This type definition corresponds to an empty struct with
274         // template parameters running from 0 up to (# args) - 1.
275         using Indices = typename make_tuple_indices<sizeof...(Args)>::type;
276         // This type definition represents storage for f's unmarshalled
277         // arguments.  decay is (most notably) stripping off const
278         // qualifiers.
279         using ArgsStorage = tuple<typename decay<Args>::type...>;
280         // Allocate a handler (i.e. function) to hold the lambda
281         // which will unmarshall RPCs and call f.
282         return new handler([=](unmarshall &u, marshall &m) -> RV {
283             // Unmarshall each argument with the correct type and store the
284             // result in a tuple.
285             ArgsStorage t = {u.grab<typename decay<Args>::type>()...};
286             // Verify successful unmarshalling of the entire input stream.
287             if (!u.okdone())
288                 return (RV)ErrorHandler::unmarshall_args_failure();
289             // Allocate space for the RPC response -- will be passed into the
290             // function as an lvalue reference.
291             R r;
292             // Perform the invocation.  Note that Indices() calls the default
293             // constructor of the empty struct with the special template
294             // parameters.
295             RV b = invoke(RV(), f, c, r, t, Indices());
296             // Marshall the response.
297             m << r;
298             // Make like a tree.
299             return b;
300         });
301     }
302 };
303
304 // More partial template specialization shenanigans to reduce the number of
305 // parameters which must be provided explicitly and to support a few common
306 // callable types.  C++11 doesn't allow partial function template
307 // specialization, so we use classes (structs).
308
309 template <class Functor, class ErrorHandler=VerifyOnFailure,
310     class Signature=Functor> struct marshalled_func;
311
312 template <class F, class ErrorHandler, class RV, class... Args>
313 struct marshalled_func<F, ErrorHandler, RV(*)(Args...)> :
314     public marshalled_func_imp<F, void, RV(Args...), ErrorHandler> {};
315
316 template <class F, class ErrorHandler, class RV, class C, class... Args>
317 struct marshalled_func<F, ErrorHandler, RV(C::*)(Args...)> :
318     public marshalled_func_imp<F, C, RV(Args...), ErrorHandler> {};
319
320 template <class F, class ErrorHandler, class Signature>
321 struct marshalled_func<F, ErrorHandler, function<Signature>> :
322     public marshalled_func_imp<F, void, Signature, ErrorHandler> {};
323
324 template <class... Args, size_t... Indices> unmarshall &
325 tuple_unmarshall_imp(unmarshall & u, tuple<Args &...> t, tuple_indices<Indices...>) {
326     (void)pass{(u >> get<Indices>(t))...};
327     return u;
328 }
329
330 template <class... Args> unmarshall &
331 operator>>(unmarshall & u, tuple<Args &...> && t) {
332     using Indices = typename make_tuple_indices<sizeof...(Args)>::type;
333     return tuple_unmarshall_imp(u, t, Indices());
334 }
335
336 template <class... Args, size_t... Indices> marshall &
337 tuple_marshall_imp(marshall & m, tuple<Args...> & t, tuple_indices<Indices...>) {
338     (void)pass{(m << get<Indices>(t))...};
339     return m;
340 }
341
342 template <class... Args> marshall &
343 operator<<(marshall & m, tuple<Args...> && t) {
344     using Indices = typename make_tuple_indices<sizeof...(Args)>::type;
345     return tuple_marshall_imp(m, t, Indices());
346 }
347
348 MARSHALLABLE(request_header)
349 MARSHALLABLE(reply_header)
350
351 #endif