
#ifndef _INCLUDED_gap_session
#define _INCLUDED_gap_session

#ifdef __cplusplus
extern "C" {
#endif

#include "GDisp.h"

/* TODO use usual Unix values */
#define GAP_SESSION_OK 0
#define GAP_SESSION_TIMEOUT 1
#define GAP_SESSION_EAGAIN 2
#define GAP_SESSION_ESTATE 3
#define GAP_SESSION_EPORT 4
#define GAP_SESSION_EINVAL 5


/* opaque session structure */
typedef struct gap_session_struct gap_session_t;

/* GAP context structure */
typedef struct gapcx_struct gapcx_t;

/* transaction context */
typedef struct gap_transaction_struct gap_transaction_t;


/**
 * callback invoked when the data has been sent
 *
 * Parameters (in the same order) :
 *
 *	void *arg	caller context
 *
 *	int rc		return code
 */
typedef void (*gap_session_got_ack_t)(void *arg, int rc);

/**
 * callback invoked when a new session has been opened, as a result
 * of calling gap_session_new.
 *
 * Parameters (in the same order) :
 *
 *	void *arg	caller context
 *
 *	int rc		return code
 *
 *	gap_session_t *s	new session
 */
typedef void (*gap_session_is_open_t)(void *arg,
				      int rc, 
				      gap_session_t *s); 

/*
 * This function is called by the session layer when it
 * receives a reply from the peer.  it is passed to send_request.
 *
 * @param s session context in which the reply is used
 * @param data reply data
 * @param len length in bytes of the reply data
 * @param transaction pointer to the protocol layer's internal request 
 *   object, which was passed to the session layer when
 *   sending the request to which this reply belongs.
 * @see send_request
 * @see send_request_s
 */
typedef void (*gap_session_got_reply_t)(void *arg,
					char *address,
					unsigned int address_len,
					char *message,
					unsigned int message_len);


/*
 * recv_request : request handler
 * 
 * This function is called by the session layer when it
 * receives a request from the peer.
 *
 * @param s session context in which the request is used
 * @param data request data
 * @param transaction pointer to the session layer's
 *   internal request object.  It must be used when sending
 *   a reply to this request.
 * @see send_reply
 * @see send_reply_s
 * @param data_ctx pointer to the already received portion
 *   of a request when a partial request is received.  The 
 *   session layer uses this pointer in recv_data when the 
 *   remaining of the request is received from the peer.
 */
typedef int (*gap_session_recv_request_t)(void *arg,
					  char *address,
					  unsigned int address_len,
					  char *message,
					  unsigned int message_len,
					  gap_transaction_t *transaction);
 
   
/**
 * initiates a new session with the server,
 * in an asynchronous fashion
 */
__export void gap_session_new(gapcx_t *gapcx,
			      void *worker,
			      const char *host,
			      unsigned short port,
			      gap_session_is_open_t ack,
			      gap_session_recv_request_t recv_request,
			      void (*close_cb)(void *),
			      void *cbarg);

__export int gap_session_new_s(gapcx_t *gapcx,
			       void *worker,
			       const char *host,
			       unsigned short port,
			       gap_session_recv_request_t recv_request,
			       void (*close_cb)(void *),
			       void *cbarg,
			       gap_session_t **s);

__export void gap_send_request(gap_session_t *s,
			       char *address, unsigned int address_len,
			       char *message, unsigned int message_len,
			       gap_session_got_ack_t transport_ack,
			       gap_session_got_reply_t protocol_ack,
			       void *cbarg);

__export void gap_send_reply(gap_session_t *s,
			     char *address, unsigned int address_len,
			     char *message, unsigned int message_len,
			     gap_transaction_t *transaction,
			     gap_session_got_ack_t transport_ack,
			     void *cbarg);

__export int gap_send_request_s(gap_session_t *s,
				char *address,
				unsigned int address_len,
				char *message,
				unsigned int message_len,
				gap_transaction_t **transaction);

__export int gap_send_reply_s(gap_session_t *s,
			      char *address, unsigned int address_len,
			      char *message, unsigned int message_len,
			      gap_transaction_t *transaction);
    
__export void gap_end_transaction(gap_session_t *s,
				  gap_transaction_t *transaction);

__export void gap_session_delete(gap_session_t *s);

/*
 * returns a session object from the session id
 */
__export gap_session_t *gap_session_get(gapcx_t *gapcx, const char *id);

__export const char *gap_session_get_id(gap_session_t *s);

/*
 * GAP instance functions
 */
typedef void (*gap_accept_cb_t)(void *ctx,
				gap_session_t *s,
				void (*auth_cb)(void *, int, const char *),
				void *auth_arg);

typedef int (*gap_acceptable_cb_t)(void *ctx,
				struct sockaddr *sa, socklen_t sa_len);

__export gapcx_t *gapcx_new(GDispCx *gdc,
			    struct in_addr *ina,
			    unsigned short port,
			    gap_accept_cb_t accept_cb,
			    void *ctx);

__export gapcx_t *gapcx_new_1(GDispCx *gdc,
			    struct in_addr *ina,
			    unsigned short port,
			    gap_accept_cb_t accept_cb,
			    gap_acceptable_cb_t acceptable_cb,
			    void *ctx);

__export gapcx_t *gapcx_new_client(GDispCx *gdc,
				   void *ctx);

__export void gapcx_delete(gapcx_t *gapcx);


/*
 * Server interface : called by server after having accepted a new connection
 */

__export void gap_session_set_callbacks(gap_session_t *s,
					gap_session_recv_request_t recv_request,
					void (*close_cb)(void *),
					void *cbarg);

__export void gap_send_request_external(gapcx_t *cx, const char *id,
					char *address,
					unsigned int address_len,
					char *message,
					unsigned int message_len,
					gap_session_got_ack_t transport_ack,
					gap_session_got_reply_t protocol_ack,
					void *cbarg);


#ifdef __cplusplus
}
#endif


#endif /* _INCLUDED_gap_session */

