Mercurial > hg > waaad
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 */