00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef _EVRPC_H_
00028 #define _EVRPC_H_
00029
00030 #ifdef __cplusplus
00031 extern "C" {
00032 #endif
00033
00034 #include <event2/event_struct.h>
00035
00071 struct evbuffer;
00072 struct event_base;
00073 struct evrpc_req_generic;
00074 struct evrpc_request_wrapper;
00075
00076
00077 struct evrpc {
00078 TAILQ_ENTRY(evrpc) next;
00079
00080
00081 const char* uri;
00082
00083
00084 void *(*request_new)(void);
00085
00086
00087 void (*request_free)(void *);
00088
00089
00090 int (*request_unmarshal)(void *, struct evbuffer *);
00091
00092
00093 void *(*reply_new)(void);
00094
00095
00096 void (*reply_free)(void *);
00097
00098
00099 int (*reply_complete)(void *);
00100
00101
00102 void (*reply_marshal)(struct evbuffer*, void *);
00103
00104
00105 void (*cb)(struct evrpc_req_generic *, void *);
00106 void *cb_arg;
00107
00108
00109 struct evrpc_base *base;
00110 };
00111
00116 #define EVRPC_STRUCT(rpcname) struct evrpc_req__##rpcname
00117
00118 struct evhttp_request;
00119 struct evrpc_status;
00120 struct evrpc_hook_meta;
00121
00122
00123
00135 #define EVRPC_HEADER(rpcname, reqstruct, rplystruct) \
00136 EVRPC_STRUCT(rpcname) { \
00137 struct evrpc_hook_meta *hook_meta; \
00138 struct reqstruct* request; \
00139 struct rplystruct* reply; \
00140 struct evrpc* rpc; \
00141 struct evhttp_request* http_req; \
00142 struct evbuffer* rpc_data; \
00143 }; \
00144 int evrpc_send_request_##rpcname(struct evrpc_pool *, \
00145 struct reqstruct *, struct rplystruct *, \
00146 void (*)(struct evrpc_status *, \
00147 struct reqstruct *, struct rplystruct *, void *cbarg), \
00148 void *);
00149
00150 struct evrpc_pool;
00151
00153 struct evrpc_request_wrapper *evrpc_make_request_ctx(
00154 struct evrpc_pool *pool, void *request, void *reply,
00155 const char *rpcname,
00156 void (*req_marshal)(struct evbuffer*, void *),
00157 void (*rpl_clear)(void *),
00158 int (*rpl_unmarshal)(void *, struct evbuffer *),
00159 void (*cb)(struct evrpc_status *, void *, void *, void *),
00160 void *cbarg);
00161
00176 #define EVRPC_MAKE_CTX(rpcname, reqstruct, rplystruct, \
00177 pool, request, reply, cb, cbarg) \
00178 evrpc_make_request_ctx(pool, request, reply, \
00179 #rpcname, \
00180 (void (*)(struct evbuffer *, void *))reqstruct##_marshal, \
00181 (void (*)(void *))rplystruct##_clear, \
00182 (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal, \
00183 (void (*)(struct evrpc_status *, void *, void *, void *))cb, \
00184 cbarg)
00185
00196 #define EVRPC_GENERATE(rpcname, reqstruct, rplystruct) \
00197 int evrpc_send_request_##rpcname(struct evrpc_pool *pool, \
00198 struct reqstruct *request, struct rplystruct *reply, \
00199 void (*cb)(struct evrpc_status *, \
00200 struct reqstruct *, struct rplystruct *, void *cbarg), \
00201 void *cbarg) { \
00202 struct evrpc_status status; \
00203 struct evrpc_request_wrapper *ctx; \
00204 ctx = evrpc_make_request_ctx(pool, request, reply, \
00205 #rpcname, \
00206 (void (*)(struct evbuffer *, void *))reqstruct##_marshal, \
00207 (void (*)(void *))rplystruct##_clear, \
00208 (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal, \
00209 (void (*)(struct evrpc_status *, void *, void *, void *))cb, \
00210 cbarg); \
00211 if (ctx == NULL) \
00212 goto error; \
00213 return (evrpc_make_request(ctx)); \
00214 error: \
00215 memset(&status, 0, sizeof(status)); \
00216 status.error = EVRPC_STATUS_ERR_UNSTARTED; \
00217 (*(cb))(&status, request, reply, cbarg); \
00218 return (-1); \
00219 }
00220
00230 #define EVRPC_REQUEST_HTTP(rpc_req) (rpc_req)->http_req
00231
00233 void evrpc_request_done(struct evrpc_req_generic *req);
00234
00243 #define EVRPC_REQUEST_DONE(rpc_req) do { \
00244 struct evrpc_req_generic *_req = (struct evrpc_req_generic *)(rpc_req); \
00245 evrpc_request_done(_req); \
00246 } while (0)
00247
00248
00249
00250 #define EVRPC_REGISTER_OBJECT(rpc, name, request, reply) \
00251 do { \
00252 (rpc)->uri = strdup(#name); \
00253 if ((rpc)->uri == NULL) { \
00254 fprintf(stderr, "failed to register object\n"); \
00255 exit(1); \
00256 } \
00257 (rpc)->request_new = (void *(*)(void))request##_new; \
00258 (rpc)->request_free = (void (*)(void *))request##_free; \
00259 (rpc)->request_unmarshal = (int (*)(void *, struct evbuffer *))request##_unmarshal; \
00260 (rpc)->reply_new = (void *(*)(void))reply##_new; \
00261 (rpc)->reply_free = (void (*)(void *))reply##_free; \
00262 (rpc)->reply_complete = (int (*)(void *))reply##_complete; \
00263 (rpc)->reply_marshal = (void (*)(struct evbuffer*, void *))reply##_marshal; \
00264 } while (0)
00265
00266 struct evrpc_base;
00267 struct evhttp;
00268
00269
00270
00277 struct evrpc_base *evrpc_init(struct evhttp *server);
00278
00287 void evrpc_free(struct evrpc_base *base);
00288
00305 #define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \
00306 do { \
00307 struct evrpc* rpc = (struct evrpc *)calloc(1, sizeof(struct evrpc)); \
00308 EVRPC_REGISTER_OBJECT(rpc, name, request, reply); \
00309 evrpc_register_rpc(base, rpc, \
00310 (void (*)(struct evrpc_req_generic*, void *))callback, cbarg); \
00311 } while (0)
00312
00313 int evrpc_register_rpc(struct evrpc_base *, struct evrpc *,
00314 void (*)(struct evrpc_req_generic*, void *), void *);
00315
00324 #define EVRPC_UNREGISTER(base, name) evrpc_unregister_rpc(base, #name)
00325
00326 int evrpc_unregister_rpc(struct evrpc_base *base, const char *name);
00327
00328
00329
00330
00331
00332 struct evhttp_connection;
00333
00337 struct evrpc_status {
00338 #define EVRPC_STATUS_ERR_NONE 0
00339 #define EVRPC_STATUS_ERR_TIMEOUT 1
00340 #define EVRPC_STATUS_ERR_BADPAYLOAD 2
00341 #define EVRPC_STATUS_ERR_UNSTARTED 3
00342 #define EVRPC_STATUS_ERR_HOOKABORTED 4
00343 int error;
00344
00345
00346 struct evhttp_request *http_req;
00347 };
00348
00364 #define EVRPC_MAKE_REQUEST(name, pool, request, reply, cb, cbarg) \
00365 evrpc_send_request_##name(pool, request, reply, cb, cbarg)
00366
00367 int evrpc_make_request(struct evrpc_request_wrapper *);
00368
00379 struct evrpc_pool *evrpc_pool_new(struct event_base *base);
00385 void evrpc_pool_free(struct evrpc_pool *pool);
00386
00395 void evrpc_pool_add_connection(struct evrpc_pool *pool,
00396 struct evhttp_connection *evcon);
00397
00406 void evrpc_pool_remove_connection(struct evrpc_pool *pool,
00407 struct evhttp_connection *evcon);
00408
00424 void evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs);
00425
00431 enum EVRPC_HOOK_TYPE {
00432 EVRPC_INPUT,
00433 EVRPC_OUTPUT
00434 };
00435
00436 #ifndef WIN32
00437
00439 #define INPUT EVRPC_INPUT
00440
00442 #define OUTPUT EVRPC_OUTPUT
00443 #endif
00444
00449 enum EVRPC_HOOK_RESULT {
00450 EVRPC_TERMINATE = -1,
00451 EVRPC_CONTINUE = 0,
00452 EVRPC_PAUSE = 1,
00453 };
00454
00471 void *evrpc_add_hook(void *vbase,
00472 enum EVRPC_HOOK_TYPE hook_type,
00473 int (*cb)(void *, struct evhttp_request *, struct evbuffer *, void *),
00474 void *cb_arg);
00475
00484 int evrpc_remove_hook(void *vbase,
00485 enum EVRPC_HOOK_TYPE hook_type,
00486 void *handle);
00487
00493 int
00494 evrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res);
00495
00507 void evrpc_hook_add_meta(void *ctx, const char *key,
00508 const void *data, size_t data_size);
00509
00520 int evrpc_hook_find_meta(void *ctx, const char *key,
00521 void **data, size_t *data_size);
00522
00528 struct evhttp_connection *evrpc_hook_get_connection(void *ctx);
00529
00531 struct evrpc_pool* evrpc_request_get_pool(struct evrpc_request_wrapper *ctx);
00532 void evrpc_request_set_pool(struct evrpc_request_wrapper *ctx,
00533 struct evrpc_pool *pool);
00534 void evrpc_request_set_cb(struct evrpc_request_wrapper *ctx,
00535 void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg),
00536 void *cb_arg);
00537
00538 #ifdef __cplusplus
00539 }
00540 #endif
00541
00542 #endif