Navigation


source: freeDiameter/include/freeDiameter/libfreeDiameter.h @ 20:277ec00d793e

Last change on this file since 20:277ec00d793e was 20:277ec00d793e, checked in by Sebastien Decugis <sdecugis@nict.go.jp>, 12 years ago

Backup before typhoon... Progress on server side

File size: 90.6 KB
Line 
1/*********************************************************************************************************
2* Software License Agreement (BSD License)                                                               *
3* Author: Sebastien Decugis <sdecugis@nict.go.jp>                                                        *
4*                                                                                                        *
5* Copyright (c) 2009, WIDE Project and NICT                                                              *
6* All rights reserved.                                                                                   *
7*                                                                                                        *
8* Redistribution and use of this software in source and binary forms, with or without modification, are  *
9* permitted provided that the following conditions are met:                                              *
10*                                                                                                        *
11* * Redistributions of source code must retain the above                                                 *
12*   copyright notice, this list of conditions and the                                                    *
13*   following disclaimer.                                                                                *
14*                                                                                                        *
15* * Redistributions in binary form must reproduce the above                                              *
16*   copyright notice, this list of conditions and the                                                    *
17*   following disclaimer in the documentation and/or other                                               *
18*   materials provided with the distribution.                                                            *
19*                                                                                                        *
20* * Neither the name of the WIDE Project or NICT nor the                                                 *
21*   names of its contributors may be used to endorse or                                                  *
22*   promote products derived from this software without                                                  *
23*   specific prior written permission of WIDE Project and                                                *
24*   NICT.                                                                                                *
25*                                                                                                        *
26* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
27* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
28* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
29* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT     *
30* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    *
31* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
32* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
33* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                                             *
34*********************************************************************************************************/
35
36/* This file contains the definitions of functions and types used by the libfreeDiameter library.
37 *
38 * This library is meant to be used by both the freeDiameter daemon and its extensions.
39 * It provides the tools to manipulate Diameter messages and related data.
40 * This file should always be included as #include <freeDiameter/libfreeDiameter.h>
41 *
42 * The file contains the following parts:
43 *      DEBUG
44 *      MACROS
45 *      THREADS
46 *      LISTS
47 *      DICTIONARY
48 *      SESSIONS
49 *      MESSAGES
50 *      DISPATCH
51 *      QUEUES
52 */
53
54#ifndef _LIBFREEDIAMETER_H
55#define _LIBFREEDIAMETER_H
56
57#ifndef FD_IS_CONFIG
58#error "You must include 'freeDiameter-host.h' before this file."
59#endif /* FD_IS_CONFIG */
60
61#include <pthread.h>
62#include <string.h>
63#include <assert.h>
64#include <errno.h>
65#include <arpa/inet.h>
66#include <sys/socket.h>
67#include <netdb.h>
68#include <stdio.h>
69#include <stdlib.h>
70#include <unistd.h>
71
72/*============================================================*/
73/*                          DEBUG                             */
74/*============================================================*/
75#ifndef ASSERT
76#define ASSERT(x) assert(x)
77#endif /* ASSERT */
78
79/*
80 * FUNCTION:    fd_log_debug
81 *
82 * PARAMETERS:
83 *  format      : Same format string as in the printf function
84 *  ...         : Same list as printf
85 *
86 * DESCRIPTION:
87 *  Log internal information for use of developpers only.
88 * The format and arguments may contain UTF-8 encoded data. The
89 * output medium (file or console) is expected to support this encoding.
90 *
91 * This function assumes that a global mutex called "fd_log_lock" exists
92 * in the address space of the current process.
93 *
94 * RETURN VALUE:
95 *  None.
96 */
97void fd_log_debug ( char * format, ... );
98extern pthread_mutex_t  fd_log_lock;
99
100/*
101 * FUNCTION:    fd_log_threadname
102 *
103 * PARAMETERS:
104 *  name        : \0-terminated string containing a name to identify the current thread.
105 *
106 * DESCRIPTION:
107 *  Name the current thread, useful for debugging multi-threaded problems.
108 *
109 * This function assumes that a global thread-specific key called "fd_log_thname" exists
110 * in the address space of the current process.
111 *
112 * RETURN VALUE:
113 *  None.
114 */
115void fd_log_threadname ( char * name );
116extern pthread_key_t    fd_log_thname;
117
118/*
119 * FUNCTION:    fd_log_time
120 *
121 * PARAMETERS:
122 *  buf         : An array where the time must be stored
123 *  len         : size of the buffer
124 *
125 * DESCRIPTION:
126 *  Writes the current timestamp (in human readable format) in a buffer.
127 *
128 * RETURN VALUE:
129 *  pointer to buf.
130 */
131char * fd_log_time ( char * buf, size_t len );
132
133
134/* levels definitions */
135#define NONE 0  /* Display no debug message */
136#define INFO 1  /* Display errors only */
137#define FULL 2  /* Display additional information to follow code execution */
138#define ANNOYING 4 /* Very verbose, for example in loops */
139#define FCTS 6  /* Display entry parameters of most functions */
140#define CALL 9  /* Display calls to most functions (with CHECK macros) */
141
142/* Default level is INFO */
143#ifndef TRACE_LEVEL
144#define TRACE_LEVEL INFO
145#endif /* TRACE_LEVEL */
146
147/* The level of the file being compiled. */
148static int local_debug_level = TRACE_LEVEL;
149
150/* A global level, changed by configuration or cmd line for example. default is 0. */
151extern int fd_g_debug_lvl;
152
153/* Some portability code to get nice function name in __PRETTY_FUNCTION__ */
154#if __STDC_VERSION__ < 199901L
155# if __GNUC__ >= 2
156#  define __func__ __FUNCTION__
157# else /* __GNUC__ >= 2 */
158#  define __func__ "<unknown>"
159# endif /* __GNUC__ >= 2 */
160#endif /* __STDC_VERSION__ < 199901L */
161#ifndef __PRETTY_FUNCTION__
162#define __PRETTY_FUNCTION__ __func__
163#endif /* __PRETTY_FUNCTION__ */
164
165/* Boolean for tracing at a certain level */
166#define TRACE_BOOL(_level_) ( (_level_) <= local_debug_level + fd_g_debug_lvl )
167
168/* The general debug macro, each call results in two lines of debug messages (change the macro for more compact output) */
169#define TRACE_DEBUG(level,format,args... ) {                                                                                    \
170        if ( TRACE_BOOL(level) ) {                                                                                              \
171                char __buf[25];                                                                                                 \
172                char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed");                                       \
173                fd_log_debug("\t | tid:%-20s\t%s\tin %s@%s:%d\n"                                                                \
174                          "\t%s|%*s" format "\n",                                                                               \
175                                        __thn, fd_log_time(__buf, sizeof(__buf)), __PRETTY_FUNCTION__, __FILE__, __LINE__,      \
176                                        (level < FULL)?"@":" ",level, "", ## args);                                             \
177        }                                                                                                                       \
178}
179
180/* Helper for function entry -- for very detailed trace of the execution */
181#define TRACE_ENTRY(_format,_args... ) \
182        TRACE_DEBUG(FCTS, "->%s (" #_args ") = (" _format ") >", __PRETTY_FUNCTION__, ##_args );
183
184/* Helper for debugging by adding traces -- for debuging a specific location of the code */
185#define TRACE_HERE()    \
186        TRACE_DEBUG(NONE, " -- debug checkpoint -- ");
187
188/* Helper for tracing the CHECK_* macros bellow -- very very verbose code execution! */
189#define TRACE_DEBUG_ALL( str )  \
190        TRACE_DEBUG(CALL, str );
191
192/* For development only, to keep track of TODO locations in the code */
193#ifndef ERRORS_ON_TODO
194#define TODO( _msg, _args... ) \
195        TRACE_DEBUG(NONE, "TODO: " _msg , ##_args);
196#else /* ERRORS_ON_TODO */
197#define TODO( _msg, _args... ) \
198        "TODO" = _msg ## _args; /* just a stupid compilation error to spot the todo */
199#endif /* ERRORS_ON_TODO */
200
201
202/* Macros to check a return value and branch out in case of error.
203 * These macro must be used only when errors are highly improbable, not for expected errors.
204 */
205
206/* Check the return value of a system function and execute fallback in case of error */
207#define CHECK_SYS_DO( __call__, __fallback__  ) {                                       \
208        int __ret__;                                                                    \
209        TRACE_DEBUG_ALL( "Check SYS: " #__call__ );                                     \
210        __ret__ = (__call__);                                                           \
211        if (__ret__ < 0) {                                                              \
212                int __err__ = errno;    /* We may handle EINTR here */                  \
213                TRACE_DEBUG(NONE, "ERROR: in '" #__call__ "' :\t%s", strerror(__err__));\
214                __fallback__;                                                           \
215        }                                                                               \
216}
217/* Check the return value of a system function, return error code on error */
218#define CHECK_SYS( __call__  ) {                                                        \
219        int __ret__;                                                                    \
220        TRACE_DEBUG_ALL( "Check SYS: " #__call__ );                                     \
221        __ret__ = (__call__);                                                           \
222        if (__ret__ < 0) {                                                              \
223                int __err__ = errno;    /* We may handle EINTR here */                  \
224                TRACE_DEBUG(NONE, "ERROR: in '" #__call__ "' :\t%s", strerror(__err__));\
225                return __err__;                                                         \
226        }                                                                               \
227}
228
229/* Check the return value of a POSIX function and execute fallback in case of error or special value */
230#define CHECK_POSIX_DO2( __call__, __speval__, __fallback1__, __fallback2__ ) {                 \
231        int __ret__;                                                                            \
232        TRACE_DEBUG_ALL( "Check POSIX: " #__call__ );                                           \
233        __ret__ = (__call__);                                                                   \
234        if (__ret__ != 0) {                                                                     \
235                if (__ret__ == (__speval__)) {                                                  \
236                        __fallback1__;                                                          \
237                } else {                                                                        \
238                        TRACE_DEBUG(NONE, "ERROR: in '" #__call__ "':\t%s", strerror(__ret__)); \
239                        __fallback2__;                                                          \
240                }                                                                               \
241        }                                                                                       \
242}
243
244/* Check the return value of a POSIX function and execute fallback in case of error */
245#define CHECK_POSIX_DO( __call__, __fallback__ )                                        \
246        CHECK_POSIX_DO2( (__call__), 0, , __fallback__ );
247
248/* Check the return value of a POSIX function and return it if error */
249#define CHECK_POSIX( __call__ ) {                                                       \
250        int __v__;                                                                      \
251        CHECK_POSIX_DO( __v__ = (__call__), return __v__ );                             \
252}
253
254/* Check that a memory allocator did not return NULL, otherwise log an error and execute fallback */
255#define CHECK_MALLOC_DO( __call__, __fallback__ ) {                                     \
256        void *  __ret__;                                                                \
257        TRACE_DEBUG_ALL( "Check MALLOC: " #__call__ );                                  \
258        __ret__ = (void *)( __call__ );                                                 \
259        if (__ret__ == NULL) {                                                          \
260                int __err__ = errno;                                                    \
261                TRACE_DEBUG(NONE, "ERROR: in '" #__call__ "':\t%s", strerror(__err__)); \
262                __fallback__;                                                           \
263        }                                                                               \
264}
265
266/* Check that a memory allocator did not return NULL, otherwise return ENOMEM */
267#define CHECK_MALLOC( __call__ )                                                        \
268        CHECK_MALLOC_DO( __call__, return ENOMEM );
269
270
271/* The next macros can be used also for expected errors */
272
273/* Check parameters at function entry, execute fallback on error */
274#define CHECK_PARAMS_DO( __bool__, __fallback__ )                                       \
275        TRACE_DEBUG_ALL( "Check PARAMS: " #__bool__ );                                  \
276        if ( ! (__bool__) ) {                                                           \
277                TRACE_DEBUG(INFO, "Invalid parameter received in '" #__bool__ "'");     \
278                __fallback__;                                                           \
279        }
280/* Check parameters at function entry, return EINVAL if the boolean is false (similar to assert) */
281#define CHECK_PARAMS( __bool__ )                                                        \
282        CHECK_PARAMS_DO( __bool__, return EINVAL );
283
284/* Check the return value of an internal function, log and propagate */
285#define CHECK_FCT_DO( __call__, __fallback__ ) {                                        \
286        int __ret__;                                                                    \
287        TRACE_DEBUG_ALL( "Check FCT: " #__call__ );                                     \
288        __ret__ = (__call__);                                                           \
289        if (__ret__ != 0) {                                                             \
290                TRACE_DEBUG(INFO, "Error in '" #__call__ "':\t%s", strerror(__ret__));  \
291                __fallback__;                                                           \
292        }                                                                               \
293}
294/* Check the return value of a function call, return any error code */
295#define CHECK_FCT( __call__ ) {                                                         \
296        int __v__;                                                                      \
297        CHECK_FCT_DO( __v__ = (__call__), return __v__ );                               \
298}
299
300
301/*============================================================*/
302/*                          MACROS                            */
303/*============================================================*/
304
305/* helper macros (pre-processor hacks to allow macro arguments) */
306#define __str( arg )  #arg
307#define _stringize( arg ) __str( arg )
308#define __agr( arg1, arg2 ) arg1 ## arg2
309#define _aggregate( arg1, arg2 ) __agr( arg1, arg2 )
310
311/* Some aliases to socket addresses structures */
312#define sSS     struct sockaddr_storage
313#define sSA     struct sockaddr
314#define sSA4    struct sockaddr_in
315#define sSA6    struct sockaddr_in6
316
317/* Dump one sockaddr Node information */
318#define sSA_DUMP_NODE( sa, flag ) {                             \
319        sSA * __sa = (sSA *)(sa);                               \
320        char __addrbuf[INET6_ADDRSTRLEN];                       \
321        if (__sa) {                                             \
322          int __rc = getnameinfo(__sa,                          \
323                        sizeof(sSS),                            \
324                        __addrbuf,                              \
325                        sizeof(__addrbuf),                      \
326                        NULL,                                   \
327                        0,                                      \
328                        flag);                                  \
329          if (__rc)                                             \
330                fd_log_debug((char *)gai_strerror(__rc));       \
331          else                                                  \
332                fd_log_debug(&__addrbuf[0]);                    \
333        } else {                                                \
334                fd_log_debug("(NULL / ANY)");                   \
335        }                                                       \
336}
337/* if needed, add sSA_DUMP_SERVICE */
338
339/* A l4 protocol name (TCP / SCTP) */
340#define IPPROTO_NAME( _proto )                                  \
341        ( ((_proto) == IPPROTO_TCP) ? "TCP" :                   \
342                (((_proto) == IPPROTO_SCTP) ? "SCTP" :          \
343                        "Unknown"))
344
345/* The sockaddr length of a sSS structure */
346#define sSSlen( _ss_ )  \
347        ( (socklen_t) ( ((_ss_)->ss_family == AF_INET) ? (sizeof(sSA4)) :               \
348                                (((_ss_)->ss_family == AF_INET6) ? (sizeof(sSA6)) :     \
349                                        0 ) ) )
350
351/* Define the value of IP loopback address */
352#ifndef INADDR_LOOPBACK
353#define INADDR_LOOPBACK inet_addr("127.0.0.1")
354#endif /* INADDR_LOOPBACK */
355
356/* create a V4MAPPED address */
357#define IN6_ADDR_V4MAP( a6, a4 ) {                      \
358        ((uint32_t *)(a6))[0] = 0;                      \
359        ((uint32_t *)(a6))[1] = 0;                      \
360        ((uint32_t *)(a6))[2] = htonl(0xffff);          \
361        ((uint32_t *)(a6))[3] = (uint32_t)(a4);         \
362}
363
364/* Retrieve a v4 value from V4MAPPED address ( takes a s6_addr as param) */
365#define IN6_ADDR_V4UNMAP( a6 )                          \
366        (((in_addr_t *)(a6))[3])
367
368
369/* We provide macros to convert 64 bit values to and from network byte-order, on systems where it is not already provided. */
370#ifndef HAVE_NTOHLL     /* Defined in config.h, if the ntohll symbol is defined on the system */
371# if HOST_BIG_ENDIAN
372    /* In big-endian systems, we don't have to change the values, since the order is the same as network */
373#   define ntohll(x) (x)
374#   define htonll(x) (x)
375# else /* HOST_BIG_ENDIAN */
376    /* For these systems, we must reverse the bytes. Use ntohl and htonl on sub-32 blocs, and inverse these blocs. */
377#   define ntohll(x) (typeof (x))( (((uint64_t)ntohl( (uint32_t)(x))) << 32 ) | ((uint64_t) ntohl( ((uint64_t)(x)) >> 32 )))
378#   define htonll(x) (typeof (x))( (((uint64_t)htonl( (uint32_t)(x))) << 32 ) | ((uint64_t) htonl( ((uint64_t)(x)) >> 32 )))
379# endif /* HOST_BIG_ENDIAN */
380#endif /* HAVE_NTOHLL */
381
382/* This macro will give the next multiple of 4 for an integer (used for padding sizes of AVP). */
383#define PAD4(_x) ((_x) + ( (4 - (_x)) & 3 ) )
384
385/* Useful to display as safe ASCII a value (will garbage UTF-8 output...) */
386#define ASCII(_c) ( ((_c < 32) || (_c > 127)) ? ( _c ? '?' : ' ' ) : _c )
387
388/* Compare timespec structures */
389#define TS_IS_INFERIOR( ts1, ts2 )              \
390        (    ((ts1)->tv_sec  < (ts2)->tv_sec )  \
391          || (((ts1)->tv_sec  == (ts2)->tv_sec ) && ((ts1)->tv_nsec < (ts2)->tv_nsec) ))
392
393
394/*============================================================*/
395/*                          THREADS                           */
396/*============================================================*/
397
398/* Terminate a thread */
399static __inline__ int fd_thr_term(pthread_t * th)
400{
401        int ret = 0;
402        void * th_ret = NULL;
403       
404        CHECK_PARAMS(th);
405       
406        /* Test if it was already terminated */
407        if (*th == (pthread_t)NULL)
408                return 0;
409       
410        /* Cancel the thread if it is still running - ignore error if it was already terminated */
411        (void) pthread_cancel(*th);
412       
413        /* Then join the thread */
414        CHECK_POSIX_DO( ret = pthread_join(*th, &th_ret), /* continue */ );
415       
416        if (th_ret != NULL) {
417                TRACE_DEBUG(FULL, "The thread returned the following value: %p (ignored)", th_ret);
418        }
419       
420        /* Clean the location */
421        *th = (pthread_t)NULL;
422       
423        return ret;
424}
425
426/* Cleanups for cancellation (all threads should be safely cancelable...) */
427static __inline__ void fd_cleanup_mutex( void * mutex )
428{
429        CHECK_POSIX_DO( pthread_mutex_unlock((pthread_mutex_t *)mutex), /* */);
430}
431               
432static __inline__ void fd_cleanup_rwlock( void * rwlock )
433{
434        CHECK_POSIX_DO( pthread_rwlock_unlock((pthread_rwlock_t *)rwlock), /* */);
435}
436
437static __inline__ void fd_cleanup_buffer( void * buffer )
438{
439        free(buffer);
440}
441
442/*============================================================*/
443/*                          LISTS                             */
444/*============================================================*/
445
446/* The following structure represents a chained list element  */
447struct fd_list {
448        struct fd_list  *next; /* next element in the list */
449        struct fd_list  *prev; /* previous element in the list */
450        struct fd_list  *head; /* head of the list */
451        void            *o;    /* additional avialbe pointer used for start of the parento object or other purpose */
452};
453
454/* Initialize a list element */
455#define FD_LIST_INITIALIZER( _list_name ) \
456        { .next = & _list_name, .prev = & _list_name, .head = & _list_name, .o = NULL }
457#define FD_LIST_INITIALIZER_O( _list_name, _obj ) \
458        { .next = & _list_name, .prev = & _list_name, .head = & _list_name, .o = _obj }
459void fd_list_init ( struct fd_list * list, void *obj );
460
461/* Return boolean, true if the list is empty */
462#define FD_IS_LIST_EMPTY( _list ) ((((struct fd_list *)(_list))->head == (_list)) && (((struct fd_list *)(_list))->next == (_list)))
463
464/* Insert an item in a list at known position */
465void fd_list_insert_after  ( struct fd_list * ref, struct fd_list * item );
466void fd_list_insert_before ( struct fd_list * ref, struct fd_list * item );
467
468/* Insert an item in an ordered list -- ordering function provided. If duplicate object found, EEXIST and it is returned in ref_duplicate */
469int fd_list_insert_ordered( struct fd_list * head, struct fd_list * item, int (*cmp_fct)(void *, void *), void ** ref_duplicate);
470
471/* Unlink an item from a list */
472void fd_list_unlink ( struct fd_list * item );
473
474/* Compute a hash value of a string (session id, diameter id, ...) */
475uint32_t fd_hash ( char * string, size_t len );
476
477
478
479/*============================================================*/
480/*                        DICTIONARY                          */
481/*============================================================*/
482/* Structure that contains the complete dictionary definitions */
483struct dictionary;
484
485/* Structure that contains a dictionary object */
486struct dict_object;
487
488/* Types of object in the dictionary. */
489enum dict_object_type {
490        DICT_VENDOR     = 1,    /* Vendor */
491        DICT_APPLICATION,       /* Diameter Application */
492        DICT_TYPE,              /* AVP data type */
493        DICT_ENUMVAL,           /* Named constant (value of an enumerated AVP type) */
494        DICT_AVP,               /* AVP */
495        DICT_COMMAND,           /* Diameter Command */
496        DICT_RULE               /* a Rule for AVP in command or grouped AVP */
497#define DICT_TYPE_MAX   DICT_RULE
498};
499       
500/* Initialize a dictionary */
501int fd_dict_init(struct dictionary ** dict);
502/* Destroy a dictionary */
503int fd_dict_fini(struct dictionary ** dict);
504
505/*
506 * FUNCTION:    fd_dict_new
507 *
508 * PARAMETERS:
509 *  dict        : Pointer to the dictionnary where the object is created
510 *  type        : What kind of object must be created
511 *  data        : pointer to the data for the object.
512 *               type parameter is used to determine the type of data (see bellow for detail).
513 *  parent      : a reference to a parent object, if needed.
514 *  ref         : upon successful creation, reference to new object is stored here if !null.
515 *
516 * DESCRIPTION:
517 *  Create a new object in the dictionary.
518 *  See following object sections in this header file for more information on data and parent parameters format.
519 *
520 * RETURN VALUE:
521 *  0           : The object is created in the dictionary.
522 *  EINVAL      : A parameter is invalid.
523 *  EEXIST      : This object is already defined in the dictionary (with conflicting data).
524 *                If "ref" is not NULL, it points to the existing element on return.
525 *  (other standard errors may be returned, too, with their standard meaning. Example:
526 *    ENOMEM    : Memory allocation for the new object element failed.)
527 */
528int fd_dict_new ( struct dictionary * dict, enum dict_object_type type, void * data, struct dict_object * parent, struct dict_object **ref );
529
530/*
531 * FUNCTION:    fd_dict_search
532 *
533 * PARAMETERS:
534 *  dict        : Pointer to the dictionnary where the object is searched
535 *  type        : type of object that is being searched
536 *  criteria    : how the object must be searched. See object-related sections bellow for more information.
537 *  what        : depending on criteria, the data that must be searched.
538 *  result      : On successful return, pointer to the object is stored here.
539 *  retval      : this value is returned if the object is not found and result is not NULL.
540 *
541 * DESCRIPTION:
542 *   Perform a search in the dictionary.
543 *   See the object-specific sections bellow to find how to look for each objects.
544 *   If the "result" parameter is NULL, the function is used to check if an object is in the dictionary.
545 *   Otherwise, a reference to the object is stored in result if found.
546 *   If result is not NULL and the object is not found, retval is returned (should be 0 or ENOENT usually)
547 *
548 * RETURN VALUE:
549 *  0           : The object has been found in the dictionary, or *result is NULL.
550 *  EINVAL      : A parameter is invalid.
551 *  ENOENT      : No matching object has been found, and result was NULL.
552 */
553int fd_dict_search ( struct dictionary * dict, enum dict_object_type type, int criteria, void * what, struct dict_object **result, int retval );
554
555/* Special case: get the generic error command object */
556int fd_dict_get_error_cmd(struct dictionary * dict, struct dict_object **obj);
557
558/*
559 * FUNCTION:    fd_dict_getval
560 *
561 * PARAMETERS:
562 *  object      : Pointer to a dictionary object.
563 *  data        : pointer to a structure to hold the data for the object.
564 *                The type is the same as "data" parameter in fd_dict_new function.
565 *
566 * DESCRIPTION:
567 *  Retrieve content of a dictionary object.
568 *  See following object sections in this header file for more information on data and parent parameters format.
569 *
570 * RETURN VALUE:
571 *  0           : The content of the object has been retrieved.
572 *  EINVAL      : A parameter is invalid.
573 */
574int fd_dict_getval ( struct dict_object * object, void * val);
575int fd_dict_gettype ( struct dict_object * object, enum dict_object_type * type);
576int fd_dict_getdict ( struct dict_object * object, struct dictionary ** dict);
577
578/* Debug functions */
579void fd_dict_dump_object(struct dict_object * obj);
580void fd_dict_dump(struct dictionary * dict);
581
582
583/*
584 ***************************************************************************
585 *
586 * Vendor object
587 *
588 * These types are used to manage vendors in the dictionary
589 *
590 ***************************************************************************
591 */
592
593/* Type to hold a Vendor ID: "SMI Network Management Private Enterprise Codes" (RFC3232) */
594typedef uint32_t        vendor_id_t;
595
596/* Type to hold data associated to a vendor */
597struct dict_vendor_data {
598        vendor_id_t      vendor_id;     /* ID of a vendor */
599        char            *vendor_name;   /* The name of this vendor */
600};
601
602/* The criteria for searching a vendor object in the dictionary */
603enum {
604        VENDOR_BY_ID = 10,      /* "what" points to a vendor_id_t */
605        VENDOR_BY_NAME,         /* "what" points to a string */
606        VENDOR_OF_APPLICATION   /* "what" points to a struct dict_object containing an application (see bellow) */
607};
608
609/***
610 *  API usage :
611
612Note: the value of "vendor_name" is copied when the object is created, and the string may be disposed afterwards.
613On the other side, when value is retrieved with dict_getval, the string is not copied and MUST NOT be freed. It will
614be freed automatically along with the object itself with call to dict_fini later.
615 
616- fd_dict_new:
617 The "parent" parameter is not used for vendors.
618 Sample code to create a vendor:
619 {
620         int ret;
621         struct dict_object * myvendor;
622         struct dict_vendor_data myvendordata = { 23455, "my vendor name" };  -- just an example...
623         ret = fd_dict_new ( dict, DICT_VENDOR, &myvendordata, NULL, &myvendor );
624 }
625
626- fd_dict_search:
627 Sample codes to look for a vendor object, by its id or name:
628 {
629         int ret;
630         struct dict_object * vendor_found;
631         vendor_id_t vendorid = 23455;
632         ret = fd_dict_search ( dict, DICT_VENDOR, VENDOR_BY_ID, &vendorid, &vendor_found, ENOENT);
633         - or -
634         ret = fd_dict_search ( dict, DICT_VENDOR, VENDOR_BY_NAME, "my vendor name", &vendor_found, ENOENT);
635 }
636 
637 - fd_dict_getval:
638 Sample code to retrieve the data from a vendor object:
639 {
640         int ret;
641         struct dict_object * myvendor;
642         struct dict_vendor_data myvendordata;
643         ret = fd_dict_search ( dict, DICT_VENDOR, VENDOR_BY_NAME, "my vendor name", &myvendor, ENOENT);
644         ret = fd_dict_getval ( myvendor, &myvendordata );
645         printf("my vendor id: %d\n", myvendordata.vendor_id );
646 }
647                 
648 
649*/
650         
651/*
652 ***************************************************************************
653 *
654 * Application object
655 *
656 * These types are used to manage Diameter applications in the dictionary
657 *
658 ***************************************************************************
659 */
660
661/* Type to hold a Diameter application ID: IANA assigned value for this application. */
662typedef uint32_t        application_id_t;
663
664/* Type to hold data associated to an application */
665struct dict_application_data {
666        application_id_t         application_id;        /* ID of the application */
667        char                    *application_name;      /* The name of this application */
668};
669
670/* The criteria for searching an application object in the dictionary */
671enum {
672        APPLICATION_BY_ID = 20,         /* "what" points to a application_id_t */
673        APPLICATION_BY_NAME,            /* "what" points to a string */
674        APPLICATION_OF_TYPE,            /* "what" points to a struct dict_object containing a type object (see bellow) */
675        APPLICATION_OF_COMMAND          /* "what" points to a struct dict_object containing a command (see bellow) */
676};
677
678/***
679 *  API usage :
680
681The "parent" parameter of dict_new may point to a vendor object to inform of what vendor defines the application.
682for standard-track applications, the "parent" parameter should be NULL.
683The vendor associated to an application is retrieved with VENDOR_OF_APPLICATION search criteria on vendors.
684
685- fd_dict_new:
686 Sample code for application creation:
687 {
688         int ret;
689         struct dict_object * vendor;
690         struct dict_object * appl;
691         struct dict_vendor_data vendor_data = {
692                 23455,
693                 "my vendor name"
694         };
695         struct dict_application_data app_data = {
696                 9789,
697                 "my vendor's application"
698         };
699       
700         ret = fd_dict_new ( dict, DICT_VENDOR, &vendor_data, NULL, &vendor );
701         ret = fd_dict_new ( dict, DICT_APPLICATION, &app_data, vendor, &appl );
702 }
703
704- fd_dict_search:
705 Sample code to retrieve the vendor of an application
706 {
707         int ret;
708         struct dict_object * vendor, * appli;
709         
710         ret = fd_dict_search ( dict, DICT_APPLICATION, APPLICATION_BY_NAME, "my vendor's application", &appli, ENOENT);
711         ret = fd_dict_search ( dict, DICT_VENDOR, VENDOR_OF_APPLICATION, appli, &vendor, ENOENT);
712 }
713 
714 - fd_dict_getval:
715 Sample code to retrieve the data from an application object:
716 {
717         int ret;
718         struct dict_object * appli;
719         struct dict_application_data appl_data;
720         ret = fd_dict_search ( dict, DICT_APPLICATION, APPLICATION_BY_NAME, "my vendor's application", &appli, ENOENT);
721         ret = fd_dict_getval ( appli, &appl_data );
722         printf("my application id: %s\n", appl_data.application_id );
723 }
724
725*/
726
727/*
728 ***************************************************************************
729 *
730 * Type object
731 *
732 * These types are used to manage AVP data types in the dictionary
733 *
734 ***************************************************************************
735 */
736
737/* Type to store any AVP value */ 
738union avp_value {
739        struct {
740                uint8_t *data;  /* bytes buffer */
741                size_t   len;   /* length of the data buffer */
742        }           os;         /* Storage for an octet string, data is alloc'd and must be freed */
743        int32_t     i32;        /* integer 32 */
744        int64_t     i64;        /* integer 64 */
745        uint32_t    u32;        /* unsigned 32 */
746        uint64_t    u64;        /* unsigned 64 */
747        float       f32;        /* float 32 */
748        double      f64;        /* float 64 */
749};
750
751/* These are the basic AVP types defined in RFC3588bis */
752enum dict_avp_basetype {
753        AVP_TYPE_GROUPED,
754        AVP_TYPE_OCTETSTRING,
755        AVP_TYPE_INTEGER32,
756        AVP_TYPE_INTEGER64,
757        AVP_TYPE_UNSIGNED32,
758        AVP_TYPE_UNSIGNED64,
759        AVP_TYPE_FLOAT32,
760        AVP_TYPE_FLOAT64
761#define AVP_TYPE_MAX AVP_TYPE_FLOAT64
762};
763
764/* Callbacks that can be associated with a derived type to easily interpret the AVP value. */
765/*
766 * CALLBACK:    dict_avpdata_interpret
767 *
768 * PARAMETERS:
769 *   val         : Pointer to the AVP value that must be interpreted.
770 *   interpreted : The result of interpretation is stored here. The format and meaning depends on each type.
771 *
772 * DESCRIPTION:
773 *   This callback can be provided with a derived type in order to facilitate the interpretation of formated data.
774 *  For example, when an AVP of type "Address" is received, it can be used to convert the octetstring into a struct sockaddr.
775 *  This callback is not called directly, but through the message's API msg_avp_value_interpret function.
776 *
777 * RETURN VALUE:
778 *  0           : Operation complete.
779 *  !0          : An error occurred, the error code is returned.
780 */
781typedef int (*dict_avpdata_interpret) (union avp_value * value, void * interpreted);
782/*
783 * CALLBACK:    dict_avpdata_encode
784 *
785 * PARAMETERS:
786 *   data       : The formated data that must be stored in the AVP value.
787 *   val        : Pointer to the AVP value storage area where the data must be stored.
788 *
789 * DESCRIPTION:
790 *   This callback can be provided with a derived type in order to facilitate the encoding of formated data.
791 *  For example, it can be used to convert a struct sockaddr in an AVP value of type Address.
792 *  This callback is not called directly, but through the message's API msg_avp_value_encode function.
793 *  If the callback is defined for an OctetString based type, the created string must be malloc'd. free will be called
794 *  automatically later.
795 *
796 * RETURN VALUE:
797 *  0           : Operation complete.
798 *  !0          : An error occurred, the error code is returned.
799 */
800typedef int (*dict_avpdata_encode) (void * data, union avp_value * val);
801
802
803/* Type to hold data associated to a derived AVP data type */
804struct dict_type_data {
805        enum dict_avp_basetype   type_base;     /* How the data of such AVP must be interpreted */
806        char                    *type_name;     /* The name of this type */
807        dict_avpdata_interpret   type_interpret;/* cb to convert the AVP value in more comprehensive format (or NULL) */
808        dict_avpdata_encode      type_encode;   /* cb to convert formatted data into an AVP value (or NULL) */
809};
810
811/* The criteria for searching a type object in the dictionary */
812enum {
813        TYPE_BY_NAME = 30,              /* "what" points to a string */
814        TYPE_OF_ENUMVAL,                /* "what" points to a struct dict_object containing an enumerated constant (DICT_ENUMVAL, see bellow). */
815        TYPE_OF_AVP                     /* "what" points to a struct dict_object containing an AVP object. */
816};
817
818
819/***
820 *  API usage :
821
822- fd_dict_new:
823 The "parent" parameter may point to an application object, when a type is defined by a Diameter application.
824 
825 Sample code:
826 {
827         int ret;
828         struct dict_object * mytype;
829         struct dict_type_data mytypedata =
830                {
831                 AVP_TYPE_OCTETSTRING,
832                 "Address",
833                 NULL,
834                 NULL
835                };
836         ret = fd_dict_new ( dict, DICT_TYPE, &mytypedata, NULL, &mytype );
837 }
838
839- fd_dict_search:
840 Sample code:
841 {
842         int ret;
843         struct dict_object * address_type;
844         ret = fd_dict_search ( dict, DICT_TYPE, TYPE_BY_NAME, "Address", &address_type, ENOENT);
845 }
846 
847*/
848         
849/*
850 ***************************************************************************
851 *
852 * Enumerated values object
853 *
854 * These types are used to manage named constants of some AVP,
855 * for enumerated types. Waaad allows contants for types others than Unsigned32
856 *
857 ***************************************************************************
858 */
859
860/* Type to hold data of named constants for AVP */
861struct dict_enumval_data {
862        char            *enum_name;     /* The name of this constant */
863        union avp_value  enum_value;    /* Value of the constant. Union term depends on parent type's base type. */
864};
865
866/* The criteria for searching a constant in the dictionary */
867enum {
868        ENUMVAL_BY_STRUCT = 40, /* "what" points to a struct dict_enumval_request as defined bellow */
869};
870
871struct dict_enumval_request {
872        /* Identifier of the parent type, one of the following must not be NULL */
873        struct dict_object      *type_obj;
874        char                    *type_name;
875       
876        /* Search criteria for the constant */
877        struct dict_enumval_data search; /* search.enum_value is used only if search.enum_name == NULL */
878};
879
880/***
881 *  API usage :
882
883- fd_dict_new:
884 The "parent" parameter must point to a derived type object.
885 Sample code to create a type "Boolean" with two constants "True" and "False":
886 {
887         int ret;
888         struct dict_object * type_boolean;
889         struct dict_type_data type_boolean_data =
890                {
891                 AVP_TYPE_INTEGER32,
892                 "Boolean",
893                 NULL,
894                 NULL
895                };
896         struct dict_enumval_data boolean_false =
897                {
898                 .enum_name="False",
899                 .enum_value.i32 = 0
900                };
901         struct dict_enumval_data boolean_true =
902                {
903                 .enum_name="True",
904                 .enum_value.i32 = -1
905                };
906         ret = fd_dict_new ( dict, DICT_TYPE, &type_boolean_data, NULL, &type_boolean );
907         ret = fd_dict_new ( dict, DICT_ENUMVAL, &boolean_false, type_boolean, NULL );
908         ret = fd_dict_new ( dict, DICT_ENUMVAL, &boolean_true , type_boolean, NULL );
909         
910 }
911
912- fd_dict_search:
913 Sample code to look for a constant name, by its value:
914 {
915         int ret;
916         struct dict_object * value_found;
917         struct dict_enumval_request boolean_by_value =
918                {
919                 .type_name = "Boolean",
920                 .search.enum_name=NULL,
921                 .search.enum_value.i32 = -1
922                };
923         
924         ret = fd_dict_search ( dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &boolean_by_value, &value_found, ENOENT);
925 }
926 
927 - fd_dict_getval:
928 Sample code to retrieve the data from a constant object:
929 {
930         int ret;
931         struct dict_object * value_found;
932         struct dict_enumval_data boolean_data = NULL;
933         struct dict_enumval_request boolean_by_value =
934                {
935                 .type_name = "Boolean",
936                 .search.enum_name=NULL,
937                 .search.enum_value.i32 = 0
938                };
939         
940         ret = fd_dict_search ( dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &boolean_by_value, &value_found, ENOENT);
941         ret = fd_dict_getval ( value_found, &boolean_data );
942         printf(" Boolean with value 0: %s", boolean_data.enum_name );
943 }
944*/
945         
946/*
947 ***************************************************************************
948 *
949 * AVP object
950 *
951 * These objects are used to manage AVP definitions in the dictionary
952 *
953 ***************************************************************************
954 */
955
956/* Type to hold an AVP code. For vendor 0, these codes are assigned by IANA. Otherwise, it is managed by the vendor */
957typedef uint32_t        avp_code_t;
958
959/* Values of AVP flags */
960#define AVP_FLAG_VENDOR         0x80
961#define AVP_FLAG_MANDATORY      0x40
962#define AVP_FLAG_RESERVED3      0x20
963#define AVP_FLAG_RESERVED4      0x10
964#define AVP_FLAG_RESERVED5      0x08
965#define AVP_FLAG_RESERVED6      0x04
966#define AVP_FLAG_RESERVED7      0x02
967#define AVP_FLAG_RESERVED8      0x01
968
969/* For dumping flags and values */
970#define DUMP_AVPFL_str  "%c%c"
971#define DUMP_AVPFL_val(_val) (_val & AVP_FLAG_VENDOR)?'V':'-' , (_val & AVP_FLAG_MANDATORY)?'M':'-'
972
973/* Type to hold data associated to an avp */
974struct dict_avp_data {
975        avp_code_t               avp_code;      /* Code of the avp */
976        vendor_id_t              avp_vendor;    /* Vendor of the AVP, or 0 */
977        char                    *avp_name;      /* Name of this AVP */
978        uint8_t                  avp_flag_mask; /* Mask of fixed AVP flags */
979        uint8_t                  avp_flag_val;  /* Values of the fixed flags */
980        enum dict_avp_basetype   avp_basetype;  /* Basic type of data found in the AVP */
981};
982
983/* The criteria for searching an avp object in the dictionary */
984enum {
985        AVP_BY_CODE = 50,       /* "what" points to an avp_code_t, vendor is always 0 */
986        AVP_BY_NAME,            /* "what" points to a string, vendor is always 0 */
987        AVP_BY_CODE_AND_VENDOR, /* "what" points to a struct dict_avp_request (see bellow), where avp_vendor and avp_code are set */
988        AVP_BY_NAME_AND_VENDOR  /* "what" points to a struct dict_avp_request (see bellow), where avp_vendor and avp_name are set */
989};
990
991/* Struct used for some researchs */
992struct dict_avp_request {
993        vendor_id_t      avp_vendor;
994        avp_code_t       avp_code;
995        char            *avp_name;
996};
997
998
999/***
1000 *  API usage :
1001
1002If "parent" parameter is not NULL during AVP creation, it must point to a DICT_TYPE object.
1003The extended type is then attached to the AVP. In case where it is an enumerated type, the value of
1004AVP is automatically interpreted in debug messages, and in message checks.
1005The derived type of an AVP can be retrieved with: dict_search ( DICT_TYPE, TYPE_OF_AVP, avp, ... )
1006
1007To create the rules (ABNF) for children of Grouped AVP, see the DICT_RULE related part.
1008
1009- fd_dict_new:
1010 Sample code for AVP creation:
1011 {
1012         int ret;
1013         struct dict_object * user_name_avp;
1014         struct dict_object * boolean_type;
1015         struct dict_object * sample_boolean_avp;
1016         struct dict_avp_data user_name_data = {
1017                 1,                                     // code
1018                 0,                                     // vendor
1019                 "User-Name",                           // name
1020                 AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,  // fixed mask: V and M values must always be defined as follow. other flags can be set or cleared
1021                 AVP_FLAG_MANDATORY,                    // the V flag must be cleared, the M flag must be set.
1022                 AVP_TYPE_OCTETSTRING                   // User-Name AVP contains OctetString data (further precision such as UTF8String can be given with a parent derived type)
1023         };
1024         struct dict_avp_data sample_boolean_data = {
1025                 31337,
1026                 23455,
1027                 "Sample-Boolean",
1028                 AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,
1029                 AVP_FLAG_VENDOR,
1030                 AVP_TYPE_INTEGER32                     // This MUST be the same as parent type's
1031         };
1032       
1033         -- Create an AVP with a base type --
1034         ret = fd_dict_new ( dict, DICT_AVP, &user_name_data, NULL, &user_name_avp );
1035         
1036         -- Create an AVP with a derived type --
1037         ret = fd_dict_search ( dict, DICT_TYPE, TYPE_BY_NAME, "Boolean", &boolean_type, ENOENT);
1038         ret = fd_dict_new ( dict, DICT_AVP, &sample_boolean_data , boolean_type, &sample_boolean_avp );
1039         
1040 }
1041
1042- fd_dict_search:
1043 Sample code to look for an AVP
1044 {
1045         int ret;
1046         struct dict_object * avp_username;
1047         struct dict_object * avp_sampleboolean;
1048         struct dict_avp_request avpvendorboolean =
1049                {
1050                 .avp_vendor = 23455,
1051                 .avp_name   = "Sample-Boolean"
1052                };
1053         
1054         ret = fd_dict_search ( dict, DICT_AVP, AVP_BY_NAME, "User-Name", &avp_username, ENOENT);
1055         
1056         ret = fd_dict_search ( dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &avpvendorboolean, &avp_sampleboolean, ENOENT);
1057         
1058 }
1059 
1060 - fd_dict_getval:
1061 Sample code to retrieve the data from an AVP object:
1062 {
1063         int ret;
1064         struct dict_object * avp_username;
1065         struct dict_avp_data user_name_data;
1066         ret = fd_dict_search ( dict, DICT_AVP, AVP_BY_NAME, "User-Name", &avp_username, ENOENT);
1067         ret = fd_dict_getval ( avp_username, &user_name_data );
1068         printf("User-Name code: %d\n", user_name_data.avp_code );
1069 }
1070
1071*/
1072
1073/*
1074 ***************************************************************************
1075 *
1076 * Command object
1077 *
1078 * These types are used to manage commands objects in the dictionary
1079 *
1080 ***************************************************************************
1081 */
1082
1083/* Type to hold a Diameter command code: IANA assigned values. 0x0-0x7fffff=standard, 0x800000-0xfffffd=vendors, 0xfffffe-0xffffff=experimental */
1084typedef uint32_t        command_code_t;
1085
1086/* Values of command flags */
1087#define CMD_FLAG_REQUEST        0x80
1088#define CMD_FLAG_PROXIABLE      0x40
1089#define CMD_FLAG_ERROR          0x20
1090#define CMD_FLAG_RETRANSMIT     0x10
1091#define CMD_FLAG_RESERVED5      0x08
1092#define CMD_FLAG_RESERVED6      0x04
1093#define CMD_FLAG_RESERVED7      0x02
1094#define CMD_FLAG_RESERVED8      0x01
1095
1096/* For dumping flags and values */
1097#define DUMP_CMDFL_str  "%c%c%c%c"
1098#define DUMP_CMDFL_val(_val) (_val & CMD_FLAG_REQUEST)?'R':'-' , (_val & CMD_FLAG_PROXIABLE)?'P':'-' , (_val & CMD_FLAG_ERROR)?'E':'-' , (_val & CMD_FLAG_RETRANSMIT)?'T':'-'
1099
1100/* Type to hold data associated to a command */
1101struct dict_cmd_data {
1102        command_code_t   cmd_code;      /* code of the command */
1103        char            *cmd_name;      /* Name of the command */
1104        uint8_t          cmd_flag_mask; /* Mask of fixed-value flags */
1105        uint8_t          cmd_flag_val;  /* values of the fixed flags */
1106};
1107
1108/* The criteria for searching an avp object in the dictionary */
1109enum {
1110        CMD_BY_NAME = 60,       /* "what" points to a string */
1111        CMD_BY_CODE_R,          /* "what" points to a command_code_t. The "Request" command is returned. */
1112        CMD_BY_CODE_A,          /* "what" points to a command_code_t. The "Answer" command is returned. */
1113        CMD_ANSWER              /* "what" points to a struct dict_object of a request command. The corresponding "Answer" command is returned. */
1114};
1115
1116
1117/***
1118 *  API usage :
1119
1120The "parent" parameter of dict_new may point to an application object to inform of what application defines the command.
1121The application associated to a command is retrieved with APPLICATION_OF_COMMAND search criteria on applications.
1122
1123To create the rules for children of commands, see the DICT_RULE related part.
1124
1125Note that the "Request" and "Answer" commands are two independant objects. This allows to have different rules for each.
1126
1127- fd_dict_new:
1128 Sample code for command creation:
1129 {
1130         int ret;
1131         struct dict_object * cer;
1132         struct dict_object * cea;
1133         struct dict_cmd_data ce_data = {
1134                 257,                                   // code
1135                 "Capabilities-Exchange-Request",       // name
1136                 CMD_FLAG_REQUEST,                      // mask
1137                 CMD_FLAG_REQUEST                       // value. Only the "R" flag is constrained here, set.
1138         };
1139       
1140         ret = fd_dict_new (dict,  DICT_COMMAND, &ce_data, NULL, &cer );
1141         
1142         ce_data.cmd_name = "Capabilities-Exchange-Answer";
1143         ce_data.cmd_flag_val = 0;                      // Same constraint on "R" flag, but this time it must be cleared.
1144
1145         ret = fd_dict_new ( dict, DICT_COMMAND, &ce_data, NULL, &cea );
1146 }
1147
1148- fd_dict_search:
1149 Sample code to look for a command
1150 {
1151         int ret;
1152         struct dict_object * cer, * cea;
1153         command_code_t code = 257;
1154         ret = fd_dict_search ( dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &cer, ENOENT);
1155         ret = fd_dict_search ( dict, DICT_COMMAND, CMD_BY_CODE_R, &code, &cer, ENOENT);
1156 }
1157 
1158 - fd_dict_getval:
1159 Sample code to retrieve the data from a command object:
1160 {
1161         int ret;
1162         struct dict_object * cer;
1163         struct dict_object * cea;
1164         struct dict_cmd_data cea_data;
1165         ret = fd_dict_search ( dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &cer, ENOENT);
1166         ret = fd_dict_search ( dict, DICT_COMMAND, CMD_ANSWER, cer, &cea, ENOENT);
1167         ret = fd_dict_getval ( cea, &cea_data );
1168         printf("Answer to CER: %s\n", cea_data.cmd_name );
1169 }
1170
1171*/
1172
1173/*
1174 ***************************************************************************
1175 *
1176 * Rule object
1177 *
1178 * These objects are used to manage rules in the dictionary (ABNF implementation)
1179 * This is used for checking messages validity (more powerful than a DTD)
1180 *
1181 ***************************************************************************
1182 */
1183
1184/* This defines the kind of rule that is defined */
1185enum rule_position {
1186        RULE_FIXED_HEAD = 1,    /* The AVP must be at the head of the group. The rule_order field is used to specify the position. */
1187        RULE_REQUIRED,          /* The AVP must be present in the parent, but its position is not defined. */
1188        RULE_OPTIONAL,          /* The AVP may be present in the message. Used to specify a max number of occurences for example */
1189        RULE_FIXED_TAIL         /* The AVP must be at the end of the group. The rule_order field is used to specify the position. */
1190};
1191
1192/* Content of a RULE object data */
1193struct dict_rule_data {
1194        struct dict_object      *rule_avp;      /* Pointer to the AVP object that is concerned by this rule */
1195        enum rule_position       rule_position; /* The position in which the rule_avp must appear in the parent */
1196        unsigned                 rule_order;    /* for RULE_FIXED_* rules, the place. 1,2,3.. for HEAD rules; ...,3,2,1 for TAIL rules. */
1197        int                      rule_min;      /* Minimum number of occurences. -1 means "default": 0 for optional rules, 1 for other rules */
1198        int                      rule_max;      /* Maximum number of occurences. -1 means no maximum. 0 means the AVP is forbidden. */
1199};
1200
1201/* The criteria for searching a rule in the dictionary */
1202enum {
1203        RULE_BY_AVP_AND_PARENT = 70     /* "what" points to a struct dict_rule_request -- see bellow. This is used to query "what is the rule for this AVP in this group?" */
1204};
1205
1206/* Structure for querying the dictionary about a rule */
1207struct dict_rule_request {
1208        struct dict_object      *rule_parent;   /* The grouped avp or command to which the rule apply */
1209        struct dict_object      *rule_avp;      /* The AVP concerned by this rule */
1210};
1211
1212
1213/***
1214 *  API usage :
1215
1216The "parent" parameter can not be NULL. It points to the object (grouped avp or command) to which this rule apply (i.e. for which the ABNF is defined).
1217
1218- fd_dict_new:
1219 Sample code for rule creation. Let's create the Proxy-Info grouped AVP for example.
1220 {
1221        int ret;
1222        struct dict_object * proxy_info_avp;
1223        struct dict_object * proxy_host_avp;
1224        struct dict_object * proxy_state_avp;
1225        struct dict_object * diameteridentity_type;
1226        struct dict_rule_data rule_data;
1227        struct dict_type_data di_type_data = { AVP_TYPE_OCTETSTRING, "DiameterIdentity", NULL, NULL };
1228        struct dict_avp_data proxy_info_data = { 284, 0, "Proxy-Info", AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, AVP_FLAG_MANDATORY, AVP_TYPE_GROUPED };
1229        struct dict_avp_data proxy_host_data = { 280, 0, "Proxy-Host", AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, AVP_FLAG_MANDATORY, AVP_TYPE_OCTETSTRING };
1230        struct dict_avp_data proxy_state_data = { 33, 0, "Proxy-State",AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, AVP_FLAG_MANDATORY, AVP_TYPE_OCTETSTRING };
1231       
1232        -- Create the parent AVP
1233        ret = fd_dict_new ( dict, DICT_AVP, &proxy_info_data, NULL, &proxy_info_avp );
1234       
1235        -- Create the first child AVP.
1236        ret = fd_dict_new ( dict, DICT_TYPE, &di_type_data, NULL, &diameteridentity_type );
1237        ret = fd_dict_new ( dict, DICT_AVP, &proxy_host_data, diameteridentity_type, &proxy_host_avp );
1238       
1239        -- Create the other child AVP
1240        ret = fd_dict_new ( dict, DICT_AVP, &proxy_state_data, NULL, &proxy_state_avp );
1241       
1242        -- Now we can create the rules. Both children AVP are mandatory.
1243        rule_data.rule_position = RULE_REQUIRED;
1244        rule_data.rule_min = -1;
1245        rule_data.rule_max = -1;
1246       
1247        rule_data.rule_avp = proxy_host_avp;
1248        ret = fd_dict_new ( dict, DICT_RULE, &rule_data, proxy_info_avp, NULL );
1249       
1250        rule_data.rule_avp = proxy_state_avp;
1251        ret = fd_dict_new ( dict, DICT_RULE, &rule_data, proxy_info_avp, NULL );
1252}
1253
1254- fd_dict_search and fd_dict_getval are similar to previous examples.
1255
1256*/
1257               
1258/* Define some hard-coded values */
1259/* Commands Codes */
1260#define CC_CAPABILITIES_EXCHANGE        257
1261#define CC_RE_AUTH                      258
1262#define CC_ACCOUNTING                   271
1263#define CC_ABORT_SESSION                274
1264#define CC_SESSION_TERMINATION          275
1265#define CC_DEVICE_WATCHDOG              280
1266#define CC_DISCONNECT_PEER              282
1267
1268/* AVPs (Vendor 0) */
1269#define AC_PROXY_STATE                  33
1270#define AC_HOST_IP_ADDRESS              257
1271#define AC_AUTH_APPLICATION_ID          258
1272#define AC_ACCT_APPLICATION_ID          259
1273#define AC_VENDOR_SPECIFIC_APPLICATION_ID 260
1274#define AC_REDIRECT_HOST_USAGE          261
1275#define AC_REDIRECT_MAX_CACHE_TIME      262
1276#define AC_SESSION_ID                   263
1277#define AC_ORIGIN_HOST                  264
1278#define AC_SUPPORTED_VENDOR_ID          265
1279#define AC_VENDOR_ID                    266
1280#define AC_FIRMWARE_REVISION            267
1281#define AC_RESULT_CODE                  268
1282#define AC_PRODUCT_NAME                 269
1283#define AC_DISCONNECT_CAUSE             273
1284#define ACV_DC_REBOOTING                        0
1285#define ACV_DC_BUSY                             1
1286#define ACV_DC_NOT_FRIEND                       2
1287#define AC_ORIGIN_STATE_ID              278
1288#define AC_FAILED_AVP                   279
1289#define AC_PROXY_HOST                   280
1290#define AC_ERROR_MESSAGE                281
1291#define AC_ROUTE_RECORD                 282
1292#define AC_DESTINATION_REALM            283
1293#define AC_PROXY_INFO                   284
1294#define AC_REDIRECT_HOST                292
1295#define AC_DESTINATION_HOST             293
1296#define AC_ERROR_REPORTING_HOST         294
1297#define AC_ORIGIN_REALM                 296
1298#define AC_INBAND_SECURITY_ID           299
1299
1300/* Error codes */
1301#define ER_DIAMETER_SUCCESS                     2001
1302#define ER_DIAMETER_REALM_NOT_SERVED            3003
1303#define ER_DIAMETER_TOO_BUSY                    3004
1304#define ER_DIAMETER_REDIRECT_INDICATION         3006
1305
1306
1307/*============================================================*/
1308/*                         SESSIONS                           */
1309/*============================================================*/
1310
1311/* Modules that want to associate a state with a Session-Id must first register a handler of this type */
1312struct session_handler;
1313
1314/* This opaque structure represents a session associated with a Session-Id */
1315struct session;
1316
1317/* The state information that a module associate with a session -- each module define its own data format */
1318typedef void session_state;
1319
1320/*
1321 * FUNCTION:    fd_sess_handler_create
1322 *
1323 * PARAMETERS:
1324 *  handler     : location where the new handler must be stored.
1325 *  cleanup     : a callback function that must be called when the session with associated data is destroyed.
1326 *
1327 * DESCRIPTION:
1328 *  Create a new session handler. This is needed by a module to associate a state with a session object.
1329 * The cleanup handler is called when the session timeout expires, or fd_sess_destroy is called. It must free
1330 * the state associated with the session, and eventually trig other actions (send a STR, ...).
1331 *
1332 * RETURN VALUE:
1333 *  0           : The new handler has been created.
1334 *  EINVAL      : A parameter is invalid.
1335 *  ENOMEM      : Not enough memory to complete the operation
1336 */
1337int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(char * sid, session_state * state) );
1338/* Macro to avoid casting everywhere */
1339#define fd_sess_handler_create( _handler, _cleanup ) \
1340        fd_sess_handler_create_internal( (_handler), (void (*)(char *, session_state *))(_cleanup) )
1341
1342/*
1343 * FUNCTION:    fd_sess_handler_destroy
1344 *
1345 * PARAMETERS:
1346 *  handler     : location of an handler created by fd_sess_handler_create.
1347 *
1348 * DESCRIPTION:
1349 *  This destroys a session handler (typically called when an application is shutting down).
1350 * If sessions states are registered with this handler, the cleanup callback is called on them.
1351 *
1352 * RETURN VALUE:
1353 *  0           : The handler was destroyed.
1354 *  EINVAL      : A parameter is invalid.
1355 *  ENOMEM      : Not enough memory to complete the operation
1356 */
1357int fd_sess_handler_destroy ( struct session_handler ** handler );
1358
1359
1360
1361/*
1362 * FUNCTION:    fd_sess_new
1363 *
1364 * PARAMETERS:
1365 *  session       : The location where the session object will be created upon success.
1366 *  diamId        : \0-terminated string containing a Diameter Identity.
1367 *  opt           : Additional string. Usage is described bellow.
1368 *  optlen        : if opt is \0-terminated, this can be 0. Otherwise, the length of opt.
1369 *
1370 * DESCRIPTION:
1371 *   Create a new session object. The Session-Id string associated with this session is generated as follow:
1372 *  If diamId parameter is provided, the string is created according to the RFC: <diamId>;<high32>;<low32>[;opt] where
1373 *    diamId is a Diameter Identity.
1374 *    high32 and low32 are the parts of a monotonic 64 bits counter initialized to (time, 0) at startup.
1375 *    opt is an optional string that can be concatenated to the identifier.
1376 *  If diamId is NULL, the string is exactly the content of opt.
1377 *
1378 * RETURN VALUE:
1379 *  0           : The session is created.
1380 *  EINVAL      : A parameter is invalid.
1381 *  EALREADY    : A session with the same name already exists (returned in *session)
1382 *  ENOMEM      : Not enough memory to complete the operation
1383 */
1384int fd_sess_new ( struct session ** session, char * diamId, char * opt, size_t optlen );
1385
1386/*
1387 * FUNCTION:    fd_sess_fromsid
1388 *
1389 * PARAMETERS:
1390 *  sid         : pointer to a string containing a Session-Id (UTF-8).
1391 *  len         : length of the sid string (which does not need to be '\0'-terminated)
1392 *  session     : On success, pointer to the session object created / retrieved.
1393 *  new         : if not NULL, set to 1 on return if the session object has been created, 0 if it was simply retrieved.
1394 *
1395 * DESCRIPTION:
1396 *   Retrieve a session object from a Session-Id string. Calling this function makes an implicit call to the
1397 *  fd_sess_link function on the returned session. In case no session object was previously existing with this
1398 *  id, a new object is silently created (equivalent to fd_sess_new with flag SESSION_NEW_FULL).
1399 *
1400 * RETURN VALUE:
1401 *  0           : The session parameter has been updated.
1402 *  EINVAL      : A parameter is invalid.
1403 *  ENOMEM      : Not enough memory to complete the operation
1404 */
1405int fd_sess_fromsid ( char * sid, size_t len, struct session ** session, int * new);
1406
1407/*
1408 * FUNCTION:    fd_sess_getsid
1409 *
1410 * PARAMETERS:
1411 *  session     : Pointer to a session object.
1412 *  sid         : On success, the location of a (\0-terminated) string is stored here.
1413 *
1414 * DESCRIPTION:
1415 *   Retrieve the session identifier (Session-Id) corresponding to a session object.
1416 *  The returned sid is an UTF-8 string terminated by \0, suitable for calls to strlen and strcpy.
1417 *  It may be used for example to set the value of an AVP.
1418 *  Note that the sid string is not copied, just its reference... do not free it!
1419 *
1420 * RETURN VALUE:
1421 *  0           : The sid parameter has been updated.
1422 *  EINVAL      : A parameter is invalid.
1423 */
1424int fd_sess_getsid ( struct session * session, char ** sid );
1425
1426/*
1427 * FUNCTION:    fd_sess_settimeout
1428 *
1429 * PARAMETERS:
1430 *  session     : The session for which to set the timeout.
1431 *  timeout     : The date when the session times out.
1432 *
1433 * DESCRIPTION:
1434 *   Set the lifetime for a given session object. This function may be
1435 * called several times on the same object to update the timeout value.
1436 *   When the timeout date is reached, the cleanup handler of each
1437 * module that registered data with this session is called, then the
1438 * session is cleared.
1439 *
1440 *   There is a possible race condition between cleanup of the session
1441 * and use of its data; applications should ensure that they are not
1442 * using data from a session that is about to expire / expired.
1443 *
1444 * RETURN VALUE:
1445 *  0           : The session timeout has been updated.
1446 *  EINVAL      : A parameter is invalid.
1447 */
1448int fd_sess_settimeout( struct session * session, const struct timespec * timeout );
1449
1450/*
1451 * FUNCTION:    fd_sess_destroy
1452 *
1453 * PARAMETERS:
1454 *  session     : Pointer to a session object.
1455 *
1456 * DESCRIPTION:
1457 *   Destroys a session an all associated data, if any.
1458 * Equivalent to a session timeout expired, but the effect is immediate.
1459 *
1460 * RETURN VALUE:
1461 *  0           : The session no longer exists.
1462 *  EINVAL      : A parameter is invalid.
1463 */
1464int fd_sess_destroy ( struct session ** session );
1465
1466/*
1467 * FUNCTION:    fd_sess_reclaim
1468 *
1469 * PARAMETERS:
1470 *  session     : Pointer to a session object.
1471 *
1472 * DESCRIPTION:
1473 *   Destroys the resources of a session, only if no session_state is associated with it.
1474 *
1475 * RETURN VALUE:
1476 *  0           : The session no longer exists.
1477 *  EINVAL      : A parameter is invalid.
1478 */
1479int fd_sess_reclaim ( struct session ** session );
1480
1481
1482
1483
1484/*
1485 * FUNCTION:    fd_sess_state_store
1486 *
1487 * PARAMETERS:
1488 *  handler     : The handler with which the state is registered.
1489 *  session     : The session object with which the state is registered.
1490 *  state       : An application state (opaque data) to store with the session.
1491 *
1492 * DESCRIPTION:
1493 *  Stores an application state with a session. This state can later be retrieved
1494 * with fd_sess_state_retrieve, or implicitly in the cleanup handler when the session
1495 * is destroyed.
1496 *
1497 * RETURN VALUE:
1498 *  0           : The state has been stored.
1499 *  EINVAL      : A parameter is invalid.
1500 *  EALREADY    : Data was already associated with this session and client.
1501 *  ENOMEM      : Not enough memory to complete the operation
1502 */
1503int fd_sess_state_store_internal ( struct session_handler * handler, struct session * session, session_state ** state );
1504#define fd_sess_state_store( _handler, _session, _state ) \
1505        fd_sess_state_store_internal( (_handler), (_session), (void *)(_state) )
1506
1507/*
1508 * FUNCTION:    fd_sess_state_retrieve
1509 *
1510 * PARAMETERS:
1511 *  handler     : The handler with which the state was registered.
1512 *  session     : The session object with which the state was registered.
1513 *  state       : Location where the state must be saved if it is found.
1514 *
1515 * DESCRIPTION:
1516 *  Retrieves a state saved by fd_sess_state_store.
1517 * After this function has been called, the state is no longer associated with
1518 * the session. A new call to fd_sess_state_store must be performed in order to
1519 * store again the data with the session.
1520 *
1521 * RETURN VALUE:
1522 *  0           : *state is updated (NULL or points to the state if it was found).
1523 *  EINVAL      : A parameter is invalid.
1524 */
1525int fd_sess_state_retrieve_internal ( struct session_handler * handler, struct session * session, session_state ** state ); 
1526#define fd_sess_state_retrieve( _handler, _session, _state ) \
1527        fd_sess_state_retrieve_internal( (_handler), (_session), (void *)(_state) )
1528
1529
1530/* For debug */
1531void fd_sess_dump(int level, struct session * session);
1532void fd_sess_dump_hdl(int level, struct session_handler * handler);
1533
1534
1535/*============================================================*/
1536/*                         MESSAGES                           */
1537/*============================================================*/
1538
1539/* The following types are opaque */
1540struct  msg;    /* A message: command with children AVPs (possibly grand children) */
1541struct  avp;    /* AVP object */
1542
1543/* Some details about chaining:
1544 *
1545 *  A message is made of a header ( msg ) and 0 or more AVPs ( avp ).
1546 * The structure is a kind of tree, where some AVPs (grouped AVPs) can contain other AVPs.
1547 * Exemple:
1548 * msg
1549 *  |-avp
1550 *  |-gavp
1551 *  |   |-avp
1552 *  |   |-avp
1553 *  |   \-avp
1554 *  |-avp
1555 *  \-avp
1556 *
1557 */
1558
1559/* The following type is used to point to either a msg or an AVP */
1560typedef void msg_or_avp;
1561
1562/* The Diameter protocol version */
1563#define DIAMETER_VERSION        1
1564
1565/* In the two following types, some fields are marked (READONLY).
1566 * This means that the content of these fields will be overwritten by the daemon so modifying it is useless.
1567 */
1568
1569/* The following structure represents the header of a message. All data is in host byte order. */
1570struct msg_hdr {
1571        uint8_t          msg_version;           /* (READONLY) Version of Diameter: must be DIAMETER_VERSION. */
1572        uint32_t         msg_length;            /* (READONLY)(3 bytes) indicates the length of the message */
1573        uint8_t          msg_flags;             /* Message flags: CMD_FLAG_* */
1574        command_code_t   msg_code;              /* (3 bytes) the command-code. See dictionary-api.h for more detail */
1575        application_id_t msg_appl;              /* The application issuing this message */
1576        uint32_t         msg_hbhid;             /* The Hop-by-Hop identifier of the message */
1577        uint32_t         msg_eteid;             /* The End-to-End identifier of the message */
1578};
1579
1580/* The following structure represents the visible content of an AVP. All data is in host byte order. */
1581struct avp_hdr {
1582        avp_code_t       avp_code;              /* the AVP Code */
1583        uint8_t          avp_flags;             /* AVP_FLAG_* flags */
1584        uint32_t         avp_len;               /* (READONLY)(Only 3 bytes are used) the length of the AVP as described in the RFC */
1585        vendor_id_t      avp_vendor;            /* Only used if AVP_FLAG_VENDOR is present */
1586        union avp_value *avp_value;             /* pointer to the value of the AVP. NULL means that the value is not set / not understood.
1587                                                   One should not directly change this value. Use the msg_avp_setvalue function instead.
1588                                                   The content of the pointed structure can be changed directly, with this restriction:
1589                                                     if the AVP is an OctetString, and you change the value of the pointer avp_value->os.data, then
1590                                                     you must call free() on the previous value, and the new one must be free()-able.
1591                                                 */
1592};
1593
1594/* The following enum is used to browse inside message hierarchy (msg, gavp, avp) */
1595enum msg_brw_dir {
1596        MSG_BRW_NEXT = 1,       /* Get the next element at the same level, or NULL if this is the last element. */
1597        MSG_BRW_PREV,           /* Get the previous element at the same level, or NULL if this is the first element. */
1598        MSG_BRW_FIRST_CHILD,    /* Get the first child AVP of this element, if any. */
1599        MSG_BRW_LAST_CHILD,     /* Get the last child AVP of this element, if any. */
1600        MSG_BRW_PARENT,         /* Get the parent element of this element, if any. Only the msg_t object has no parent. */
1601        MSG_BRW_WALK            /* This is equivalent to FIRST_CHILD or NEXT or PARENT->next, first that is not NULL. Use this to walk inside all AVPs. */
1602};
1603
1604/* Some flags used in the functions bellow */
1605#define MSGFL_ALLOC_ETEID       0x01    /* When creating a message, a new end-to-end ID is allocated and set in the message */
1606#define MSGFL_ANSW_ERROR        0x02    /* When creating an answer message, set the 'E' bit and use the generic error ABNF instead of command-specific ABNF */
1607#define MSGFL_MAX               MSGFL_ANSW_ERROR        /* The biggest valid flag value */
1608
1609/**************************************************/
1610/*   Message creation, manipulation, disposal     */
1611/**************************************************/
1612/*
1613 * FUNCTION:    fd_msg_avp_new
1614 *
1615 * PARAMETERS:
1616 *  model       : Pointer to a DICT_AVP dictionary object describing the avp to create, or NULL.
1617 *  flags       : Flags to use in creation (not used yet, should be 0).
1618 *  avp         : Upon success, pointer to the new avp is stored here.
1619 *
1620 * DESCRIPTION:
1621 *   Create a new AVP instance.
1622 *
1623 * RETURN VALUE:
1624 *  0           : The AVP is created.
1625 *  EINVAL      : A parameter is invalid.
1626 *  (other standard errors may be returned, too, with their standard meaning. Example:
1627 *    ENOMEM    : Memory allocation for the new avp failed.)
1628 */
1629int fd_msg_avp_new ( struct dict_object * model, int flags, struct avp ** avp );
1630
1631/*
1632 * FUNCTION:    fd_msg_new
1633 *
1634 * PARAMETERS:
1635 *  model       : Pointer to a DICT_COMMAND dictionary object describing the message to create, or NULL.
1636 *  flags       : combination of MSGFL_* flags.
1637 *  msg         : Upon success, pointer to the new message is stored here.
1638 *
1639 * DESCRIPTION:
1640 *   Create a new empty Diameter message.
1641 *
1642 * RETURN VALUE:
1643 *  0           : The message is created.
1644 *  EINVAL      : A parameter is invalid.
1645 *  (other standard errors may be returned, too, with their standard meaning. Example:
1646 *    ENOMEM    : Memory allocation for the new message failed.)
1647 */
1648int fd_msg_new ( struct dict_object * model, int flags, struct msg ** msg );
1649
1650/*
1651 * FUNCTION:    msg_new_answer_from_req
1652 *
1653 * PARAMETERS:
1654 *  dict        : Pointer to the dictionary containing the model of the query.
1655 *  msg         : The location of the query on function call. Updated by the location of answer message on return.
1656 *  flag        : Pass MSGFL_ANSW_ERROR to indicate if the answer is an error message (will set the 'E' bit)
1657 *
1658 * DESCRIPTION:
1659 *   This function creates the empty answer message corresponding to a request.
1660 *  The header is set properly (R flag, ccode, appid, hbhid, eteid)
1661 *  The Session-Id AVP is copied if present.
1662 *  The calling code should usually call fd_msg_rescode_set function on the answer.
1663 *  Upon return, the original query may be retrieved by calling fd_msg_answ_getq on the message.
1664 *
1665 * RETURN VALUE:
1666 *  0           : Operation complete.
1667 *  !0          : an error occurred.
1668 */
1669int fd_msg_new_answer_from_req ( struct dictionary * dict, struct msg ** msg, int flag );
1670
1671/*
1672 * FUNCTION:    fd_msg_browse
1673 *
1674 * PARAMETERS:
1675 *  reference   : Pointer to a struct msg or struct avp.
1676 *  dir         : Direction for browsing
1677 *  found       : If not NULL, updated with the element that has been found, if any, or NULL if no element was found / an error occurred.
1678 *  depth       : If not NULL, points to an integer representing the "depth" of this object in the tree. This is a relative value, updated on return.
1679 *
1680 * DESCRIPTION:
1681 *   Explore the content of a message object (hierarchy). If "found" is null, only error checking is performed.
1682 *  If "depth" is provided, it is updated as follow on successful function return:
1683 *   - not modified for MSG_BRW_NEXT and MSG_BRW_PREV.
1684 *   - *depth = *depth + 1 for MSG_BRW_FIRST_CHILD and MSG_BRW_LAST_CHILD.
1685 *   - *depth = *depth - 1 for MSG_BRW_PARENT.
1686 *   - *depth = *depth + X for MSG_BRW_WALK, with X between 1 (returned the 1st child) and -N (returned the Nth parent's next).
1687 *
1688 * RETURN VALUE:
1689 *  0           : found has been updated (if non NULL).
1690 *  EINVAL      : A parameter is invalid.
1691 *  ENOENT      : No element has been found where requested, and "found" was NULL (otherwise, *found is set to NULL and 0 is returned).
1692 */
1693int fd_msg_browse_internal ( msg_or_avp * reference, enum msg_brw_dir dir, msg_or_avp ** found, int * depth );
1694/* Macro to avoid having to cast the third parameter everywhere */
1695#define fd_msg_browse( ref, dir, found, depth ) \
1696        fd_msg_browse_internal( (ref), (dir), (void *)(found), (depth) )
1697
1698
1699/*
1700 * FUNCTION:    fd_msg_avp_add
1701 *
1702 * PARAMETERS:
1703 *  reference   : Pointer to a valid msg or avp.
1704 *  dir         : location where the new AVP should be inserted, relative to the reference. MSG_BRW_PARENT and MSG_BRW_WALK are not valid.
1705 *  avp         : pointer to the AVP object that must be inserted.
1706 *
1707 * DESCRIPTION:
1708 *   Adds an AVP into an object that can contain it: grouped AVP or message.
1709 *
1710 * RETURN VALUE:
1711 *  0           : The AVP has been added.
1712 *  EINVAL      : A parameter is invalid.
1713 */
1714int fd_msg_avp_add ( msg_or_avp * reference, enum msg_brw_dir dir, struct avp *avp);
1715
1716/*
1717 * FUNCTION:    fd_msg_search_avp
1718 *
1719 * PARAMETERS:
1720 *  msg         : The message structure in which to search the AVP.
1721 *  what        : The dictionary model of the AVP to search.
1722 *  avp         : location where the AVP reference is stored if found.
1723 *
1724 * DESCRIPTION:
1725 *   Search the first top-level AVP of a given model inside a message.
1726 * Note: only the first instance of the AVP is returned by this function.
1727 * Note: only top-level AVPs are searched, not inside grouped AVPs.
1728 * Use msg_browse if you need more advanced research features.
1729 *
1730 * RETURN VALUE:
1731 *  0           : The AVP has been found.
1732 *  EINVAL      : A parameter is invalid.
1733 *  ENOENT      : No AVP has been found, and "avp" was NULL (otherwise, *avp is set to NULL and 0 returned).
1734 */
1735int fd_msg_search_avp ( struct msg * msg, struct dict_object * what, struct avp ** avp );
1736
1737/*
1738 * FUNCTION:    fd_msg_free
1739 *
1740 * PARAMETERS:
1741 *  object      : pointer to the message or AVP object that must be unlinked and freed.
1742 *
1743 * DESCRIPTION:
1744 *   Unlink and free a message or AVP object and its children.
1745 *  If the object is an AVP linked into a message, the AVP is removed before being freed.
1746 *
1747 * RETURN VALUE:
1748 *  0           : The message has been freed.
1749 *  EINVAL      : A parameter is invalid.
1750 */
1751int fd_msg_free ( msg_or_avp * object );
1752
1753/***************************************/
1754/*   Dump functions                    */
1755/***************************************/
1756/*
1757 * FUNCTION:    fd_msg_dump_*
1758 *
1759 * PARAMETERS:
1760 *  level       : the log level (INFO, FULL, ...) at which the object is dumped
1761 *  obj         : A msg or avp object.
1762 *
1763 * DESCRIPTION:
1764 *   These functions dump the content of a message to the debug log
1765 * either recursively or only the object itself.
1766 *
1767 * RETURN VALUE:
1768 *   -
1769 */
1770void fd_msg_dump_walk ( int level, msg_or_avp *obj );
1771void fd_msg_dump_one  ( int level, msg_or_avp *obj );
1772
1773
1774/*********************************************/
1775/*   Message metadata management functions   */
1776/*********************************************/
1777/*
1778 * FUNCTION:    fd_msg_model
1779 *
1780 * PARAMETERS:
1781 *  reference   : Pointer to a valid msg or avp.
1782 *  model       : on success, pointer to the dictionary model of this command or AVP. NULL if the model is unknown.
1783 *
1784 * DESCRIPTION:
1785 *   Retrieve the dictionary object describing this message or avp. If the object is unknown or the fd_msg_parse_dict has not been called,
1786 *  *model is set to NULL.
1787 *
1788 * RETURN VALUE:
1789 *  0           : The model has been set.
1790 *  EINVAL      : A parameter is invalid.
1791 */
1792int fd_msg_model ( msg_or_avp * reference, struct dict_object ** model );
1793
1794/*
1795 * FUNCTION:    fd_msg_hdr
1796 *
1797 * PARAMETERS:
1798 *  msg         : Pointer to a valid message object.
1799 *  pdata       : Upon success, pointer to the msg_hdr structure of this message. The fields may be modified.
1800 *
1801 * DESCRIPTION:
1802 *   Retrieve location of modifiable section of a message.
1803 *
1804 * RETURN VALUE:
1805 *  0           : The location has been written.
1806 *  EINVAL      : A parameter is invalid.
1807 */
1808int fd_msg_hdr ( struct msg *msg, struct msg_hdr **pdata );
1809
1810/*
1811 * FUNCTION:    fd_msg_avp_hdr
1812 *
1813 * PARAMETERS:
1814 *  avp         : Pointer to a valid avp object.
1815 *  pdata       : Upon success, pointer to the avp_hdr structure of this avp. The fields may be modified.
1816 *
1817 * DESCRIPTION:
1818 *   Retrieve location of modifiable data of an avp.
1819 *
1820 * RETURN VALUE:
1821 *  0           : The location has been written.
1822 *  EINVAL      : A parameter is invalid.
1823 */
1824int fd_msg_avp_hdr ( struct avp *avp, struct avp_hdr **pdata );
1825
1826/*
1827 * FUNCTION:    fd_msg_answ_associate, fd_msg_answ_getq, fd_msg_answ_detach
1828 *
1829 * PARAMETERS:
1830 *  answer      : the received answer message
1831 *  query       : the corresponding query that had been sent
1832 *
1833 * DESCRIPTION:
1834 *  fd_msg_answ_associate associates a query msg with the received answer.
1835 * Query is retrieved with fd_msg_answ_getq.
1836 * If answer message is freed, the query is also freed.
1837 * If the msg_answ_detach function is called, the association is removed.
1838 * This is meant to be called from the daemon only.
1839 *
1840 * RETURN VALUE:
1841 *  0     : ok
1842 *  EINVAL: a parameter is invalid
1843 */
1844int fd_msg_answ_associate( struct msg * answer, struct msg * query );
1845int fd_msg_answ_getq     ( struct msg * answer, struct msg ** query );
1846int fd_msg_answ_detach   ( struct msg * answer );
1847
1848/*
1849 * FUNCTION:    fd_msg_anscb_associate, fd_msg_anscb_get
1850 *
1851 * PARAMETERS:
1852 *  msg         : the answer message
1853 *  anscb       : the callback to associate with the message
1854 *  data        : the data to pass to the callback
1855 *
1856 * DESCRIPTION:
1857 *  Associate or retrieve a callback with an answer message.
1858 * This is meant to be called from the daemon only.
1859 *
1860 * RETURN VALUE:
1861 *  0     : ok
1862 *  EINVAL: a parameter is invalid
1863 */
1864int fd_msg_anscb_associate( struct msg * msg, void ( *anscb)(void *, struct msg **), void  * data );
1865int fd_msg_anscb_get      ( struct msg * msg, void (**anscb)(void *, struct msg **), void ** data );
1866
1867/*
1868 * FUNCTION:    fd_msg_rt_associate, fd_msg_rt_get
1869 *
1870 * PARAMETERS:
1871 *  msg         : the query message to be sent
1872 *  list        : the ordered list of possible next-peers
1873 *
1874 * DESCRIPTION:
1875 *  Associate a routing list with a query, and retrieve it.
1876 * If the message is freed, the list is also freed.
1877 *
1878 * RETURN VALUE:
1879 *  0     : ok
1880 *  EINVAL: a parameter is invalid
1881 */
1882int fd_msg_rt_associate( struct msg * msg, struct fd_list ** list );
1883int fd_msg_rt_get      ( struct msg * msg, struct fd_list ** list );
1884
1885/*
1886 * FUNCTION:    fd_msg_is_routable
1887 *
1888 * PARAMETERS:
1889 *  msg         : A msg object.
1890 *
1891 * DESCRIPTION:
1892 *   This function returns a boolean telling if a given message is routable in the Diameter network,
1893 *  or if it is a local link message only (ex: CER/CEA, DWR/DWA, ...).
1894 *
1895 * RETURN VALUE:
1896 *  0           : The message is not routable / an error occurred.
1897 *  1           : The message is routable.
1898 */
1899int fd_msg_is_routable ( struct msg * msg );
1900
1901/*
1902 * FUNCTION:    fd_msg_source_(g/s)et
1903 *
1904 * PARAMETERS:
1905 *  msg         : A msg object.
1906 *  diamid      : The diameter id of the peer from which this message was received.
1907 *  hash        : The hash for the diamid value.
1908 *  add_rr      : if true, a Route-Record AVP is added to the message with content diamid. In that case, dict must be supplied.
1909 *  dict        : a dictionary with definition of Route-Record AVP (if add_rr is true)
1910 *
1911 * DESCRIPTION:
1912 *   Store or retrieve the diameted id of the peer from which this message was received.
1913 * Will be used for example by the routing module to add the Route-Record AVP in forwarded requests,
1914 * or to direct answers to the appropriate peer.
1915 *
1916 * RETURN VALUE:
1917 *  0           : Operation complete.
1918 *  !0          : an error occurred.
1919 */
1920int fd_msg_source_set( struct msg * msg, char * diamid, uint32_t hash, int add_rr, struct dictionary * dict );
1921int fd_msg_source_get( struct msg * msg, char ** diamid, uint32_t *hash );
1922
1923/*
1924 * FUNCTION:    fd_msg_eteid_get
1925 *
1926 * PARAMETERS:
1927 *  -
1928 *
1929 * DESCRIPTION:
1930 *   Get a new unique end-to-end id value for the local peer.
1931 *
1932 * RETURN VALUE:
1933 *  The new assigned value. No error code is defined.
1934 */
1935uint32_t fd_msg_eteid_get ( void );
1936
1937
1938/***************************************/
1939/*   Manage AVP values                 */
1940/***************************************/
1941
1942/*
1943 * FUNCTION:    fd_msg_avp_setvalue
1944 *
1945 * PARAMETERS:
1946 *  avp         : Pointer to a valid avp object with a NULL avp_value pointer. The model must be known.
1947 *  value       : pointer to an avp_value. The content will be COPIED into the internal storage area.
1948 *               If data type is an octetstring, the data is also copied.
1949 *               If value is a NULL pointer, the previous data is erased and value is unset in the AVP.
1950 *
1951 * DESCRIPTION:
1952 *   Initialize the avp_value field of an AVP header.
1953 *
1954 * RETURN VALUE:
1955 *  0           : The avp_value pointer has been set.
1956 *  EINVAL      : A parameter is invalid.
1957 */
1958int fd_msg_avp_setvalue ( struct avp *avp, union avp_value *value );
1959
1960/*
1961 * FUNCTION:    fd_msg_avp_value_encode
1962 *
1963 * PARAMETERS:
1964 *  avp         : Pointer to a valid avp object with a NULL avp_value. The model must be known.
1965 *  data        : Pointer to the data that must be encoded as AVP value and stored in the AVP.
1966 *               This is only valid for AVPs of derived type for which type_data_encode callback is set. (ex: Address type)
1967 *
1968 * DESCRIPTION:
1969 *   Initialize the avp_value field of an AVP object from formatted data, using the AVP's type "type_data_encode" callback.
1970 *
1971 * RETURN VALUE:
1972 *  0           : The avp_value has been set.
1973 *  EINVAL      : A parameter is invalid.
1974 *  ENOTSUP     : There is no appropriate callback registered with this AVP's type.
1975 */
1976int fd_msg_avp_value_encode ( void *data, struct avp *avp );
1977
1978/*
1979 * FUNCTION:    fd_msg_avp_value_interpret
1980 *
1981 * PARAMETERS:
1982 *  avp         : Pointer to a valid avp object with a non-NULL avp_value value.
1983 *  data        : Upon success, formatted interpretation of the AVP value is stored here.
1984 *
1985 * DESCRIPTION:
1986 *   Interpret the content of an AVP of Derived type and store the result in data pointer. The structure
1987 * of the data pointer is dependent on the AVP type. This function calls the "type_data_interpret" callback
1988 * of the type.
1989 *
1990 * RETURN VALUE:
1991 *  0           : The avp_value has been set.
1992 *  EINVAL      : A parameter is invalid.
1993 *  ENOTSUP     : There is no appropriate callback registered with this AVP's type.
1994 */
1995int fd_msg_avp_value_interpret ( struct avp *avp, void *data );
1996
1997
1998/***************************************/
1999/*   Message parsing functions         */
2000/***************************************/
2001
2002/*
2003 * FUNCTION:    fd_msg_bufferize
2004 *
2005 * PARAMETERS:
2006 *  msg         : A valid msg object. All AVPs must have a value set.
2007 *  buffer      : Upon success, this points to a buffer (malloc'd) containing the message ready for network transmission (or security transformations).
2008 *               The buffer may be freed after use.
2009 *  len         : if not NULL, the size of the buffer is written here. In any case, this size is updated in the msg header.
2010 *
2011 * DESCRIPTION:
2012 *   Renders a message in memory as a buffer that can be sent over the network to the next peer.
2013 *
2014 * RETURN VALUE:
2015 *  0           : The location has been written.
2016 *  EINVAL      : The buffer does not contain a valid Diameter message.
2017 *  ENOMEM      : Unable to allocate enough memory to create the buffer object.
2018 */
2019int fd_msg_bufferize ( struct msg * msg, unsigned char ** buffer, size_t * len );
2020
2021/*
2022 * FUNCTION:    fd_msg_parse_buffer
2023 *
2024 * PARAMETERS:
2025 *  buffer      : Pointer to a buffer containing a message received from the network.
2026 *  buflen      : the size in bytes of the buffer.
2027 *  msg         : Upon success, this points to a valid msg object. No AVP value is resolved in this object, nor grouped AVP.
2028 *
2029 * DESCRIPTION:
2030 *   This function parses a buffer an creates a msg object to represent the structure of the message.
2031 *  Since no dictionary lookup is performed, the values of the AVPs are not interpreted. To interpret the values,
2032 *  the returned message object must be passed to fd_msg_parse_dict function.
2033 *  The buffer pointer is saved inside the message and will be freed when not needed anymore.
2034 *
2035 * RETURN VALUE:
2036 *  0           : The location has been written.
2037 *  ENOMEM      : Unable to allocate enough memory to create the msg object.
2038 *  EBADMSG     : The buffer does not contain a valid Diameter message (or is truncated).
2039 *  EINVAL      : A parameter is invalid.
2040 */
2041int fd_msg_parse_buffer ( unsigned char ** buffer, size_t buflen, struct msg ** msg );
2042
2043/*
2044 * FUNCTION:    fd_msg_parse_dict
2045 *
2046 * PARAMETERS:
2047 *  object      : A msg or AVP object as returned by fd_msg_parse_buffer.
2048 *  dict        : the dictionary containing the objects definitions to use for resolving all AVPs.
2049 *
2050 * DESCRIPTION:
2051 *   This function looks up for the command and each children AVP definitions in the dictionary.
2052 *  If the dictionary definition is found, avp_model is set and the value of the AVP is interpreted accordingly and:
2053 *   - for grouped AVPs, the children AVP are created and interpreted also.
2054 *   - for numerical AVPs, the value is converted to host byte order and saved in the avp_value field.
2055 *   - for octetstring AVPs, the string is copied into a new buffer and its address is saved in avp_value.
2056 *  If the dictionary definition is not found, avp_model is set to NULL and
2057 *  the content of the AVP is saved as an octetstring in an internal structure. avp_value is NULL.
2058 *  As a result, after this function has been called, there is no more dependency of the msg object to the message buffer, that is be freed.
2059 *
2060 * RETURN VALUE:
2061 *  0           : The message has been fully parsed as described.
2062 *  EINVAL      : The msg parameter is invalid for this operation.
2063 *  ENOMEM      : Unable to allocate enough memory to complete the operation.
2064 *  ENOTSUP     : No dictionary definition for the command or one of the mandatory AVP was found.
2065 */
2066int fd_msg_parse_dict ( msg_or_avp * object, struct dictionary * dict );
2067
2068/*
2069 * FUNCTION:    fd_msg_parse_rules
2070 *
2071 * PARAMETERS:
2072 *  object      : A msg or grouped avp object that must be verified.
2073 *  dict        : The dictionary containing the rules definitions.
2074 *  rule        : If not NULL, the first conflicting rule will be saved here if a conflict is found.
2075 *
2076 * DESCRIPTION:
2077 *   Check that the children of the object do not conflict with the dictionary rules (ABNF compliance).
2078 *
2079 * RETURN VALUE:
2080 *  0           : The message has been fully parsed and complies to the defined rules.
2081 *  EBADMSG     : A conflict was detected, or a mandatory AVP is unknown in the dictionary.
2082 *  EINVAL      : The msg or avp object is invalid for this operation.
2083 *  ENOMEM      : Unable to allocate enough memory to complete the operation.
2084 */
2085int fd_msg_parse_rules ( msg_or_avp * object, struct dictionary * dict, struct dict_object ** rule);
2086
2087
2088/*
2089 * FUNCTION:    fd_msg_update_length
2090 *
2091 * PARAMETERS:
2092 *  object      : Pointer to a valid msg or avp.
2093 *
2094 * DESCRIPTION:
2095 *   Update the length field of the object passed as parameter.
2096 * As a side effect, all children objects are also updated. Therefore, all avp_value fields of
2097 * the children AVPs must be set, or an error will occur.
2098 *
2099 * RETURN VALUE:
2100 *  0           : The size has been recomputed.
2101 *  EINVAL      : A parameter is invalid.
2102 */
2103int fd_msg_update_length ( msg_or_avp * object );
2104
2105
2106/*============================================================*/
2107/*                         DISPATCH                           */
2108/*============================================================*/
2109
2110/* Dispatch module (passing incoming messages to extensions registered callbacks)
2111 * is split between the library and the daemon.
2112 *
2113 * The library provides the support for associating dispatch callbacks with
2114 * dictionary objects.
2115 *
2116 * The daemon is responsible for calling the callbacks for a message when appropriate.
2117 *
2118 *
2119 * The dispatch module has two main roles:
2120 *  - help determine if a message can be handled locally (during the routing step)
2121 *        This decision involves only the application-id of the message.
2122 *  - pass the message to the callback(s) that will handle it (during the dispatch step)
2123 *
2124 * The first role is handled by the daemon.
2125 *
2126 * About the second, these are the possibilities for registering a dispatch callback:
2127 *
2128 * -> For All messages.
2129 *  This callback is called for all messages that are handled locally. This should be used only
2130 *  for debug purpose.
2131 *
2132 * -> by AVP value (constants only).
2133 *  This callback will be called when a message is received and contains an AVP with a specified enumerated value.
2134 *
2135 * -> by AVP.
2136 *  This callback will be called when the received message contains a certain AVP.
2137 *
2138 * -> by command-code.
2139 *  This callback will be called when the message is a specific command (and 'R' flag).
2140 *
2141 * -> by application.
2142 *  This callback will be called when the message has a specific application-id.
2143 *
2144 * ( by vendor: would this be useful? it may be added later)
2145 */
2146enum disp_how {
2147        DISP_HOW_ANY = 1,               /* Any message. This should be only used for debug. */
2148        DISP_HOW_APPID,                 /* Any message with the specified application-id */
2149        DISP_HOW_CC,                    /* Messages of the specified command-code (request or answer). App id may be specified. */
2150        DISP_HOW_AVP,                   /* Messages containing a specific AVP. Command-code and App id may be specified. */
2151        DISP_HOW_AVP_ENUMVAL            /* Messages containing a specific AVP with a specific enumerated value. Command-code and App id may be specified. */
2152};
2153/*
2154 * Several criteria may be selected at the same time, for example command-code AND application id.
2155 *
2156 * If several callbacks are registered for the same object, they are called in the order they were registered.
2157 * The order in which the callbacks are called is:
2158 *  DISP_HOW_ANY
2159 *  DISP_HOW_AVP_ENUMVAL & DISP_HOW_AVP
2160 *  DISP_HOW_CC
2161 *  DISP_HOW_APPID
2162 */
2163
2164/* When a callback is registered, a "when" argument is passed in addition to the disp_how value,
2165 * to specify which values the criteria must match. */
2166struct disp_when {
2167        struct dict_object *    app;
2168        struct dict_object *    command;
2169        struct dict_object *    avp;
2170        struct dict_object *    value;
2171};
2172
2173/* Note that all the dictionary objects should really belong to the same dictionary!
2174 *
2175 * Here is the details on this "when" argument, depending on the disp_how value.
2176 *
2177 * DISP_HOW_ANY.
2178 *  In this case, "when" must be NULL.
2179 *
2180 * DISP_HOW_APPID.
2181 *  Only the "app_id" field must be set, other fields are ignored. It points to a dictionary object of type DICT_APPLICATION.
2182 *
2183 * DISP_HOW_CC.
2184 *  The "command" field must be defined and point to a dictionary object of type DICT_COMMAND.
2185 *  The "app_id" may be also set. In the case it is set, it restricts the callback to be called only with this command-code and app id.
2186 *  The other fields are ignored.
2187 *
2188 * DISP_HOW_AVP.
2189 *  The "avp" field of the structure must be set and point to a dictionary object of type DICT_AVP.
2190 *  The "app_id" field may be set to restrict the messages matching to a specific app id.
2191 *  The "command" field may also be set to a valid DICT_COMMAND object.
2192 *  The content of the "value" field is ignored.
2193 *
2194 * DISP_HOW_AVP_ENUMVAL.
2195 *  All fields have the same constraints and meaning as in DISP_REG_AVP. In addition, the "value" field must be set
2196 *  and points to a valid DICT_ENUMVAL object.
2197 *
2198 * Here is a sumary of the fields: ( M : must be set; m : may be set; 0 : ignored )
2199 *  field:     app_id    command     avp    value
2200 * APPID :       M          0         0       0
2201 * CC    :       m          M         0       0
2202 * AVP   :       m          m         M       0
2203 * ENUMVA:       m          m         M       M
2204 */
2205
2206enum disp_action {
2207        DISP_ACT_CONT,  /* The next handler should be called, unless *msg == NULL. */
2208        DISP_ACT_SEND   /* The updated message must be sent. No further callback is called. */
2209};
2210/* The callbacks that are registered have the following prototype:
2211 *      int dispatch_callback( struct msg ** msg, struct avp * avp, struct session * session, enum disp_action * action );
2212 *
2213 * CALLBACK:    dispatch_callback
2214 *
2215 * PARAMETERS:
2216 *  msg         : the received message on function entry. may be updated to answer on return (see description)
2217 *  avp         : for callbacks registered with DISP_HOW_AVP or DISP_HOW_AVP_ENUMVAL, direct link to the triggering AVP.
2218 *  session     : if the message contains a Session-Id AVP, the corresponding session object, NULL otherwise.
2219 *  action      : upon return, this tells the daemon what to do next.
2220 *
2221 * DESCRIPTION:
2222 *   Called when a received message matchs the condition for which the callback was registered.
2223 * This callback may do any kind of processing on the message, including:
2224 *  - create an answer for a request.
2225 *  - proxy a request or message, add / remove the Proxy-Info AVP, then forward the message.
2226 *  - update a routing table or start a connection with a new peer, then forward the message.
2227 *  - ...
2228 *
2229 * When *action == DISP_ACT_SEND on callback return, the msg pointed by *msg is passed to the routing module for sending.
2230 * When *action == DISP_ACT_CONT, the next registered callback is called.
2231 *  When the last callback gives also DISP_ACT_CONT action value, a default handler is called. It's behavior is as follow:
2232 *   - if the message is an answer, it is discarded.
2233 *   - if the message is a request, it is passed again to the routing stack, and marked as non-local handling.
2234 *
2235 * RETURN VALUE:
2236 *  0           : The callback executed successfully and updated *action appropriately.
2237 *  !0          : standard errors. In case of error, the message is discarded.
2238 */
2239
2240/* This structure represents a handler for a registered callback, allowing its de-registration */
2241struct disp_hdl;
2242
2243/*
2244 * FUNCTION:    fd_disp_register
2245 *
2246 * PARAMETERS:
2247 *  cb            : The callback function to register (see dispatch_callback description above).
2248 *  how           : How the callback must be registered.
2249 *  when          : Values that must match, depending on the how argument.
2250 *  handle        : On success, a handler to the registered callback is stored here if not NULL.
2251 *                 This handler can be used to unregister the cb.
2252 *
2253 * DESCRIPTION:
2254 *   Register a new callback to handle messages delivered locally.
2255 *
2256 * RETURN VALUE:
2257 *  0           : The callback is registered.
2258 *  EINVAL      : A parameter is invalid.
2259 *  ENOMEM      : Not enough memory to complete the operation
2260 */
2261int fd_disp_register ( int (*cb)( struct msg **, struct avp *, struct session *, enum disp_action *), 
2262                        enum disp_how how, struct disp_when * when, struct disp_hdl ** handle );
2263
2264/*
2265 * FUNCTION:    fd_disp_unregister
2266 *
2267 * PARAMETERS:
2268 *  handle       : Location of the handle of the callback that must be unregistered.
2269 *
2270 * DESCRIPTION:
2271 *   Removes a callback previously registered by fd_disp_register.
2272 *
2273 * RETURN VALUE:
2274 *  0           : The callback is unregistered.
2275 *  EINVAL      : A parameter is invalid.
2276 */
2277int fd_disp_unregister ( struct disp_hdl ** handle );
2278
2279/*
2280 * FUNCTION:    fd_msg_dispatch
2281 *
2282 * PARAMETERS:
2283 *  msg         : A msg object that have already been fd_msg_parse_dict.
2284 *  session     : The session corresponding to this object, if any.
2285 *  action      : Upon return, the action that must be taken on the message
2286 *
2287 * DESCRIPTION:
2288 *   Call all handlers registered for a given message.
2289 *  The session must have already been resolved on entry.
2290 *  The msg pointed may be updated during this process.
2291 *  Upon return, the action parameter points to what must be done next.
2292 *
2293 * RETURN VALUE:
2294 *  0           : Success.
2295 *  EINVAL      : A parameter is invalid.
2296 *  (other errors)
2297 */
2298int fd_msg_dispatch ( struct msg ** msg, struct session * session, enum disp_action *action );
2299
2300
2301
2302/*============================================================*/
2303/*                     QUEUES                                 */
2304/*============================================================*/
2305
2306/* Management of FIFO queues of elements */
2307
2308/* A queue is an opaque object */
2309struct fifo;
2310
2311/*
2312 * FUNCTION:    fd_fifo_new
2313 *
2314 * PARAMETERS:
2315 *  queue       : Upon success, a pointer to the new queue is saved here.
2316 *
2317 * DESCRIPTION:
2318 *  Create a new empty queue.
2319 *
2320 * RETURN VALUE :
2321 *  0           : The queue has been initialized successfully.
2322 *  EINVAL      : The parameter is invalid.
2323 *  ENOMEM      : Not enough memory to complete the creation. 
2324 */
2325int fd_fifo_new ( struct fifo ** queue );
2326
2327/*
2328 * FUNCTION:    fd_fifo_del
2329 *
2330 * PARAMETERS:
2331 *  queue       : Pointer to an empty queue to delete.
2332 *
2333 * DESCRIPTION:
2334 *  Destroys a queue. This is only possible if no thread is waiting for an element,
2335 * and the queue is empty.
2336 *
2337 * RETURN VALUE:
2338 *  0           : The queue has been destroyed successfully.
2339 *  EINVAL      : The parameter is invalid.
2340 */
2341int fd_fifo_del ( struct fifo  ** queue );
2342
2343/*
2344 * FUNCTION:    fd_fifo_length
2345 *
2346 * PARAMETERS:
2347 *  queue       : The queue from which to retrieve the number of elements.
2348 *  length      : Upon success, the current number of elements in the queue is stored here.
2349 *
2350 * DESCRIPTION:
2351 *  Retrieve the number of elements in a queue.
2352 *
2353 * RETURN VALUE:
2354 *  0           : The length of the queue has been written.
2355 *  EINVAL      : A parameter is invalid.
2356 */
2357int fd_fifo_length ( struct fifo * queue, int * length );
2358int fd_fifo_length_noerr ( struct fifo * queue ); /* no error checking version */
2359
2360/*
2361 * FUNCTION:    fd_fifo_setthrhd
2362 *
2363 * PARAMETERS:
2364 *  queue       : The queue for which the thresholds are being set.
2365 *  data        : An opaque pointer that is passed to h_cb and l_cb callbacks.
2366 *  high        : The high-level threshold. If the number of elements in the queue increase to this value, h_cb is called.
2367 *  h_cb        : if not NULL, a callback to call when the queue lengh is bigger than "high".
2368 *  low         : The low-level threshold. Must be < high.
2369 *  l_cb        : If the number of elements decrease to low, this callback is called.
2370 *
2371 * DESCRIPTION:
2372 *  This function allows to adjust the number of producer / consumer threads of a queue.
2373 * If the consumer are slower than the producers, the number of elements in the queue increase.
2374 * By setting a "high" value, we allow a callback to be called when this number is too high.
2375 * The typical use would be to create an additional consumer thread in this callback.
2376 * If the queue continues to grow, the callback will be called again when the length is 2 * high, then 3*high, ... N * high
2377 * (the callback itself should implement a limit on the number of consumers that can be created)
2378 * When the queue starts to decrease, and the number of elements go under ((N - 1) * high + low, the l_cb callback is called
2379 * and would typially stop one of the consumer threads. If the queue continues to reduce, l_cb is again called at (N-2)*high + low,
2380 * and so on.
2381 *
2382 * Since there is no destructor for the data pointer, if cleanup operations are required, they should be performed in
2383 * l_cb when the length of the queue is becoming < low.
2384 *
2385 * Note that the callbacks are called synchronously, during fd_fifo_post or fd_fifo_get. Their operation should be quick.
2386 *
2387 * RETURN VALUE:
2388 *  0           : The thresholds have been set
2389 *  EINVAL      : A parameter is invalid.
2390 */
2391int fd_fifo_setthrhd ( struct fifo * queue, void * data, uint16_t high, void (*h_cb)(struct fifo *, void **), uint16_t low, void (*l_cb)(struct fifo *, void **) );
2392
2393/*
2394 * FUNCTION:    fd_fifo_post
2395 *
2396 * PARAMETERS:
2397 *  queue       : The queue in which the element must be posted.
2398 *  item        : The element that is put in the queue.
2399 *
2400 * DESCRIPTION:
2401 *  An element is added in a queue. Elements are retrieved from the queue in FIFO order
2402 *  with the fd_fifo_get, fd_fifo_tryget, or fd_fifo_timedget functions.
2403 *
2404 * RETURN VALUE:
2405 *  0           : The element is queued.
2406 *  EINVAL      : A parameter is invalid.
2407 *  ENOMEM      : Not enough memory to complete the operation.
2408 */
2409int fd_fifo_post_int ( struct fifo * queue, void ** item );
2410#define fd_fifo_post(queue, item) \
2411        fd_fifo_post_int((queue), (void *)(item))
2412
2413/*
2414 * FUNCTION:    fd_fifo_get
2415 *
2416 * PARAMETERS:
2417 *  queue       : The queue from which the first element must be retrieved.
2418 *  item        : On return, the first element of the queue is stored here.
2419 *
2420 * DESCRIPTION:
2421 *  This function retrieves the first element from a queue. If the queue is empty, the function will block the
2422 * thread until a new element is posted to the queue, or until the thread is canceled (in which case the
2423 * function does not return).
2424 *
2425 * RETURN VALUE:
2426 *  0           : A new element has been retrieved.
2427 *  EINVAL      : A parameter is invalid.
2428 */
2429int fd_fifo_get_int ( struct fifo * queue, void ** item );
2430#define fd_fifo_get(queue, item) \
2431        fd_fifo_get_int((queue), (void *)(item))
2432
2433/*
2434 * FUNCTION:    fd_fifo_tryget
2435 *
2436 * PARAMETERS:
2437 *  queue       : The queue from which the element must be retrieved.
2438 *  msg         : On return, the message is stored here.
2439 *
2440 * DESCRIPTION:
2441 *  This function is similar to fd_fifo_get, except that it will not block if
2442 * the queue is empty, but return EWOULDBLOCK instead.
2443 *
2444 * RETURN VALUE:
2445 *  0           : A new element has been retrieved.
2446 *  EINVAL      : A parameter is invalid.
2447 *  EWOULDBLOCK : The queue was empty.
2448 */
2449int fd_fifo_tryget_int ( struct fifo * queue, void ** item );
2450#define fd_fifo_tryget(queue, item) \
2451        fd_fifo_tryget_int((queue), (void *)(item))
2452
2453/*
2454 * FUNCTION:    fd_fifo_timedget
2455 *
2456 * PARAMETERS:
2457 *  queue       : The queue from which the element must be retrieved.
2458 *  item        : On return, the element is stored here.
2459 *  abstime     : the absolute time until which we allow waiting for an item.
2460 *
2461 * DESCRIPTION:
2462 *  This function is similar to fd_fifo_get, except that it will block if the queue is empty
2463 * only until the absolute time abstime (see pthread_cond_timedwait for + info).
2464 * If the queue is still empty when the time expires, the function returns ETIMEDOUT
2465 *
2466 * RETURN VALUE:
2467 *  0           : A new item has been retrieved.
2468 *  EINVAL      : A parameter is invalid.
2469 *  ETIMEDOUT   : The time out has passed and no item has been received.
2470 */
2471int fd_fifo_timedget_int ( struct fifo * queue, void ** item, const struct timespec *abstime );
2472#define fd_fifo_timedget(queue, item, abstime) \
2473        fd_fifo_timedget_int((queue), (void *)(item), (abstime))
2474
2475/* Dump a fifo list and optionally its inner elements -- beware of deadlocks! */
2476void fd_fifo_dump(int level, char * name, struct fifo * queue, void (*dump_item)(int level, void * item));
2477
2478#endif /* _LIBFREEDIAMETER_H */
Note: See TracBrowser for help on using the repository browser.