X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;ds=inline;f=src%2Fmessaging%2Fmessage.cpp;h=bd11602a748011bc86b6718a1022ce9d6cb8d263;hb=refs%2Fheads%2Fg-release;hp=0c6b262e617226eff9a4e1e5fa586118e22a355f;hpb=8cb3c6f5d5062b83f17a5739e0671490beb543de;p=ric-plt%2Fxapp-frame-cpp.git diff --git a/src/messaging/message.cpp b/src/messaging/message.cpp index 0c6b262..bd11602 100644 --- a/src/messaging/message.cpp +++ b/src/messaging/message.cpp @@ -41,27 +41,100 @@ #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 ) { - this->mrc = mrc; // the message router context for sends - this->mbuf = mbuf; +xapp::Message::Message( rmr_mbuf_t* mbuf, void* mrc ) : + mrc( mrc ), // the message router context for sends + mbuf( mbuf ) +{ /* empty body */ } + +xapp::Message::Message( void* rmr_ctx, int payload_len ) : + mrc( rmr_ctx ), // the message router context for sends + mbuf( rmr_alloc_msg( rmr_ctx, payload_len ) ) +{ /* empty body */ } + + +/* + 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 ) : + mrc( soi.mrc ) +{ + int payload_size; + + 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 ); } -Message::Message( void* mrc, int payload_len ) { - this->mrc = mrc; - this->mbuf = rmr_alloc_msg( mrc, payload_len ); +/* + 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 +153,55 @@ Message::~Message() { This function will return a NULL pointer if malloc fails. */ //char* Message::Copy_payload( ){ -std::unique_ptr Message::Copy_payload( ){ - unsigned char* new_payload = NULL; +std::unique_ptr 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( new_payload ); } - return std::unique_ptr( new_payload ); + return NULL; } /* Makes a copy of the MEID and returns a smart pointer to it. */ -std::unique_ptr Message::Get_meid(){ +std::unique_ptr xapp::Message::Get_meid() const { 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( 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() const { + return rmr_payload_size( mbuf ); // rmr can handle a nil pointer } -int Message::Get_mtype(){ +int xapp::Message::Get_mtype() const { + 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 Message::Get_src(){ - unsigned char* m = NULL; +std::unique_ptr xapp::Message::Get_src() const { + 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 +209,38 @@ std::unique_ptr Message::Get_src(){ return std::unique_ptr( m ); } -int Message::Get_state( ){ +int xapp::Message::Get_state( ) const { + 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() const { + 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() const { + int rval = 0; + if( mbuf != NULL ) { - return mbuf->len; + rval = mbuf->len; } - return 0; + return rval; } /* @@ -167,7 +251,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() const { if( mbuf != NULL ) { return std::unique_ptr( mbuf->payload ); } @@ -175,19 +259,25 @@ Msg_component Message::Get_payload(){ return NULL; } -void Message::Set_meid( std::unique_ptr new_meid ) { +void xapp::Message::Set_meid( std::shared_ptr new_meid ) { if( mbuf != NULL ) { - rmr_str2meid( mbuf, (unsigned char *) new_meid.get() ); + rmr_str2meid( mbuf, 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 +291,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 +328,51 @@ 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; + } + + if( payload_len != NO_CHANGE ) { + mbuf->len = payload_len; + } - mbuf->mtype = mtype; - mbuf->sub_id = subid; - 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; + + case MESSAGE: + mbuf = rmr_send_msg( mrc, mbuf ); + break; - if( stype == RESPONSE ) { - mbuf = rmr_rts_msg( mrc, mbuf ); - } else { - mbuf = rmr_send_msg( mrc, mbuf ); + case WORMHOLE_MSG: + mbuf = rmr_wh_send_msg( mrc, whid, mbuf ); + break; + + default: + break; // because sonar doesn't like defaultless switches even when there is no work :( + } + + state = mbuf->state == RMR_OK; } - return mbuf->state == RMR_OK; + return state; } /* @@ -271,23 +384,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 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 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 response ) { - return Send( NOCHANGE, NOCHANGE, response_len, response.get(), RESPONSE ); +bool xapp::Message::Send_response( int response_len, std::shared_ptr 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 +413,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 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 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 payload ) { - return Send( NOCHANGE, NOCHANGE, payload_len, payload.get(), MESSAGE ); +bool xapp::Message::Send_msg( int payload_len, std::shared_ptr 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 payload ) { + return Send( mtype, subid, payload_len, payload.get(), WORMHOLE_MSG, whid ); } + + +} // namespace