Internet-Draft Yoshihiro Ohba Expires: April, 2003 Victor Fajardo Dilip Patel Toshiba America Research, Inc. (TARI) October 2, 2002 Diameter C++ API Status of This Memo This document is an Internet-Draft and is in full conformance with all provisions of Section 10 of RFC 2026. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF), its areas, and its working groups. Note that other groups may also distribute working documents as Internet- Drafts. Internet-Drafts are draft documents, valid for a maximum of six months, and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." The list of current Internet-Drafts can be accessed at http://www.ietf.org/ietf/1id-abstracts.txt. The list of Internet-Draft Shadow Directories can be accessed at http://www.ietf.org/shadow.html. Abstract The Diameter authentication, authorization, and accounting (AAA) protocol provides support for peering AAA transactions across the Internet. This document describes a standardized API for the Diameter protocol. The API is defined for the C++ language. The intent of the API is to foster source code portability across multiple programming platforms, leveraging the object-oriented nature of C++ and reusing what is already defined in the Diameter C API as much as possible. The C++ API can also be used as a basis to define more platform-independent API such as Java-based API. Expires April, 2003 [Page 1] Internet-Draft Diameter C++ API October 2, 2002 Table of Contents 1. Introduction ........................................... 3 2. Binding Independent Considerations ..................... 3 3. C++ API ................................................ 4 3.1. Constant Types ......................................... 4 3.1.1. IP Address and Port .................................... 4 3.1.2. Command Code ........................................... 4 3.1.3. Vendor Identifier ...................................... 4 3.1.4. Application Identifier ................................. 4 3.1.5. Attribute/Value Pair Code .............................. 4 3.1.6. Session Handle ......................................... 5 3.1.7. Application Handle ..................................... 5 3.1.8. API Return Codes ....................................... 5 3.1.9. AVP Data Type Codes .................................... 6 3.1.10. AVP Flags .............................................. 6 3.1.11. Notification Event Types ............................... 6 3.1.12. Session Event Types .................................... 7 3.1.13. Result Codes ........................................... 7 3.1.14. Application Identifier Values .......................... 8 3.1.15. Accounting Types ....................................... 8 3.1.16. Security Types ......................................... 8 3.1.17. AVP Data Types ......................................... 9 3.2. Class Library Overview ................................ 10 3.2.1. Message Parser ........................................ 10 3.2.1.1. Dictionary Data ....................................... 11 3.2.1.2. Dictionary Manager .................................... 11 3.2.1.3. Parser Data ........................................... 12 3.2.1.3.1. Message Buffer ........................................ 12 3.2.1.3.2. AVP Container Entry ................................... 13 3.2.1.3.3. AVP Container ......................................... 13 3.2.1.3.4. AVP Container List .................................... 14 3.2.1.4. AVP Container Entry Manager ........................... 15 3.2.1.5. AVP Container Manager ................................. 15 3.2.1.6. Diameter Header ....................................... 16 3.2.1.7. Error Status .......................................... 17 3.2.1.8. Parser ................................................ 18 3.2.1.8.1. Diameter Header Parser ................................ 19 3.2.1.8.2. Diameter Payload Parser ............................... 21 3.2.1.9. AAA Message ........................................... 22 3.2.2. Session, Event and Message Control .................... 22 3.2.2.1. Application Core ...................................... 23 3.2.2.2. Event Notification .................................... 24 3.2.2.2.1. Message Subscription Argument ......................... 25 3.2.2.2.2 Message Subscription Base Class ....................... 25 3.2.2.2.3 Derived Subscription Classes .......................... 25 3.2.2.2.4. Event Notification Registrar .......................... 26 3.2.2.3. Session Management .................................... 27 3.2.2.3.1. Session Base Class .................................... 27 3.2.2.3.2. Session Client Class .................................. 28 3.2.2.3.3. Session Server Class .................................. 29 3.2.2.3.4. Session Lookup Class .................................. 30 3.2.2.4 Message Control ....................................... 30 4. Acknowledgments ....................................... 31 5. References ............................................ 31 6. Authors' Information .................................. 31 7. Full Copyright Statement .............................. 32 Expires April, 2003 [Page 2] Internet-Draft Diameter C++ API October 2, 2002 A. Appendix - Sample Usage ............................... 32 A.1. Parser Usage .......................................... 32 A.1.1. Dictionary Initialization ............................. 32 A.1.2. Input Parser Usage .................................... 32 A.1.3. Output Parser Usage ................................... 34 A.1.4. Relay/Proxy Agent Parser Usage ........................ 36 cxxapi.nroff:2528: warning: `ni' not defined A.2. Application Usage ..................................... 38 A.2.1. Client Application Usage .............................. 38 A.2.2. Server Application Usage .............................. 40 1. Introduction Similar to the C language [CAPI], the C++ language API is designed around callback mechanism (or referred to as event notification mechanism in this document). Although the C API and C++ API are functionally equivalent, object-oriented nature of the C++ API better fits with C++-based application programs than C API for the following reasons. First, since classes are defined in a hierarchical manner in the C++ API, it is easy for applications to define a new class for their own purpose by deriving from the classes defined in the C++ API and reusing what is already defined. Second, the exception handling capability of C++ can provide a better way for handling errors in that applications cannot ignore the exception (otherwise, program will exit), which would make the applications easy to find out the place of the error and reduce the possibility of bugs caused by, either intentionally or unintentionally, ignoring the error. Third, there are some restrictions on the callback mechanism in the C API. In the callback mechanism defined in the C API in which callback functions are allowed to take only one argument (i.e., AAAMessage), it is difficult to extend the callback mechanism so that callback functions can take arbitrary numbers and types of arguments without converting them to a pointer to void type, where such conversion tends to become a place of bugs that are difficult to find. The C++ API solves this problem based on registering (a pointer to) a class instance, i.e., a set of variables and associated functions altogether, allowing flexible and extensible callbacks. The design policy of the C++ API is (i) reuse what is defined in the C API as much as possible, and (ii) leverage object-oriented nature of C++. The C++ API can also be used as a basis to define more platform- independent API such as Java-based API. 2. Binding Independent Considerations All the basic consideration for implementation described in section 2 of [CAPI] are applied to the C++ language API described in this document. Expires April, 2003 [Page 3] Internet-Draft Diameter C++ API October 2, 2002 3. C++ API 3.1. Constant Types The C++ API requires the C++ STL (Standard Template Library) to reuse commonly used classes such as vector, list, string, etc. 3.1.1. IP Address and Port o Synopsis typedef sockaddr_storage IP_ADDR; o Description The same as defined in [CAPI]. 3.1.2. Command Code o Synopsis typedef uint32_t AAACommandCode; o Description The same as defined in [CAPI]. 3.1.3. Vendor Identifier o Synopsis typedef uint32_t AAAVendorId; o Description The same as defined in [CAPI]. 3.1.4. Application Identifier o Synopsis typedef uint32_t AAAApplicationId; o Description AAAApplicationId is an identifier used for specifying an authentication or accounting application. 3.1.5. Attribute/Value Pair Code o Synopsis Expires April, 2003 [Page 4] Internet-Draft Diameter C++ API October 2, 2002 typedef uint32_t AAA_AVPCode; o Description The same as defined in [CAPI]. 3.1.6. Session Handle o Synopsis typedef void *AAASessionHandle; o Description AAASessionHandle is an identifier for a particular AAA session. It is used in the session APIs and when a message is created. 3.1.7. Application Handle o Synopsis typedef void *AAAApplicationHandle; o Description AAAApplicationId identifies a particular client session to the API. The application id is passed to AAAStartSession(), and is attached to incoming messages, to indicate with which client session the message is associated. 3.1.8. API Return Codes o Synopsis typedef enum { AAA_ERR_NOT_FOUND = -2, AAA_ERR_FAILURE = -1, AAA_ERR_SUCCESS = 0, AAA_ERR_NOMEM, AAA_ERR_PROTO, AAA_ERR_SECURITY, AAA_ERR_PARAMETER, AAA_ERR_CONFIG, AAA_ERR_UNKNOWN_CMD, AAA_ERR_MISSING_AVP, AAA_ERR_ALREADY_INIT, AAA_ERR_TIMED_OUT, AAA_ERR_CANNOT_SEND_MSG, AAA_ERR_ALREADY_REGISTERED, AAA_ERR_CANNOT_REGISTER, AAA_ERR_NOT_INITIALIZED, AAA_ERR_NETWORK_ERROR, AAA_ERR_MSG_UNPROCESSED, AAA_ERR_INVALID_STATE, Expires April, 2003 [Page 5] Internet-Draft Diameter C++ API October 2, 2002 AAA_ERR_PARSING_FAILED, } AAAReturnCode; o Description The same as defined in [CAPI] except that several types are newly added. 3.1.9. AVP Data Type Codes o Synopsis typedef enum { AAA_AVP_DATA_TYPE, AAA_AVP_STRING_TYPE, AAA_AVP_ADDRESS_TYPE, AAA_AVP_INTEGER32_TYPE, AAA_AVP_INTEGER64_TYPE, AAA_AVP_UINTEGER32_TYPE, AAA_AVP_UINTEGER64_TYPE, AAA_AVP_UTF8_STRING_TYPE, AAA_AVP_ENUM_TYPE, AAA_AVP_DIAMID_TYPE, AAA_AVP_DIAMURI_TYPE, AAA_AVP_GROUPED_TYPE, AAA_AVP_TIME_TYPE, } AAA_AVPDataType; o Description The same as defined in [CAPI] except that several types are newly added. 3.1.10. AVP Flags o Synopsis typedef enum { AAA_AVP_FLAG_NONE = 0, AAA_AVP_FLAG_MANDATORY = 0x1, AAA_AVP_FLAG_RESERVED = 0x2, AAA_AVP_FLAG_VENDOR_SPECIFIC = 0x4, AAA_AVP_FLAG_END_TO_END_ENCRYPT = 0x10, AAA_AVP_FLAG_UNKNOWN = 0x10000, AAA_AVP_FLAG_ENCRYPT = 0x40000, } AAA_AVPFlag; o Description The same as defined in [CAPI]. 3.1.11. Notification Event Types o Synopsis Expires April, 2003 [Page 6] Internet-Draft Diameter C++ API October 2, 2002 typedef enum { AAA_EVENT_TYPE_MESSAGE = 0, AAA_EVENT_TYPE_DISCONNECT, AAA_EVENT_TYPE_TIMEOUT, AAA_EVENT_TYPE_ABORT_SESSION } AAA_EVENT_TYPE; o Description Used with the C++ event subscription classes. These denotes the predefined events available in the C++ class library. 3.1.12. Session Event Types o Synopsis typedef enum { SESSION_EVENT_AUTH_REQUEST = 0, SESSION_EVENT_AUTH_SUCCESS, SESSION_EVENT_AUTH_FAILED, SESSION_EVENT_NO_SERVICE, SESSION_EVENT_PROC_ERROR } SESSION_EVENT; o Description Used with the C++ session classes. These denotes events that an application can use to notify the C++ class library of the current applications state. 3.1.13. Result Codes o Synopsis typedef enum { DIAMETER_MULTI_ROUND_AUTH = 1001 DIAMETER_SUCCESS = 2001 DIAMETER_LIMITED_SUCCESS = 2002 DIAMETER_COMMAND_UNSUPPORTED = 3001 DIAMETER_UNABLE_TO_DELIVER = 3002 DIAMETER_REALM_NOT_SERVED = 3003 DIAMETER_TOO_BUSY = 3004 DIAMETER_LOOP_DETECTED = 3005 DIAMETER_REDIRECT_INDICATION = 3006 DIAMETER_APPLICATION_UNSUPPORTED = 3007 DIAMETER_INVALID_HDR_BITS = 3008 DIAMETER_INVALID_AVP_BITS = 3009 DIAMETER_UNKNOWN_PEER = 3010 DIAMETER_AUTHENTICATION_REJECTED = 4001 DIAMETER_OUT_OF_SPACE = 4002 DIAMETER_AVP_UNSUPPORTED = 5001 DIAMETER_UNKNOWN_SESSION_ID = 5002 DIAMETER_AUTHORIZATION_REJECTED = 5003 DIAMETER_INVALID_AVP_VALUE = 5004 DIAMETER_MISSING_AVP = 5005 DIAMETER_RESOURCES_EXCEEDED = 5006 DIAMETER_CONTRADICTING_AVPS = 5007 Expires April, 2003 [Page 7] Internet-Draft Diameter C++ API October 2, 2002 DIAMETER_AVP_NOT_ALLOWED = 5008 DIAMETER_AVP_OCCURS_TOO_MANY_TIMES = 5009 DIAMETER_UNSUPPORTED_TRANSFORM = 5010 DIAMETER_NO_COMMON_APPLICATION = 5011 DIAMETER_UNSUPPORTED_VERSION = 5012 DIAMETER_UNABLE_TO_COMPLY = 5013 DIAMETER_INVALID_BIT_IN_HEADER = 5014 DIAMETER_INVALID_AVP_LENGTH = 5015 DIAMETER_INVALID_MESSAGE_LENGTH = 5016 DIAMETER_INVALID_AVP_BIT_COMBO = 5017 } DIAMETER_RESULT_CODE; o Description 3.1.14. Application Identifier Values o Synopsis #define NASREQ 1 #define MOBILE_IP 4 #define RELAY 0xffffffff o Description As defined in Section 2.4 of [DIAM]. 3.1.15. Accounting Types o Synopsis typedef enum { AAA_ACCT_EVENT = 1, AAA_ACCT_START = 2, AAA_ACCT_INTERIM = 3, AAA_ACCT_STOP = 4 } AAAAcctMessageType; o Description The same as defined in [CAPI]. 3.1.16. Security Types o Synopsis typedef enum { AAA_SEC_NOT_DEFINED = -2, AAA_SEC_NOT_CONNECTED = -1, AAA_SEC_NO_SECURITY = 0, AAA_SEC_CMS_SECURITY = 1, AAA_SEC_CMS_PROXIED = 2 } AAASecurityStatus; o Description Expires April, 2003 [Page 8] Internet-Draft Diameter C++ API October 2, 2002 The same as defined in [CAPI]. 3.1.17. AVP Data Types o Synopsis typedef int32_t diameter_integer32_t; typedef quad_t diameter_integer64_t; typedef u_int32_t diameter_unsigned32_t; typedef u_quad_t diameter_unsigned64_t; typedef string* diameter_octetstring_t; typedef diameter_octetstring_t diameter_utf8string_t; typedef struct { diameter_octetstring_t fqdn; u_int16_t port; u_int8_t transport:2; u_int8_t protocol:2; u_int8_t scheme:2; } diameter_uri_t; typedef diameter_utf8string_t diameter_identity_t; typedef diameter_octetstring_t diameter_ipaddress_t; typedef class AAAAvpContainerList* diameter_grouped_t; // // values possible for transport field of diameter_diamident_t // // avp_t is a special type used only in this library // for constructing a raw AVP. When using this type, specify // "AVP" as the avp_container type. // The string contains the entire AVP including AVP header. // typedef diameter_octetstring_t avp_t; // values possible for transport field of diameter_uri_t enum { TRANSPORT_PROTO_TCP = 0, TRANSPORT_PROTO_SCTP, TRANSPORT_PROTO_UDP, }; // values possible for protocol field of diameter_uri_t enum { AAA_PROTO_DIAMETER = 0, AAA_PROTO_RADIUS, AAA_PROTO_TACACSPLUS, }; // values possible for scheme field of diameter_uri_t enum { AAA_SCHEME_AAA = 0, AAA_SCHEME_AAAS }; o Description Expires April, 2003 [Page 9] Internet-Draft Diameter C++ API October 2, 2002 This type is newly defined for the C++ API to contain the value of an AVP. 3.2. Class Library Overview The Diameter C++ API consist of two (2) main sections. The first is a message parser which is responsible solely for composition, decomposition, verification and manipulation of diameter message. It is also responsible for loading the XML base dictionary. And the second is the Session, Event and Message Control section which is responsible for instantiating user sessions (both server and client), registering event notifications from the class library and transmission of messages composed by service specific applications. The C++ API requires the C++ STL (Standard Template Library) to reuse commonly used classes such as vector, list, string, etc. 3.2.1. Message Parser Figure 1 shows the basic parser class structure. The basic parser class, AAAParser, has three private members: rawData, appData and dictData. The rawData contains data to be used by lower layer entities that handle less structured data such as a Diameter header or a payload represented as a simple octet string. The appData member contains data to be used by applications that handle more structured data such as a structured Diameter header object or a list of AVPs. The dictData contains dictionary data needed for performing data conversion between the rawData and the appData. There are two classes, HeaderParser and PayloadParser, derived from the basic parser class in order to parse Diameter header and payload, respectively. AAAParserData AAAParserData AAADictionaryData (rawData) (appData) (dictData) | | | -------------------------------------------- | AAAParser Fig. 1. The Basic Parser Class Structure Figures 1(a) shows the bindings of HeaderParser. A AAAMessageBuffer class instance is used for storing a Diameter header as raw data. A AAADiameterHeader instance contains a structured Diameter header in which each header field is stored in a distinct member variable. Figures 1(b) shows the bindings of PayloadParser. A AAAMessageBuffer class instance is used for storing a Diameter payload as raw data. For rawData, either a list of AVP containers (AAAAvpContainerList) or an AVP container (AAAAvpContainer) can be specified, depending on whether the application needs to get or set values for all the AVPs in the payload or just for a specific type of AVPs. The HeaderParser and PayloadParser have an option to perform strict format checking against dictionary so that a mis-specified command Expires April, 2003 [Page 10] Internet-Draft Diameter C++ API October 2, 2002 flags (in the case of HeaderParser), a missing AVP or a mis-placed AVP (in the case of PayloadParser) can be detected by the API in addition to basic command length or AVP length/flags check, which would simplify message processing in applications. AAAMessageBuffer AAADiameterHeader AAADictionaryData (rawData) (appData) (dictData) | | | -------------------------------------------- | HeaderParser [derived from AAAParser] Fig. 1(a). HeaderParser Class Bindings AAAAvpContainerEntry AAAAvpContainerEntry | | | | AAAAvpContainer AAAAvpContainer | | | | AAAAvpContainerList | | | +---------+-------+ | | AAAMessageBuffer | AAADictionaryData (rawData) (appData) (dictData) | | | -------------------------------------------- | PayloadParser [derived from AAAParser] Fig. 1(b). PayloadParser Class Bindings 3.2.1.1. Dictionary Data The following class is defined as the base class of dictionary data. Any class that is to be used by the parser as a dictionary entry such as a command or an AVP dictionary is derived from this class. o Definition class AAADictionaryData {}; 3.2.1.2. Dictionary Manager The following class is defined for managing command and AVP dictionaries. Expires April, 2003 [Page 11] Internet-Draft Diameter C++ API October 2, 2002 o Definition class AAADictionaryManager { public: void init(char *dictFile); boolean_t getCommandCode(char *commandName, AAACommandCode *commandCode, AAAVendorId *vendorId); }; o Description void init() - This function initializes the command and AVP dictionaries based on an appropriate set of command and AVP dictionary files described in XML format [XML]. boolean_t getCommandCode() - Used for translating the command name into a pair of command code and vendor id. If translation is successful true is returned. Otherwise, false is returned. 3.2.1.3. Parser Data The following class is defined as the base class of parser data. Any class that is to be used by the parser as source data or destination data must be derived from this class. o Definition class AAAParserData {}; 3.2.1.3.1. Message Buffer This class defines a buffer to be used for storing raw data including Diameter header and payload. o Definition class AAAMessageBuffer: public AAAParserData { public: AAAMessageBuffer(char *buf, u_int32_t s, u_int32_t offset=0) { data = buf; size = s; this->offset = offset; } AAAMessageBuffer() { data = NULL; size = 0; offset = 0;} char *data; u_int32_t size; u_int32_t offset; }; o Description Expires April, 2003 [Page 12] Internet-Draft Diameter C++ API October 2, 2002 The definition of this class is straightforward. 3.2.1.3.2. AVP Container Entry This class is is used as a placeholder to pass an AVP value between application programs and the API. o Definition class AAAAvpContainerEntry : public AAAParserData { public: AAA_AVPDataType type; union { avp_t avp_val; diameter_integer32_t integer32_val; diameter_integer64_t integer64_val; diameter_unsigned32_t unsigned32_val; diameter_unsigned64_t unsigned64_val; diameter_utf8string_t utf8string_val; diameter_unsigned32_t enumerated_val; diameter_octetstring_t octetstring_val; diameter_identity_t identity_val; diameter_uri_t uri_val; diameter_octetstring_t ipaddress_val; diameter_grouped_t grouped_val; }; }; 3.2.1.3.3. AVP Container This class is used to hold a list of AAAAvpContainerEntry instances of the same AVP type. o Definition class AAAAvpContainer : public AAAParserData { public: AAAAvpContainer(); ~AAAAvpContainer(); void releaseEntries(); int size(); void add(AAAAvpContainerEntry*); void remove(AAAAvpContainerEntry*); const char* getAvpName(); void setAvpName(const char*); AAAAvpContainerEntry* operator[](int); protected: char *avpName; vector entry; }; o Description Expires April, 2003 [Page 13] Internet-Draft Diameter C++ API October 2, 2002 releaseEntries() - This function returns all the AAAAvpContainerEntry pointers in the container to the free list. It is the responsibility of applications to call this function as soon as processing of the containers are completed. int size() - This function returns the number of the AAAAvpContainerEntry elements in the container. void add(AAAAvpContainerEntry*) - This function adds a AAAAvpContainerEntry pointer to the container. void remove(AAAAvpContainerEntry*) - This function removes a AAAAvpContainerEntry pointer from the container. const char* getAvpName() void setAvpName(const char*): These functions are used to set or get the AVP name. corresponding to the container. operator[](int) - This arry operator returns a pointer to the AAAvpContainerEntry element at the specified index. 3.2.1.3.4. AVP Container List This class is used to hold a list of AAAAvpContainer entities of a Diameter command. o Definition class AAAAvpContainerList : public AAAParserData { public: AAAAvpContainerList(); ~AAAAvpContainerList(); void add(AAAAvpContainer*); void remove(AAAAvpContainer*); void prepend(AAAAvpContainer*); void releaseContainers(); AAAAvpContainer* search(char*); protected: vector avpc_l; }; o Description Expires April, 2003 [Page 14] Internet-Draft Diameter C++ API October 2, 2002 void add(AAAAvpContainer*) - This function adds the specified container to the internal list. void remove(AAAAvpContainer*) - This function removes the specified container from the internal list. remove(AAAAvpContainer*) - This function prepends the specified container to the internal list. AAAAvpContainer* search(char*) - This function searches the internal list for a container corresponding to the specified name. void releaseContainers() - This function returns all the containers in the list to the free list. It is the responsibility of applications to call this function as soon as processing of the containers are completed. 3.2.1.4. AVP Container Entry Manager This class is used to acquire and release an instance of AAAAvpContainerEntry. A pool of AAAAvpContainerEntry instances are managed by this class. The pool management policy is invisible to application. In other words, the API is flexible to apply a number of pool management policies. o Definition class AAAAvpContainerEntryManager { public: AAAAvpContainerEntry *acquire(AAA_AVPDataType); void release(AAAAvpContainerEntry*); }; o Description AAAAvpContainerEntry *acquire(AAA_AVPDataType) - This function assigns a AAAAvpContainerEntry resource of a specific type. void release(AAAAvpContainerEntry*) - This function release a AAAAvpContainerEntry resource. 3.2.1.5. AVP Container Manager Expires April, 2003 [Page 15] Internet-Draft Diameter C++ API October 2, 2002 This class is used to acquire and release an instance of AAAAvpContainer. A pool of AAAAvpContainer instances are managed by this class. The pool management policy is invisible to application. In other words, the API is flexible to apply a number of pool management policies. o Definition class AAAAvpContainerManager { public: AAAAvpContainer *acquire(const char*); void release(AAAAvpContainer*); }; o Description AAAAvpContainer *acquire(const char*) - This function assigns a AAAAvpContainer resource of a specific name. void release(AAAAvpContainer*) - This function release a AAAAvpContainer resource. 3.2.1.6. Diameter Header This class is used for handling Diameter header. o Definition struct hdr_flag { u_int8_t r:1; u_int8_t p:1; u_int8_t e:1; u_int8_t rsvd:5; }; #define HEADER_SIZE 20 class AAADiameterHeader : public AAAParserData { public: AAADiameterHeader(u_int8_t ver, u_int32_t length, struct hdr_flag flags, AAACommandCode code, AAAApplicationId appId, u_int32_t hh, u_int32_t ee) { this->ver = ver; this->length = length; this->flags = flags; this->code = code; Expires April, 2003 [Page 16] Internet-Draft Diameter C++ API October 2, 2002 this->appId = appId; this->hh = hh; this->ee = ee; } AAADiameterHeader() {} u_int8_t ver; u_int32_t length:24; struct hdr_flag flags; AAACommandCode code:24; AAAApplicationId appId; u_int32_t hh; u_int32_t ee; }; o Description The definition is straightforward except that hh and ee represents Hop-by-Hop Identifier and End-to-End Identifier, respectively. 3.2.1.7. Error Status This definition is used to notify the application of a parser error. o Definition enum { NORMAL = 0, BUG = 1, }; // The following error code is defined for error type "BUG" enum { MISSING_CONTAINER = 1, TOO_MUCH_AVP_ENTRIES, TOO_LESS_AVP_ENTRIES, PROHIBITED_CONTAINER, INVALID_CONTAINER_PARAM, INVALID_CONTAINER_CONTENTS, UNSUPPORTED_FUNCTIONALITY, INVALID_PARSER_USAGE MISSING_AVP_DICTIONARY_ENTRY }; class AAAErrorStatus { private: int type; // error type (NORMAL or BUG) int code; // either a diameter result code or a bug_code above string avp; // errornous AVP public: AAAErrorStatus(void) { type = NORMAL; code = DIAMETER_SUCCESS; }; void get(int&, int&, string&); Expires April, 2003 [Page 17] Internet-Draft Diameter C++ API October 2, 2002 void get(int&, int&); void set(int, int); void set(int, int, AAADictionaryData*); }; o Description There are two types of error categories returned from the ParseRawToApp() or ParseAppToRaw() member functions of the classes derived from the AAAParser class. One type (NORMAL) is normal error which is described in the Diameter specification [DIAM]. The other type (BUG) is related to application problam's misusage of the Message Parser part of the API. A number of error codes are defined for BUG type errors. AAAErrorStatus class is defined to carry error information such as error type, error code, and contents of an errornous AVP which is needed for specific errors. The following member functions are defined for this class. void get(int& type, int& code, string& avp) - Used for obtaining the type and code of the error, and errnous AVP. void get(int& type, int& code) - Used for obtaining the type and code the error. void set(int type, int code, string avp) - Used by the API for setting the type and code of the error, and errnous AVP. void set(int type, int code) - Used by the API for setting the type and code the error. 3.2.1.8. Parser This is the base class for parsers. o Definition class AAAParser { public: AAAParser() {rawData = appData = NULL; dictData = NULL; } virtual ~AAAParser() {}; virtual void parseRawToApp()=0; virtual void parseAppToRaw()=0; protected: void setRawData(AAAParserData *data) { rawData = data; } void setAppData(AAAParserData *data) { appData = data; } void setDictData(AAADictionaryData* data) { dictData = data; } AAAParserData *getRawData() { return rawData; } Expires April, 2003 [Page 18] Internet-Draft Diameter C++ API October 2, 2002 AAAParserData *getAppData() { return appData; } AAADictionaryData *getDictData() { return dictData; } private: AAAParserData *rawData; // Raw data AAAParserData *appData; // Application data translated from/to raw data AAADictionaryData *dictData; // Dictionary data }; o Description void parseRawToApp() - Parse raw data and translate it into application level data. void parseAppToRaw() - Parse application level data and translate it into raw data. void setRawData(AAAParserData*) - Set raw data to the parser. void setAppData(AAAParserData*) - Set application level data to the parser. void setDictData(AAADictionaryData*) - Set dictionary data data to the parser. AAAParserData *getRawData() - Get raw data from the parser. AAAParserData *getAppData() - Get application level data from the parser. AAADictionaryData* getDictData() - Get dictionary data data from the parser. 3.2.1.8.1. Diameter Header Parser This class is derived from AAAParser and used to parse Diameter headers. o Definition enum ParseOption { PARSE_LOOSE = 0, PARSE_STRICT = 1, }; class HeaderParser : public AAAParser Expires April, 2003 [Page 19] Internet-Draft Diameter C++ API October 2, 2002 { public: HeaderParser() { opt = PARSE_STRICT; }; void setRawData(AAAMessageBuffer*); void setAppData(AAADiameterHeader*); void parseRawToApp() throw(AAAErrorStatus); void parseAppToRaw() throw(AAAErrorStatus); void setOption(ParseOption); const char *getCommandName(); AAADictionaryData *getDictData(); private: ParseOption opt; }; o Description void setRawData(AAAMessageBuffer*) - Set raw data (i.e., AAAMessageBuffer*) to the parser. void setAppData(AAADiameterHeader*) - Set application level data (i.e., AAADiameterHeader*) to the parser. void parseRawToApp() throw(AAAErrorStatus) - Parse raw data and translate it into application level data. AAAErrorStatus is thrown when error occurs. void parseAppToRaw() throw(AAAErrorStatus) - Parse application level data and translate it into raw data. AAAErrorStatus is thrown when error occurs. void setOption(ParseOption) - Used to set the parsing option. When ParseOption is PARSE_STRICT (default), the parser tries to search a command dictionary for an entry that corresponds to the command code and application identifier. If such an entry is found, the parser uses the entry to verify the fields in the header. const char *getCommandName() - Used to obtain the command name. A non-null pointer is returned if and only if ParseOption is PARSE_STRICT and after parseRawToApp() or parseAppToRaw() is successfully returned. AAADictionaryData *getDictData() - Used to obtain the command dictionary. A non-null pointer is returned if and only if ParseOption is PARSE_STRICT and after parseRawToApp() or parseAppToRaw() is successfully returned. Note: setDictData() is automatically called when parseRawToApp() or Expires April, 2003 [Page 20] Internet-Draft Diameter C++ API October 2, 2002 parseAppToRaw() is called with ParseOption is set to PARSE_STRICT. 3.2.1.8.2. Diameter Payload Parser This class is derived from AAAParser and used to parse Diameter payloads. o Definition class PayloadParser : public AAAParser { public: PayloadParser() {}; void setRawData(AAAMessageBuffer*); void setAppData(AAAAvpContainerList*); void setAppData(AAAAvpContainer*); void parseRawToApp() throw(AAAErrorStatus); void parseAppToRaw() throw(AAAErrorStatus); void setDictData(AAADictionaryData*); }; o Description void setRawData(AAAMessageBuffer*) - Set raw data (i.e., AAAMessageBuffer*) to the parser. void setAppData(AAAAvpContainerList*) - Set application data (i.e., AAAAvpContainerList*) to the parser. The AAAAvpContainerList SHOULD NOT contain any AAAAvpContainer instance when non-null dictionary data is specified by setDictData() (see below). void parseRawToApp() throw(AAAErrorStatus) - Parse raw data and translate it into application level data. AAAErrorStatus is thrown when error occurs. void parseAppToRaw() throw(AAAErrorStatus) - Parse application level data and translate it into raw data. AAAErrorStatus is thrown when error occurs. void setDictData(AAADictionaryData*) - This function sets a command dictionary entry which can be obtained by using HeaderParser::getDictData(). When non-null AAADictionaryData is set, the specified command dictionary is used for parsing the payload. Parsing with non-null AAADictionaryData starts after initializing the offset offset value of the AAAMessageBuffer to zero. When null AAADictionaryData is set, the parser will try to use the contents of the AAAAvpContainerList Expires April, 2003 [Page 21] Internet-Draft Diameter C++ API October 2, 2002 instance specified by setAppData() as the dictionary to parse the payload, where specific sets of AVP types need to be parsed are expected to be specified in the AAAAvpConatinerList instance before calling parseAppToRaw() or parseRawToApp() functions. Parsing with null AAADictionaryData starts from the current offset of the AAAMessageBuffer. 3.2.1.9. AAA Message This definition is used by the Message Control part of the API as a binding to the Message Parser part of the API. This class is re- defined as a replacement of the C-based AAAMessage type definition. o Definition class AAAMessage { public: AAADiameterHeader hdr; AAAAvpContainerList acl; AAAErrorStatus status; IP_ADDR originator; IP_ADDR sender; time_t secondsTillExpire; time_t startTime; void *appHandle; }; o Description The hdr member stores the contents of the current Diameter header. The acl member stores the list of AVPs. The status member stores the error status to be returned by the Message Parser part of the API. The other members are the same as defined in AAAMessage type in [CAPI]. 3.2.2. Session, Event and Message Control Expires April, 2003 [Page 22] Internet-Draft Diameter C++ API October 2, 2002 AAAMessage | | AAAMessageControl AAAMessageControl AAAMessageArg | | | | | | AAASessionClient AAASessionServer AAASubscription | | | | | | | | AAAEventNotification | | | | | | ----------------------------------------- | AAAApplicationCore Fig. 2. Session, Event and Message Control Class Bindings and Hierarchy As shown in Fig. 2. above, the Session, Event and Message Control classes are bounded to a single instance of the application core. An application identifies itself to the diameter class library by this object. All other classes are services that operates on this object. Instances of service classes maybe transient but their effect on the application core is persistent. Theoretically, this class library could easily be a shared library with each diameter application creating it's own instance of the application core. No re-entrancy protection is required since all application data are localized in the core object and resides within each application context. 3.2.2.1. Application Core This class defines the application core. It performs initialization and configuration of the AAA class library. An instance of this object must be created for the class library to be usable. Some of the operations that may be performed by this object includes opening and loading the AVP and vendor dictionaries, opening and loading diameter routing tables, opening connections with Diameter peers, loading Diameter extension libraries. Expires April, 2003 [Page 23] Internet-Draft Diameter C++ API October 2, 2002 o Definition class AAAApplicationCore { public: AAAApplicationCore(); AAAApplicationCore(char *configFileName); ~AAAApplicationCore(); AAAReturnCode Open(char *configFileName = NULL); AAAReturnCode Reload(); const char *GetConfigFileName(); const AAAApplicationHandle GetAppHandle(); private: AAAApplicationHandle handle; }; o Description Open(char *configFileName) - Loads configuration files performs initialization an. This functionality is also encapsulated in the constructor for convenience. Reload() - Reloads configuration data into runtime tables and variables (only those that can be reloaded successfully without requiring a program restart). This functionality is useful for administratively changing items like timing variables without disrupting current operations and sessions. handle - The application handle is an opaque data holder for internal use by this class. It would be a reference to data values loaded retrieved from the configuration files. It MAY also be a place holder for instance specific properties like application state, pointers to tables .. etc. As and example, GetConfigFileName() SHOULD be implemented to retrieve the filename from the appHandle. 3.2.2.2. Event Notification The class definitions below provides for event notification including message delivery to clients. The notification model is simple. All notifications are delivered via a subscription object. The subscription object encapsulates different types events specified by the AAA_EVENT enumeration. Events for message delivery would have member data variables filled in to carry the message. Other events that does not require data would not. A client interested in receiving messages and notifications would need to implement a derived class from the abstract base class AAASubscription. An instance of this class would then need to be subscribed via AAAEventNotification. The derived class needs to be Expires April, 2003 [Page 24] Internet-Draft Diameter C++ API October 2, 2002 persistent during the lifetime of the application core or while not being unsubscribed via AAAEventNotification. The AAAEVentNotification instance is service class of the application and can therefore be transient. 3.2.2.2.1. Message Subscription Argument Base class for encapsulating subscription arguments. Application clients defining new types of subscriptions will have to derive a class base on this class if it needs to associate an argument with the subscription. o Definition class AAA_EVENT_ARG { public: }; 3.2.2.2.2 Message Subscription Base Class This is a base class that encapsulates registration of command specific messages. An application client needs to define a class derived from this class and implement it's Event() function. A client application needs to define different classes for EACH command message it is interested in. The type of command is dictated by the values set in AAAMessageArg that is passed to the constructor of the AAAMessageSubscription. It is important to note that the event notifier will de-reference the AAASubscription pointer to an AAAMessageSubscription if the type is determined to be AAA_EVENT_TYPE_MESSAGE. Also, the application client is responsible for allocation AAAMessageArg and passing it to the constructor. This allocated message argument is filled by the notifier with incoming messages. o Definition class AAASubscription { public: AAASubscription(AAA_EVENT_TYPE typeArg, AAA_EVENT_ARG* argArg = NULL); virtual AAAReturnCode Event() = 0; AAA_EVENT_TYPE GetType(); AAA_EVENT_ARG* GetArg(); protected: AAA_EVENT_TYPE type; AAA_EVENT_ARG* arg; }; o Description Event() - This is the virtual method that needs to be implemented by subscription specific classes. 3.2.2.2.3 Derived Subscription Classes Expires April, 2003 [Page 25] Internet-Draft Diameter C++ API October 2, 2002 The classes defined here are derived from AAASubscription to provide a generic way of responding to AAA_EVENT_- TYPE_DISCONNECT, AAA_EVENT_TYPETIMEOUT and AAA_EVENT_- _ABORT_SESSION. The proper event type is designated automatically in the constructor and the Event() function is a do nothing event that returns success. Additional classes derived from AAA_EVENT_ARG are also defined to hold subscription specific information. o Definition class AAAMessageArg : public AAA_EVENT_ARG { public: AAAMessage message; }; class AAAMessageSubscription : public AAASubscription { public: AAAMessageSubscription(AAAMessageArg *messageArg) : AAASubscription(AAA_EVENT_TYPE_MESSAGE, messageArg) {}; virtual AAAReturnCode Event() = 0; }; class AAASessionArg : public AAA_EVENT_ARG { public: AAASessionHandle handle; }; class AAADisconnectSubscription : public AAASubscription { public: AAADisconnectSubscription(AAASessionArg *sessionArg) : AAASubscription(AAA_EVENT_TYPE_DISCONNECT, sessionArg) {} ; virtual AAAReturnCode Event() { return AAA_ERR_SUCCESS; }; }; class AAATimeoutSubscription : public AAASubscription { public: AAATimeoutSubscription(AAASessionArg *sessionArg) : AAASubscription(AAA_EVENT_TYPE_TIMEOUT, sessionArg) {} ; virtual AAAReturnCode Event() { return AAA_ERR_SUCCESS; }; }; class AAAAbortSessionSubscription : public AAASubscription { public: AAAAbortSessionSubscription(AAASessionArg *sessionArg) : AAASubscription(AAA_EVENT_TYPE_ABORT_SESSION, sessionArg) {} ; virtual AAAReturnCode Event() { return AAA_ERR_SUCCESS; }; }; 3.2.2.2.4. Event Notification Registrar This is the service class used to subscribe and unsubscribe AAASubscription based object to the application core. The service class requires an instance of the application on which to operate on. Expires April, 2003 [Page 26] Internet-Draft Diameter C++ API October 2, 2002 o Definition class AAAEventNotification { public: AAAEventNotification(AAAApplicationCore &appCore); ~AAAEventNotification(); AAAReturnCode Subscribe(AAASubscription *subscription); AAAReturnCode UnSubscribe(AAASubscription *subscription); private: AAAApplicationCore *core; }; o Description Subscribe(AAASubscription *subscription) - This function is used to register an AAASubscription object to the application core. An instance of the AAASubscription derived class must have a valid AAA_EVENT_TYPE defined via the AAASubscription constructor. UnSubscribe(AAASubscription *subscription) This is a symmetric function to Subscribe() and requires the AAASubscription derived object to be passed to it for de- registration. 3.2.2.3. Session Management The class definitions in this section allow the client to open, close, and manipulate sessions and servers to accept or reject a session request. As with the event notification class, an instance of the application core is required. The session management model has two (2) parts, client and server. Creating a session entity is the responsibility of both the client and server. The client is the active entity and can start and end a session. The server can either accept or reject (via abort) a session request. The server accepts or rejects a session from incoming messages received from the event notification subscription. A base class is provided to encapsulates the session specific information and would not typically be used directly by the client application. The client and server derived class provides the functionality required by the application to act either as a diameter client or server. A helper class for searching the internal database for existing sessions is also provided. Currently, searches can be made based on messages. However, the class may be extended to allow searches using other keys or information. 3.2.2.3.1. Session Base Class The following defines a base class for representing session data Expires April, 2003 [Page 27] Internet-Draft Diameter C++ API October 2, 2002 o Definition class AAASession { public: AAASession(AAAApplicationCore &appCore); virtual ~AAASession(); AAAReturnCode SetMessageTimeout(time_t timeout); AAAReturnCode SetApplicationId(diameter_unsigned32_t id); virtual AAAReturnCode Update(SESSION_EVENT event) = 0; const AAASessionHandle GetSessionHandle(); const AAAApplicationCore *GetAppCore(); protected: AAASessionHandle handle; AAAApplicationCore *core; }; o Description SetMessageTimeout(time_t timeout) - This function sets the timeout, in seconds, for all AAAMessages in a particular session. SetApplicationId(diameter_unsigned32_t id) - Set's the application to be supported by this instance of the diameter protocol. Update(SESSION_EVENT event) - This functions allows an applications to impose a state transition whether serving as a diameter client or server. GetSessionHandle() - This function returns the session handle instance. GetAppCore() - This function returns the application core pointer to which this session is attached to. 3.2.2.3.2. Session Client Class Derived class to provide functionality of a diameter client. Expires April, 2003 [Page 28] Internet-Draft Diameter C++ API October 2, 2002 o Definition class AAASessionClient : public AAASession { public: AAASessionClient(AAAApplicationCore &appCore); ~AAASessionClient(); AAAReturnCode Start(); AAAReturnCode Update(SESSION_EVENT event); AAAReturnCode End(); }; o Description Start() - This function allows a client to start a session and store session information in the internal database. Update(SESSION_EVENT event) - This functions is a client implementation of the update base function. End() - This function, invoked by a client, terminates a session. 3.2.2.3.3. Session Server Class Derived class to provide functionality of a diameter server. o Definition class AAASessionServer : public AAASession { public: AAASessionServer(AAAApplicationCore &appCore); ~AAASessionServer(); AAAReturnCode Accept(AAAMessage *message); AAAReturnCode Update(SESSION_EVENT event); AAAReturnCode Abort(); }; o Description Accept(AAAMessage *message) - This function, invoked by the server, formally accepts a session request (transition to an open session) and store the session information in the internal database. Update(SESSION_EVENT event) - This functions is a server implementation of the update base function. Abort() Expires April, 2003 [Page 29] Internet-Draft Diameter C++ API October 2, 2002 This function allows the server to terminate a session after being accepted. 3.2.2.3.4. Session Lookup Class This class allows a diameter client or server application to query existing sessions in the internal database. o Definition class AAASessionLookup { public: AAASessionLookup(AAAApplicationCore &appCore); virtual ~AAASessionLookup(); const AAASession *Query(AAASessionHandle handle); const AAASession *Query(AAAMessage *message); protected: AAAApplicationCore *core; }; o Description Query(AAASessionHandle handle) - Searches for an existing session in the internal database based on a given session handle. Query(AAAMessage *message) - Searches for an existing session in the internal database based on an AAAMessage. 3.2.2.4 Message Control The class definition in this section allows a client application to send messages to a destination. It provides diameter client the functionality to direct a message to a particular server, determine the server for a message, etc. It also allows a server to respond to messages received from clients. The model provided for message control is to associate it with an existing session since the functionality provided is for delivery of messages to known entities via established sessions. The message control class requires an instance of a session and therefore associates the message control to the application core. Expires April, 2003 [Page 30] Internet-Draft Diameter C++ API October 2, 2002 o Definition class AAAMessageControl { public: AAAMessageControl(AAASession &session); ~AAAMessageControl(); AAAReturnCode SetResultCode(AAAMessage *response, AAAMessage *request, AAAResultCode resultCode); AAAReturnCode Send(AAAMessage *message); protected: AAASession *session; }; o Description Send(AAAMessage *message) - This function sends a message to the server. SetResultCode(AAAMessage *response, AAAMessage *request, AAAResultCode resultCode) This function sets the result code for a response message and makes all changes based on the original request and the application defined result code. 4. Acknowledgments The authors would like to thank Shaun Astarabadi, Shin-ichi Baba, John-Luc Bakker, Dick Bridges, David Frascone and members of the ITSUMO Project for their support and valuable comments on this work. 5. References [CAPI] J. Kempf, et al., "The DIAMETER API", Internet-Draft, Work in progress, March 2002. [DIAM] P. Calhoun, et al., "Diameter Base Protocol", Internet-Draft, Work in progress, July 2002. [XML] D. Frascone, et al., "Diameter XML Dictionary", Internet-Draft, Work in progress, February 2002. 6. Authors' Information Yoshihiro Ohba Toshiba America Research, Inc. P.O. Box 136 Convent Station, NJ 07961-0136 USA Phone: +1 973 829 5174 Fax: +1 973 829 5601 Email: yohba@tari.toshiba.com Expires April, 2003 [Page 31] Internet-Draft Diameter C++ API October 2, 2002 Victor Fajardo Toshiba America Research, Inc. P.O. Box 136 Convent Station, NJ 07961-0136 USA Email: vfajardo@optonline.net Dilip Patel Toshiba America Research, Inc. P.O. Box 136 Convent Station, NJ 07961-0136 USA Email: dilris@yahoo.com 7. Full Copyright Statement Copyright (C) The Internet Society (2002). All Rights Reserved. This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Inter net organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English. The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns. This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE." A. Appendix - Sample Usage A.1. Parser Usage A.1.1. Dictionary Initialization The following two lines are expected to exist in program initialization part. AAADictionaryManager dm; dm.init(); A.1.2. Input Parser Usage The following sample code shows how received octet string data Expires April, 2003 [Page 32] Internet-Draft Diameter C++ API October 2, 2002 containing a Diameter message is parsed into high-level data structures. void rtest(char *buf, int size) { int i, j; AAAMessage msg; HeaderParser hp; AAAMessageBuffer aBuffer; aBuffer = AAAMessageBuffer(rbuf, HEADER_SIZE); hp.setRawData(&aBuffer); hp.setAppData(&msg.hdr); hp.setOption(PARSE_STRICT); try { hp.parseRawToApp(); } catch (AAAErrorStatus st) { cout << "header error" << endl; exit(1); } cout << "received command: " << hp.getCommandName() << endl; print_header(msg.hdr); PayloadParser pp; aBuffer = AAAMessageBuffer(rbuf+HEADER_SIZE, msg.hdr.length - HEADER_SIZE); pp.setRawData(&aBuffer); pp.setAppData(&msg.acl); pp.setDictData(hp.getDictData()); try { pp.parseRawToApp(); } catch (AAAErrorStatus st) { int code, type; string avp; msg.status.get(type, code); cout << "Disassemble failure. Status code = " << code << endl; exit(1); } cout << "Disassemble success." << endl; if (AAAAvpContainer* c_prinfo = msg.acl.search("Proxy-Info")) { for (i=0; isize(); i++) { AAAAvpContainerList *acl = (*c_prinfo)[i]->grouped_val; cout << "Proxy Info = [" << endl; if (AAAAvpContainer *c_prhost = acl->search("Proxy-Host")) { for (j=0; jsize(); j++) { Expires April, 2003 [Page 33] Internet-Draft Diameter C++ API October 2, 2002 diameter_identity_t prhost = (*c_prhost)[j]->identity_val; cout << "" << "Proxy-Host = " << prhost->data() << endl; } } if (AAAAvpContainer *c_prstate = acl->search("Proxy-State")) { for (j=0; jsize(); j++) { diameter_octetstring_t state = (*c_prstate)[j]->octetstring_val; cout << "" << "Proxy-State = " << state->data() << endl; } } cout << "]" << endl; } } if (AAAAvpContainer* c_appid = msg.acl.search("Acct-Application-Id")) { for (i=0; isize(); i++) { diameter_integer32_t appid = (*c_appid)[i]->integer32_val; cout << "Acct-Application-Id = " << appid << endl; } } if (AAAAvpContainer* c_dhost = msg.acl.search("Destination-Host")) { for (i=0; isize(); i++) { diameter_identity_t dhost = (*c_dhost)[i]->identity_val; cout << "Destination-Host = " << dhost->data() << endl; } } if (AAAAvpContainer* c_rrecord = msg.acl.search("Route-Record")) { for (i=0; isize(); i++) { diameter_identity_t rrecord = (*c_rrecord)[i]->identity_val; cout << "Route-Record = " << rrecord->data() << endl; } } if (AAAAvpContainer* c_any = msg.acl.search("AVP")) { for (i=0; isize(); i++) { avp_t any = (*c_any)[i]->avp_val; cout << "Received one AVP of type cout << " please parse this AVP by yourself" << endl; memcpy(rAvp, any->c_str(), rAvp_len = any->length()); } } msg.acl.releaseContainers(); } A.1.3. Output Parser Usage The following sample code shows how high-level data structures Expires April, 2003 [Page 34] Internet-Draft Diameter C++ API October 2, 2002 corresponding to a Diameter message is parsed into octet string data. // This is a test for NAS to originate a request message void stest_nas_request(char *buf, int size) { AAAAvpContainerManager cm; AAAAvpContainerEntryManager em; AAAAvpContainer *c_appid = cm.acquire("Acct-Application-Id"); AAAAvpContainer *c_dhost = cm.acquire("Destination-Host"); hdr_flag flag = {1,1,0}; AAADiameterHeader h(1, 0, flag, 9999999, 0, 1, 10); AAAMessage msg; AAAAvpContainerEntry *e; cout << __FUNCTION__ << endl; msg.hdr = h; HeaderParser hp; AAAMessageBuffer headerBuffer, payloadBuffer; headerBuffer = AAAMessageBuffer(buf, HEADER_SIZE); // The first call of hp.set() checks validity of // flags and gets a AAACommand structure. hp.setRawData(&headerBuffer); hp.setAppData(&msg.hdr); hp.setOption(PARSE_STRICT); try { hp.parseAppToRaw(); } catch (AAAErrorStatus st) { cout << "header error" << endl; exit(1); } e = em.acquire(AAA_AVP_INTEGER32_TYPE); diameter_integer32_t *appid = &e->integer32_val; c_appid->add(e); e = em.acquire(AAA_AVP_DIAMID_TYPE); diameter_identity_t dhost = e->identity_val; c_dhost->add(e); msg.acl.add(c_dhost); msg.acl.add(c_appid); /* Acct-Application-Id */ *appid = 1; /* Destination-Host */ dhost->assign("aaa.com"); PayloadParser pp; payloadBuffer = AAAMessageBuffer(buf + HEADER_SIZE, size - HEADER_SIZE); pp.setRawData(&payloadBuffer); pp.setAppData(&msg.acl); Expires April, 2003 [Page 35] Internet-Draft Diameter C++ API October 2, 2002 pp.setDictData(hp.getDictData()); try { pp.parseAppToRaw(); } catch (AAAErrorStatus st) { cout << "assemble failed" << endl; exit(1); } msg.hdr.length = HEADER_SIZE + payloadBuffer.offset; // Set the actual message length to header try { hp.parseAppToRaw(); } catch (AAAErrorStatus st) { cout << "header error" << endl; exit(1); } cout << "assemble success. total length = " << msg.hdr.length << endl; // release all containers after parse. msg.acl.releaseContainers(); } A.1.4. Relay/Proxy Agent Parser Usage The following sample code shows how a Diameter relay or proxy agent handles messages, expecically adding Route-Record and Proxy-Info AVPs without using command dictinoary. void stest_proxy_request(char *buf, int size) { AAAMessage msg; HeaderParser hp; AAAMessageBuffer aBuffer; AAAAvpContainerManager cm; AAAAvpContainerEntryManager em; AAAAvpContainerEntry *e; cout << __FUNCTION__ << endl; // parse header aBuffer = AAAMessageBuffer(buf, HEADER_SIZE); hp.setRawData(&aBuffer); hp.setAppData(&msg.hdr); hp.setOption(PARSE_LOOSE); try { hp.parseRawToApp(); Expires April, 2003 [Page 36] Internet-Draft Diameter C++ API October 2, 2002 } catch (AAAErrorStatus st) { cout << "header error" << endl; exit(1); } AAAAvpContainer *c_prinfo = cm.acquire("Proxy-Info"); AAAAvpContainer *c_rrecord = cm.acquire("Route-Record"); AAAAvpContainer *c_any = cm.acquire("AVP"); // wildcard AVP msg.acl.add(c_rrecord); msg.acl.add(c_prinfo); msg.acl.add(c_any); PayloadParser pp; aBuffer = AAAMessageBuffer(buf+HEADER_SIZE, msg.hdr.length - HEADER_SIZE); pp.setRawData(&aBuffer); pp.setAppData(&msg.acl); pp.setDictData(NULL); // No dictionary to be used. try { pp.parseRawToApp(); } catch (AAAErrorStatus st) { cout << "failed to get specific sets of AVPs." << endl; exit(1); } // add one Route-Record AVP e = em.acquire(AAA_AVP_DIAMID_TYPE); c_rrecord->add(e); diameter_identity_t rrecord = e->identity_val; rrecord->assign("xxx.com"); // add one Proxy-Info AVP e = em.acquire(AAA_AVP_GROUPED_TYPE); diameter_grouped_t group = e->grouped_val; c_prinfo->add(e); AAAAvpContainer *c_prhost = cm.acquire("Proxy-Host"); e = em.acquire(AAA_AVP_DIAMID_TYPE); diameter_identity_t prhost = e->identity_val; prhost->assign("bbb.ccc.com"); c_prhost->add(e); group->add(c_prhost); AAAAvpContainer *c_prstate = cm.acquire("Proxy-State"); e = em.acquire(AAA_AVP_DIAMID_TYPE); diameter_identity_t prstate = e->identity_val; prstate->assign("abcde"); c_prstate->add(e); group->add(c_prstate); // Move the wildcard AVP container to the head, since this container // may contain AVPs that are position-constraint. msg.acl.remove(c_any); msg.acl.prepend(c_any); Expires April, 2003 [Page 37] Internet-Draft Diameter C++ API October 2, 2002 aBuffer = AAAMessageBuffer(buf+HEADER_SIZE, size - HEADER_SIZE); try { pp.parseAppToRaw(); } catch (AAAErrorStatus st) { cout << "failed to set specific sets of AVPs." << endl; exit(1); } // adjast the header; msg.hdr.length = HEADER_SIZE + aBuffer.offset; aBuffer = AAAMessageBuffer(buf, HEADER_SIZE); try { hp.parseAppToRaw(); } catch (AAAErrorStatus st) { cout << "header error" << endl; } cout << "setting specific avp success. total length (must be 108) = " << msg.hdr.length << endl; // release container after parse. msg.acl.releaseContainers(); } A.2. Application Usage A.2.1. Client Application Usage The following is a sample shows how a client application can start a session, subscribe to a message and send a service specific request within a threaded context. // An instance of the client application core AAAApplicationCore clientCore; // An implementation of a message subscription // Note that event needs to be overridden class ClientMsgSubscription : public AAAMessageSubscription { public: ClientMsgSubscription(AAAMessageArg *messageArg) : AAAMessageSubscription(messageArg) {}; virtual AAAReturnCode Event(); }; // Event implementation AAAReturnCode ClientMsgSubscription::Event() { AAAMessageArg *msg = (AAAMessageArg*)arg; Expires April, 2003 [Page 38] Internet-Draft Diameter C++ API October 2, 2002 cout << "CLIENT: " << "MsgSubscription: code=" << msg->message.hdr.code; cout << ", vendor=" << msg->message.hdr.vendor << endl; // // Lookup client session can be done via session id AVP of the message // AAASessionLookup lookup(clientCore); AAASessionClient *client = (AAASessionClient*)lookup.Query(&msg->message); // **** PROCESS MESSAGE HERE **** // // containers allocated by parser can now be released here // msg->message.acl.releaseContainers(); return (AAA_ERR_SUCCESS); } // Sample client thread function void *clientThread(void *arg) { // // Load configuration file and // create active instance of // application core // clientCore.Open("client.conf"); clientCore.SetApplicationId(NASREQ); // // Setup message arg // AAAMessageArg msgArg; msgArg.message.hdr.code = ...; msgArg.message.hdr.vendor = 0; // // Subscribe to a messsage // AAAEventNotification notifier(clientCore); ClientMsgSubscription msgSub(&msgArg); notifier.Subscribe(&msgSub); // // Initiate a client session // AAASessionClient clntSession(clientCore); clntSession.Start(); // // Formulate a service specific messasge here // and transmit // .... Expires April, 2003 [Page 39] Internet-Draft Diameter C++ API October 2, 2002 .... AAAMessageControl msgControl(clntSession); msgControl.Send(&srvcMsg); // // **** INITIATE A SYSTEM SPECIFIC IDLE LOOP HERE // ... ... // // Cleanup session when done // clntSession.End(); return (NULL); } A.2.2. Server Application Usage The following is a sample shows how a server application can start a server session, subscribe to a message and accept (or reject) an incomming request. // An instance of the server application core and a server session AAAApplicationCore serverCore; AAASessionServer serverSession; // An implementation of a message subscription // Note that event needs to be overridden class ServerMsgSubscription : public AAAMessageSubscription { public: ServerMsgSubscription(AAAMessageArg *messageArg) : AAAMessageSubscription(messageArg) {}; virtual AAAReturnCode Event(); }; // Event implementation AAAReturnCode ServerMsgSubscription::Event() { AAAMessageArg *msg = (AAAMessageArg*)arg; cout << "SERVER: Event subscribtion: code=" << msg->message.hdr.code; cout << ", vendor=" << msg->message.hdr.vendor << endl; // // Inspect message here and decide wether to accept or reject // ... ... // Expires April, 2003 [Page 40] Internet-Draft Diameter C++ API October 2, 2002 // A server can accept or reject an incomming service // specific request within the messsage event context. // serverSession.Accept(&msg->message); // // containers allocated by parser can now be released here // msg->message.acl.releaseContainers(); return (AAA_ERR_SUCCESS); } // Sample server thread function void *serverThread(void *arg) { // // Load configuration file and // create active instance of // application core // serverCore.Open("server.conf"); serverCore.SetApplicationId(NASREQ); // // Setup message arg // AAAMessageArg msgArg; msgArg.message.hdr.code = ...; msgArg.message.hdr.vendor = 0; // // Subscribe to a messsage // AAAEventNotification notifier(serverCore); ClientMsgSubscription msgSub(&msgArg); notifier.Subscribe(&msgSub); // // **** INITIATE A SYSTEM SPECIFIC IDLE LOOP HERE // ... ... return (NULL); } Expires April, 2003 [Page 41]