ANNA Suite  2020b
Multipurpose development suite for Telco applications
Public Member Functions | Static Public Attributes | Protected Member Functions | Protected Attributes | Friends | List of all members
anna::diameter::codec::Message Class Reference

#include <Message.hpp>

Inheritance diagram for anna::diameter::codec::Message:
Inheritance graph
[legend]
Collaboration diagram for anna::diameter::codec::Message:
Collaboration graph
[legend]

Public Member Functions

 Message (Engine *engine=NULL)
 
 Message (CommandId id, Engine *engine=NULL)
 
void setEngine (Engine *engine)
 
virtual ~Message ()
 
void setId (CommandId id) noexcept(false)
 
void setId (const char *name) noexcept(false)
 
void setVersion (U8 version)
 
void setProxiableBit (bool activate=true)
 
void setErrorBit (bool activate=true)
 
void setPotentiallyReTransmittedMessageBit (bool activate=true)
 
void setApplicationId (U32 aid) noexcept(false)
 
void setHopByHop (U32 hbh)
 
void setEndToEnd (U32 ete)
 
void setHeaderToAnswer (const Message &request) noexcept(false)
 
void setStandardToAnswer (const Message &request, const std::string &originHost, const std::string &originRealm, int resultCode=helpers::base::AVPVALUES__Result_Code::DIAMETER_SUCCESS) noexcept(false)
 
void setResultCode (int rc=helpers::base::AVPVALUES__Result_Code::DIAMETER_SUCCESS) noexcept(false)
 
int getResultCode () const
 
AvpaddAvp (AvpId id) noexcept(false)
 
AvpaddAvp (const char *name) noexcept(false)
 
AvpaddAvp (Avp *avp)
 
bool removeAvp (AvpId id, int ocurrence=1) noexcept(false)
 
bool removeAvp (const char *name, int ocurrence=1) noexcept(false)
 
virtual void clear (bool resetEngine=true) noexcept(false)
 
void decode (const anna::DataBlock &db, Message *ptrAnswer=NULL) noexcept(false)
 
void fix ()
 
bool valid (Message *ptrAnswer=NULL) const noexcept(false)
 
void fromXML (const anna::xml::Node *messageNode) noexcept(false)
 
void loadXMLFile (const std::string &xmlPathFile) noexcept(false)
 
void loadXMLString (const std::string &xmlString) noexcept(false)
 
const CommandIdgetId () const
 
U8 getVersion () const
 
bool isRequest () const
 
bool isAnswer () const
 
const U32getApplicationId () const
 
const U32getHopByHop () const
 
const U32getEndToEnd () const
 
const anna::diameter::stack::CommandgetStackCommand () const noexcept(false)
 
bool requestBit () const
 
bool proxiableBit () const
 
bool errorBit () const
 
bool potentiallyReTransmittedMessageBit () const
 
const AvpgetAvp (AvpId id, int ocurrence=1, anna::Exception::Mode::_v emode=anna::Exception::Mode::Throw) const noexcept(false)
 
AvpgetAvp (AvpId id, int ocurrence=1, anna::Exception::Mode::_v emode=anna::Exception::Mode::Throw) noexcept(false)
 
const AvpgetAvp (const char *name, int ocurrence=1, anna::Exception::Mode::_v emode=anna::Exception::Mode::Throw) const noexcept(false)
 
AvpgetAvp (const char *name, int ocurrence=1, anna::Exception::Mode::_v emode=anna::Exception::Mode::Throw) noexcept(false)
 
int countAvp (AvpId id) const
 
int countAvp (const char *name) const noexcept(false)
 
int countChilds () const
 
const anna::DataBlockcode () noexcept(false)
 
anna::xml::NodeasXML (anna::xml::Node *parent) const
 
std::string asXMLString (bool normalize=false) const
 
bool isLike (const std::string &pattern) const
 

Static Public Attributes

static const int HeaderLength
 
static const U8 RBitMask
 
static const U8 PBitMask
 
static const U8 EBitMask
 
static const U8 TBitMask
 

Protected Member Functions

virtual EnginegetEngine () const noexcept(false)
 
virtual void initialize ()
 

Protected Attributes

Enginea_engine
 

Friends

class Avp
 
bool operator== (const Message &m1, const Message &m2)
 

Detailed Description

Diameter message generic container

   RFC 3588                Diameter Based Protocol           September 2003
   3.  Diameter Header
      A summary of the Diameter header format is shown below.  The fields
      are transmitted in network byte order.
       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |    Version    |                 Message Length                |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      | command flags |                  Command-Code                 |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                         Application-ID                        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                      Hop-by-Hop Identifier                    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                      End-to-End Identifier                    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |  AVPs ...
      +-+-+-+-+-+-+-+-+-+-+-+-+-

Constructor & Destructor Documentation

◆ Message() [1/2]

anna::diameter::codec::Message::Message ( Engine engine = NULL)

Default constructor

Parameters
engineCodec engine used

◆ Message() [2/2]

anna::diameter::codec::Message::Message ( CommandId  id,
Engine engine = NULL 
)

Identified constructor

Parameters
idCommand identifier as pair (code,request-indicator).
engineCodec engine used

◆ ~Message()

virtual anna::diameter::codec::Message::~Message ( )
virtual

Destructor

Member Function Documentation

◆ addAvp() [1/3]

Avp* anna::diameter::codec::Message::addAvp ( AvpId  id)
inlinenoexcept

Adds an avp child providing its identifier and reserve internal memory it.

Parameters
idAvp identifier as pair (code,vendor-id).
Returns
Pointer to the new created avp.
457 { return Avp::addAvp(a_avps, a_insertionPositionForChilds, id, getEngine()); }
virtual Engine * getEngine() const noexcept(false)

◆ addAvp() [2/3]

Avp* anna::diameter::codec::Message::addAvp ( const char *  name)
noexcept

Same as addAvp but providing dictionary logical name for Avp searched

◆ addAvp() [3/3]

Avp* anna::diameter::codec::Message::addAvp ( Avp avp)

Adds an avp child providing a persistent pointer (must be maintained by application). It is not allowed to add an avp with no codec engine configured, neither if the engine is not the same.

Parameters
avpAvp external pointer. If NULL provided, nothing is done and NULL returned. Also NULL returned for bad engine configuration.
Returns
Pointer to the added avp (again).

◆ asXML()

anna::xml::Node* anna::diameter::codec::Message::asXML ( anna::xml::Node parent) const

Class xml representation

Parameters
parentParent XML node on which hold this instance information.
Returns
XML document with relevant information for this instance.

◆ asXMLString()

std::string anna::diameter::codec::Message::asXMLString ( bool  normalize = false) const

Class xml string representation

Parameters
normalizeOptional normalization which sorts attribute names and removes newlines in the xml representation in order to ease regexp matching.
Returns
XML string representation with relevant information for this instance.

◆ clear()

virtual void anna::diameter::codec::Message::clear ( bool  resetEngine = true)
virtualnoexcept

Clears and initializes Message class information. Application must clear auxiliary message objects before adding Avps in a new context if the same object is reused. Application don't need to clear a message object before decode operation (decode invokes clear before any other task). Any reimplementation must first invoke base class method.

Parameters
resetEngineSets to NULL the codec engine (true, default) or respect its current value (false). If you are going to reuse the message instance it is better to clear all the information (default) to manage different stacks, because if you don't initialize the engine to NULL, the second use of the message will keep the same engine deduced from the first decoding/loading operation, which could be wrong if the second message belongs to a different application identifier.

◆ code()

const anna::DataBlock& anna::diameter::codec::Message::code ( )
noexcept

Encodes datablock with the class content. In case that validation is enabled (codec::Engine::ValidationMode) an exception will be launched in a moment which depends on validation depth (codec::Engine::ValidationDepth). If you want to see validation errors but go on with encoding, you should try/catch valid() procedure out of code.

Returns
DataBlock encoded (internal memory used)

◆ countAvp() [1/2]

int anna::diameter::codec::Message::countAvp ( AvpId  id) const
inline

Counts the number of ocurrences of Avps (first level) with the identifier provided

Parameters
idAvp identifier (pair code + vendor-id).
686 { return Avp::countAvp(a_avps, id); }

◆ countAvp() [2/2]

int anna::diameter::codec::Message::countAvp ( const char *  name) const
noexcept

Same as countAvp but providing dictionary logical name for Avp searched

◆ countChilds()

int anna::diameter::codec::Message::countChilds ( ) const
inline

Counts the number of children

Parameters
idAvp identifier (pair code + vendor-id).
698 { return Avp::countChilds(a_avps); }
int countChilds() const noexcept(false)
Definition: Avp.hpp:759

◆ decode()

void anna::diameter::codec::Message::decode ( const anna::DataBlock db,
Message ptrAnswer = NULL 
)
noexcept

Decodes buffer provided over class content. If an error ocurred, decoding will stop launching exception (fatal error) or a warning trace (perhaps the achieved message is valid against all odds then validation will go on). In case that validation is enabled (codec::Engine::ValidationMode) an exception will be launched in a moment which depends on validation depth (codec::Engine::ValidationDepth).

You could decode multiple times over the same object. A basic cleanup is done respecting the codec engine.

Parameters
dbbuffer data block processed. Before decoding, the whole message instance will be cleared (no need to invoke clear before decode).
ptrAnswerAnswer set by application (could be empty or not), who is responsible for its memory reservation, and automatically built regarding standard. If message analyzed realizes to be an answer, internal reference becomes NULL because no answer is built for answers. By default, automatic answer is not built.

◆ errorBit()

bool anna::diameter::codec::Message::errorBit ( ) const
inline

Returns E bit activation state

625 { return ((a_flags & EBitMask) != 0x00); }
static const U8 EBitMask
Definition: Message.hpp:219

◆ fix()

void anna::diameter::codec::Message::fix ( )

Fix childrens content regarding dictionary avp positions. Message could remain invalid because of possible fixed/mandatory avps. This is useful to give flexibility to the application during message construction before encoding or representing the data. Is not recommended to fix a recently decoded message because possible validation problems will be hidden.

◆ fromXML()

void anna::diameter::codec::Message::fromXML ( const anna::xml::Node messageNode)
noexcept

Interpret xml data in order to dump over the class content. You could apply this multiple times over the same object. A basic cleanup is done respecting the codec engine.

Parameters
messageNodeMessage root node obtained from ::xmlFileTo

◆ getApplicationId()

const U32& anna::diameter::codec::Message::getApplicationId ( ) const
inline

Gets the message application id

Returns
aid Application-id.
599 { return a_applicationId; }

◆ getAvp() [1/4]

const Avp* anna::diameter::codec::Message::getAvp ( AvpId  id,
int  ocurrence = 1,
anna::Exception::Mode::_v  emode = anna::Exception::Mode::Throw 
) const
inlinenoexcept

Access content for internal Avps. Exception mode allows different combinations like cascade access:

   try {
      message->getAvp(anna::diameter::helpers::base::AVP__Multiple_Services_Credit_Control, anna::Exception::Mode::Throw)
             ->getAvp(anna::diameter::helpers::base::AVP__Rating_Group, anna::Exception::Mode::Throw);
   }
   catch(anna::RuntimeException) {;}

Or step access:

   const Avp *mscc = message->getAvp(anna::diameter::helpers::base::AVP__Multiple_Services_Credit_Control);
   const Avp *rg;
   if (mscc) rg = mscc->getAvp(anna::diameter::helpers::base::AVP__Rating_Group);

Replacing procedures becomes easy because an Avp can be searched and its pointer reconfigured by mean setId and data part setters. Deleting procedures must use removeAvp. Access is internally cached to speed up the search operations. This cache is reset after calling fix or removeAvp methods.

Parameters
idAvp identifier (pair code + vendor-id).
ocurrenceOrder of appearance for the searched avp. Zero position is rejected, but negative values could be used to reverse access positions: i.e. -1 is the last ocurrence, -2 is the second to last (penultimate), etc.
emodeExcepcion mode handling: Ignore (no action is taken), Throw (excepcion when missing avp), Trace (trace situation as warning).
659  {
660  return Avp::getAvp(a_avps, (find_container&)a_finds, id, ocurrence, getEngine(), emode);
661  }
std::map< find_key, Avp * > find_container
Definition: Avp.hpp:83
virtual Engine * getEngine() const noexcept(false)

◆ getAvp() [2/4]

Avp* anna::diameter::codec::Message::getAvp ( AvpId  id,
int  ocurrence = 1,
anna::Exception::Mode::_v  emode = anna::Exception::Mode::Throw 
)
inlinenoexcept
663  {
664  return const_cast<Avp*>(Avp::getAvp(a_avps, (find_container&)a_finds, id, ocurrence, getEngine(), emode));
665  }
friend class Avp
Definition: Message.hpp:795
std::map< find_key, Avp * > find_container
Definition: Avp.hpp:83
virtual Engine * getEngine() const noexcept(false)

◆ getAvp() [3/4]

const Avp* anna::diameter::codec::Message::getAvp ( const char *  name,
int  ocurrence = 1,
anna::Exception::Mode::_v  emode = anna::Exception::Mode::Throw 
) const
inlinenoexcept

Same as getAvp but providing dictionary logical name for Avp searched

671  {
672  return _getAvp(name, ocurrence, emode);
673  }

◆ getAvp() [4/4]

Avp* anna::diameter::codec::Message::getAvp ( const char *  name,
int  ocurrence = 1,
anna::Exception::Mode::_v  emode = anna::Exception::Mode::Throw 
)
inlinenoexcept
675  {
676  return const_cast<Avp*>(_getAvp(name, ocurrence, emode));
677  }
friend class Avp
Definition: Message.hpp:795

◆ getEndToEnd()

const U32& anna::diameter::codec::Message::getEndToEnd ( ) const
inline

Gets the message end-to-end

Returns
ete End-to-end identifier.
611 { return a_endToEnd; }

◆ getEngine()

virtual Engine* anna::diameter::codec::Message::getEngine ( ) const
protectedvirtualnoexcept

Codec Engine getter: avoids have to create base engine when using its child

◆ getHopByHop()

const U32& anna::diameter::codec::Message::getHopByHop ( ) const
inline

Gets the message hop-by-hop

Returns
hbh Hop-by-hop identifier.
605 { return a_hopByHop; }

◆ getId()

const CommandId& anna::diameter::codec::Message::getId ( ) const
inline

Gets Message identifier as pair (code, request indicator).

576 { return a_id; }

◆ getResultCode()

int anna::diameter::codec::Message::getResultCode ( ) const

Gets the Result-Code AVP value from an answer message (for requests, returns -1). If missing, -1 value is returned.

Returns
Result-Code value for answers, -1 for request and answers without Result-Code AVP inside

◆ getStackCommand()

const anna::diameter::stack::Command* anna::diameter::codec::Message::getStackCommand ( ) const
inlinenoexcept

Gets stack command (dictionary command reference).

616 { return getStackCommand(a_id); }
const anna::diameter::stack::Command * getStackCommand() const noexcept(false)
Definition: Message.hpp:616
Here is the call graph for this function:

◆ getVersion()

U8 anna::diameter::codec::Message::getVersion ( ) const
inline

Gets the command version. By default, messages initializes with value 1.

Returns
version Message version
583 { return a_version; }

◆ initialize()

virtual void anna::diameter::codec::Message::initialize ( )
protectedvirtual

Initializes Message class information. Any reimplementation must first invoke base class method.

Reimplemented in anna::diameter::codec::tme::Message.

◆ isAnswer()

bool anna::diameter::codec::Message::isAnswer ( ) const
inline

Gets Message answer indicator.

593 { return !isRequest(); }
bool isRequest() const
Definition: Message.hpp:588

◆ isLike()

bool anna::diameter::codec::Message::isLike ( const std::string &  pattern) const

Matchs a regular expression (string pattern) regarding xml string serialization for this message. The message xml representation is internally normalized (attribute names are sort and newlines are removed) in order to ease regexp matching.

You could use simple regular expressions. For example, the pattern '<avp data="(.)*32251@3gpp.org" name="Service-Context-Id">' detects PS charging contexts because of data suffix specification '32251.nosp@m.@3gp.nosp@m.p.org' for that AVP. The pattern '<message(.)* name="Capabilities-Exchange-Request"' detects a CER message. And so on.

It would seems strange or 'creative' to use regular expressions within an hex string representation, but anyway you could also do such kind of things to check non-printable data parts within the message: for example, the pattern '<avp hex-data="0a[A-Fa-f0-9]{2}0a0a" name="Framed-IP-Address">' matchs IP addresses for '10.x.10.10' where x = [0..255].

Normally only printable 'data' fields are used for matching issues.

Now imagine 'message.xml' containing this avp:

...
<avp name="Subscription-Id">
   <avp alias="END_USER_E164" data="0" name="Subscription-Id-Type">
   <avp data="616[0-9]{6}" name="Subscription-Id-Data">
</avp>'
...

You could also extract AVP xml normalized representation in this way:

anna::diameter::codec::Message myMessage;
myMessage.loadXMLFile("message.xml");
std::string subscriptionId = myMessage.getAvp("Subscription-Id")->getAvp("Subscription-Id-Type")->asXMLString(true);
// Former is '<avp data="616[0-9]{6}" name="Subscription-Id-Data">'

And then use to match incoming messages:

bool match = incomingMessage.isLike(subscriptionId);

Using a complex pattern (many avps, grouped ones) is possible, indeed testing ADML engine supports 'waitfe/fc-xml' operations which load entire diameter messages to be used as a whole regular expression (hop-by-hop, end-to-end and Origin-State-Id avp is automatically replaced by '[0-9]+' to make possible the comparison).

Those operations makes all the work, but if you use the API, you may take into account:

  • Respect indentation for inner Message xml representation (normally 3 spaces).
  • Sort alphabetically the attribute names in every xml node.
  • Remove all the newlines in the xml representation as normalization stage.
  • Ignore flags and set the fix mode for the message.
Returns
Returns the match result

◆ isRequest()

bool anna::diameter::codec::Message::isRequest ( ) const
inline

Gets Message request indicator.

588 { return a_id.second; }

◆ loadXMLFile()

void anna::diameter::codec::Message::loadXMLFile ( const std::string &  xmlPathFile)
noexcept

Interpret a xml file in order to create a diameter message You could apply this multiple times over the same object. A basic cleanup is done respecting the codec engine.

See also
functions::messageXmlDocumentFromXmlFile
fromXML
Parameters
xmlPathFileComplete path file to the xml document which represents the diameter message

◆ loadXMLString()

void anna::diameter::codec::Message::loadXMLString ( const std::string &  xmlString)
noexcept

Interpret a xml string in order to create a diameter message You could apply this multiple times over the same object. A basic cleanup is done respecting the codec engine.

See also
functions::messageXmlDocumentFromXmlString
fromXML
Parameters
xmlStringxml representation of the diameter message

◆ potentiallyReTransmittedMessageBit()

bool anna::diameter::codec::Message::potentiallyReTransmittedMessageBit ( ) const
inline

Returns T bit activation state

628 { return ((a_flags & TBitMask) != 0x00); }
static const U8 TBitMask
Definition: Message.hpp:220

◆ proxiableBit()

bool anna::diameter::codec::Message::proxiableBit ( ) const
inline

Returns P bit activation state

622 { return ((a_flags & PBitMask) != 0x00); }
static const U8 PBitMask
Definition: Message.hpp:218

◆ removeAvp() [1/2]

bool anna::diameter::codec::Message::removeAvp ( AvpId  id,
int  ocurrence = 1 
)
inlinenoexcept

Removes an Avp within message (first level) and free resources.

Parameters
idAvp identifier (pair code + vendor-id).
ocurrenceOrder of appearance for the searched avp. Zero value means remove all avps with provided identifier at first level (no recursiveness would be allowed in the API in order to avoid unexpected behaviour). Negative values could be used to reverse access positions: i.e. -1 is the last ocurrence, -2 is the second to last (penultimate), etc.
Returns
Returns true if something was removed. False in other cases (including i.e. when this message is empty).
488 { return Avp::removeAvp(a_avps, (find_container&)a_finds, id, ocurrence, getEngine()); }
std::map< find_key, Avp * > find_container
Definition: Avp.hpp:83
virtual Engine * getEngine() const noexcept(false)

◆ removeAvp() [2/2]

bool anna::diameter::codec::Message::removeAvp ( const char *  name,
int  ocurrence = 1 
)
noexcept

Same as removeAvp but providing dictionary logical name for Avp searched

◆ requestBit()

bool anna::diameter::codec::Message::requestBit ( ) const
inline

Returns R bit activation state

619 { return ((a_flags & RBitMask) != 0x00); }
static const U8 RBitMask
Definition: Message.hpp:217

◆ setApplicationId()

void anna::diameter::codec::Message::setApplicationId ( U32  aid)
noexcept

Sets the message application id.

The codec engine could be configured to force a stack selection based in this field value: see #selectStackWithApplicationId. In multistack applications (in case of being monothread), you only have to take care about how to apply this method: the thing is that you must not interleave message builds which belongs to different stacks. For example, you could think about setting the message header for message A using stack A. Then, start to add the message header fields for a second message B using another stack B. Following you would add the message A avps, but then, the stack is not going to be automatically changed (this is only done through this method). The result could be unexpected when adding/encoding messages with a dictionary which does not correspond.

Warning
do not interleave build/encode operations between different messages which uses different stacks over the same codec engine. It seems common sense, but it is not bad to advice about this.
Parameters
aidApplication-id.

◆ setEndToEnd()

void anna::diameter::codec::Message::setEndToEnd ( U32  ete)
inline

Sets the message end-to-end

Parameters
eteEnd-to-end identifier.
309 { a_endToEnd = ete; }

◆ setEngine()

void anna::diameter::codec::Message::setEngine ( Engine engine)

Sets the codec engine.

Once assigned (here or at constructor), this method SHALL NOT be used anymore. Also, the associated dictionary SHOULD NOT BE CHANGED through the engine, unless you know what are you doing. Setting a new different engine with different stack, even same engine where the stack has been dynamically changed, could cause a bad behaviour depending on the changes: in general, if the dictionary grows, nothing bad will happen, but if you remove or modified some elements which were processed with a certain format, will be interpreted as 'unknown' with the new dictionary, and then some problems may occur. If you add elements (vendors, avps, messages) is not a problem.

IMPORTANT NOTES: 1) if you want to reuse the message, as a recommendation, you should clear the message. In that way, next operation will adjust automatically the needed engine. 2) if you have dedicated message objects for each interface (application id), then you could set the corresponding engine on constructor (or setEngine), and forget about clear. The needed cleanup will be done automatically from decoding and xml loading procedures, and initialized engine will be kept along message operations.

◆ setErrorBit()

void anna::diameter::codec::Message::setErrorBit ( bool  activate = true)
inline

Sets/unsets E bit activation. Application should not have to use this because dictionary information is used in order to configure flags when Message identifier is stored. This flag MUST NOT be set in request messages (in this case, it will be ignored).

Parameters
activateActivates/deactivates the bit. True by default.
271 { if(isRequest()) return; if(activate) a_flags |= EBitMask; else a_flags &= (~EBitMask); }
bool isRequest() const
Definition: Message.hpp:588
static const U8 EBitMask
Definition: Message.hpp:219

◆ setHeaderToAnswer()

void anna::diameter::codec::Message::setHeaderToAnswer ( const Message request)
inlinenoexcept

Sets header to be an answer regarding provided request message code. Internally, updates command identifier (indeed request flag), promotes version, application identifier, hop-by-hop and end-to-end fields.

Parameters
requestMessage to be answered.
Warning
Request provided must be a request, in other case method do nothing.
320  {
321  if(!request.getId().second) return;
322 
323  a_engine = request.getEngine(); // we know this will be
324 
325  setId(CommandId(request.getId().first, !request.getId().second));
326  setVersion(request.getVersion());
327  setApplicationId(request.getApplicationId());
328  setHopByHop(request.getHopByHop()); // The same Hop-by-Hop Identifier in the request is used in the answer (RFC 6733 Section 6.2).
329  setEndToEnd(request.getEndToEnd()); // The same End-to-End Identifier in the request is used in the answer (RFC 6733 Section 6.2).
330  setProxiableBit(request.proxiableBit()); // The 'P' bit is set to the same value as the one in the request (RFC 6733 Section 6.2).
331  }
void setHopByHop(U32 hbh)
Definition: Message.hpp:303
void setVersion(U8 version)
Definition: Message.hpp:254
void setProxiableBit(bool activate=true)
Definition: Message.hpp:262
void setEndToEnd(U32 ete)
Definition: Message.hpp:309
void setId(CommandId id) noexcept(false)
Engine * a_engine
Definition: Message.hpp:150
std::pair< U24, bool > CommandId
Definition: defines.hpp:32
void setApplicationId(U32 aid) noexcept(false)

◆ setHopByHop()

void anna::diameter::codec::Message::setHopByHop ( U32  hbh)
inline

Sets the message hop-by-hop

Parameters
hbhHop-by-hop identifier.
303 { a_hopByHop = hbh; }

◆ setId() [1/2]

void anna::diameter::codec::Message::setId ( CommandId  id)
noexcept

Sets the command identifier and clear the former content.

Parameters
idCommand identifier as pair (code,request-indicator).

◆ setId() [2/2]

void anna::diameter::codec::Message::setId ( const char *  name)
noexcept

Same as setId but providing dictionary logical name for Avp searched

◆ setPotentiallyReTransmittedMessageBit()

void anna::diameter::codec::Message::setPotentiallyReTransmittedMessageBit ( bool  activate = true)
inline

Sets/unsets T bit activation. Application should not have to use this because dictionary information is used in order to configure flags when Message identifier is stored. This flag MUST NOT be set in answer messages (in this case, it will be ignored).

Parameters
activateActivates/deactivates the bit. True by default.
280 { if(isAnswer()) return; if(activate) a_flags |= TBitMask; else a_flags &= (~TBitMask); }
static const U8 TBitMask
Definition: Message.hpp:220
bool isAnswer() const
Definition: Message.hpp:593

◆ setProxiableBit()

void anna::diameter::codec::Message::setProxiableBit ( bool  activate = true)
inline

Sets/unsets P bit activation. Application should not have to use this because dictionary information is used in order to configure flags when Message identifier is stored.

Parameters
activateActivates/deactivates the bit. True by default.
262 { if(activate) a_flags |= PBitMask; else a_flags &= (~PBitMask); }
static const U8 PBitMask
Definition: Message.hpp:218

◆ setResultCode()

void anna::diameter::codec::Message::setResultCode ( int  rc = helpers::base::AVPVALUES__Result_Code::DIAMETER_SUCCESS)
noexcept

Sets a Result-Code AVP over an answer message (for requests, do nothing). If Result-Code AVP doesn't exists, is added and then filled with the value provided. If Result-Code AVP already exists, value detected is replaced if was DIAMETER_SUCCESS (non success codes are unchanged). When provided value corresponds to an protocol error, that is to say within range [3001,3010], message (E)rror bit is automatically activated.

This method is internally used during decode and/or valid procedures in order to build automatic answers, but application could call this for set another Result-Code no detected by these methods within its category or for other one (application layer). These are the Result-Codes implemented (detected) by ANNA::diameter::codec:

   Protocol Errors:
      DIAMETER_COMMAND_UNSUPPORTED
      DIAMETER_INVALID_HDR_BITS
      DIAMETER_INVALID_AVP_BITS
   Permanent Failures:
      DIAMETER_AVP_UNSUPPORTED (F)
      DIAMETER_INVALID_AVP_VALUE (F)
      DIAMETER_MISSING_AVP (F)
      DIAMETER_AVP_NOT_ALLOWED (F)
      DIAMETER_AVP_OCCURS_TOO_MANY_TIMES (F)
      DIAMETER_INVALID_BIT_IN_HEADER
      DIAMETER_INVALID_AVP_LENGTH (F)
      DIAMETER_INVALID_MESSAGE_LENGTH
      (F) Generates Failed-AVP (also DIAMETER_CONTRADICTING_AVPS and DIAMETER_INVALID_AVP_BIT_COMBO
                                values does, but these are not managed by anna::diameter::codec).
Parameters
rcResult-Code value. DIAMETER_SUCCESS by default.

◆ setStandardToAnswer()

void anna::diameter::codec::Message::setStandardToAnswer ( const Message request,
const std::string &  originHost,
const std::string &  originRealm,
int  resultCode = helpers::base::AVPVALUES__Result_Code::DIAMETER_SUCCESS 
)
noexcept

Standard minimum-answer building from requests. Adds Session-Id (mirrored from request if present), Origin-Host and Origin-Realm (which could be configured, extracted from optional Destination AVPs, etc.), and all the Proxy-Info AVPs (added in same order as appear on the request). Of course, answer message header is built from request information through setHeaderToAnswer. Finally, message is fixed regarding dictionary elements order (fix).

Summing up, as RFC 6733 Section 6.2, says:

     6.2.  Diameter Answer Processing
        When a request is locally processed, the following procedures MUST be
        applied to create the associated answer, in addition to any
        additional procedures that MAY be discussed in the Diameter
        application defining the command:
        o  The same Hop-by-Hop Identifier in the request is used in the
           answer.
        o  The local host's identity is encoded in the Origin-Host AVP.
        o  The Destination-Host and Destination-Realm AVPs MUST NOT be
           present in the answer message.
        o  The Result-Code AVP is added with its value indicating success or
           failure.
        o  If the Session-Id is present in the request, it MUST be included
           in the answer.
        o  Any Proxy-Info AVPs in the request MUST be added to the answer
           message, in the same order they were present in the request.
        o  The 'P' bit is set to the same value as the one in the request.
        o  The same End-to-End identifier in the request is used in the
           answer.
        Note that the error messages (see Section 7) are also subjected to
        the above processing rules.
Regarding errors, is recommended to use this over automatic answer built at decode and/or valid procedures, which would had added
Result-Code and/or Failed-AVP AVPs if proceed, but be aware of DIAMETER_COMMAND_UNSUPPORTED Result-Code, because becomes impossible
to fix (Session-Id SHOULD appear immediately following the Diameter header, and fix do this manually even if no information about
the command structure is known, but perhaps another fixed AVPs could not comply... use getResultCode to find out this situation before
using setStandardToAnswer). Anyway, application could add another Failed-AVP content no detected internally, for example:
DIAMETER_CONTRADICTING_AVPS or DIAMETER_INVALID_AVP_BIT_COMBO). Also, application could add more Failed-AVP avps with other
wrong avps, or accumulate wrong avps inside the one and only Failed-AVP managed by the stack. The standard is open to add multiple
avps inside Failed-AVP or multiple Failed-AVP avps with single or multiple avps inside. This depends on application criteria regarding
other nodes. However, internally the Anna::diameter stack only provides one Failed-AVP with the first wrong avp found, as RFC 6733 says
in section 7.5.
If application decoding and/or validation operations are ok, user may search for other problems and put the appropiate Result-Code.
For example, DIAMETER_TOO_BUSY (3004) depends on congestion issues at business layer and cannot be decided with the only message
information automatically (not all the Result-Code values are taken into account, only those which correspond to anomalies managed
by anna::diameter::codec). Application Result-Codes could be provided in this prototype, being DIAMETER_SUCCESS the default value if missing.
 
Parameters
requestMessage to be answered.
originHostMandatory Origin-Host diameter identity value provided by application. If answer has already an Origin-Host, this will be ignored.
originRealmMandatory Origin-Realm diameter identity value provided by application. If answer has already an Origin-Realm, this will be ignored.
resultCodeResult-Code value assigned by application. If non-success value is already assigned, this will be ignored. DIAMETER_SUCCESS is provided by default.
Warning
Request provided must be a request, in other case method do nothing.

◆ setVersion()

void anna::diameter::codec::Message::setVersion ( U8  version)
inline

Sets the command version. By default, messages initializes with value 1.

Parameters
versionVersion provided
254 { a_version = version; }

◆ valid()

bool anna::diameter::codec::Message::valid ( Message ptrAnswer = NULL) const
noexcept

Validates the message regarding dictionary rules like enumerated range, flags coherence, mandatory and fixed types, cardinality qualifiers, etc.

Returns
Boolean indicating validation result
Parameters
ptrAnswerAnswer set by application (could be empty or not), who is responsible for its memory reservation, and automatically built regarding standard. If message analyzed realizes to be an answer, internal reference becomes NULL because no answer is built for answers. By default, automatic answer is not built.

Friends And Related Function Documentation

◆ Avp

friend class Avp
friend

◆ operator==

bool operator== ( const Message m1,
const Message m2 
)
friend

Comparison operator by mean serialization

Parameters
m1Instance 1 for Message class
m2Instance 2 for Message class
Returns
Comparison result
733 { return (m1.asXMLString() == m2.asXMLString()); }

Member Data Documentation

◆ a_engine

Engine* anna::diameter::codec::Message::a_engine
mutableprotected

Codec Engine

◆ EBitMask

const U8 anna::diameter::codec::Message::EBitMask
static

◆ HeaderLength

const int anna::diameter::codec::Message::HeaderLength
static

◆ PBitMask

const U8 anna::diameter::codec::Message::PBitMask
static

◆ RBitMask

const U8 anna::diameter::codec::Message::RBitMask
static

◆ TBitMask

const U8 anna::diameter::codec::Message::TBitMask
static

The documentation for this class was generated from the following file: