3 ==================================================================================
4 Copyright (c) 2020 Nokia
5 Copyright (c) 2020 AT&T Intellectual Property.
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
11 http://www.apache.org/licenses/LICENSE-2.0
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18 ==================================================================================
23 Abstract: A message wrapper. This should completely hide the
24 underlying transport (RMR) message structure from
25 the user application. For the most part, the getters
26 are used by the framwork; it is unlikely that other
27 than adding/extracting the MEID, the user app will
28 be completely unaware of information that is not
29 presented in the callback parms.
32 Author: E. Scott Daniels
42 #include "message.hpp"
48 // --------------- private ------------------------------------------------
50 // --------------- builders/operators -------------------------------------
53 Create a new message wrapper for an existing RMR msg buffer.
55 xapp::Message::Message( rmr_mbuf_t* mbuf, void* mrc ) :
56 mrc( mrc ), // the message router context for sends
60 xapp::Message::Message( void* rmr_ctx, int payload_len ) :
61 mrc( rmr_ctx ), // the message router context for sends
62 mbuf( rmr_alloc_msg( rmr_ctx, payload_len ) )
67 Copy builder. Given a source object instance (soi), create a copy.
68 Creating a copy should be avoided as it can be SLOW!
70 xapp::Message::Message( const Message& soi ) :
75 payload_size = rmr_payload_size( soi.mbuf ); // rmr can handle a nil pointer
76 mbuf = rmr_realloc_payload( soi.mbuf, payload_size, RMR_COPY, RMR_CLONE );
80 Assignment operator. Simiolar to the copycat, but "this" object exists and
81 may have data that needs to be released prior to making a copy of the soi.
83 Message& xapp::Message::operator=( const Message& soi ) {
86 if( this != &soi ) { // cannot do self assignment
88 rmr_free_msg( mbuf ); // release the old one so we don't leak
91 payload_size = rmr_payload_size( soi.mbuf ); // rmr can handle a nil pointer
93 mbuf = rmr_realloc_payload( soi.mbuf, payload_size, RMR_COPY, RMR_CLONE );
100 Move builder. Given a source object instance (soi), move the information from
101 the soi ensuring that the destriction of the soi doesn't trash things from
104 xapp::Message::Message( Message&& soi ) :
108 soi.mrc = NULL; // prevent closing of RMR stuff on soi destroy
113 Move Assignment operator. Move the message data to the existing object
114 ensure the object reference is cleaned up, and ensuring that the source
115 object references are removed.
117 Message& xapp::Message::operator=( Message&& soi ) {
118 if( this != &soi ) { // cannot do self assignment
120 rmr_free_msg( mbuf ); // release the old one so we don't leak
137 xapp::Message::~Message() {
139 rmr_free_msg( mbuf );
146 // --- getters/setters -----------------------------------------------------
148 Copy the payload bytes, and return a smart pointer (unique) to it.
149 If the application needs to update the payload in place for a return
150 to sender call, or just to access the payload in a more efficent manner
151 (without the copy), the Get_payload() function should be considered.
153 This function will return a NULL pointer if malloc fails.
155 //char* Message::Copy_payload( ){
156 std::unique_ptr<unsigned char> xapp::Message::Copy_payload( ){
159 unsigned char* new_payload = new unsigned char[mbuf->len];
160 memcpy( new_payload, mbuf->payload, mbuf->len );
161 return std::unique_ptr<unsigned char>( new_payload );
168 Makes a copy of the MEID and returns a smart pointer to it.
170 std::unique_ptr<unsigned char> xapp::Message::Get_meid() const {
171 unsigned char* m = NULL;
173 m = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_MEID );
174 rmr_get_meid( mbuf, m );
176 return std::unique_ptr<unsigned char>( m );
180 Return the total size of the payload (the amount that can be written to
181 as opposed to the portion of the payload which is currently in use.
182 If mbuf isn't valid (nil, or message has a broken header) the return
185 int xapp::Message::Get_available_size() const {
186 return rmr_payload_size( mbuf ); // rmr can handle a nil pointer
189 int xapp::Message::Get_mtype() const {
190 int rval = INVALID_MTYPE;
200 Makes a copy of the source field and returns a smart pointer to it.
202 std::unique_ptr<unsigned char> xapp::Message::Get_src() const {
203 unsigned char* m = new unsigned char[RMR_MAX_SRC];
206 rmr_get_src( mbuf, m );
209 return std::unique_ptr<unsigned char>( m );
212 int xapp::Message::Get_state( ) const {
213 int state = INVALID_STATUS;
222 int xapp::Message::Get_subid() const {
223 int rval = INVALID_SUBID;
233 Return the amount of the payload (bytes) which is used. See
234 Get_available_size() to get the total usable space in the payload.
236 int xapp::Message::Get_len() const {
247 This returns a smart (unique) pointer to the payload portion of the
248 message. This provides the user application with the means to
249 update the payload in place to avoid multiple copies. The
250 user programme is responsible to determing the usable payload
251 length by calling Message:Get_available_size(), and ensuring that
252 writing beyond the indicated size does not happen.
254 Msg_component xapp::Message::Get_payload() const {
256 return std::unique_ptr<unsigned char, unfreeable>( mbuf->payload );
262 void xapp::Message::Set_meid( std::shared_ptr<unsigned char> new_meid ) {
264 rmr_str2meid( mbuf, new_meid.get() );
268 void xapp::Message::Set_mtype( int new_type ){
270 mbuf->mtype = new_type;
274 void xapp::Message::Set_len( int new_len ){
275 if( mbuf != NULL && new_len >= 0 ) {
280 void xapp::Message::Set_subid( int new_subid ){
282 mbuf->sub_id = new_subid;
287 // -------------- send functions ---------------------------------
290 This assumes that the contents of the mbuf were set by either a send attempt that
291 failed with a retry and thus is ready to be processed by RMR.
292 Exposed to the user, but not expected to be frequently used.
294 bool xapp::Message::Send( ) {
298 mbuf = rmr_send_msg( mrc, mbuf ); // send and pick up new mbuf
299 state = mbuf->state == RMR_OK; // overall state for caller
306 Similar to Send(), this assumes that the message is already set up and this is a retry.
307 Exposed to the user, but not expected to be frequently used.
309 bool xapp::Message::Reply( ) {
313 mbuf = rmr_rts_msg( mrc, mbuf ); // send and pick up new mbuf
314 state = mbuf->state == RMR_OK; // state for caller based on send
322 This will setup the message (type etc.) ensure the message payload space is
323 large enough and copy in the payload (if a new payload is given), then will
324 either send or rts the message based on the stype parm.
326 If payload is nil, then we assume the user updated the payload in place and
329 This is public, but most users should use Send_msg or Send_response functions.
331 bool xapp::Message::Send( int mtype, int subid, int payload_len, unsigned char* payload, int stype, rmr_whid_t whid ) {
335 if( mtype != NO_CHANGE ) {
338 if( subid != NO_CHANGE ) {
339 mbuf->sub_id = subid;
342 if( payload_len != NO_CHANGE ) {
343 mbuf->len = payload_len;
346 if( payload != NULL ) { // if we have a payload, ensure msg has room, realloc if needed, then copy
347 mbuf = rmr_realloc_payload( mbuf, payload_len, RMR_NO_COPY, RMR_NO_CLONE ); // ensure message is large enough
352 memcpy( mbuf->payload, payload, mbuf->len );
357 mbuf = rmr_rts_msg( mrc, mbuf );
361 mbuf = rmr_send_msg( mrc, mbuf );
365 mbuf = rmr_wh_send_msg( mrc, whid, mbuf );
369 break; // because sonar doesn't like defaultless switches even when there is no work :(
372 state = mbuf->state == RMR_OK;
379 Send a response to the endpoint that sent the original message.
381 Response can be null and the assumption will be that the message payload
382 was updated in place and no additional copy is needed before sending the message.
384 The second form of the call allows for a stack allocated buffer (e.g. char foo[120]) to
385 be passed as the payload.
387 bool xapp::Message::Send_response( int mtype, int subid, int response_len, std::shared_ptr<unsigned char> response ) {
388 return Send( mtype, subid, response_len, response.get(), RESPONSE, NO_WHID );
391 bool xapp::Message::Send_response( int mtype, int subid, int response_len, unsigned char* response ) {
392 return Send( mtype, subid, response_len, response, RESPONSE, NO_WHID );
396 These allow a response message to be sent without changing the mtype/subid.
398 bool xapp::Message::Send_response( int response_len, std::shared_ptr<unsigned char> response ) {
399 return Send( NO_CHANGE, NO_CHANGE, response_len, response.get(), RESPONSE, NO_WHID );
402 bool xapp::Message::Send_response( int response_len, unsigned char* response ) {
403 return Send( NO_CHANGE, NO_CHANGE, response_len, response, RESPONSE, NO_WHID );
408 Send a message based on message type routing.
410 Payload can be null and the assumption will be that the message payload
411 was updated in place and no additional copy is needed before sending the message.
413 Return is a new mbuf suitable for sending another message, or the original buffer with
414 a bad state sent if there was a failure.
416 bool xapp::Message::Send_msg( int mtype, int subid, int payload_len, std::shared_ptr<unsigned char> payload ) {
417 return Send( mtype, subid, payload_len, payload.get(), MESSAGE, NO_WHID );
420 bool xapp::Message::Send_msg( int mtype, int subid, int payload_len, unsigned char* payload ) {
421 return Send( mtype, subid, payload_len, payload, MESSAGE, NO_WHID );
425 Similar send functions that allow the message type/subid to remain unchanged
427 bool xapp::Message::Send_msg( int payload_len, std::shared_ptr<unsigned char> payload ) {
428 return Send( NO_CHANGE, NO_CHANGE, payload_len, payload.get(), MESSAGE, NO_WHID );
431 bool xapp::Message::Send_msg( int payload_len, unsigned char* payload ) {
432 return Send( NO_CHANGE, NO_CHANGE, payload_len, payload, MESSAGE, NO_WHID );
437 Wormhole send allows an xAPP to send a message directly based on an existing
438 wormhole ID (use xapp::Wormhole_open() to get one). Wormholes should NOT be
439 used for reponse messages, but are intended for things like route tables and
440 alarm messages where routing doesn't exist/apply.
442 bool xapp::Message::Wormhole_send( int whid, int mtype, int subid, int payload_len, std::shared_ptr<unsigned char> payload ) {
443 return Send( mtype, subid, payload_len, payload.get(), WORMHOLE_MSG, whid );