
/*
 * Subscriber API 
 */

#ifndef _INCLUDED_subscriber
#define _INCLUDED_subscriber

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

#include "pasdisp.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * subscriber_t : A subscriber
 *
 * A subscriber is a client to the notification service which expresses
 * interest in particular events.  When the notification service receives
 * a notification about one of these events from a publisher, it relays
 * the notification to the subscriber.
 *
 * A subscriber may also unsubscribe, that is cancel an active subscription.
 */
typedef struct subscriber_struct subscriber_t;

struct publisher_struct;


/**
 * subscription object
 *
 */
typedef struct subscription_struct subscription_t;

/**
 * generic callback function
 *
 * callback functions of this type are invoked by the 
 * library to acknowledge an asynchronous call.
 *
 * Arguments:
 *
 *	arg	Context variable passed by the caller
 *
 *	rc	Return code
 *
 *	data	contains a newly created context in the
 *		case of an open.
 */
typedef void (*subscriber_cb_t)(void *arg, int rc, void *data);

/**
 * subscriber callback.  This is the function called by the library
 * when a notification is received in response of one of the subscriber's
 * active subscriptions.
 *
 * @param	arg	context pointer passed to subscribe (notify_arg)
 *
 * @param	event	event reference (URI).  The reason for this argument
 *			is that the event reference of the notification
 *			although it matches that of the subscrition, may
 *			contain additional information : event attributes.
 *			For example, if the event reference of the subscription
 *			is:
 *				enp://yoyo.com/event
 *			the event reference of a notification matching this 
 *			subscription might be:
 *				enp://yoyo.com/event&uid=1234
 *
 * @param	data	the notification's body.  It is a MIME object.
 *
 * @param	datalen	length of data
 *
 * @return	0 if successful,  non-zero otherwise.
 */
typedef int (*subscriber_notify_cb_t)(void *arg, char *event,
				      char *data, int datalen);

/**
 * fetch result callback.  This is the function called by the library
 * when the response to a fetch command is received.
 *
 * @param	arg	context pointer passed to subscribe (notify_arg)
 *
 * @param	rc	return code.  0 = success. >0 = error.
 *
 * @param	event	event reference (URI).  The reason for this argument
 *			is that the event reference of the notification
 *			although it matches that of the subscrition, may
 *			contain additional information : event attributes.
 *			For example, if the event reference of the subscription
 *			is:
 *				enp://yoyo.com/event
 *			the event reference of a notification matching this 
 *			subscription might be:
 *				enp://yoyo.com/event&uid=1234
 *
 * @param	data	the notification's body.  It is a MIME object.
 *
 * @param	datalen	length of data
 *
 * @return	0 if successful,  non-zero otherwise.
 */
typedef int (*subscriber_result_cb_t)(void *arg, int rc, 
				      char *event,
				      char *data, int datalen);


/**
 * creates a new subscriber asynchronously
 *
 * @param	disp	thread dispatcher context, returned by 
 *			pas_dispatcher_new
 * @see	pas_dispatcher_new
 *
 * @param	worker	application worker.  If not NULL, it is grouped
 *			with the worker(s) created by ENS to service this 
 *			subscriber session.  This is useful in order to 
 *			prevent 2 threads from accessing the subscriber
 *			data at the same time.  It is only usable if the 
 *			GDisp context is created and dispatched by the 
 *			caller.
 *
 * @param	host	hostname or IP address of the notification
 *			server
 *
 * @param	port	server port number for the subscribe service
 *
 * @param	cbdone	callback invoked when the subscriber session
 *			becomes active and subscriptions can be issued.
 *
 * @param	cbarg	first argument of cbdone when called by the 
 *			library.  The other 2 arguments are a status code
 *			and the new subscriber_t.
 *
 */
__export void subscriber_new_a(pas_dispatcher_t *disp,
			       void *worker,
			       const char *host,
			       unsigned short port,
			       subscriber_cb_t cbdone,
			       void *cbarg);
#define subscriber_new subscriber_new_a

/**
 * creates a new subscriber synchronously
 *
 * @param	disp	publish and subcribe dispatcher returned by
 *			pas_dispatch_new
 *
 * @param	worker	application worker.  If not NULL, it is grouped
 *			with the worker(s) created by ENS to service this 
 *			subscriber session.  This is useful in order to 
 *			prevent 2 threads from accessing the subscriber
 *			data at the same time.  It is only usable if the 
 *			GDisp context is created and dispatched by the 
 *			caller.
 *
 * @param	host	hostname or IP address of the notification
 *			server
 *
 * @param	port	server port number for the subscribe service
 *
 * @return	a new active subscriber.
 */
__export subscriber_t *subscriber_new_s(pas_dispatcher_t *disp,
					void *worker,
					const char *host,
					unsigned short port);


/**
 * establishes a subscription asynchronously
 *
 * @param	subscriber	the disappearing subscriber 
 * 
 * @param	event_ref	URI identifying the event's resource.
 *
 * @param	notify_cb	callback invoked when a notification 
 *				matching this subscription is received.
 *
 * @param	notify_arg	first argument of notify_arg when invoked.
 *				May be called at any time, by any thread, 
 *				while the subscription is still active.
 *
 * @param	cbdone		called when unsubcribe transaction with the
 *				service has completed.  The first argument is
 *				cbarg below, the second argument is a status 
 *				code, and the third argument is the
 *				a pointer to an opaqu subscription object.
 *
 * @param	cbarg		first argument of cbdone when invoked.
 *
 */
__export void subscribe_a(subscriber_t *subscriber,
			  const char *event_ref,
			  subscriber_notify_cb_t notify_cb,
			  void *notify_arg,
			  subscriber_cb_t cbdone,
			  void *cbarg);
#define subscribe subscribe_a

/**
 * cancels a subscription asynchronously
 *
 * @param	subscriber	the disappearing subscriber 
 * 
 * @param	subscription	subscription to cancel.
 *
 * @param	cbdone		called when unsubcribe transaction with the
 *				service has completed.
 *
 * @param	cbarg		first argument of cbdone when invoked.
 */
__export void unsubscribe_a(subscriber_t *subscriber,
			    subscription_t *subscription,
			    subscriber_cb_t cbdone,
			    void *cbarg);
#define unsubscribe unsubscribe_a


/**
 * terminates a subscriber
 *
 * @param	subscriber	the disappearing subscriber 
 */
__export void subscriber_delete(subscriber_t *subscriber);


/**
 * creates a publisher, using the credentials of the subscriber.
 * The goal is to simplify the creation of a publisher/subscriber
 * client, and to conserve resources in cases where publish and
 * subscribe services are closely tied.
 * The publisher is only valid as long as the subscriber is valid,
 * that is until subscriber delete has been called.
 *
 * @param	subscriber	the subscriber
 *
 * @return	the publisher, or NULL if trhe creation failed, in which
 *		case the publisher API (publisher_new) may have to be used. 
 */
__export struct publisher_struct *subscriber_get_publisher(subscriber_t *subscriber);


/**
 * In some ennviroments, connections on which nothing happens for 
 * some period of time are automatically closed.  This can lead to
 * lost notifications.  To worrkaround this problem, the subscriber
 * API can be made to send a NOOP command every so often, in order to 
 * keep the connection open. 
 *
 * @param	subscriber	subscriber
 * @param	keepalive_interval	number of milliseconds 
 *					between each NOOP
 */
__export void subscriber_keepalive(subscriber_t *subscriber, 
				   int keepalive_interval);



/**
 * RENL : Reliable Event Notification Link
 * 
 * A RENL is composed of a publisher and a subscriber and a RENL id
 * identifying notifications from the publisher received by the
 * subscriber that are subject to acknowledgment.  A RENL
 * is an agreement negociated outside of the publish/subscribe
 * protocol, between the publisher and the subscriber.
 *
 * In order to enable a RENL, the subscriber must declare its 
 * existence to the library.  From this point the library will
 * generate notification acknowledgment on behalf of the subcriber
 * application, transparently.  The RENL can be revoked at any time
 * by the subscriber.
 */
#ifndef _RENL_DEFINED_
#define _RENL_DEFINED_ 1
typedef struct renl_struct renl_t;
#endif /* _RENL_DEFINED_ */



/**
 * Makes a subscription part of a RENL
 *
 * @param	subscription	the subscription
 *
 * @param	renl_id		unique RENL identifier.  this allows 2 peers
 *				to be able to set up multiple RENL's between
 *				the two of them.
 *
 * @param	publisher	authenticated identity of the peer.
 *
 * @return	opaque renl object
 *
 */
__export renl_t *renl_create_subscriber(subscription_t *subscription,
					const char *renl_id, 
					const char *publisher);
    
/**
 * cancels a RENL.  This does not not cancel the subscription.  It 
 * merely tells the library not to acknowledge any more notifications
 * received within the constext of this subscription.  It also 
 * destroys the RENL object, which may therefore no longer be
 * used by the application.
 *
 * All RENL's are automatically destroyed when the subscription is cancelled.
 * Therefore, this function does not need to be called to freeup any RENL-
 * related memory.
 *
 * @param	renl	the RENL to cancel
 *
 */
__export void renl_cancel_subscriber(renl_t *renl);
    


#ifdef __cplusplus
}
#endif

#endif /* _INCLUDED_subscriber */

