#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 );
}
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() 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<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() 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<unsigned char> Message::Get_src(){
- unsigned char* m = NULL;
+std::unique_ptr<unsigned char> 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 );
}
return std::unique_ptr<unsigned char>( 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;
}
/*
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<unsigned char, unfreeable>( mbuf->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() );
+ 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;
}
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;
}
/*
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;
}
/*
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 );
}
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