Navigation


Changes between Initial Version and Version 1 of Dev/API


Ignore:
Timestamp:
Mar 1, 2011, 5:16:33 PM (13 years ago)
Author:
Sebastien Decugis
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Dev/API

    v1 v1  
     1[[PageOutline(2-4)]]
     2= The freeDiameter API =
     3
     4The complete API is documented in header files in [source:freeDiameter/include/freeDiameter include/freeDiameter folder]. The following is a short summary of each module's purpose.
     5
     6== Debug support ==
     7
     8''Namespace:'' fd_log_* ; ''Source file(s):'' [source:freeDiameter/libfdproto/log.c]
     9
     10Almost all functions from the freeDiameter framework use the function {{{fd_log_debug}}} to output information. This function is very similar to {{{printf}}}, but future versions of the daemon will allow the output to be directly stored into a file.
     11
     12We also use some preprocessor macros extensively through the code, defined in {{{libfdproto.h}}}. The {{{TRACE_DEBUG(level, format, ...}}} macro is used to issue a debug message only if the current debug level (see [wiki:Usage] for information on setting this level) allows it. In addition, this macro cat output a lot of meta-information if DEBUG support is compiled in. Meta-information include the current thread name, the location in source files where the debug message was issued, the timestamp, etc.
     13
     14Another family of macro that is used extensively is the {{{CHECK_*}}} macro. For example:
     15 CHECK_FCT_DO::
     16   This function takes two parameters.
     17   The first parameter is a function call, the second is a "fallback path".
     18   When this macro is called:
     19   * Optionally if the debug level is very high, it issues a debug message
     20     with the function call
     21   * Then the function call is executed.
     22   * If the return value is 0, the call is successful, "fallback path" is not executed.
     23   * Otherwise, the error code is dumped in debug, then "fallback path" is executed.
     24
     25There are several families of CHECK_* macro:
     26 * CHECK_FCT*: Use for calls to freeDiameter functions. This considers a non-0 return code as a standard error message.
     27 * CHECK_POSIX*: Use for calls to the pthread_* functions. This also considers a non-0 return code as a standard error message.
     28 * CHECK_SYS*: Use for other system calls. This considers <0 return codes as an error and retrieves the error code from {{{errno}}} variable.
     29 * CHECK_MALLOC*: Use for memory allocations ({{{malloc}}}, {{{strdup}}}, ...). This considers a NULL return value as an error, and reads the error code in {{{errno}}}.
     30 * CHECK_PARAMS*: Use for validating input parameters of functions. A value that evaluates to false is considered an error condition, similar to the {{{assert}}} function.
     31
     32In each family, the macro exists in two flavours:
     33 * <macro>(call): In case of failure, displays an error message and return the error code.
     34 * <macro>_DO(call, fallback): In case of failure, displays an error message then execute the ''fallback'' code.
     35
     36
     37== Binary strings ==
     38
     39''Namespace:'' fd_os_* ; ''Source file(s):'' [source:freeDiameter/libfdproto/ostr.c]
     40
     41''Note: this is new in freeDiameter 1.1.x.''
     42
     43
     44In order to differentiate the contents of buffers, we use the following types instead of simple {{{char *}}}:
     45
     46 uint8_t *::
     47   For bulk data, for example received from the network. We do not make any assumption on the contents. This data may not be suitable for any string operation such as {{{strlen}}} or {{{printf}}}.
     48
     49 os0_t::
     50   This is a pointer to a binary buffer that ''should not'' contain NUL bytes ('\0') except as its terminating byte. This type always come with a {{{size_t}}} information, that does not include the final NUL. It therefore ''should'' be safe to use '''some''' string operations, but it is generally a good idea to avoid it. There is no guarantee in particular that the contents is valid UTF-8 characters, so {{{printf}}} should be avoided (except for debug purpose).
     51
     52There are a few functions that allows the manipulation of {{{os0_t}}} data: {{{fd_os_is_valid_os0}}} (checks if a buffer contains a NUL byte), {{{os0dup}}} (safe and fast equivalent to strdup), {{{fd_os_cmp}}} (fast comparison function that does '''not''' mimic {{{strcmp}}}) and {{{fd_os_almostcasecmp}}} (a kind of case-insensitive counterpart).
     53
     54 !DiamId_t::
     55   Buffers with this type should contain valid Diameter Identity buffer. It means that it contains only letters, digits, hyphens and dots. In particular, if a Diameter Identity is internationalized, this contains the {{{stringprep}}} transformation result ("xn--..."). Note however that if the framework is compiled with option [wiki:Installation#cmakeflags DIAMID_IDNA_IGNORE], the buffer might contain unexpected characters. Treat with care.
     56
     57There are also some functions to handle this type, such as {{{fd_os_is_valid_DiameterIdentity}}} (checks if a buffer complies to the definition), and {{{fd_os_validate_DiameterIdentity}}} (transforms a string into a valid !DiamId_t).
     58
     59
     60
     61== Lists: fd_list ==
     62
     63''Namespace:'' fd_list_* ; ''Source file(s):'' [source:freeDiameter/libfdproto/lists.c]
     64
     65The {{{fd_list}}} structure is used extensively in the framework. It gives a unified way to handle [http://en.wikipedia.org/wiki/Doubly-linked_list#Circular_Doubly-linked_lists circular doubly-linked lists] in the code. You can find many examples of use throughout the code.
     66
     67Although our implementation is not optimal in terms of memory occupation (the fd_list structure contains 4 pointers: next in list, previous in list, pointer to list root, and a last pointer that is available for use depending on where the list is used), it is quite simple to use and very flexible.
     68
     69Macros:
     70 * FD_LIST_INITIALIZER: To statically initialize an empty list.
     71 * FD_IS_LIST_EMPTY: returns 0 if the list is not empty, !0 otherwise.
     72
     73Main functions:
     74 * fd_list_insert_after: insert a new element in a list after given position.
     75 * fd_list_unlink: remove an element from a list.
     76
     77=== Sample code ===
     78
     79Typically, this structure will be included in a bigger structure that needs to be chained in list, like this:
     80{{{
     81#!c
     82struct my_data {
     83   ...
     84   struct fd_list chaining;
     85   ...
     86};
     87}}}
     88
     89Now, if you want to create a list of my_data elements, you declare an empty list first:
     90{{{
     91#!c
     92struct fd_list my_data_list = FD_LIST_INITIALIZER(my_data_list);
     93}}}
     94
     95Add a new my_data in the list:
     96{{{
     97#!c
     98struct my_data * n;
     99
     100/* Allocate the my_data element */
     101CHECK_MALLOC( n = malloc(sizeof(struct my_data)) );
     102memset(n, 0, sizeof(struct my_data));
     103
     104/* Initialize the chaining element */
     105fd_list_init(&n->chaining, n);
     106
     107/* Initialize other fields */
     108...
     109
     110/* Now, add the element 'n' at the end of the list */
     111fd_list_insert_before(&my_data_list, &n->chaining);
     112}}}
     113
     114And here is how to iterate through the list:
     115{{{
     116#!c
     117struct fd_list * li; /* list item */
     118
     119for (li = my_data_list.next; li != &my_data_list; li = li->next) {
     120   struct my_data * md = li->o;
     121   
     122   /* Do something with this my_data element */
     123
     124}
     125}}}
     126
     127
     128== Diameter Dictionary support ==
     129
     130''Namespace:'' fd_dict_* ; ''Source file(s):'' [source:freeDiameter/libfdproto/dictionary.c]
     131
     132This module provides support for a dictionary of Diameter objects. Because the Diameter protocol does not include any "Type" information in the AVP headers, it is impossible to parse a message and interpret the attribute contents without a dictionary definition that maps each code & vendor combination to a type.
     133
     134The freeDiameter dictionary contains much more information though: the {{{dict_object_type}}} enum shows all the types of objects that can be defined in the dictionary: vendors, applications, types, constants values, AVPs, commands, and rules. These types are explained bellow.
     135
     136A dictionary in freeDiameter is of type {{{struct dictionary *}}}. It is initialized with {{{fd_dict_init}}} and destroyed with {{{fd_dict_fini}}}. The ''libfdproto'' library does not depend on an instance of a dictionary. On the other hand, the ''libfdcore'' defines a global dictionary that can be used by extensions also. This instance is accessed with {{{fd_g_config->cnf_dict}}}.
     137
     138A dictionary contains a collection of {{{struct dict_object *}}} objects, which are vendors, applications, etc. The API to access these objects is independant of the type of the object. The main functions are:
     139 * fd_dict_new: create a new object and store in a dictionary.
     140 * fd_dict_search: Search for an object in a dictionary.
     141
     142The [source:freeDiameter/include/freeDiameter/libfdproto.h] file contains a lot of information and example on using these function for each type of objects. You may also find additional information in [http://lists.freediameter.net/pipermail/dev/2011-February/000143.html this archived mail].
     143
     144 vendor::
     145   This associates a name with a vendor code as defined by "SMI Network Management Private Enterprise Codes" (RFC3232). This allows for a nicer debug output, but also provides a hash table for the AVP definitions.
     146
     147 application::
     148   This associates a Diameter application code ([http://www.iana.org/assignments/aaa-parameters/aaa-parameters.xml#aaa-parameters-45 IANA assigned]) with its name. In addition, the application can be associated with a Vendor during its creation.
     149
     150 type::
     151   This corresponds to the "Derived type" defined in RFC3588. An AVP can be either defined with a Base Type (OctetString, Unsigned32, ...) or a Derived Type. In terms of pure parsing, it does not change anything, but defining a Derived Type allows to:
     152   * define functions to handle the data with a specific encoding for example (see [http://lists.freediameter.net/pipermail/dev/2011-February/000143.html this mail] for more details).
     153   * and/or define constants values for this type. This is a bit different from the Diameter RFC that defines all AVP with constant values as Enumerated type.
     154
     155 constants::
     156   This corresponds to the values of Enumerated AVPs defined by Diameter standard -- with the following differences:
     157   * In our dictionary model, a constant is defined for a type specific to the AVP, whereas the RFC only uses "Enumerated" derived type for all AVPs. We use the convention name "Enumerated (''AVP-name'')" to distinguish the different Enumerated types. In addition, if the RFC does not specifically defines the AVP as enumerated, but we want to do it, we use "Enumerated* (''AVP-name'')" template name.
     158   * In our dictionary model, constants can be defined not only for Unsigned32 values (as specified in Diameter) but also for any other basic type (floats, integer64, ...)
     159
     160 AVP::
     161   This object associates AVP code and vendor to its name, flags, and basic type, which allows for parsing the Diameter message and interpreting the content of the AVP (for example, we can learn if an AVP containts OctetString data or if this is a Grouped AVP containing other AVPs in its data portion). Optionaly, the AVP can be associated with a Derived Type when it is created, which allows some additional features.
     162
     163 command::
     164   This associates a command code to the command name and flags. Note that usually two dictionary objects must be created for each code: one for the "*-Request" (R flag set) and one for the "*-Answer" (R flag cleared).
     165
     166 rules::
     167   This is a simple way to implement the ABNF rules from the RFC for commands and grouped AVPs, and have an automatic validation of the messages based on these rules.
     168
     169
     170As a "good practice", it is better to keep dictionary definitions of standard objects (i.e. that are defined in an RFC for example) as separate extensions from the applications that will use these objects. The rationale is that Diameter definitions are meant to be reused across applications, so we avoid code duplication and allow for faster development by keeping the dictionary definitions separated. Such dictionary-only extensions are conventionally named {{{dict_*.fdx}}} (see [wiki:Extensions] for the list of existing extensions).
     171
     172
     173== Sessions support ==
     174
     175== Messages management ==
     176
     177== libfdcore configuration ==
     178
     179== Queues and events ==
     180
     181== Peers ==
     182
     183== Routing and Dispatching ==
     184
     185----