Annotation of embedaddon/libevent/evrpc.h, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (c) 2006 Niels Provos <provos@citi.umich.edu>
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. The name of the author may not be used to endorse or promote products
                     14:  *    derived from this software without specific prior written permission.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27: #ifndef _EVRPC_H_
                     28: #define _EVRPC_H_
                     29: 
                     30: #ifdef __cplusplus
                     31: extern "C" {
                     32: #endif
                     33: 
                     34: /** @file evrpc.h
                     35:  *
                     36:  * This header files provides basic support for an RPC server and client.
                     37:  *
                     38:  * To support RPCs in a server, every supported RPC command needs to be
                     39:  * defined and registered.
                     40:  *
                     41:  * EVRPC_HEADER(SendCommand, Request, Reply);
                     42:  *
                     43:  *  SendCommand is the name of the RPC command.
                     44:  *  Request is the name of a structure generated by event_rpcgen.py.
                     45:  *    It contains all parameters relating to the SendCommand RPC.  The
                     46:  *    server needs to fill in the Reply structure.
                     47:  *  Reply is the name of a structure generated by event_rpcgen.py.  It
                     48:  *    contains the answer to the RPC.
                     49:  *
                     50:  * To register an RPC with an HTTP server, you need to first create an RPC
                     51:  * base with:
                     52:  *
                     53:  *   struct evrpc_base *base = evrpc_init(http);
                     54:  *
                     55:  * A specific RPC can then be registered with
                     56:  *
                     57:  * EVRPC_REGISTER(base, SendCommand, Request, Reply,  FunctionCB, arg);
                     58:  *
                     59:  * when the server receives an appropriately formatted RPC, the user callback
                     60:  * is invokved.   The callback needs to fill in the reply structure.
                     61:  *
                     62:  * void FunctionCB(EVRPC_STRUCT(SendCommand)* rpc, void *arg);
                     63:  *
                     64:  * To send the reply, call EVRPC_REQUEST_DONE(rpc);
                     65:  *
                     66:  * See the regression test for an example.
                     67:  */
                     68: 
                     69: struct evbuffer;
                     70: struct event_base;
                     71: struct evrpc_req_generic;
                     72: 
                     73: /* Encapsulates a request */
                     74: struct evrpc {
                     75:        TAILQ_ENTRY(evrpc) next;
                     76: 
                     77:        /* the URI at which the request handler lives */
                     78:        const char* uri;
                     79: 
                     80:        /* creates a new request structure */
                     81:        void *(*request_new)(void);
                     82: 
                     83:        /* frees the request structure */
                     84:        void (*request_free)(void *);
                     85: 
                     86:        /* unmarshals the buffer into the proper request structure */
                     87:        int (*request_unmarshal)(void *, struct evbuffer *);
                     88: 
                     89:        /* creates a new reply structure */
                     90:        void *(*reply_new)(void);
                     91: 
                     92:        /* creates a new reply structure */
                     93:        void (*reply_free)(void *);
                     94: 
                     95:        /* verifies that the reply is valid */
                     96:        int (*reply_complete)(void *);
                     97:        
                     98:        /* marshals the reply into a buffer */
                     99:        void (*reply_marshal)(struct evbuffer*, void *);
                    100: 
                    101:        /* the callback invoked for each received rpc */
                    102:        void (*cb)(struct evrpc_req_generic *, void *);
                    103:        void *cb_arg;
                    104: 
                    105:        /* reference for further configuration */
                    106:        struct evrpc_base *base;
                    107: };
                    108: 
                    109: /** The type of a specific RPC Message
                    110:  *
                    111:  * @param rpcname the name of the RPC message
                    112:  */
                    113: #define EVRPC_STRUCT(rpcname) struct evrpc_req__##rpcname
                    114: 
                    115: struct evhttp_request;
                    116: struct evrpc_status;
                    117: 
                    118: /* We alias the RPC specific structs to this voided one */
                    119: struct evrpc_req_generic {
                    120:        /* the unmarshaled request object */
                    121:        void *request;
                    122: 
                    123:        /* the empty reply object that needs to be filled in */
                    124:        void *reply;
                    125: 
                    126:        /* 
                    127:         * the static structure for this rpc; that can be used to
                    128:         * automatically unmarshal and marshal the http buffers.
                    129:         */
                    130:        struct evrpc *rpc;
                    131: 
                    132:        /*
                    133:         * the http request structure on which we need to answer.
                    134:         */
                    135:        struct evhttp_request* http_req;
                    136: 
                    137:        /*
                    138:         * callback to reply and finish answering this rpc
                    139:         */
                    140:        void (*done)(struct evrpc_req_generic* rpc); 
                    141: };
                    142: 
                    143: /** Creates the definitions and prototypes for an RPC
                    144:  *
                    145:  * You need to use EVRPC_HEADER to create structures and function prototypes
                    146:  * needed by the server and client implementation.  The structures have to be
                    147:  * defined in an .rpc file and converted to source code via event_rpcgen.py
                    148:  *
                    149:  * @param rpcname the name of the RPC
                    150:  * @param reqstruct the name of the RPC request structure
                    151:  * @param replystruct the name of the RPC reply structure
                    152:  * @see EVRPC_GENERATE()
                    153:  */
                    154: #define EVRPC_HEADER(rpcname, reqstruct, rplystruct) \
                    155: EVRPC_STRUCT(rpcname) {        \
                    156:        struct reqstruct* request; \
                    157:        struct rplystruct* reply; \
                    158:        struct evrpc* rpc; \
                    159:        struct evhttp_request* http_req; \
                    160:        void (*done)(struct evrpc_status *, \
                    161:            struct evrpc* rpc, void *request, void *reply);          \
                    162: };                                                                  \
                    163: int evrpc_send_request_##rpcname(struct evrpc_pool *, \
                    164:     struct reqstruct *, struct rplystruct *, \
                    165:     void (*)(struct evrpc_status *, \
                    166:        struct reqstruct *, struct rplystruct *, void *cbarg),  \
                    167:     void *);
                    168: 
                    169: /** Generates the code for receiving and sending an RPC message
                    170:  *
                    171:  * EVRPC_GENERATE is used to create the code corresponding to sending
                    172:  * and receiving a particular RPC message
                    173:  *
                    174:  * @param rpcname the name of the RPC
                    175:  * @param reqstruct the name of the RPC request structure
                    176:  * @param replystruct the name of the RPC reply structure
                    177:  * @see EVRPC_HEADER()
                    178:  */
                    179: #define EVRPC_GENERATE(rpcname, reqstruct, rplystruct) \
                    180: int evrpc_send_request_##rpcname(struct evrpc_pool *pool, \
                    181:     struct reqstruct *request, struct rplystruct *reply, \
                    182:     void (*cb)(struct evrpc_status *, \
                    183:        struct reqstruct *, struct rplystruct *, void *cbarg),  \
                    184:     void *cbarg) { \
                    185:        struct evrpc_status status;                                 \
                    186:        struct evrpc_request_wrapper *ctx;                          \
                    187:        ctx = (struct evrpc_request_wrapper *) \
                    188:            malloc(sizeof(struct evrpc_request_wrapper));           \
                    189:        if (ctx == NULL)                                            \
                    190:                goto error;                                         \
                    191:        ctx->pool = pool;                                           \
                    192:        ctx->evcon = NULL;                                          \
                    193:        ctx->name = strdup(#rpcname);                               \
                    194:        if (ctx->name == NULL) {                                    \
                    195:                free(ctx);                                          \
                    196:                goto error;                                         \
                    197:        }                                                           \
                    198:        ctx->cb = (void (*)(struct evrpc_status *, \
                    199:                void *, void *, void *))cb;                         \
                    200:        ctx->cb_arg = cbarg;                                        \
                    201:        ctx->request = (void *)request;                             \
                    202:        ctx->reply = (void *)reply;                                 \
                    203:        ctx->request_marshal = (void (*)(struct evbuffer *, void *))reqstruct##_marshal; \
                    204:        ctx->reply_clear = (void (*)(void *))rplystruct##_clear;    \
                    205:        ctx->reply_unmarshal = (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal; \
                    206:        return (evrpc_make_request(ctx));                           \
                    207: error:                                                             \
                    208:        memset(&status, 0, sizeof(status));                         \
                    209:        status.error = EVRPC_STATUS_ERR_UNSTARTED;                  \
                    210:        (*(cb))(&status, request, reply, cbarg);                    \
                    211:        return (-1);                                                \
                    212: }
                    213: 
                    214: /** Provides access to the HTTP request object underlying an RPC
                    215:  *
                    216:  * Access to the underlying http object; can be used to look at headers or
                    217:  * for getting the remote ip address
                    218:  *
                    219:  * @param rpc_req the rpc request structure provided to the server callback
                    220:  * @return an struct evhttp_request object that can be inspected for
                    221:  * HTTP headers or sender information.
                    222:  */
                    223: #define EVRPC_REQUEST_HTTP(rpc_req) (rpc_req)->http_req
                    224: 
                    225: /** Creates the reply to an RPC request
                    226:  * 
                    227:  * EVRPC_REQUEST_DONE is used to answer a request; the reply is expected
                    228:  * to have been filled in.  The request and reply pointers become invalid
                    229:  * after this call has finished.
                    230:  * 
                    231:  * @param rpc_req the rpc request structure provided to the server callback
                    232:  */
                    233: #define EVRPC_REQUEST_DONE(rpc_req) do { \
                    234:   struct evrpc_req_generic *_req = (struct evrpc_req_generic *)(rpc_req); \
                    235:   _req->done(_req); \
                    236: } while (0)
                    237:   
                    238: 
                    239: /* Takes a request object and fills it in with the right magic */
                    240: #define EVRPC_REGISTER_OBJECT(rpc, name, request, reply) \
                    241:   do { \
                    242:     (rpc)->uri = strdup(#name); \
                    243:     if ((rpc)->uri == NULL) {                   \
                    244:       fprintf(stderr, "failed to register object\n");  \
                    245:       exit(1);                                         \
                    246:     } \
                    247:     (rpc)->request_new = (void *(*)(void))request##_new; \
                    248:     (rpc)->request_free = (void (*)(void *))request##_free; \
                    249:     (rpc)->request_unmarshal = (int (*)(void *, struct evbuffer *))request##_unmarshal; \
                    250:     (rpc)->reply_new = (void *(*)(void))reply##_new; \
                    251:     (rpc)->reply_free = (void (*)(void *))reply##_free; \
                    252:     (rpc)->reply_complete = (int (*)(void *))reply##_complete; \
                    253:     (rpc)->reply_marshal = (void (*)(struct evbuffer*, void *))reply##_marshal; \
                    254:   } while (0)
                    255: 
                    256: struct evrpc_base;
                    257: struct evhttp;
                    258: 
                    259: /* functions to start up the rpc system */
                    260: 
                    261: /** Creates a new rpc base from which RPC requests can be received
                    262:  *
                    263:  * @param server a pointer to an existing HTTP server
                    264:  * @return a newly allocated evrpc_base struct
                    265:  * @see evrpc_free()
                    266:  */
                    267: struct evrpc_base *evrpc_init(struct evhttp *server);
                    268: 
                    269: /** 
                    270:  * Frees the evrpc base
                    271:  *
                    272:  * For now, you are responsible for making sure that no rpcs are ongoing.
                    273:  *
                    274:  * @param base the evrpc_base object to be freed
                    275:  * @see evrpc_init
                    276:  */
                    277: void evrpc_free(struct evrpc_base *base);
                    278: 
                    279: /** register RPCs with the HTTP Server
                    280:  *
                    281:  * registers a new RPC with the HTTP server, each RPC needs to have
                    282:  * a unique name under which it can be identified.
                    283:  *
                    284:  * @param base the evrpc_base structure in which the RPC should be
                    285:  *   registered.
                    286:  * @param name the name of the RPC
                    287:  * @param request the name of the RPC request structure
                    288:  * @param reply the name of the RPC reply structure
                    289:  * @param callback the callback that should be invoked when the RPC
                    290:  * is received.  The callback has the following prototype
                    291:  *   void (*callback)(EVRPC_STRUCT(Message)* rpc, void *arg)
                    292:  * @param cbarg an additional parameter that can be passed to the callback.
                    293:  *   The parameter can be used to carry around state.
                    294:  */
                    295: #define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \
                    296:   do { \
                    297:     struct evrpc* rpc = (struct evrpc *)calloc(1, sizeof(struct evrpc)); \
                    298:     EVRPC_REGISTER_OBJECT(rpc, name, request, reply); \
                    299:     evrpc_register_rpc(base, rpc, \
                    300:        (void (*)(struct evrpc_req_generic*, void *))callback, cbarg);  \
                    301:   } while (0)
                    302: 
                    303: int evrpc_register_rpc(struct evrpc_base *, struct evrpc *,
                    304:     void (*)(struct evrpc_req_generic*, void *), void *);
                    305: 
                    306: /**
                    307:  * Unregisters an already registered RPC
                    308:  *
                    309:  * @param base the evrpc_base object from which to unregister an RPC
                    310:  * @param name the name of the rpc to unregister
                    311:  * @return -1 on error or 0 when successful.
                    312:  * @see EVRPC_REGISTER()
                    313:  */
                    314: #define EVRPC_UNREGISTER(base, name) evrpc_unregister_rpc(base, #name)
                    315: 
                    316: int evrpc_unregister_rpc(struct evrpc_base *base, const char *name);
                    317: 
                    318: /*
                    319:  * Client-side RPC support
                    320:  */
                    321: 
                    322: struct evrpc_pool;
                    323: struct evhttp_connection;
                    324: 
                    325: /** 
                    326:  * provides information about the completed RPC request.
                    327:  */
                    328: struct evrpc_status {
                    329: #define EVRPC_STATUS_ERR_NONE          0
                    330: #define EVRPC_STATUS_ERR_TIMEOUT       1
                    331: #define EVRPC_STATUS_ERR_BADPAYLOAD    2
                    332: #define EVRPC_STATUS_ERR_UNSTARTED     3
                    333: #define EVRPC_STATUS_ERR_HOOKABORTED   4
                    334:        int error;
                    335: 
                    336:        /* for looking at headers or other information */
                    337:        struct evhttp_request *http_req;
                    338: };
                    339: 
                    340: struct evrpc_request_wrapper {
                    341:        TAILQ_ENTRY(evrpc_request_wrapper) next;
                    342: 
                    343:         /* pool on which this rpc request is being made */
                    344:         struct evrpc_pool *pool;
                    345: 
                    346:         /* connection on which the request is being sent */
                    347:        struct evhttp_connection *evcon;
                    348: 
                    349:        /* event for implementing request timeouts */
                    350:        struct event ev_timeout;
                    351: 
                    352:        /* the name of the rpc */
                    353:        char *name;
                    354: 
                    355:        /* callback */
                    356:        void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg);
                    357:        void *cb_arg;
                    358: 
                    359:        void *request;
                    360:        void *reply;
                    361: 
                    362:        /* unmarshals the buffer into the proper request structure */
                    363:        void (*request_marshal)(struct evbuffer *, void *);
                    364: 
                    365:        /* removes all stored state in the reply */
                    366:        void (*reply_clear)(void *);
                    367: 
                    368:        /* marshals the reply into a buffer */
                    369:        int (*reply_unmarshal)(void *, struct evbuffer*);
                    370: };
                    371: 
                    372: /** launches an RPC and sends it to the server
                    373:  *
                    374:  * EVRPC_MAKE_REQUEST() is used by the client to send an RPC to the server.
                    375:  *
                    376:  * @param name the name of the RPC
                    377:  * @param pool the evrpc_pool that contains the connection objects over which
                    378:  *   the request should be sent.
                    379:  * @param request a pointer to the RPC request structure - it contains the
                    380:  *   data to be sent to the server.
                    381:  * @param reply a pointer to the RPC reply structure.  It is going to be filled
                    382:  *   if the request was answered successfully
                    383:  * @param cb the callback to invoke when the RPC request has been answered
                    384:  * @param cbarg an additional argument to be passed to the client
                    385:  * @return 0 on success, -1 on failure
                    386:  */
                    387: #define EVRPC_MAKE_REQUEST(name, pool, request, reply, cb, cbarg)      \
                    388:        evrpc_send_request_##name(pool, request, reply, cb, cbarg)
                    389: 
                    390: int evrpc_make_request(struct evrpc_request_wrapper *);
                    391: 
                    392: /** creates an rpc connection pool
                    393:  * 
                    394:  * a pool has a number of connections associated with it.
                    395:  * rpc requests are always made via a pool.
                    396:  *
                    397:  * @param base a pointer to an struct event_based object; can be left NULL
                    398:  *   in singled-threaded applications
                    399:  * @return a newly allocated struct evrpc_pool object
                    400:  * @see evrpc_pool_free()
                    401:  */
                    402: struct evrpc_pool *evrpc_pool_new(struct event_base *base);
                    403: /** frees an rpc connection pool
                    404:  *
                    405:  * @param pool a pointer to an evrpc_pool allocated via evrpc_pool_new()
                    406:  * @see evrpc_pool_new()
                    407:  */
                    408: void evrpc_pool_free(struct evrpc_pool *pool);
                    409: /*
                    410:  * adds a connection over which rpc can be dispatched.  the connection
                    411:  * object must have been newly created.
                    412:  */
                    413: void evrpc_pool_add_connection(struct evrpc_pool *, 
                    414:     struct evhttp_connection *);
                    415: 
                    416: /**
                    417:  * Sets the timeout in secs after which a request has to complete.  The
                    418:  * RPC is completely aborted if it does not complete by then.  Setting
                    419:  * the timeout to 0 means that it never timeouts and can be used to
                    420:  * implement callback type RPCs.
                    421:  *
                    422:  * Any connection already in the pool will be updated with the new
                    423:  * timeout.  Connections added to the pool after set_timeout has be
                    424:  * called receive the pool timeout only if no timeout has been set
                    425:  * for the connection itself.
                    426:  *
                    427:  * @param pool a pointer to a struct evrpc_pool object
                    428:  * @param timeout_in_secs the number of seconds after which a request should
                    429:  *   timeout and a failure be returned to the callback.
                    430:  */
                    431: void evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs);
                    432: 
                    433: /**
                    434:  * Hooks for changing the input and output of RPCs; this can be used to
                    435:  * implement compression, authentication, encryption, ...
                    436:  */
                    437: 
                    438: enum EVRPC_HOOK_TYPE {
                    439:        EVRPC_INPUT,            /**< apply the function to an input hook */
                    440:        EVRPC_OUTPUT            /**< apply the function to an output hook */
                    441: };
                    442: 
                    443: #ifndef WIN32
                    444: /** Deprecated alias for EVRPC_INPUT.  Not available on windows, where it
                    445:  * conflicts with platform headers. */
                    446: #define INPUT EVRPC_INPUT
                    447: /** Deprecated alias for EVRPC_OUTPUT.  Not available on windows, where it
                    448:  * conflicts with platform headers. */
                    449: #define OUTPUT EVRPC_OUTPUT
                    450: #endif
                    451: 
                    452: /** adds a processing hook to either an rpc base or rpc pool
                    453:  *
                    454:  * If a hook returns -1, the processing is aborted.
                    455:  *
                    456:  * The add functions return handles that can be used for removing hooks.
                    457:  *
                    458:  * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
                    459:  * @param hook_type either INPUT or OUTPUT
                    460:  * @param cb the callback to call when the hook is activated
                    461:  * @param cb_arg an additional argument for the callback
                    462:  * @return a handle to the hook so it can be removed later
                    463:  * @see evrpc_remove_hook()
                    464:  */
                    465: void *evrpc_add_hook(void *vbase,
                    466:     enum EVRPC_HOOK_TYPE hook_type,
                    467:     int (*cb)(struct evhttp_request *, struct evbuffer *, void *),
                    468:     void *cb_arg);
                    469: 
                    470: /** removes a previously added hook
                    471:  *
                    472:  * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
                    473:  * @param hook_type either INPUT or OUTPUT
                    474:  * @param handle a handle returned by evrpc_add_hook()
                    475:  * @return 1 on success or 0 on failure
                    476:  * @see evrpc_add_hook()
                    477:  */
                    478: int evrpc_remove_hook(void *vbase,
                    479:     enum EVRPC_HOOK_TYPE hook_type,
                    480:     void *handle);
                    481: 
                    482: #ifdef __cplusplus
                    483: }
                    484: #endif
                    485: 
                    486: #endif /* _EVRPC_H_ */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>