1275970Scy/*
2275970Scy * Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu>
3275970Scy * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
4275970Scy *
5275970Scy * Redistribution and use in source and binary forms, with or without
6275970Scy * modification, are permitted provided that the following conditions
7275970Scy * are met:
8275970Scy * 1. Redistributions of source code must retain the above copyright
9275970Scy *    notice, this list of conditions and the following disclaimer.
10275970Scy * 2. Redistributions in binary form must reproduce the above copyright
11275970Scy *    notice, this list of conditions and the following disclaimer in the
12275970Scy *    documentation and/or other materials provided with the distribution.
13275970Scy * 3. The name of the author may not be used to endorse or promote products
14275970Scy *    derived from this software without specific prior written permission.
15275970Scy *
16275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17275970Scy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18275970Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19275970Scy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20275970Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21275970Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25275970Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26275970Scy */
27275970Scy#ifndef EVENT2_RPC_H_INCLUDED_
28275970Scy#define EVENT2_RPC_H_INCLUDED_
29275970Scy
30275970Scy#ifdef __cplusplus
31275970Scyextern "C" {
32275970Scy#endif
33275970Scy
34275970Scy/** @file rpc.h
35275970Scy *
36275970Scy * This header files provides basic support for an RPC server and client.
37275970Scy *
38275970Scy * To support RPCs in a server, every supported RPC command needs to be
39275970Scy * defined and registered.
40275970Scy *
41275970Scy * EVRPC_HEADER(SendCommand, Request, Reply);
42275970Scy *
43275970Scy *  SendCommand is the name of the RPC command.
44275970Scy *  Request is the name of a structure generated by event_rpcgen.py.
45275970Scy *    It contains all parameters relating to the SendCommand RPC.  The
46275970Scy *    server needs to fill in the Reply structure.
47275970Scy *  Reply is the name of a structure generated by event_rpcgen.py.  It
48275970Scy *    contains the answer to the RPC.
49275970Scy *
50275970Scy * To register an RPC with an HTTP server, you need to first create an RPC
51275970Scy * base with:
52275970Scy *
53275970Scy *   struct evrpc_base *base = evrpc_init(http);
54275970Scy *
55275970Scy * A specific RPC can then be registered with
56275970Scy *
57275970Scy * EVRPC_REGISTER(base, SendCommand, Request, Reply,  FunctionCB, arg);
58275970Scy *
59275970Scy * when the server receives an appropriately formatted RPC, the user callback
60275970Scy * is invoked.   The callback needs to fill in the reply structure.
61275970Scy *
62275970Scy * void FunctionCB(EVRPC_STRUCT(SendCommand)* rpc, void *arg);
63275970Scy *
64275970Scy * To send the reply, call EVRPC_REQUEST_DONE(rpc);
65275970Scy *
66275970Scy * See the regression test for an example.
67275970Scy */
68275970Scy
69275970Scy/**
70275970Scy   Determines if the member has been set in the message
71275970Scy
72275970Scy   @param msg the message to inspect
73275970Scy   @param member the member variable to test for presences
74275970Scy   @return 1 if it's present or 0 otherwise.
75275970Scy*/
76275970Scy#define EVTAG_HAS(msg, member) \
77275970Scy	((msg)->member##_set == 1)
78275970Scy
79275970Scy#ifndef EVENT2_RPC_COMPAT_H_INCLUDED_
80275970Scy
81275970Scy/**
82275970Scy   Assigns a value to the member in the message.
83275970Scy
84275970Scy   @param msg the message to which to assign a value
85275970Scy   @param member the name of the member variable
86275970Scy   @param value the value to assign
87275970Scy*/
88275970Scy#define EVTAG_ASSIGN(msg, member, value) \
89275970Scy	(*(msg)->base->member##_assign)((msg), (value))
90275970Scy/**
91275970Scy   Assigns a value to the member in the message.
92275970Scy
93275970Scy   @param msg the message to which to assign a value
94275970Scy   @param member the name of the member variable
95275970Scy   @param value the value to assign
96275970Scy   @param len the length of the value
97275970Scy*/
98275970Scy#define EVTAG_ASSIGN_WITH_LEN(msg, member, value, len)	\
99275970Scy	(*(msg)->base->member##_assign)((msg), (value), (len))
100275970Scy/**
101275970Scy   Returns the value for a member.
102275970Scy
103275970Scy   @param msg the message from which to get the value
104275970Scy   @param member the name of the member variable
105275970Scy   @param pvalue a pointer to the variable to hold the value
106275970Scy   @return 0 on success, -1 otherwise.
107275970Scy*/
108275970Scy#define EVTAG_GET(msg, member, pvalue) \
109275970Scy	(*(msg)->base->member##_get)((msg), (pvalue))
110275970Scy/**
111275970Scy   Returns the value for a member.
112275970Scy
113275970Scy   @param msg the message from which to get the value
114275970Scy   @param member the name of the member variable
115275970Scy   @param pvalue a pointer to the variable to hold the value
116275970Scy   @param plen a pointer to the length of the value
117275970Scy   @return 0 on success, -1 otherwise.
118275970Scy*/
119275970Scy#define EVTAG_GET_WITH_LEN(msg, member, pvalue, plen)	\
120275970Scy	(*(msg)->base->member##_get)((msg), (pvalue), (plen))
121275970Scy
122275970Scy#endif  /* EVENT2_RPC_COMPAT_H_INCLUDED_ */
123275970Scy
124275970Scy/**
125275970Scy   Adds a value to an array.
126275970Scy*/
127275970Scy#define EVTAG_ARRAY_ADD_VALUE(msg, member, value) \
128275970Scy	(*(msg)->base->member##_add)((msg), (value))
129275970Scy/**
130275970Scy   Allocates a new entry in the array and returns it.
131275970Scy*/
132275970Scy#define EVTAG_ARRAY_ADD(msg, member) \
133275970Scy	(*(msg)->base->member##_add)(msg)
134275970Scy/**
135275970Scy   Gets a variable at the specified offset from the array.
136275970Scy*/
137275970Scy#define EVTAG_ARRAY_GET(msg, member, offset, pvalue)	\
138275970Scy	(*(msg)->base->member##_get)((msg), (offset), (pvalue))
139275970Scy/**
140275970Scy   Returns the number of entries in the array.
141275970Scy*/
142275970Scy#define EVTAG_ARRAY_LEN(msg, member) ((msg)->member##_length)
143275970Scy
144275970Scy
145275970Scystruct evbuffer;
146275970Scystruct event_base;
147275970Scystruct evrpc_req_generic;
148275970Scystruct evrpc_request_wrapper;
149275970Scystruct evrpc;
150275970Scy
151275970Scy/** The type of a specific RPC Message
152275970Scy *
153275970Scy * @param rpcname the name of the RPC message
154275970Scy */
155275970Scy#define EVRPC_STRUCT(rpcname) struct evrpc_req__##rpcname
156275970Scy
157275970Scystruct evhttp_request;
158275970Scystruct evrpc_status;
159275970Scystruct evrpc_hook_meta;
160275970Scy
161275970Scy/** Creates the definitions and prototypes for an RPC
162275970Scy *
163275970Scy * You need to use EVRPC_HEADER to create structures and function prototypes
164275970Scy * needed by the server and client implementation.  The structures have to be
165275970Scy * defined in an .rpc file and converted to source code via event_rpcgen.py
166275970Scy *
167275970Scy * @param rpcname the name of the RPC
168275970Scy * @param reqstruct the name of the RPC request structure
169275970Scy * @param replystruct the name of the RPC reply structure
170275970Scy * @see EVRPC_GENERATE()
171275970Scy */
172275970Scy#define EVRPC_HEADER(rpcname, reqstruct, rplystruct) \
173275970ScyEVRPC_STRUCT(rpcname) {	\
174275970Scy	struct evrpc_hook_meta *hook_meta; \
175275970Scy	struct reqstruct* request; \
176275970Scy	struct rplystruct* reply; \
177275970Scy	struct evrpc* rpc; \
178275970Scy	struct evhttp_request* http_req; \
179275970Scy	struct evbuffer* rpc_data; \
180275970Scy};								     \
181275970Scyint evrpc_send_request_##rpcname(struct evrpc_pool *, \
182275970Scy    struct reqstruct *, struct rplystruct *, \
183275970Scy    void (*)(struct evrpc_status *, \
184275970Scy	struct reqstruct *, struct rplystruct *, void *cbarg),	\
185275970Scy    void *);
186275970Scy
187275970Scystruct evrpc_pool;
188275970Scy
189275970Scy/** use EVRPC_GENERATE instead */
190275970Scystruct evrpc_request_wrapper *evrpc_make_request_ctx(
191275970Scy	struct evrpc_pool *pool, void *request, void *reply,
192275970Scy	const char *rpcname,
193275970Scy	void (*req_marshal)(struct evbuffer*, void *),
194275970Scy	void (*rpl_clear)(void *),
195275970Scy	int (*rpl_unmarshal)(void *, struct evbuffer *),
196275970Scy	void (*cb)(struct evrpc_status *, void *, void *, void *),
197275970Scy	void *cbarg);
198275970Scy
199275970Scy/** Creates a context structure that contains rpc specific information.
200275970Scy *
201275970Scy * EVRPC_MAKE_CTX is used to populate a RPC specific context that
202275970Scy * contains information about marshaling the RPC data types.
203275970Scy *
204275970Scy * @param rpcname the name of the RPC
205275970Scy * @param reqstruct the name of the RPC request structure
206275970Scy * @param replystruct the name of the RPC reply structure
207275970Scy * @param pool the evrpc_pool over which to make the request
208275970Scy * @param request a pointer to the RPC request structure object
209275970Scy * @param reply a pointer to the RPC reply structure object
210275970Scy * @param cb the callback function to call when the RPC has completed
211275970Scy * @param cbarg the argument to supply to the callback
212275970Scy */
213275970Scy#define EVRPC_MAKE_CTX(rpcname, reqstruct, rplystruct, \
214275970Scy    pool, request, reply, cb, cbarg)					\
215275970Scy	evrpc_make_request_ctx(pool, request, reply,			\
216275970Scy	    #rpcname,							\
217275970Scy	    (void (*)(struct evbuffer *, void *))reqstruct##_marshal,	\
218275970Scy	    (void (*)(void *))rplystruct##_clear,			\
219275970Scy	    (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal, \
220275970Scy	    (void (*)(struct evrpc_status *, void *, void *, void *))cb, \
221275970Scy	    cbarg)
222275970Scy
223275970Scy/** Generates the code for receiving and sending an RPC message
224275970Scy *
225275970Scy * EVRPC_GENERATE is used to create the code corresponding to sending
226275970Scy * and receiving a particular RPC message
227275970Scy *
228275970Scy * @param rpcname the name of the RPC
229275970Scy * @param reqstruct the name of the RPC request structure
230275970Scy * @param replystruct the name of the RPC reply structure
231275970Scy * @see EVRPC_HEADER()
232275970Scy */
233275970Scy#define EVRPC_GENERATE(rpcname, reqstruct, rplystruct)			\
234275970Scy	int evrpc_send_request_##rpcname(struct evrpc_pool *pool,	\
235275970Scy	    struct reqstruct *request, struct rplystruct *reply,	\
236275970Scy	    void (*cb)(struct evrpc_status *,				\
237275970Scy		struct reqstruct *, struct rplystruct *, void *cbarg),	\
238275970Scy	    void *cbarg) {						\
239275970Scy	return evrpc_send_request_generic(pool, request, reply,	\
240275970Scy	    (void (*)(struct evrpc_status *, void *, void *, void *))cb, \
241275970Scy	    cbarg,							\
242275970Scy	    #rpcname,							\
243275970Scy	    (void (*)(struct evbuffer *, void *))reqstruct##_marshal,	\
244275970Scy	    (void (*)(void *))rplystruct##_clear,			\
245275970Scy	    (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal); \
246275970Scy}
247275970Scy
248275970Scy/** Provides access to the HTTP request object underlying an RPC
249275970Scy *
250275970Scy * Access to the underlying http object; can be used to look at headers or
251275970Scy * for getting the remote ip address
252275970Scy *
253275970Scy * @param rpc_req the rpc request structure provided to the server callback
254275970Scy * @return an struct evhttp_request object that can be inspected for
255275970Scy * HTTP headers or sender information.
256275970Scy */
257275970Scy#define EVRPC_REQUEST_HTTP(rpc_req) (rpc_req)->http_req
258275970Scy
259275970Scy/** completes the server response to an rpc request */
260275970Scyvoid evrpc_request_done(struct evrpc_req_generic *req);
261275970Scy
262275970Scy/** accessors for request and reply */
263275970Scyvoid *evrpc_get_request(struct evrpc_req_generic *req);
264275970Scyvoid *evrpc_get_reply(struct evrpc_req_generic *req);
265275970Scy
266275970Scy/** Creates the reply to an RPC request
267275970Scy *
268275970Scy * EVRPC_REQUEST_DONE is used to answer a request; the reply is expected
269275970Scy * to have been filled in.  The request and reply pointers become invalid
270275970Scy * after this call has finished.
271275970Scy *
272275970Scy * @param rpc_req the rpc request structure provided to the server callback
273275970Scy */
274275970Scy#define EVRPC_REQUEST_DONE(rpc_req) do { \
275275970Scy  struct evrpc_req_generic *req_ = (struct evrpc_req_generic *)(rpc_req); \
276275970Scy  evrpc_request_done(req_);					\
277275970Scy} while (0)
278275970Scy
279275970Scy
280275970Scystruct evrpc_base;
281275970Scystruct evhttp;
282275970Scy
283275970Scy/* functions to start up the rpc system */
284275970Scy
285275970Scy/** Creates a new rpc base from which RPC requests can be received
286275970Scy *
287275970Scy * @param server a pointer to an existing HTTP server
288275970Scy * @return a newly allocated evrpc_base struct
289275970Scy * @see evrpc_free()
290275970Scy */
291275970Scystruct evrpc_base *evrpc_init(struct evhttp *server);
292275970Scy
293275970Scy/**
294275970Scy * Frees the evrpc base
295275970Scy *
296275970Scy * For now, you are responsible for making sure that no rpcs are ongoing.
297275970Scy *
298275970Scy * @param base the evrpc_base object to be freed
299275970Scy * @see evrpc_init
300275970Scy */
301275970Scyvoid evrpc_free(struct evrpc_base *base);
302275970Scy
303275970Scy/** register RPCs with the HTTP Server
304275970Scy *
305275970Scy * registers a new RPC with the HTTP server, each RPC needs to have
306275970Scy * a unique name under which it can be identified.
307275970Scy *
308275970Scy * @param base the evrpc_base structure in which the RPC should be
309275970Scy *   registered.
310275970Scy * @param name the name of the RPC
311275970Scy * @param request the name of the RPC request structure
312275970Scy * @param reply the name of the RPC reply structure
313275970Scy * @param callback the callback that should be invoked when the RPC
314275970Scy * is received.  The callback has the following prototype
315275970Scy *   void (*callback)(EVRPC_STRUCT(Message)* rpc, void *arg)
316275970Scy * @param cbarg an additional parameter that can be passed to the callback.
317275970Scy *   The parameter can be used to carry around state.
318275970Scy */
319275970Scy#define EVRPC_REGISTER(base, name, request, reply, callback, cbarg)	\
320275970Scy	evrpc_register_generic(base, #name,				\
321275970Scy	    (void (*)(struct evrpc_req_generic *, void *))callback, cbarg, \
322275970Scy	    (void *(*)(void *))request##_new, NULL,			\
323275970Scy	    (void (*)(void *))request##_free,				\
324275970Scy	    (int (*)(void *, struct evbuffer *))request##_unmarshal,	\
325275970Scy	    (void *(*)(void *))reply##_new, NULL,			\
326275970Scy	    (void (*)(void *))reply##_free, \
327275970Scy	    (int (*)(void *))reply##_complete, \
328275970Scy	    (void (*)(struct evbuffer *, void *))reply##_marshal)
329275970Scy
330275970Scy/**
331275970Scy   Low level function for registering an RPC with a server.
332275970Scy
333275970Scy   Use EVRPC_REGISTER() instead.
334275970Scy
335275970Scy   @see EVRPC_REGISTER()
336275970Scy*/
337275970Scyint evrpc_register_rpc(struct evrpc_base *, struct evrpc *,
338275970Scy    void (*)(struct evrpc_req_generic*, void *), void *);
339275970Scy
340275970Scy/**
341275970Scy * Unregisters an already registered RPC
342275970Scy *
343275970Scy * @param base the evrpc_base object from which to unregister an RPC
344275970Scy * @param name the name of the rpc to unregister
345275970Scy * @return -1 on error or 0 when successful.
346275970Scy * @see EVRPC_REGISTER()
347275970Scy */
348275970Scy#define EVRPC_UNREGISTER(base, name) evrpc_unregister_rpc((base), #name)
349275970Scy
350275970Scyint evrpc_unregister_rpc(struct evrpc_base *base, const char *name);
351275970Scy
352275970Scy/*
353275970Scy * Client-side RPC support
354275970Scy */
355275970Scy
356275970Scystruct evhttp_connection;
357275970Scystruct evrpc_status;
358275970Scy
359275970Scy/** launches an RPC and sends it to the server
360275970Scy *
361275970Scy * EVRPC_MAKE_REQUEST() is used by the client to send an RPC to the server.
362275970Scy *
363275970Scy * @param name the name of the RPC
364275970Scy * @param pool the evrpc_pool that contains the connection objects over which
365275970Scy *   the request should be sent.
366275970Scy * @param request a pointer to the RPC request structure - it contains the
367275970Scy *   data to be sent to the server.
368275970Scy * @param reply a pointer to the RPC reply structure.  It is going to be filled
369275970Scy *   if the request was answered successfully
370275970Scy * @param cb the callback to invoke when the RPC request has been answered
371275970Scy * @param cbarg an additional argument to be passed to the client
372275970Scy * @return 0 on success, -1 on failure
373275970Scy */
374275970Scy#define EVRPC_MAKE_REQUEST(name, pool, request, reply, cb, cbarg)	\
375275970Scy	evrpc_send_request_##name((pool), (request), (reply), (cb), (cbarg))
376275970Scy
377275970Scy/**
378275970Scy   Makes an RPC request based on the provided context.
379275970Scy
380275970Scy   This is a low-level function and should not be used directly
381275970Scy   unless a custom context object is provided.  Use EVRPC_MAKE_REQUEST()
382275970Scy   instead.
383275970Scy
384275970Scy   @param ctx a context from EVRPC_MAKE_CTX()
385275970Scy   @returns 0 on success, -1 otherwise.
386275970Scy   @see EVRPC_MAKE_REQUEST(), EVRPC_MAKE_CTX()
387275970Scy*/
388275970Scyint evrpc_make_request(struct evrpc_request_wrapper *ctx);
389275970Scy
390275970Scy/** creates an rpc connection pool
391275970Scy *
392275970Scy * a pool has a number of connections associated with it.
393275970Scy * rpc requests are always made via a pool.
394275970Scy *
395275970Scy * @param base a pointer to an struct event_based object; can be left NULL
396275970Scy *   in singled-threaded applications
397275970Scy * @return a newly allocated struct evrpc_pool object
398275970Scy * @see evrpc_pool_free()
399275970Scy */
400275970Scystruct evrpc_pool *evrpc_pool_new(struct event_base *base);
401275970Scy/** frees an rpc connection pool
402275970Scy *
403275970Scy * @param pool a pointer to an evrpc_pool allocated via evrpc_pool_new()
404275970Scy * @see evrpc_pool_new()
405275970Scy */
406275970Scyvoid evrpc_pool_free(struct evrpc_pool *pool);
407275970Scy
408275970Scy/**
409275970Scy * Adds a connection over which rpc can be dispatched to the pool.
410275970Scy *
411275970Scy * The connection object must have been newly created.
412275970Scy *
413275970Scy * @param pool the pool to which to add the connection
414275970Scy * @param evcon the connection to add to the pool.
415275970Scy */
416275970Scyvoid evrpc_pool_add_connection(struct evrpc_pool *pool,
417275970Scy    struct evhttp_connection *evcon);
418275970Scy
419275970Scy/**
420275970Scy * Removes a connection from the pool.
421275970Scy *
422275970Scy * The connection object must have been newly created.
423275970Scy *
424275970Scy * @param pool the pool from which to remove the connection
425275970Scy * @param evcon the connection to remove from the pool.
426275970Scy */
427275970Scyvoid evrpc_pool_remove_connection(struct evrpc_pool *pool,
428275970Scy    struct evhttp_connection *evcon);
429275970Scy
430275970Scy/**
431275970Scy * Sets the timeout in secs after which a request has to complete.  The
432275970Scy * RPC is completely aborted if it does not complete by then.  Setting
433275970Scy * the timeout to 0 means that it never timeouts and can be used to
434275970Scy * implement callback type RPCs.
435275970Scy *
436275970Scy * Any connection already in the pool will be updated with the new
437275970Scy * timeout.  Connections added to the pool after set_timeout has be
438275970Scy * called receive the pool timeout only if no timeout has been set
439275970Scy * for the connection itself.
440275970Scy *
441275970Scy * @param pool a pointer to a struct evrpc_pool object
442275970Scy * @param timeout_in_secs the number of seconds after which a request should
443275970Scy *   timeout and a failure be returned to the callback.
444275970Scy */
445275970Scyvoid evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs);
446275970Scy
447275970Scy/**
448275970Scy * Hooks for changing the input and output of RPCs; this can be used to
449275970Scy * implement compression, authentication, encryption, ...
450275970Scy */
451275970Scy
452275970Scyenum EVRPC_HOOK_TYPE {
453275970Scy	EVRPC_INPUT,		/**< apply the function to an input hook */
454275970Scy	EVRPC_OUTPUT		/**< apply the function to an output hook */
455275970Scy};
456275970Scy
457275970Scy#ifndef _WIN32
458275970Scy/** Deprecated alias for EVRPC_INPUT.  Not available on windows, where it
459275970Scy * conflicts with platform headers. */
460275970Scy#define INPUT EVRPC_INPUT
461275970Scy/** Deprecated alias for EVRPC_OUTPUT.  Not available on windows, where it
462275970Scy * conflicts with platform headers. */
463275970Scy#define OUTPUT EVRPC_OUTPUT
464275970Scy#endif
465275970Scy
466275970Scy/**
467275970Scy * Return value from hook processing functions
468275970Scy */
469275970Scy
470275970Scyenum EVRPC_HOOK_RESULT {
471275970Scy	EVRPC_TERMINATE = -1,	/**< indicates the rpc should be terminated */
472275970Scy	EVRPC_CONTINUE = 0,	/**< continue processing the rpc */
473275970Scy	EVRPC_PAUSE = 1		/**< pause processing request until resumed */
474275970Scy};
475275970Scy
476275970Scy/** adds a processing hook to either an rpc base or rpc pool
477275970Scy *
478275970Scy * If a hook returns TERMINATE, the processing is aborted. On CONTINUE,
479275970Scy * the request is immediately processed after the hook returns.  If the
480275970Scy * hook returns PAUSE, request processing stops until evrpc_resume_request()
481275970Scy * has been called.
482275970Scy *
483275970Scy * The add functions return handles that can be used for removing hooks.
484275970Scy *
485275970Scy * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
486275970Scy * @param hook_type either INPUT or OUTPUT
487275970Scy * @param cb the callback to call when the hook is activated
488275970Scy * @param cb_arg an additional argument for the callback
489275970Scy * @return a handle to the hook so it can be removed later
490275970Scy * @see evrpc_remove_hook()
491275970Scy */
492275970Scyvoid *evrpc_add_hook(void *vbase,
493275970Scy    enum EVRPC_HOOK_TYPE hook_type,
494275970Scy    int (*cb)(void *, struct evhttp_request *, struct evbuffer *, void *),
495275970Scy    void *cb_arg);
496275970Scy
497275970Scy/** removes a previously added hook
498275970Scy *
499275970Scy * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
500275970Scy * @param hook_type either INPUT or OUTPUT
501275970Scy * @param handle a handle returned by evrpc_add_hook()
502275970Scy * @return 1 on success or 0 on failure
503275970Scy * @see evrpc_add_hook()
504275970Scy */
505275970Scyint evrpc_remove_hook(void *vbase,
506275970Scy    enum EVRPC_HOOK_TYPE hook_type,
507275970Scy    void *handle);
508275970Scy
509275970Scy/** resume a paused request
510275970Scy *
511275970Scy * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
512275970Scy * @param ctx the context pointer provided to the original hook call
513275970Scy */
514275970Scyint
515275970Scyevrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res);
516275970Scy
517275970Scy/** adds meta data to request
518275970Scy *
519275970Scy * evrpc_hook_add_meta() allows hooks to add meta data to a request. for
520275970Scy * a client request, the meta data can be inserted by an outgoing request hook
521275970Scy * and retrieved by the incoming request hook.
522275970Scy *
523275970Scy * @param ctx the context provided to the hook call
524275970Scy * @param key a NUL-terminated c-string
525275970Scy * @param data the data to be associated with the key
526275970Scy * @param data_size the size of the data
527275970Scy */
528275970Scyvoid evrpc_hook_add_meta(void *ctx, const char *key,
529275970Scy    const void *data, size_t data_size);
530275970Scy
531275970Scy/** retrieves meta data previously associated
532275970Scy *
533275970Scy * evrpc_hook_find_meta() can be used to retrieve meta data associated to a
534275970Scy * request by a previous hook.
535275970Scy * @param ctx the context provided to the hook call
536275970Scy * @param key a NUL-terminated c-string
537275970Scy * @param data pointer to a data pointer that will contain the retrieved data
538275970Scy * @param data_size pointer to the size of the data
539275970Scy * @return 0 on success or -1 on failure
540275970Scy */
541275970Scyint evrpc_hook_find_meta(void *ctx, const char *key,
542275970Scy    void **data, size_t *data_size);
543275970Scy
544275970Scy/**
545275970Scy * returns the connection object associated with the request
546275970Scy *
547275970Scy * @param ctx the context provided to the hook call
548275970Scy * @return a pointer to the evhttp_connection object
549275970Scy */
550275970Scystruct evhttp_connection *evrpc_hook_get_connection(void *ctx);
551275970Scy
552275970Scy/**
553275970Scy   Function for sending a generic RPC request.
554275970Scy
555275970Scy   Do not call this function directly, use EVRPC_MAKE_REQUEST() instead.
556275970Scy
557275970Scy   @see EVRPC_MAKE_REQUEST()
558275970Scy */
559275970Scyint evrpc_send_request_generic(struct evrpc_pool *pool,
560275970Scy    void *request, void *reply,
561275970Scy    void (*cb)(struct evrpc_status *, void *, void *, void *),
562275970Scy    void *cb_arg,
563275970Scy    const char *rpcname,
564275970Scy    void (*req_marshal)(struct evbuffer *, void *),
565275970Scy    void (*rpl_clear)(void *),
566275970Scy    int (*rpl_unmarshal)(void *, struct evbuffer *));
567275970Scy
568275970Scy/**
569275970Scy   Function for registering a generic RPC with the RPC base.
570275970Scy
571275970Scy   Do not call this function directly, use EVRPC_REGISTER() instead.
572275970Scy
573275970Scy   @see EVRPC_REGISTER()
574275970Scy */
575275970Scyint
576275970Scyevrpc_register_generic(struct evrpc_base *base, const char *name,
577275970Scy    void (*callback)(struct evrpc_req_generic *, void *), void *cbarg,
578275970Scy    void *(*req_new)(void *), void *req_new_arg, void (*req_free)(void *),
579275970Scy    int (*req_unmarshal)(void *, struct evbuffer *),
580275970Scy    void *(*rpl_new)(void *), void *rpl_new_arg, void (*rpl_free)(void *),
581275970Scy    int (*rpl_complete)(void *),
582275970Scy    void (*rpl_marshal)(struct evbuffer *, void *));
583275970Scy
584275970Scy/** accessors for obscure and undocumented functionality */
585275970Scystruct evrpc_pool* evrpc_request_get_pool(struct evrpc_request_wrapper *ctx);
586275970Scyvoid evrpc_request_set_pool(struct evrpc_request_wrapper *ctx,
587275970Scy    struct evrpc_pool *pool);
588275970Scyvoid evrpc_request_set_cb(struct evrpc_request_wrapper *ctx,
589275970Scy    void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg),
590275970Scy    void *cb_arg);
591275970Scy
592275970Scy#ifdef __cplusplus
593275970Scy}
594275970Scy#endif
595275970Scy
596275970Scy#endif /* EVENT2_RPC_H_INCLUDED_ */
597