TOP

Version-Neutral API (OssNas namespace)

Applies to: NAS/C++ 5G r15.4.0 v7.1.0

The following functions and classes are not dependent on the version of the NAS protocol, so they are placed in the OssNas namespace.

Memory Management

All memory allocations throughout the OSS NAS/C++ 5G runtime are performed using the following functions:

void *ossNasMalloc(size_t size);
void ossNasFree(void *buf);
void *ossNasRealloc(void *buf, size_t size);

By default, the standard malloc()/realloc()/free() functions are used, but users can provide their own memory management through the following function:

void ossNasSetCppMallocFreeRealloc(void *(*mallocp)(size_t), void (*freep)(void *), void *(*reallocp)(void *, size_t));

Users can access the current memory management routines through the following function:

void ossNasGetCppMallocFreeRealloc(void *(**mallocp)(size_t), void (**freep)(void *), void *(**reallocp)(void *, size_t));

Error Handling

The following exception class is implemented:

    
class OssNasException
{
public:
    OssNasException(int code, const char *message = NULL, const char *desc = NULL);
    OssNasException(const OssNasException &);
    ~OssNasException();
    int getCode();
    const char *getMessage();
    const char *getDescription();
};

Each exception class contains a numeric error code (see the Error Codes section for possible values), a text description of the error code, and possibly a detailed message.

All error signaling is done by throwing instances of the OssNasException class. No error codes are returned as return values.

Several OSS NAS/C++ 5G API functions can generate multiple error and warning messages during a single invocation of the function. When an encode/decode error or other unexpected event occurs during the execution of an encode/decode operation performed internally by those functions, the operation generates either a severe error condition or a recoverable error condition.

A severe error condition is generated when the unexpected event is such that the encode/decode operation either cannot continue or would produce a meaningless result if it did.

For example

  • An output buffer that is too small to contain the output data
  • An out of range choice index
  • A missing mandatory IE (Information Element)
  • An unknown IE with the "comprehension required" requirement

When a severe error condition occurs, the operation terminates immediately and is considered failed.

A recoverable error condition is generated when the unexpected event is such that the operation can continue safely but will be considered failed when it terminates.

For example

  • A field with a missing fixed value that is required by the specification
  • A field with a value that is forbidden by the specification

Eventually, the operation will terminate either when it reaches completion or because of a severe error condition. In either case, the operation will be considered failed.

In decode operations, many unexpected events will generate a severe or recoverable error condition when they occur in a mandatory part of a message or inside an optional IE with "comprehension required", but will not generate an error when they occur inside an optional IE without "comprehension required". In the latter case, the invalid optional IE is treated as if it was not part of the input (the encoded message), and will be marked as absent in the output (the decoded message). Eventually, the decode operation will be considered successful unless a severe or recoverable error condition occurs.

When an error condition occurs, the OSS NAS/C++ 5G API functions produce an error message. An error message has the following format:

  • A message code, formatted as follows:
    • The letter E (encode) or D (decode), to identify the operation
    • A four-digit number, 0001 to 9999, to identify the condition
    • The letter S= (severe error), W=(warning), or E=(recoverable error) to indicate the severity
    • A colon (:) and a space
  • A text description of the condition (US-ASCII character string), followed by a semicolon (;) and a space
  • The word check
  • The path of the field in or after which the condition occurred, formatted as follows:
    ( field ('ident' | #elem ) (type: basetype) of )* PDU 'pduname'
    where:
    • ident is the ASN.1 identifier of a component of a SEQUENCE or CHOICE type.
    • elem is the ordinal number of an element of a SEQUENCE OF type.
    • basetype is one of SEQUENCE, CHOICE, SEQUENCE OF.
    • pduname is the name of the PDU type (NASMessage).
    with spaces inserted between words.

Examples:

D0065E: An unknown information element was detected in the encoded data; check field 'protocolConfigurationOptions' of field 'activateDefaultEPSBearerContextRequest' (type: SEQUENCE) of field 'body' (type: CHOICE) of field 'esmMessage' (type: SEQUENCE) of PDU 'NASMessage'

D0061W: A forbidden value was detected in the encoded data; check field 'systemIdentification' of field #2 (type: SEQUENCE) of field 'supportedCodecs' (type: SEQUENCE OF) of field 'attachRequest' (type: SEQUENCE) of field 'body' (type: CHOICE) of field 'plain' (type: SEQUENCE) of field 'emmMessage' (type: CHOICE) of PDU 'NASMessage'

The OSS NAS/C++ 5G API functions use a pre-allocated memory buffer to store the messages produced for error conditions that occur during one execution of the operation. In most cases, this buffer is large enough to contain all error messages produced by an operation, however, in rare cases it may be filled. Usually this is not an issue, since a user application is rarely interested in all error messages produced by a single function call that has produced many such messages.

When a call to one of the functions listed above generates at least one severe or recoverable error condition, it signals the error by throwing an OssNasException instance. The thrown object contains the error code of the first severe or recoverable error condition that occurred during the operation. If necessary, consult the message component of the thrown object.

Common Encoder-Decoder Class

OssNasCoderBase is a common ancestor class for encoding-decoding classes.

Definition

class OssNasCoderBase
{
public:
    ~OssNasCoderBase();
    unsigned long getFlags();
    unsigned long getEncodingFlags();
    unsigned long getDecodingFlags();
    void setFlags(unsigned long flags);
    void setEncodingFlags(unsigned long flags);
    void setDecodingFlags(unsigned long flags);
    int getOriginator();
    void setOriginator(int originator);
    void binary2XML(const OssString & in, OssString **out, OSS_UINT32 *encsize);
    void binary2JSON(const OssString & in, OssString **out, OSS_UINT32 *encsize);
};

This class has protected constructors and is not intended for user instantiation. Also, it has some protected methods that are used by its successors. The protected methods are not described here.

Methods

void setEncodingFlags(unsigned long flags);
This method helps control the behavior of encoding functions. It sets the value of the encoding flags word in the OssNasCoderBase object. Currently there are no user-accessible encoding flags defined, so this function is for future use.
void setDecodingFlags(unsigned long flags);
This method helps control the behavior of decoding functions. It sets the value of the decoding flags word in the OssNASCoderBase object. Currently there are no user-accessible decoding flags defined, so this function is for future use.
void setFlags(unsigned long flags);
This method sets both the encoding and decoding flags to the same value. Currently, there are two user-accessible flags:
  • The OSSNAS_OLDXML flag forces the binary2XML() and print() functions to produce XML documents in the format that was used by old releases of the OSS NAS/C++ tools. This format does not fully conform to ITU-T Recommendation X.693 (ISO/IEC 8825-4:2015): Information technology - ASN.1 encoding rules: XML Encoding Rules (XER).
  • The OSSNAS_OLD_MNC_WITH_SPACE flag restores the old decoder behavior to decode a two-digit MNC value into a string of size 3 with a trailing space and forces the encoder to reject MNC strings of size 2 without a trailing space. By default, the decoder decodes a two-digit MNC value into a string of size 2 and the encoder accepts MNC strings of size 2.
unsigned long getEncodingFlags();
This method returns the current value of the encoding flags word. As there are no user-accessible encoding flags defined, this function is for future use.
unsigned long getDecodingFlags();
This method returns the current value of the encoding flags word. As there are no user-accessible decoding flags defined, this function is for future use.
unsigned long getFlags();
This method returns the logical OR of the encoding flags word and the decoding flags word.
void setOriginator(int originator);
The function sets the originator for a NAS message that will be encoded or decoded. This setting affects the behavior of the encoding and decoding functions. In the NAS protocol, certain messages can only be sent by one of the two originators, and the interpretation of other messages depends on the originator of the message. The parameter can be either 1 (UE) or 2 (Network). You can use the OSSNAS_ORIG_UE or OSSNAS_ORIG_NETWORK symbolic names instead of numeric values.
int getOriginator();
The function returns the current originator value set by the setOriginator function.
void binary2XML(const OssString & in, OssString **out, OSS_UINT32 *encsize);
The function converts the encoded NAS message to the textual XML form. The first argument (in) is a buffer that contains the input encoded message. The second argument (out) is a pointer variable. If it is not NULL, it points to the output buffer. If it is NULL, a new buffer long enough to hold the result will be dynamically allocated by the function and assigned to the out pointer. In this case, the output buffer will be owned by the caller. When the buffer is no longer needed, the caller is responsible for deallocating the buffer using the delete operator. The third argument (encsize), if not NULL, points to the integer variable. The function will set it to the length of the resulting XML encoding in bytes. This is especially useful if you call the function using a pre-allocated buffer (*out != NULL). In that case, the size of the output string is different from the size of the buffer, so you need this parameter to obtain the former. If encsize is NULL, this information is lost.
void binary2JSON(const OssString & in, OssString **out, OSS_UINT32 *encsize);
The function converts the encoded NAS message to the textual JSON form. The first argument (in) is a buffer that contains the input encoded message. The second argument (out) is a pointer variable. If it is not NULL, it points to the output buffer. If it is NULL, a new buffer long enough to hold the result will be dynamically allocated by the function and assigned to the out pointer. In this case, the output buffer will be owned by the caller. When the buffer is no longer needed, the caller is responsible for deallocating the buffer using the delete operator. The third argument (encsize), if not NULL, points to the integer variable. The function will set it to the length of the resulting JSON encoding in bytes. This is especially useful if you call the function using a pre-allocated buffer (*out != NULL). In that case, the size of the output string is different from the size of the buffer, so you need this parameter to obtain the former. If encsize is NULL, this information is lost.

Encoder-Decoder Class Template

The application instantiates the OssNasCoder template class to encode/decode NAS messages. The template parameter is the NAS message representation class. Your product version supports version 15.4.0 of NAS, so the classes that can be used as the template parameter are

OssNas::v5GS1540::NASMessage: OssNasCoder<OssNas::v5GS1540::NASMessage> coder1540; /* coder to encode/decode OssNas::v5GS1540::NASMessage */

If you need support for other versions of NAS, contact OSS Nokalva at info@oss.com.

Definition

template <class Message>
class OssNasCoder : public OssNasCoderBase
{
public:
    OssNasCoder();
    void encode(const Message & msg, OssString **buf, OSS_UINT32 *encsize);
    const Message *decode(const OssString & buf);
    const Message *decodeJSON(const OssString & buf);
    const Message *decodeXML(const OssString & buf);
    void print(const Message & msg);
    void deleteDecoded(const Message *msg);
    int do_getTotalNumberOfWarningConditions( ) ;
    int do_getNumberOfWarningMessagesLogged( ) ;
    const char * const do_getWarningMessage( int n, int &msgLen );
    int do_getTotalNumberOfErrorConditions( ) ;
    int do_getNumberOfErrorMessagesLogged( ) ;
    const char * const do_getErrorMessage( int n, int &msgLen );
}

Methods

void encode(const Message & msg, OssString **buf, OSS_UINT32 *encsize);
The method encodes a binary structure containing NAS message data into a memory buffer. The first argument (msg) is the binary structure. The second argument (buf) is a pointer variable. If it is not NULL, it points to the output buffer. If it is NULL, a new buffer long enough to hold the encoding will be dynamically allocated by the function and assigned to the buf pointer. In this case, the output buffer will be owned by the caller. When the buffer is no longer needed, the caller is responsible for deallocating the buffer using the delete operator. The third argument (encsize), if not NULL, points to the integer variable. The function will set it to the length of the resulting XML encoding in bytes. This is especially useful if you call the function using a pre-allocated buffer (*buf != NULL). In that case, the size of the output string is different from the size of the buffer, so you need this parameter to obtain the former. If encsize is NULL, this information is lost.
const Message *decode(const OssString & buf);
This function decodes a NAS message from a memory buffer. The buffer is passed as the function parameter and the decoded binary structure is returned as the result. The decoded message is owned by the coder object. The user cannot modify or deallocate it explicitly, which is why it is declared const. If the user needs to modify it, he can make a copy of it using the copy constructor or assignment operator. To instruct the coder object to deallocate a decoded value, the user must use the deleteDecoded function.

As of release 6.1, the decoding of certain variable-length IEs ending with one or more optional octets (UE network capability IE, Mobile station classmark 3 IE, and MS network capability IE) has been modified so any missing optional octets at the end of the IE are treated as zeros. This allows the decoding operation to proceed without error even when an IE is sent that lacks one or more fields at the end, provided that the octets that would have carried the missing fields are marked as optional in the relevant technical specification. This could occur when the sender intentionally omits one or more trailing zero octets from those IEs (e.g., in order to save space) or when the sender uses an older NAS release and the NAS release used by the recipient extends the definition of those IEs by one or more octets.

The parts of the NAS*.h header file that correspond to the three IEs in question have been modified in a non-backward-compatible way. If you have existing code that uses the NAS API, you will have to make minor changes to your code to support the new structures.
const Message *decodeJSON(const OssString & buf);
const Message *decodeXML(const OssString & buf);
These functions decode from a memory buffer a JSON encoded and an XML encoded NAS message, respectively. The format of the input message should correspond to the format of messages produced by the binary2JSON() and binary2XML() functions. The buffer is passed as a function parameter and the decoded binary structure is returned as a result. The decoded message is owned by the coder object. The user cannot modify or deallocate it explicitly, which is why it is declared const. If the user needs to modify it, he can make a copy of it using the copy constructor or assignment operator. To instruct the coder object to deallocate a decoded value, the user must use the deleteDecoded function.

These functions can generate only a single error message. Note that an unknown or duplicate information element always leads to an error.
void print(const Message & msg);
This function prints a decoded NAS message to the standard output in XML form. The first argument (msg) is the binary structure containing the NAS message data.
void deleteDecoded(const Message *msg);
The function instructs the coder to deallocate a decoded NAS binary structure. As stated in the decode method description, the result of a decoding operation is owned by the coder object and cannot be deallocated by the usual delete operator. The user must use the deleteDecoded function instead.

Note also that this class is derived from the OssNasCoderBase class, so it can use all the methods of the OssNasCoderBase class.

The following functions retrieve information about the error and warning messages generated by the latest call to encode/decode/print APIs.

int getTotalNumberOfWarningConditions( );
This function returns the total number of warning conditions that occurred during the encoding/ decoding/printing of a PDU.
int getNumberOfWarningMessagesLogged( );
This function returns the number of warning conditions which are logged in the internal buffer during the encoding/decoding/printing of a PDU.
const char * const getWarningMessage( int n, int &msgLen );
This function returns the nth of the logged warning messages. The returned message is not Null terminated, and the message length is returned in the output parameter msgLen. The warning message is owned by the coder object. You cannot modify or deallocate it.
int getTotalNumberOfErrorConditions ( );
This function returns the total number of error conditions that occurred during the encoding/decoding/printing of a PDU.
int getNumberOfErrorMessagesLogged ( );
This function returns the total number of error conditions which are logged in the internal buffer during the encoding/decoding/printing of a PDU.
const char * const getErrorMessage( int n, int &msgLen );
This function returns the nth of the logged error messages. The returned message is not Null terminated, and the message length is returned in the output parameter msgLen. The error message is owned by the coder object. You cannot modify or deallocate it.

Important C++ Classes of the OssNAS namespace

NAS messages are often mapped to a complex hierarchy of C++ classes; however, these classes follow certain simple patterns, as shown below:

  1. A Protocol element consists of several sub-elements of different types.
    This Protocol element is represented by a class whose data members are classes which represent its sub-elements.
  2. A Protocol element is a sequence of uniform elements.
    This Protocol element, which consists of several elements of the same type, is represented by a specific class derived from the OssList class.
  3. A Protocol element is a selection from a set of alternatives.
    This Protocol element, which can contain one of the many alternatives of different types, is represented by a specific class derived from the OssChoice class. It can be considered as the C++ version of the C union construct.

These fundamental base classes, OssChoice and OssList, are defined in the OssNAS namespace and are discussed in the OssChoice and OssList sections.

Octet strings and character strings are mapped to the OssString class. Bit strings are mapped to the OssBitString class. They are also present in the version neutral OssNAS namespace. Classes defined in the OssNAS namespace can be found in include/nascpp.h.

Octet and character strings (OssString)

Octet and character strings are represented by the OssString class.

Definition

class OssString { 

public: 
OssString(); 
OssString(const OssString &); 
OssString & operator = (const OssString &); 
~OssString(); 
int operator == (const OssString &) const; 
int operator != (const OssString &) const; 
void *operator new(size_t); 
void operator delete(void *); 
OssString(const char *); 
OssString(OSS_UINT32 length, const char *); 
OSS_UINT32 length() const; 
char *get_buffer(); 
const char *get_buffer() const; 
void resize(OSS_UINT32); 
void set(const char *); 
void set(OSS_UINT32 length, const char *); 
// ownership-transferring functions 
char *release_buffer(OSS_UINT32 & length); 
void grab(OSS_UINT32 length, char *); 
// higher level functions 
char & operator [] (OSS_UINT32 pos); 
const char & operator [] (OSS_UINT32 pos) const; 
char elem(OSS_UINT32 pos);
OssString & operator += (const OssString &); 
OssString & operator += (const char *);
};

Methods

OssString(const char *);
This method is an initialization constructor for OssString. A C null-terminated string in the input parameter is copied to the OssString object.
OssString(OSS_UINT32 length, const char *);
This method initializes the string with an array of chars. The length of the array is determined by the first parameter. The data is copied to the OssString object. This method can initialize the OssString object with a char sequence that contains zero-value bytes.
OSS_UINT32 length() const;
This method returns the current length of the string. Note that no extra zero byte is appended to the string value.
char * get_buffer();
const char * get_buffer() const;
These methods return the address of the internal character array of the OssString object. No copying occurs. When you make any changes to the array, they automatically affect the value of the OssString object. Note that there is no zero byte at the end of the byte sequence, and its length can be determined by the length() method. Therefore, pay particular attention while printing the byte sequence returned by these two methods as a simple null-terminated string: '\0' should be added to the end of it.
void resize(OSS_UINT32);
This method changes the length of the OssString object. If the current length value is greater than the new length value, the length of the character array is reduced, otherwise, if the current length value is less than the new length value, the character array is expanded. The address of the character array is invalidated (because the array may be moved to another place in memory). If the array was expanded, the values of the expansion bytes are unpredictable. Make sure you set them later as needed.
void set(const char *);
This method sets the new value of the OssString object from a C null-terminated string. The string is copied to the OssString object leaving the input array unchanged. The old value of the OssString object is destroyed, and the address of its old internal character array is invalidated.
void set(OSS_UINT32 length, const char *);
This method sets the new value of the OssString object from a character array. The length of the array is determined by the first parameter. The array is copied to the OssString object. The source array is unchanged. The old OssString value is destroyed. This method can set a value that contains zero bytes.
char & operator [] (OSS_UINT32 pos);
const char & operator [] (OSS_UINT32 pos) const;
These methods return a reference to the character at the position specified by the parameter. If the position lies outside the current bounds, the result is unpredictable. The indexing operators of the OssString class don't check whether the specified number of characters is within the bounds of the string. Use the length() method to find out the exact number of characters in OssString. Make sure you do not pass a value greater than the length value to the indexing operators.
char elem(OSS_UINT32 pos) const;
This method returns a character at the position specified by the parameter. If the position lies outside the current bounds, the result is unpredictable. This method does not check whether the specified number of characters is within the bounds of the string. Use the length() method, to find out the exact number of characters in OssString. Make sure you do not pass a position value greater than the length value to this method.
OssString & operator += (const OssString &);
OssString & operator += (const char *);
These methods append the value of the parameter to the OssString value. In the second form, the parameter is a null-terminated C string. All pointers inside the OssString buffer are invalidated because the internal character array may be moved to another location in memory.

The following two functions are ownership-transferring functions:

char * release_buffer(OSS_UINT32 &);
This method returns a pointer to the internal character array. The length of the array is assigned to the first parameter. The OssString object is reset to the empty string value. The returned value is now owned by the caller. The caller is responsible for deallocating it using the NAS memory deallocation function (ossNasFree) when needed.
void grab(OSS_UINT32 length, char *);
This method assigns a new value to the OssString object. The address of the character array is defined by the second parameter, and its length is defined by the first parameter. The character array must be dynamically allocated with the NAS memory allocation function (ossNasMalloc). After the call, this array is owned by the OssString object. No data copying occurs. You should not deallocate the array or use it in another ownership-transferring function. Note that the source array should not contain any extra bytes (such as a trailing zero byte); its size is determined by the length parameter.

Bit String (OssBitString)

Bit strings are represented by the OssBitString class.

Definition

class OssBitString { 

public: 
void *operator new(size_t); 
void operator delete(void *); 
OssBitString(); 
OssBitString(const OssBitString &); 
OssBitString & operator = (const OssBitString &);
~OssBitString(); 
int operator == (const OssBitString &) const; 
int operator != (const OssBitString &) const; 
OssBitString(OSS_UINT32 length, const unsigned char *); 
OSS_UINT32 length() const; 
unsigned char *get_buffer(); 
const unsigned char *get_buffer() const; 
void resize(OSS_UINT32); 
void set(OSS_UINT32 length, const unsigned char *); 
// ownership-transferring functions 
unsigned char *release_buffer(OSS_UINT32 & length); 
void grab(OSS_UINT32 length, unsigned char *); 
// higher level functions 
void set(OSS_UINT32 pos); 
void clear(OSS_UINT32 pos); 
void invert(OSS_UINT32 pos); 
void set(OSS_UINT32 pos, OSS_UINT32 length); 
void clear(OSS_UINT32 pos, OSS_UINT32 length); 
void invert(OSS_UINT32 pos, OSS_UINT32 length); 
void assign(OSS_UINT32 pos, int bit); 
int test(OSS_UINT32 pos) const; 
OssBit operator [] (OSS_UINT32 pos); 
const OssBit operator [] (OSS_UINT32 pos) const; 
};

Methods

OssBitString(OSS_UINT32 length, const unsigned char *);
This method initializes the bit string with an array of chars. The length of the array (in bits) is determined by the first parameter. The data is copied to the OssBitString object leaving the initial array unchanged.
OSS_UINT32 length() const;
This method returns the current length of the bit string in bits.
unsigned char * get_buffer();
const unsigned char * get_buffer() const;
These methods return the address of the internal character array of the OssBitString object. No copying occurs. If you make any changes to the array, they automatically affect the value of OssBitString. The length of the buffer (in bits) can be determined by the length() function. The bits in the character array are numbered with the most significant bit first, i.e., the most significant bit of the first byte represents bit 0, the least significant bit of the first byte represents bit 7, the most significant bit of the second byte represents bit 8, etc.
void resize(OSS_UINT32);
This method changes the length of the OssBitString object. If the current length value is greater than the new length value, the size of the buffer is reduced, otherwise, if the current length value is less than the new length value, the size of the buffer is expanded (in this case the additional bits will have undefined values; you should explicitly set them as you need). The address of the buffer is invalidated because it may be moved to another location in memory.
void set(OSS_UINT32 length, const unsigned char *);
This method sets the new value of OssBitString from a character array. The length of the array (in bits) is determined by the first parameter. The old OssBitString value is destroyed.
void set(OSS_UINT32 pos); void clear(OSS_UINT32 pos);
void invert(OSS_UINT32 pos);
These methods set, clear, and invert the bit in OssBitString at the specified position. If the specified position is outside the current bounds, the result is unpredictable.
void set(OSS_UINT32 pos, OSS_UINT32 length);
void clear(OSS_UINT32 pos, OSS_UINT32 length);
void invert(OSS_UINT32 pos, OSS_UINT32 length);
These methods set, clear, and invert a substring of the bit string. The substring starts at the pos position and has a length of length bits.
void assign(OSS_UINT32 pos, int bit);
If "bit" is 0, this method clears the bit at the pos position. Otherwise, it sets the bit to 1.
int test(OSS_UINT32 pos) const;
This method returns the value of the bit at the pos position.
OssBit operator[] (OSS_UINT32 pos);
const OssBit operator[] (OSS_UINT32 pos) const;
These methods return an OssBit object that serves as a reference to an individual bit inside OssBitString. OssBit is a utility class (see nascpp.h). An OssBit object can be set from an integer and converted to an integer. When you set an OssBit object from an integer, the corresponding bit is set in the bit string, when you convert it to an integer, the corresponding bit is returned in the bit string. The pos parameter must be inside the current bounds of OssBitString, otherwise, the behavior of the method is unpredictable.

The following two methods are ownership-transferring methods:

unsigned char * release_buffer(OSS_UINT32 &);
This method returns a pointer to the internal character array. The length of the array (in bits) is assigned to the first parameter. The OssBitString object is reset to the empty value. The returned value is now owned by the caller. The caller is responsible for deallocating it using the NAS deallocation function (ossNasFree) when needed.
void grab(OSS_UINT32 length, unsigned char *);
This method assigns a new value to the OssBitString object. The address of the character array is set according to the second parameter, and its length (in bits) is set from the first parameter. The character array must be dynamically allocated with the NAS memory allocation function (ossNasMalloc). After the call, this array becomes owned by the OssBitString object. No data copying occurs. You should not deallocate the input array or use it in another ownership-transferring function.

The OssChoice Class

A protocol element that can contain only one of several possible alternatives of different types is represented by a specific class derived from the OssChoice class. The OssChoice class is a common ancestor for all the classes representing choices of several possible alternatives. It has a private constructor and cannot be instantiated by the user. It contains common code used for all such types and provides the implementation for the new and delete operators. Apart from those operators, it has only one user-accessible function, namely get_selection().

Definition

class OSS_PUBLIC OssChoice
{
protected:
    OSS_UINT32 _choice;
    OssChoice();
public:
    void *operator new(size_t);
    void operator delete(void *);
    OSS_UINT32 get_selection() const;
};

Methods

OSS_UINT32 get_selection() const;
This method returns an integer value, which indicates the currently used alternative. The meaning of the values is specific to a particular class derived from OssChoice (possible values are declared in the Id internal enumeration type).

NAS protocol elements derived from OssChoice

There are fourteen classes that represent NAS protocol elements that are derived classes of OssChoice. These are the same for all NAS releases supported by OSS Nokalva. These classes are listed below. Note that some of them use internal names __choice<number> because they are the sub elements of some NAS Messages or other protocol elements.

NASMessage, DetachRequest, EMMMessage, EPSMobileIdentity, MobileIdentity, TAIListElement, __choice1 (Plain EmmMessage body), __choice2 (EsmMessage body), __choice3 (MultibandSupport), __choice4 (PDNAddress Information), __choice5 (packetFilterList), __choice6 (mccMNCAndSessionID), __choice7 ( TFTParameter contents), __choice8 (packetFilterComponentValue)

All these fourteen classes have the following common structure:

class DerivedFromChoice: public OssChoice { 
public: 
// Enumeration and Typedef'ed members list 
enum Id { 
unselected, 
<altname1>_chosen = 1, 
<altname2>_chosen = 2, 
... 
<altnamen>_chosen = n 
} 
typedef <alt1-type> <altname1>; 
typedef <alt2-type> <altname2>; 
... 
typedef <altn-type> <altnamen>; 

// Constructors [and destructor] 
DerivedFromChoice (); 
DerivedFromChoice(const <type> & that); 
~ DerivedFromChoice(); 

// Overloaded operators: assignment, equality, inequality 
DerivedFromChoice& operator = (const DerivedFromChoice& that); 
int operator == (const DerivedFromChoice& that) const; 
int operator != (const DerivedFromChoice& that) const; 

// Getter and Setter for each field 
<alt1-type> * get_<altname1>(); 
const <alt1-type> * get_<altname1>() const; 
void set_<altname1>(const <alt1-type> &); 

Private:
   union{
altname1 *altname1_field;
altname2 *altname2_filed;
   ...
   ...
Altnamen * altnamen_field;
   }

  cleanup();
};

The OssList class

A protocol element that consists of several sub-elements of the same type is represented by a specific class derived from the OssList class. The OssList class is not user-instantiable.

Definition

class OSS_PUBLIC OssList
{
protected:
    void *head;
    OssList();
    ~OssList();
    OssIndex do_prepend(OssIndex);
    OssIndex do_prepend(OssList *);
    OssIndex do_insert_after(OssIndex, OssIndex);
    OssIndex do_insert_after(OssIndex, OssList *);
    OssList *do_extract_after(OssIndex, OssIndex);
    OssIndex do_extract_front();
    OssIndex do_extract_after(OssIndex);
    void do_copy(const OssList &, void * (*func)(void *));
    void do_destroy(void (*func)(void *));
    int do_compare(const OssList &, int (*func)(void *, void *)) const;
public:
    void *operator new(size_t);
    void operator delete(void *);
    int empty() const;
    OssIndex first() const;
    OssIndex next(OssIndex index) const;
};

typedef void * OssIndex;

Methods

OssList has the following public methods:

int empty() const;
This method returns 1 if the sequence is empty (consists of 0 elements); otherwise, it returns 0.
OssIndex first() const;
This method returns an OssIndex value for the first element. If the sequence is empty, OSS_NOINDEX is returned.
OssIndex next(OssIndex) const;
This method returns an OssIndex value that represents the next position relative to the OssIndex value passed as a parameter. If the parameter points to the last sequence element, OSS_NOINDEX is returned.

NAS protocol elements derived from OssList

There are twelves classes that represent NAS protocol elements which are the derived classes of OssList. These are the same for all NAS releases supported by OSS Nokalva.

These classes are:

SupportedCodecList, TrackingAreaIdentityList, PLMNList, EmergencyNumberList, ProtocolAndContainerList, PacketFilterIdentifierList, PacketFilterList, TFTParameterList, TAIListElement_TACList, TAISubListElementList, PacketFilterComponentList, TFTPacketFilterIdentifierList

These twelve classes have the following common structure:

class DerivedFromList : public OssList {
public:
  typedef  component; // The element in the List

  // Constructors and destructor
  DerivedFromList();
  DerivedFromList(const DerivedFromList & that);
  ~DerivedFromList();

  // Operators: assignment, equality, inequality
  DerivedFromList & operator = (const DerivedFromList & that);
  int operator == (const DerivedFromList & that) const;
  int operator != (const DerivedFromList & that) const;

  // Component methods
  component * at(OssIndex pos);
  const component * at(OssIndex pos) const;

  OssIndex prepend(const component &val);
  OssIndex prepend(DerivedFromList * seq);

  OssIndex insert_after(OssIndex pos, const component &val);
  OssIndex insert_after(OssIndex pos, DerivedFromList * seq);

  int remove_front();
  int remove_after(OssIndex pos);

  DerivedFromList * extract_after(OssIndex begin, OssIndex end);
};

Methods

component * at(OssIndex);
const component * at(OssIndex) const;
These methods return the pointer to the component of the sequence indicated by the OssIndex object passed as a parameter.
OssIndex prepend(const component &val);
This method creates a new sequence of elements, copies the contents of the parameter (using deep copy) to the newly created element, and prepends the sequence with this element (so it becomes the first element of the sequence). The OssIndex value for the newly created element is returned. All other OssIndex values for this sequence remain valid.
OssIndex prepend(DerivedFromList *);
This method prepends a sequence with the entire contents of another sequence of the same type (so the last element of the parameter object will precede the first element of "this" object before the call). The object passed as a parameter becomes empty.
OssIndex insert_after(OssIndex, const component &);
This method inserts a deep copy of the object passed as the second parameter after the position represented by the first parameter. If the first parameter is OSS_NOINDEX, the object is inserted at the beginning of the sequence. The second parameter is unchanged. The OssIndex value for the newly inserted element is returned.
OssIndex insert_after(OssIndex, DerivedFromList *);
This method inserts a sequence of the same type passed as the second parameter after the position specified by the first parameter. If the first parameter is OSS_NOINDEX, the object is inserted at the beginning of the sequence. The second parameter becomes empty; all its components are transferred to "this" sequence. No copying occurs. All OssIndexes for "this" sequence remain valid. The OssIndex value for the first of the inserted elements is returned by the function.
int remove_front();
This method deletes the first element of the sequence. This method returns 0 if the delete operation was successful; otherwise, a non-zero error code is retuned (if the sequence was empty). Any existing pointers or OssIndexes to the deleted element are invalidated.
int remove_after(OssIndex);
This method deletes the element that follows the position specified by OssIndex from the sequence. If the parameter is OSS_NOINDEX, the first element is deleted. If the delete operation was successful, it returns 0; otherwise it returns a non-zero error code.
DerivedFromList* extract_after(OssIndex, OssIndex);
This method extracts the subset of "this" sequence elements, i.e., removes it from "this" sequence and creates a new sequence that consists of the removed components. The first parameter is OssIndex for the element which precedes the element to be moved, and the second parameter is OssIndex for the last element to be moved.

This documentation applies to the OSS NAS Tools for C++ for 5G v7.1.0 for 3GPP Release 15.4.0.

Copyright © 2021 OSS Nokalva, Inc. All rights reserved.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means electronic, mechanical, photocopying, recording or otherwise, without the prior permission of OSS Nokalva, Inc.
Every distributed copy of the OSS NAS Tools for C++ for 5G is associated with a specific license and related unique license number. That license determines, among other things, what functions of the OSS NAS Tools for C++ for 5G are available to you.