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 this->mrc = mrc; // the message router context for sends
60 xapp::Message::Message( void* mrc, int payload_len ) {
62 this->mbuf = rmr_alloc_msg( mrc, payload_len );
66 Copy builder. Given a source object instance (soi), create a copy.
67 Creating a copy should be avoided as it can be SLOW!
69 xapp::Message::Message( const Message& soi ) {
73 payload_size = rmr_payload_size( soi.mbuf ); // rmr can handle a nil pointer
74 mbuf = rmr_realloc_payload( soi.mbuf, payload_size, RMR_COPY, RMR_CLONE );
78 Assignment operator. Simiolar to the copycat, but "this" object exists and
79 may have data that needs to be released prior to making a copy of the soi.
81 Message& xapp::Message::operator=( const Message& soi ) {
84 if( this != &soi ) { // cannot do self assignment
86 rmr_free_msg( mbuf ); // release the old one so we don't leak
89 payload_size = rmr_payload_size( soi.mbuf ); // rmr can handle a nil pointer
91 mbuf = rmr_realloc_payload( soi.mbuf, payload_size, RMR_COPY, RMR_CLONE );
98 Move builder. Given a source object instance (soi), move the information from
99 the soi ensuring that the destriction of the soi doesn't trash things from
102 xapp::Message::Message( Message&& soi ) {
106 soi.mrc = NULL; // prevent closing of RMR stuff on soi destroy
111 Move Assignment operator. Move the message data to the existing object
112 ensure the object reference is cleaned up, and ensuring that the source
113 object references are removed.
115 Message& xapp::Message::operator=( Message&& soi ) {
116 if( this != &soi ) { // cannot do self assignment
118 rmr_free_msg( mbuf ); // release the old one so we don't leak
135 xapp::Message::~Message() {
137 rmr_free_msg( mbuf );
144 // --- getters/setters -----------------------------------------------------
146 Copy the payload bytes, and return a smart pointer (unique) to it.
147 If the application needs to update the payload in place for a return
148 to sender call, or just to access the payload in a more efficent manner
149 (without the copy), the Get_payload() function should be considered.
151 This function will return a NULL pointer if malloc fails.
153 //char* Message::Copy_payload( ){
154 std::unique_ptr<unsigned char> xapp::Message::Copy_payload( ){
155 unsigned char* new_payload = NULL;
158 new_payload = (unsigned char *) malloc( sizeof( unsigned char ) * mbuf->len );
159 memcpy( new_payload, mbuf->payload, mbuf->len );
162 return std::unique_ptr<unsigned char>( new_payload );
166 Makes a copy of the MEID and returns a smart pointer to it.
168 std::unique_ptr<unsigned char> xapp::Message::Get_meid(){
169 unsigned char* m = NULL;
171 m = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_MEID );
172 rmr_get_meid( mbuf, m );
174 return std::unique_ptr<unsigned char>( m );
178 Return the total size of the payload (the amount that can be written to
179 as opposed to the portion of the payload which is currently in use.
180 If mbuf isn't valid (nil, or message has a broken header) the return
183 int xapp::Message::Get_available_size(){
184 return rmr_payload_size( mbuf ); // rmr can handle a nil pointer
187 int xapp::Message::Get_mtype(){
188 int rval = INVALID_MTYPE;
198 Makes a copy of the source field and returns a smart pointer to it.
200 std::unique_ptr<unsigned char> xapp::Message::Get_src(){
201 unsigned char* m = NULL;
203 m = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_SRC );
204 memset( m, 0, sizeof( unsigned char ) * RMR_MAX_SRC );
207 rmr_get_src( mbuf, m );
210 return std::unique_ptr<unsigned char>( m );
213 int xapp::Message::Get_state( ){
214 int state = INVALID_STATUS;
223 int xapp::Message::Get_subid(){
224 int rval = INVALID_SUBID;
234 Return the amount of the payload (bytes) which is used. See
235 Get_available_size() to get the total usable space in the payload.
237 int xapp::Message::Get_len(){
248 This returns a smart (unique) pointer to the payload portion of the
249 message. This provides the user application with the means to
250 update the payload in place to avoid multiple copies. The
251 user programme is responsible to determing the usable payload
252 length by calling Message:Get_available_size(), and ensuring that
253 writing beyond the indicated size does not happen.
255 Msg_component xapp::Message::Get_payload(){
257 return std::unique_ptr<unsigned char, unfreeable>( mbuf->payload );
263 void xapp::Message::Set_meid( std::shared_ptr<unsigned char> new_meid ) {
265 rmr_str2meid( mbuf, (unsigned char *) new_meid.get() );
269 void xapp::Message::Set_mtype( int new_type ){
271 mbuf->mtype = new_type;
275 void xapp::Message::Set_len( int new_len ){
276 if( mbuf != NULL && new_len >= 0 ) {
281 void xapp::Message::Set_subid( int new_subid ){
283 mbuf->sub_id = new_subid;
288 // -------------- send functions ---------------------------------
291 This assumes that the contents of the mbuf were set by either a send attempt that
292 failed with a retry and thus is ready to be processed by RMR.
293 Exposed to the user, but not expected to be frequently used.
295 bool xapp::Message::Send( ) {
299 mbuf = rmr_send_msg( mrc, mbuf ); // send and pick up new mbuf
300 state = mbuf->state == RMR_OK; // overall state for caller
307 Similar to Send(), this assumes that the message is already set up and this is a retry.
308 Exposed to the user, but not expected to be frequently used.
310 bool xapp::Message::Reply( ) {
314 mbuf = rmr_rts_msg( mrc, mbuf ); // send and pick up new mbuf
315 state = mbuf->state == RMR_OK; // state for caller based on send
323 This will setup the message (type etc.) ensure the message payload space is
324 large enough and copy in the payload (if a new payload is given), then will
325 either send or rts the message based on the stype parm.
327 If payload is nil, then we assume the user updated the payload in place and
330 This is public, but most users should use Send_msg or Send_response functions.
332 bool xapp::Message::Send( int mtype, int subid, int payload_len, unsigned char* payload, int stype, rmr_whid_t whid ) {
336 if( mtype != NO_CHANGE ) {
339 if( subid != NO_CHANGE ) {
340 mbuf->sub_id = subid;
343 if( payload_len != NO_CHANGE ) {
344 mbuf->len = payload_len;
347 if( payload != NULL ) { // if we have a payload, ensure msg has room, realloc if needed, then copy
348 mbuf = rmr_realloc_payload( mbuf, payload_len, RMR_NO_COPY, RMR_NO_CLONE ); // ensure message is large enough
353 memcpy( mbuf->payload, payload, mbuf->len );
358 mbuf = rmr_rts_msg( mrc, mbuf );
362 mbuf = rmr_send_msg( mrc, mbuf );
366 mbuf = rmr_wh_send_msg( mrc, whid, mbuf );
370 state = mbuf->state == RMR_OK;
377 Send a response to the endpoint that sent the original message.
379 Response can be null and the assumption will be that the message payload
380 was updated in place and no additional copy is needed before sending the message.
382 The second form of the call allows for a stack allocated buffer (e.g. char foo[120]) to
383 be passed as the payload.
385 bool xapp::Message::Send_response( int mtype, int subid, int response_len, std::shared_ptr<unsigned char> response ) {
386 return Send( mtype, subid, response_len, response.get(), RESPONSE, NO_WHID );
389 bool xapp::Message::Send_response( int mtype, int subid, int response_len, unsigned char* response ) {
390 return Send( mtype, subid, response_len, response, RESPONSE, NO_WHID );
394 These allow a response message to be sent without changing the mtype/subid.
396 bool xapp::Message::Send_response( int response_len, std::shared_ptr<unsigned char> response ) {
397 return Send( NO_CHANGE, NO_CHANGE, response_len, response.get(), RESPONSE, NO_WHID );
400 bool xapp::Message::Send_response( int response_len, unsigned char* response ) {
401 return Send( NO_CHANGE, NO_CHANGE, response_len, response, RESPONSE, NO_WHID );
406 Send a message based on message type routing.
408 Payload can be null and the assumption will be that the message payload
409 was updated in place and no additional copy is needed before sending the message.
411 Return is a new mbuf suitable for sending another message, or the original buffer with
412 a bad state sent if there was a failure.
414 bool xapp::Message::Send_msg( int mtype, int subid, int payload_len, std::shared_ptr<unsigned char> payload ) {
415 return Send( mtype, subid, payload_len, payload.get(), MESSAGE, NO_WHID );
418 bool xapp::Message::Send_msg( int mtype, int subid, int payload_len, unsigned char* payload ) {
419 return Send( mtype, subid, payload_len, payload, MESSAGE, NO_WHID );
423 Similar send functions that allow the message type/subid to remain unchanged
425 bool xapp::Message::Send_msg( int payload_len, std::shared_ptr<unsigned char> payload ) {
426 return Send( NO_CHANGE, NO_CHANGE, payload_len, payload.get(), MESSAGE, NO_WHID );
429 bool xapp::Message::Send_msg( int payload_len, unsigned char* payload ) {
430 return Send( NO_CHANGE, NO_CHANGE, payload_len, payload, MESSAGE, NO_WHID );
435 Wormhole send allows an xAPP to send a message directly based on an existing
436 wormhole ID (use xapp::Wormhole_open() to get one). Wormholes should NOT be
437 used for reponse messages, but are intended for things like route tables and
438 alarm messages where routing doesn't exist/apply.
440 bool xapp::Message::Wormhole_send( int whid, int mtype, int subid, int payload_len, std::shared_ptr<unsigned char> payload ) {
441 return Send( mtype, subid, payload_len, payload.get(), WORMHOLE_MSG, whid );