
#ifndef _INCLUDED_ens_encdec
#define _INCLUDED_ens_encdec

#ifdef _WIN32
#define __export __declspec(dllexport)
#else /* #ifdef _WIN32 */
#define __export
#endif /* #ifdef _WIN32 */

#ifdef __cplusplus
extern "C" {
#endif

/*
 * notification primitives
 */
typedef enum ens_op {
    ENS_OP_SUBSCRIBE = 1,
    ENS_OP_NOTIFY = 2,
    ENS_OP_UNSUBSCRIBE = 3,
    ENS_OP_LOGOUT = 4,
    ENS_OP_NOOP = 5
} ens_op_t;

typedef struct ens_request {
    char *id;
    char *sid;
    ens_op_t op;
    char *event_ref;
    char *event_data;
    unsigned int data_len;
    char *expiration;
} ens_request_t;

typedef struct enp_session_struct enp_session_t;

typedef struct enp_env_struct enp_env_t;

/**
 * callback function for async calls 
 *
 *	void *arg	caller context
 *
 *	int rc		return code
 *
 *	void *data	reply data
 *		+ If the return code is an error return code
 *		data may contain a string describing the 
 *		error.
 *		+ If the return code is an success return code
 *		data may contain the response to the request,
 *		which may be an object (ens_session_t for session_new)
 *		or a string of protocol data.
 *
 *	int len		reply data length
 */
typedef void (*enp_session_cb_t)(void *, int, void *, int);

typedef int (*enp_recv_request_cb_t)(void *, ens_request_t *);

typedef struct enp_fntable {

    /* cleanup */
    void (*cleanup)(enp_env_t *env);
    
    /*
     * send_request : asynchronous request initiator
     * 
     * This function is called by the service layer to send
     * an event notification request (notify, subscribe, ...).
     * The request is passed down to the session layer by
     * calling session_send_request.
     *
     * @param s session context in which the request is sent
     * @param request request object
     * @param ack callback invoked by the module 
     *   when it has finished sending the request.
     * @param arg used as the first argument of the 
     *   ack callback when it is invoked.
     */
    void (*send_request)(enp_session_t *s,
			 ens_request_t *request, 
			 enp_session_cb_t ack,
			 void *cbarg);
    
    void (*session_new)(enp_env_t *env,
			void *worker,
			const char *host,
			unsigned short port,
			enp_session_cb_t ack,
			enp_recv_request_cb_t recv,
			void (*close_cb)(void *),
			void *ctx);
    
    enp_session_t *(*session_new_s)(enp_env_t *env,
				    void *worker,
				    const char *host,
				    unsigned short port,
				    int *rc,
				    enp_recv_request_cb_t recv,
				    void (*close_cb)(void *),
				    void *ctx);

    void (*session_set_callbacks)(enp_session_t *s,
				  enp_recv_request_cb_t recv_cb,
				  void (*close_cb)(void *),
				  void *ctx);

    void (*session_delete)(enp_session_t *s);

    const char *(*session_id)(enp_session_t *s);

} enp_fntable_t;


/*
 * enp_init : init function for the module.
 *
 * The protocol module MUST implement this function otherwise
 * the module will not be able to load.
 *
 * @param recv_request_cb service layer request handler, i.e., 
 *   callback used by the protocol module to bubble up a request
 *   to the service layer.
 *   The first argument of the callback is the session in which the
 *   request is received.  The second one is the request itself.
 */

/* so that "enp_init" does not have to be hardcoded all over the place */
#define ENP_INIT_FUNC "enp_init"

typedef enp_env_t *(*enp_init_fn_t)(void *,
				    void (*)(void *, enp_session_t *),
				    void *,
				    enp_fntable_t **);

__export enp_env_t *enp_init(void *gdisp_context,
			     void (*new_session_cb)(void *, enp_session_t *),
			     void *user_context,
			     enp_fntable_t **ftab);


#ifdef __cplusplus
}
#endif


#endif /* _INCLUDED_ens_encdec */

