view include/waaad/session-api.h @ 415:540ed390c04f

Added sess_destroy function
author Sebastien Decugis <sdecugis@nict.go.jp>
date Tue, 16 Jun 2009 13:37:46 +0900
parents 860f41038ea2
children
line wrap: on
line source

/*********************************************************************************************************
* Software License Agreement (BSD License)                                                               *
* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
*													 *
* Copyright (c) 2009, WIDE Project and NICT								 *
* All rights reserved.											 *
* 													 *
* Redistribution and use of this software in source and binary forms, with or without modification, are  *
* permitted provided that the following conditions are met:						 *
* 													 *
* * Redistributions of source code must retain the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer.										 *
*    													 *
* * Redistributions in binary form must reproduce the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer in the documentation and/or other						 *
*   materials provided with the distribution.								 *
* 													 *
* * Neither the name of the WIDE Project or NICT nor the 						 *
*   names of its contributors may be used to endorse or 						 *
*   promote products derived from this software without 						 *
*   specific prior written permission of WIDE Project and 						 *
*   NICT.												 *
* 													 *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
*********************************************************************************************************/

/* This file contains the definitions of types and functions related to the sessions management
 * and that can be called by extensions. 
 *
 * The waaad daemon does not provide a full support to the sessions state machines as described in the RFC3588.
 * It only provides a basic support to associate some state information with a session identifier, and retrieve 
 * this data easily.
 *
 * It is up to the extension that implements the Auth or Accnt application to manage the state machine and the 
 * ASR/ASA, RAR/RAA, and STR/STA messages, as well as timeouts and other session-related management information.
 *
 * In the daemon, a session is an opaque object (sess_id_t) associated with a value of a Session-Id AVP.
 * In case this session object is not used (details bellow), the session disappears when the message containing the AVP
 * is freed.
 *
 * A new session can also be created as the result of an explicit request (function sess_new), when a client 
 * application starts a new exchange.
 *
 * Sessions objects have a reference counter. When the last reference to the session is deleted, the session is freed.
 * The reference counter is incremented with sess_link and decremented with sess_unlink function.
 *
 * An extension that wants to associate data with session(s) must first register as session module client 
 * with the sess_regext function to get an identifier object (sess_reg_t).
 * 
 * The module manages tuplets ( sess_id_t *, sess_reg_t *, void *). The following functions are used to manage these tuplets:
 * sess_data_reg  : associate a pointer with a given session for a given module client.
 * sess_data_dereg: removes an association.
 * sess_data_get  : get the pointer associated with an association without changing it.
 *
 * Note that creating an association calls sess_link as a side effect, and removing the association calls sess_unlink.
 *
 * QUICK TUTORIAL:
 *  For an extension that wants to implement a session state machine, here is a quick guide.
 *
 * First, the extension must define a structure to save the session state, for example appstate_t.
 *
 * Since the extension will use the session module, it creates a sess_reg_t by calling sess_regext.
 *
 * If the extension behaves as a client, it receives external events that trig the start of a new sessions.
 * When such event occurs, the extension calls sess_new with the appropriate parameters to create a new session.
 * It initializes an appstate_t structure with the data of this session and creates an association with sess_data_reg (%).
 * Then it creates a message (application-specific) to request authentication and/or authorization for the service
 * and the message is sent.
 *
 * Later, assuming that the extension has registered appropriate callbacks in the dispatcher module, when a message
 * is received, the extension can retrieve the state of the session with the sess_data_get function.
 *
 * Finaly, when the extension decides to terminate the session (timer, or as result of a message exchange), it
 * calls sess_data_dereg in order to destroy the binding in the daemon. When last message refering this session is freed,
 * the session data is freed.
 *
 * (%) A this time, the extension must call sess_unlink in order to counter the effects of the sess_new function.
 * This allows to have the session destroyed when no more data is associated to it.
 * 
 */
 
#ifndef _SESSION_API_H
#define _SESSION_API_H

#include <stddef.h>
#include <waaad/message-api.h>

/* The following type identifies a client of the sessions module. 
 * Several clients may register independent data on the same session. 
 */
typedef void sess_reg_t;

/* The following type represents a session (identified by a session-id avp). */
typedef void sess_id_t;

/* The following enum controls the behavior of the sess_new function */
typedef enum {
	SESSION_NEW_DEFAULT = 0,	/* "<diameterId>;<high32>;<low32>[;opt]" opt may be NULL */
	SESSION_NEW_SEQUENCE,		/* "<diameterId>;opt" opt must not be NULL and must be eternally unique */
	SESSION_NEW_FULL,		/* "opt" opt must not be NULL and must contain the sender's identity */
	SESSION_NEW_OTHER		/* "<otherId>;<high32>;<low32>[;opt]". opt points to an FQDN, optionnaly followed by [;opt]"  */
} sess_flags_t;

#ifndef IN_EXTENSION

/*
 * FUNCTION:	sess_new
 *
 * PARAMETERS:
 *  session	  : The location where the session object will be stored on success.
 *  flags	  : How the session-id string must be generated.
 *  opt           : Additional string. Meaning depends on the flags.
 *
 * DESCRIPTION: 
 *   Create a new session object. The session-id string associated with this session is generated as follow:
 * - SESSION_NEW_DEFAULT: The string is created according to the RFC: <diameterId>;<high32>;<low32>[;opt] where
 *    diameterId is the Diameter Identity of the local peer.
 *    high32 and low32 are the parts of a monotonic 64 bits counter initialized to (time, 0) at startup.
 *    opt is an optional string that can be postponed to the identifier.
 * - SESSION_NEW_SEQUENCE: The string is semi-automatic: the diameter id of the local peer is used, and then
 *    the content of the opt string is added. Caller must ensure that opt is eternally unique.
 * - SESSION_NEW_FULL: the opt parameter contains the full string. It must start with the diameter id of the peer,
 *    followed by a ";".
 * - SESSION_NEW_OTHER: opt is an FQDN. The session is generated for another DiameterId. if opt contains a ';', 
 *    the part following it is used as the opt parameter in DEFAULT case. This flag is used for example for gateway functions.
 *
 * RETURN VALUE:
 *  0      	: The session is created.
 *  EINVAL 	: A parameter is invalid.
 *  EALREADY	: A session with the same name already exists
 *  ENOMEM	: Not enough memory to complete the operation
 */
int sess_new ( sess_id_t ** session, sess_flags_t flags, char * opt );

/*
 * FUNCTION:	sess_fromsid
 *
 * PARAMETERS:
 *  sid	  	: pointer to a string containing a session-id.
 *  len		: length of the sid string (which does not need to be '\0'-terminated)
 *  session	: On success, pointer to the session object corresponding.
 *  new		: if not NULL, set to 1 on return if the session object has been created, 0 otherwise.
 *
 * DESCRIPTION: 
 *   Retrieve a session object from a session-id string. Calling this function makes an implicit call to the
 *  sess_link function on the returned session. In case no session object was previously existing with this 
 *  id, a new object is silently created.
 *
 * RETURN VALUE:
 *  0      	: The session parameter has been updated.
 *  EINVAL 	: A parameter is invalid.
 *  ENOMEM	: Not enough memory to complete the operation
 */
int sess_fromsid ( char * sid, size_t len, sess_id_t ** session, int * new);

/*
 * FUNCTION:	sess_getsid
 *
 * PARAMETERS:
 *  session	: Pointer to a session object.
 *  sid	  	: On success, the location of a (\0-terminated) string is stored here.
 *
 * DESCRIPTION: 
 *   Retrieve the session identifier corresponding to a session object.
 *  The returned sid is a string terminated by \0, suitable for calls to strlen and strcpy.
 *  It may be used for example to set the value of an AVP.
 *  Note that the sid string is not copied, just its reference... do not free it!
 *
 * RETURN VALUE:
 *  0      	: The sid parameter has been updated.
 *  EINVAL 	: A parameter is invalid.
 */
int sess_getsid ( sess_id_t * session, char ** sid );

/*
 * FUNCTION:	sess_link
 *
 * PARAMETERS:
 *  session	: Pointer to a session object.
 *
 * DESCRIPTION: 
 *   Increase the reference counter of a session object.
 *
 * RETURN VALUE:
 *  0      	: The refcount has been increased.
 *  EINVAL 	: A parameter is invalid.
 */
int sess_link ( sess_id_t * session );

/*
 * FUNCTION:	sess_unlink
 *
 * PARAMETERS:
 *  session	: Pointer to a session object.
 *
 * DESCRIPTION: 
 *   Decrease the reference counter of a session object. When this counter reaches 0, the object is freed.
 *
 * RETURN VALUE:
 *  0      	: The refcount has been increased.
 *  EINVAL 	: A parameter is invalid.
 */
int sess_unlink ( sess_id_t ** session );

/*
 * FUNCTION:	sess_destroy
 *
 * PARAMETERS:
 *  session	: Pointer to a session object.
 *
 * DESCRIPTION: 
 *   Destroys a session an all associated data, if any.
 *
 * RETURN VALUE:
 *  0      	: The session no longer exists.
 *  EINVAL 	: A parameter is invalid.
 */
int sess_destroy ( sess_id_t ** session );

/*
 * FUNCTION:	sess_regext
 *
 * PARAMETERS:
 *  client	: location where the new client's identifier must be stored.
 *
 * DESCRIPTION: 
 *  Create a new client identifier. This is a pre-requisite to using the session capability of the daemon.
 * This identifier must be then used with sess_data_* functions.
 *
 * RETURN VALUE:
 *  0      	: The new client handler has been created.
 *  EINVAL 	: A parameter is invalid.
 *  ENOMEM	: Not enough memory to complete the operation
 */
int sess_regext ( sess_reg_t ** client );

/*
 * FUNCTION:	sess_deregext
 *
 * PARAMETERS:
 *  client	: The client handler that must be freed.
 *
 * DESCRIPTION: 
 *  Destroys a client handler of the sessions module.
 * Any data still registered with this handler will have its cleanup callback called, if any.
 *
 * RETURN VALUE:
 *  0      	: The client handler has been destroyed.
 *  EINVAL 	: A parameter is invalid.
 */
int sess_deregext ( sess_reg_t * client );

/*
 * FUNCTION:	sess_data_reg
 *
 * PARAMETERS:
 *  session	: Pointer to the session with which the data must be associated.
 *  client	: Client handler with which the data must be associated.
 *  data	: The data that must be associated with the session. This is opaque data to the daemon.
 *  cleanup	: If not NULL, this function will be called if sess_deregext is called on the client.
 *
 * DESCRIPTION: 
 *  Associate a pointer with the session. The data pointed has a meaning only to the client that registers it.
 * This makes an implicit call to sess_link.
 *
 * RETURN VALUE:
 *  0      	: The data has been registered.
 *  EINVAL 	: A parameter is invalid.
 *  EALREADY	: Data was already associated with this session and client.
 *  ENOMEM	: Not enough memory to complete the operation
 */
int sess_data_reg ( sess_id_t * session, sess_reg_t * client, void * data, void (*cleanup)(void *) ); 

/*
 * FUNCTION:	sess_data_get
 *
 * PARAMETERS:
 *  session	: the session from which the data must be retrieved.
 *  client	: the client that registered the data.
 *  data	: Location where the data must be written upon success.
 *
 * DESCRIPTION: 
 *  Retrieve data that was previously registered with sess_data_reg from a session.
 *
 * RETURN VALUE:
 *  0      	: The data has been retrieved.
 *  EINVAL 	: A parameter is invalid.
 *  ENOENT	: No data was associated with this session and client
 */
int sess_data_get ( sess_id_t * session, sess_reg_t * client, void ** data ); 

/*
 * FUNCTION:	sess_data_dereg
 *
 * PARAMETERS:
 *  session	: the session with which the data is associated.
 *  client	: the client that registered the data.
 *  data	: if !NULL, the pointer to the data is written here before being unregistered.
 *
 * DESCRIPTION: 
 *  Remove data from the session module. If data is not NULL, the data is stored in the "data" parameter so
 * that the caller can clean it up properly. Otherwise, if data is NULL, the cleanup function is called if any. 
 * This function makes an implicit call to sess_unlink.
 *
 * RETURN VALUE:
 *  0      	: The data is not registered anymore.
 *  EINVAL 	: A parameter is invalid.
 *  ENOENT	: No data was associated with this session and client
 */
int sess_data_dereg ( sess_id_t * session, sess_reg_t * client, void ** data );



#endif /* ! IN_EXTENSION */

/* The version of this API, to check binary compatibility -- increment each time a change is made in api_sess_t */
#define WAAAD_API_SESSION_VER	2

/* Now define the type of the structure that contains the callback to pass to extensions */
typedef struct {
	/* The header is common to all sub-API pieces */
	size_t	length;		/* The size of this structure, may be useful for extensions not using the facility */
	int	version;	/* The version of this API/ABI, must be WAAAD_API_SESSION_VER */
	
	/* the remaining is session-specific */
	int (*sess_new)        ( sess_id_t ** session, sess_flags_t flags, char * opt );
	int (*sess_fromsid)    ( char * sid, size_t len, sess_id_t ** session, int * new);
	int (*sess_getsid)     ( sess_id_t * session, char ** sid );
	int (*sess_link)       ( sess_id_t * session );
	int (*sess_unlink)     ( sess_id_t ** session );
	int (*sess_destroy)    ( sess_id_t ** session );
	int (*sess_regext)     ( sess_reg_t ** client );
	int (*sess_deregext)   ( sess_reg_t * client );
	int (*sess_data_reg)   ( sess_id_t * session, sess_reg_t * client, void * data, void (*cleanup)(void *) ); 
	int (*sess_data_get)   ( sess_id_t * session, sess_reg_t * client, void ** data ); 
	int (*sess_data_dereg) ( sess_id_t * session, sess_reg_t * client, void ** data );
} api_sess_t;

#ifdef IN_EXTENSION

/* From within the extensions, we register callbacks in the following global structure */
#ifdef DECLARE_API_POINTERS
api_sess_t * g_api_session=NULL;
#else /* DECLARE_API_POINTERS */
extern api_sess_t * g_api_session;
#endif /* DECLARE_API_POINTERS */

/* These defines allow to call functions from extension in the same way as in waaad */
#define sess_new	g_api_session->sess_new
#define sess_fromsid	g_api_session->sess_fromsid
#define sess_getsid	g_api_session->sess_getsid
#define sess_link	g_api_session->sess_link
#define sess_unlink	g_api_session->sess_unlink
#define sess_destroy	g_api_session->sess_destroy
#define sess_regext	g_api_session->sess_regext
#define sess_deregext	g_api_session->sess_deregext
#define sess_data_reg	g_api_session->sess_data_reg
#define sess_data_get	g_api_session->sess_data_get
#define sess_data_dereg	g_api_session->sess_data_dereg


#else /* IN_EXTENSION */

/* From the daemon, we must initialize the API object, in extension.c */
# define MY_WAAAD_API_SESSION_VER 2
# if MY_WAAAD_API_SESSION_VER != WAAAD_API_SESSION_VER
#  error "You must update API_INIT_SESSION also"
# endif

#define API_INIT_SESSION( api_session )				\
{								\
	(api_session).length          = sizeof(api_sess_t);	\
	(api_session).version         = WAAAD_API_SESSION_VER;	\
	(api_session).sess_new        = sess_new;		\
	(api_session).sess_fromsid    = sess_fromsid;		\
	(api_session).sess_getsid     = sess_getsid;		\
	(api_session).sess_link       = sess_link;		\
	(api_session).sess_unlink     = sess_unlink;		\
	(api_session).sess_destroy    = sess_destroy;		\
	(api_session).sess_regext     = sess_regext;		\
	(api_session).sess_deregext   = sess_deregext;		\
	(api_session).sess_data_reg   = sess_data_reg;		\
	(api_session).sess_data_get   = sess_data_get;		\
	(api_session).sess_data_dereg = sess_data_dereg;	\
}							

#endif /* IN_EXTENSION */

#endif /* ! _MESSAGE_API_H */
"Welcome to our mercurial repository"