Add metrics to the framework
[ric-plt/xapp-frame-cpp.git] / src / messaging / message.cpp
index 0c6b262..a8b8089 100644 (file)
 
 #include "message.hpp"
 
+namespace xapp {
+
+
+
 // --------------- private ------------------------------------------------
 
-// --------------- builders -----------------------------------------------
+// --------------- builders/operators  -------------------------------------
 
 /*
        Create a new message wrapper for an existing RMR msg buffer.
 */
-Message::Message( rmr_mbuf_t* mbuf, void* mrc ) {
+xapp::Message::Message( rmr_mbuf_t* mbuf, void* mrc ) {
        this->mrc = mrc;                        // the message router context for sends
        this->mbuf = mbuf;
 }
 
-Message::Message( void* mrc, int payload_len ) {
+xapp::Message::Message( void* mrc, int payload_len ) {
        this->mrc = mrc;
        this->mbuf = rmr_alloc_msg( mrc, payload_len );
 }
 
+/*
+       Copy builder.  Given a source object instance (soi), create a copy.
+       Creating a copy should be avoided as it can be SLOW!
+*/
+xapp::Message::Message( const Message& soi ) {
+       int payload_size;
+
+       mrc = soi.mrc;
+       payload_size = rmr_payload_size( soi.mbuf );            // rmr can handle a nil pointer
+       mbuf = rmr_realloc_payload( soi.mbuf, payload_size, RMR_COPY, RMR_CLONE );
+}
+
+/*
+       Assignment operator. Simiolar to the copycat, but "this" object exists and
+       may have data that needs to be released prior to making a copy of the soi.
+*/
+Message& xapp::Message::operator=( const Message& soi ) {
+       int     payload_size;
+
+       if( this != &soi ) {                            // cannot do self assignment
+               if( mbuf != NULL ) {
+                       rmr_free_msg( mbuf );           // release the old one so we don't leak
+               }
+
+               payload_size = rmr_payload_size( soi.mbuf );            // rmr can handle a nil pointer
+               mrc = soi.mrc;
+               mbuf = rmr_realloc_payload( soi.mbuf, payload_size, RMR_COPY, RMR_CLONE );
+       }
+
+       return *this;
+}
+
+/*
+       Move builder.  Given a source object instance (soi), move the information from
+       the soi ensuring that the destriction of the soi doesn't trash things from
+       under us.
+*/
+xapp::Message::Message( Message&& soi ) {
+       mrc = soi.mrc;
+       mbuf = soi.mbuf;
+
+       soi.mrc = NULL;         // prevent closing of RMR stuff on soi destroy
+       soi.mbuf = NULL;
+}
+
+/*
+       Move Assignment operator. Move the message data to the existing object
+       ensure the object reference is cleaned up, and ensuring that the source
+       object references are removed.
+*/
+Message& xapp::Message::operator=( Message&& soi ) {
+       if( this != &soi ) {                            // cannot do self assignment
+               if( mbuf != NULL ) {
+                       rmr_free_msg( mbuf );           // release the old one so we don't leak
+               }
+
+               mrc = soi.mrc;
+               mbuf = soi.mbuf;
+
+               soi.mrc = NULL;
+               soi.mbuf = NULL;
+       }
+
+       return *this;
+}
+
+
 /*
        Destroyer.
 */
-Message::~Message() {
+xapp::Message::~Message() {
        if( mbuf != NULL ) {
                rmr_free_msg( mbuf );
        }
@@ -80,54 +151,55 @@ Message::~Message() {
        This function will return a NULL pointer if malloc fails.
 */
 //char* Message::Copy_payload( ){
-std::unique_ptr<unsigned char> Message::Copy_payload( ){
-       unsigned char*  new_payload = NULL;
+std::unique_ptr<unsigned char> xapp::Message::Copy_payload( ){
 
        if( mbuf != NULL ) {
-               new_payload = (unsigned char *) malloc( sizeof( unsigned char ) * mbuf->len );
+               unsigned char*  new_payload = new unsigned char[mbuf->len];
                memcpy( new_payload, mbuf->payload, mbuf->len );
+               return std::unique_ptr<unsigned char>( new_payload );
        }
 
-       return std::unique_ptr<unsigned char>( new_payload );
+       return NULL;
 }
 
 /*
        Makes a copy of the MEID and returns a smart pointer to it.
 */
-std::unique_ptr<unsigned char> Message::Get_meid(){
+std::unique_ptr<unsigned char> xapp::Message::Get_meid(){
        unsigned char* m = NULL;
 
-       if( m != NULL ) {
-               m = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_MEID );
-               rmr_get_meid( mbuf, m );
-       }
+       m = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_MEID );
+       rmr_get_meid( mbuf, m );
 
        return std::unique_ptr<unsigned char>( m );
 }
 
-int Message::Get_available_size(){
-       if( mbuf != NULL ) {
-               return rmr_payload_size( mbuf );
-       }
-
-       return 0;
+/*
+       Return the total size of the payload (the amount that can be written to
+       as opposed to the portion of the payload which is currently in use.
+       If mbuf isn't valid (nil, or message has a broken header) the return
+       will be -1.
+*/
+int xapp::Message::Get_available_size(){
+       return rmr_payload_size( mbuf );                // rmr can handle a nil pointer
 }
 
-int    Message::Get_mtype(){
+int    xapp::Message::Get_mtype(){
+       int rval = INVALID_MTYPE;
+
        if( mbuf != NULL ) {
-               return mbuf->mtype;
+               rval = mbuf->mtype;
        }
 
-       return INVALID_MTYPE;
+       return rval;
 }
 
 /*
        Makes a copy of the source field and returns a smart pointer to it.
 */
-std::unique_ptr<unsigned char> Message::Get_src(){
-       unsigned char* m = NULL;
+std::unique_ptr<unsigned char> xapp::Message::Get_src(){
+       unsigned char* m = new unsigned char[RMR_MAX_SRC]; 
 
-       m = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_SRC );
        if( m != NULL ) {
                rmr_get_src( mbuf, m );
        }
@@ -135,28 +207,38 @@ std::unique_ptr<unsigned char> Message::Get_src(){
        return std::unique_ptr<unsigned char>( m );
 }
 
-int    Message::Get_state( ){
+int    xapp::Message::Get_state( ){
+       int state = INVALID_STATUS;
+
        if( mbuf != NULL ) {
-               return mbuf->state;
+               state =  mbuf->state;
        }
 
-       return INVALID_STATUS;
+       return state;
 }
 
-int    Message::Get_subid(){
+int    xapp::Message::Get_subid(){
+       int     rval = INVALID_SUBID;
+
        if( mbuf != NULL ) {
-               return mbuf->sub_id;
+               rval =mbuf->sub_id;
        }
 
-       return INVALID_SUBID;
+       return rval;
 }
 
-int    Message::Get_len(){
+/*
+       Return the amount of the payload (bytes) which is used. See
+       Get_available_size() to get the total usable space in the payload.
+*/
+int    xapp::Message::Get_len(){
+       int rval = 0;
+
        if( mbuf != NULL ) {
-               return mbuf->len;
+               rval = mbuf->len;
        }
 
-       return 0;
+       return rval;
 }
 
 /*
@@ -167,7 +249,7 @@ int Message::Get_len(){
        length by calling Message:Get_available_size(), and ensuring that
        writing beyond the indicated size does not happen.
 */
-Msg_component Message::Get_payload(){
+Msg_component xapp::Message::Get_payload(){
        if( mbuf != NULL ) {
                return std::unique_ptr<unsigned char, unfreeable>( mbuf->payload );
        }
@@ -175,19 +257,25 @@ Msg_component Message::Get_payload(){
        return NULL;
 }
 
-void Message::Set_meid( std::unique_ptr<unsigned char> new_meid ) {
+void xapp::Message::Set_meid( std::shared_ptr<unsigned char> new_meid ) {
        if( mbuf != NULL ) {
                rmr_str2meid( mbuf, (unsigned char *) new_meid.get() );
        }
 }
 
-void Message::Set_mtype( int new_type ){
+void xapp::Message::Set_mtype( int new_type ){
        if( mbuf != NULL ) {
                mbuf->mtype = new_type;
        }
 }
 
-void Message::Set_subid( int new_subid ){
+void xapp::Message::Set_len( int new_len ){
+       if( mbuf != NULL  && new_len >= 0 ) {
+               mbuf->len = new_len;
+       }
+}
+
+void xapp::Message::Set_subid( int new_subid ){
        if( mbuf != NULL ) {
                mbuf->sub_id = new_subid;
        }
@@ -201,26 +289,30 @@ void Message::Set_subid( int new_subid ){
        failed with a retry and thus is ready to be processed by RMR.
        Exposed to the user, but not expected to be frequently used.
 */
-bool Message::Send( ) {
-       if( mbuf == NULL ) {
-               return false;
+bool xapp::Message::Send( ) {
+       bool state = false;
+
+       if( mbuf != NULL ) {
+               mbuf =  rmr_send_msg( mrc, mbuf );      // send and pick up new mbuf
+               state = mbuf->state == RMR_OK;          // overall state for caller
        }
 
-       mbuf =  rmr_send_msg( mrc, mbuf );
-       return mbuf->state == RMR_OK;
+       return state;
 }
 
 /*
        Similar to Send(), this assumes that the message is already set up and this is a retry.
        Exposed to the user, but not expected to be frequently used.
 */
-bool Message::Reply( ) {
-       if( mbuf == NULL ) {
-               return false;
+bool xapp::Message::Reply( ) {
+       bool state = false;
+
+       if( mbuf != NULL ) {
+               mbuf =  rmr_rts_msg( mrc, mbuf );               // send and pick up new mbuf
+               state = mbuf->state == RMR_OK;                  // state for caller based on send
        }
 
-       mbuf =  rmr_rts_msg( mrc, mbuf );
-       return mbuf->state == RMR_OK;
+       return state;
 }
 
 /*
@@ -234,32 +326,48 @@ bool Message::Reply( ) {
 
        This is public, but most users should use Send_msg or Send_response functions.
 */
-bool Message::Send( int mtype, int subid, int payload_len, unsigned char* payload, int stype ) {
+bool xapp::Message::Send( int mtype, int subid, int payload_len, unsigned char* payload, int stype, rmr_whid_t whid ) {
+       bool state = false;
 
-       if( mbuf == NULL ) {
-               return false;
-       }
+       if( mbuf != NULL ) {
+               if( mtype != NO_CHANGE ) {
+                       mbuf->mtype = mtype;
+               }
+               if( subid != NO_CHANGE ) {
+                       mbuf->sub_id = subid;
+               }
 
-       mbuf->mtype = mtype;
-       mbuf->sub_id = subid;
-       mbuf->len = payload_len;
+               if( payload_len != NO_CHANGE ) {
+                       mbuf->len = payload_len;
+               }
 
-       if( payload != NULL ) {                 // if we have a payload, ensure msg has room, realloc if needed, then copy
-               mbuf = rmr_realloc_payload( mbuf, payload_len, RMR_NO_COPY, RMR_NO_CLONE );             // ensure message is large enough
-               if( mbuf == NULL ) {
-                       return false;
+               if( payload != NULL ) {                 // if we have a payload, ensure msg has room, realloc if needed, then copy
+                       mbuf = rmr_realloc_payload( mbuf, payload_len, RMR_NO_COPY, RMR_NO_CLONE );             // ensure message is large enough
+                       if( mbuf == NULL ) {
+                               return false;
+                       }
+
+                       memcpy( mbuf->payload, payload, mbuf->len );
                }
 
-               memcpy( mbuf->payload, payload, mbuf->len );
-       }
+               switch( stype ) {
+                       case RESPONSE:
+                               mbuf = rmr_rts_msg( mrc, mbuf );
+                               break;
 
-       if( stype == RESPONSE ) {
-               mbuf = rmr_rts_msg( mrc, mbuf );
-       } else {
-               mbuf = rmr_send_msg( mrc, mbuf );
+                       case MESSAGE:
+                               mbuf = rmr_send_msg( mrc, mbuf );
+                               break;
+
+                       case WORMHOLE_MSG:
+                               mbuf = rmr_wh_send_msg( mrc, whid,  mbuf );
+                               break;
+               }
+
+               state = mbuf->state == RMR_OK;
        }
 
-       return mbuf->state == RMR_OK;
+       return state;
 }
 
 /*
@@ -271,23 +379,23 @@ bool Message::Send( int mtype, int subid, int payload_len, unsigned char* payloa
        The second form of the call allows for a stack allocated buffer (e.g. char foo[120]) to
        be passed as the payload.
 */
-bool Message::Send_response(  int mtype, int subid, int response_len, std::unique_ptr<unsigned char> response ) {
-       return Send( mtype, subid, response_len, response.get(), RESPONSE );
+bool xapp::Message::Send_response(  int mtype, int subid, int response_len, std::shared_ptr<unsigned char> response ) {
+       return Send( mtype, subid, response_len, response.get(), RESPONSE, NO_WHID );
 }
 
-bool Message::Send_response(  int mtype, int subid, int response_len, unsigned char* response ) {
-       return Send( mtype, subid, response_len, response, RESPONSE );
+bool xapp::Message::Send_response(  int mtype, int subid, int response_len, unsigned char* response ) {
+       return Send( mtype, subid, response_len, response, RESPONSE, NO_WHID );
 }
 
 /*
        These allow a response message to be sent without changing the mtype/subid.
 */
-bool Message::Send_response(  int response_len, std::unique_ptr<unsigned char> response ) {
-       return Send( NOCHANGE, NOCHANGE, response_len, response.get(), RESPONSE );
+bool xapp::Message::Send_response(  int response_len, std::shared_ptr<unsigned char> response ) {
+       return Send( NO_CHANGE, NO_CHANGE, response_len, response.get(), RESPONSE, NO_WHID );
 }
 
-bool Message::Send_response(  int response_len, unsigned char* response ) {
-       return Send( NOCHANGE, NOCHANGE, response_len, response, RESPONSE );
+bool xapp::Message::Send_response(  int response_len, unsigned char* response ) {
+       return Send( NO_CHANGE, NO_CHANGE, response_len, response, RESPONSE, NO_WHID );
 }
 
 
@@ -300,21 +408,35 @@ bool Message::Send_response(  int response_len, unsigned char* response ) {
        Return is a new mbuf suitable for sending another message, or the original buffer with
        a bad state sent if there was a failure.
 */
-bool Message::Send_msg(  int mtype, int subid, int payload_len, std::unique_ptr<unsigned char> payload ) {
-       return Send( mtype, subid, payload_len, payload.get(), MESSAGE );
+bool xapp::Message::Send_msg(  int mtype, int subid, int payload_len, std::shared_ptr<unsigned char> payload ) {
+       return Send( mtype, subid, payload_len, payload.get(), MESSAGE, NO_WHID );
 }
 
-bool Message::Send_msg(  int mtype, int subid, int payload_len, unsigned char* payload ) {
-       return Send( mtype, subid, payload_len, payload, MESSAGE );
+bool xapp::Message::Send_msg(  int mtype, int subid, int payload_len, unsigned char* payload ) {
+       return Send( mtype, subid, payload_len, payload, MESSAGE, NO_WHID );
 }
 
 /*
        Similar send functions that allow the message type/subid to remain unchanged
 */
-bool Message::Send_msg(  int payload_len, std::unique_ptr<unsigned char> payload ) {
-       return Send( NOCHANGE, NOCHANGE, payload_len, payload.get(), MESSAGE );
+bool xapp::Message::Send_msg(  int payload_len, std::shared_ptr<unsigned char> payload ) {
+       return Send( NO_CHANGE, NO_CHANGE, payload_len, payload.get(), MESSAGE, NO_WHID );
+}
+
+bool xapp::Message::Send_msg(  int payload_len, unsigned char* payload ) {
+       return Send( NO_CHANGE, NO_CHANGE, payload_len, payload, MESSAGE, NO_WHID );
 }
 
-bool Message::Send_msg(  int payload_len, unsigned char* payload ) {
-       return Send( NOCHANGE, NOCHANGE, payload_len, payload, MESSAGE );
+
+/*
+       Wormhole send allows an xAPP to send a message directly based on an existing
+       wormhole ID (use xapp::Wormhole_open() to get one). Wormholes should NOT be
+       used for reponse messages, but are intended for things like route tables and
+       alarm messages where routing doesn't exist/apply.
+*/
+bool xapp::Message::Wormhole_send( int whid, int mtype, int subid, int payload_len, std::shared_ptr<unsigned char> payload ) {
+       return Send( mtype, subid, payload_len, payload.get(), WORMHOLE_MSG, whid );
 }
+
+
+} // namespace