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"
44 // --------------- private ------------------------------------------------
46 // --------------- builders/operators -------------------------------------
49 Create a new message wrapper for an existing RMR msg buffer.
51 Message::Message( rmr_mbuf_t* mbuf, void* mrc ) {
52 this->mrc = mrc; // the message router context for sends
56 Message::Message( void* mrc, int payload_len ) {
58 this->mbuf = rmr_alloc_msg( mrc, payload_len );
62 Copy builder. Given a source object instance (soi), create a copy.
63 Creating a copy should be avoided as it can be SLOW!
65 Message::Message( const Message& soi ) {
69 payload_size = rmr_payload_size( soi.mbuf ); // rmr can handle a nil pointer
70 mbuf = rmr_realloc_payload( soi.mbuf, payload_size, RMR_COPY, RMR_CLONE );
74 Assignment operator. Simiolar to the copycat, but "this" object exists and
75 may have data that needs to be released prior to making a copy of the soi.
77 Message& Message::operator=( const Message& soi ) {
80 if( this != &soi ) { // cannot do self assignment
82 rmr_free_msg( mbuf ); // release the old one so we don't leak
85 payload_size = rmr_payload_size( soi.mbuf ); // rmr can handle a nil pointer
87 mbuf = rmr_realloc_payload( soi.mbuf, payload_size, RMR_COPY, RMR_CLONE );
94 Move builder. Given a source object instance (soi), move the information from
95 the soi ensuring that the destriction of the soi doesn't trash things from
98 Message::Message( Message&& soi ) {
102 soi.mrc = NULL; // prevent closing of RMR stuff on soi destroy
107 Move Assignment operator. Move the message data to the existing object
108 ensure the object reference is cleaned up, and ensuring that the source
109 object references are removed.
111 Message& Message::operator=( Message&& soi ) {
112 if( this != &soi ) { // cannot do self assignment
114 rmr_free_msg( mbuf ); // release the old one so we don't leak
131 Message::~Message() {
133 rmr_free_msg( mbuf );
140 // --- getters/setters -----------------------------------------------------
142 Copy the payload bytes, and return a smart pointer (unique) to it.
143 If the application needs to update the payload in place for a return
144 to sender call, or just to access the payload in a more efficent manner
145 (without the copy), the Get_payload() function should be considered.
147 This function will return a NULL pointer if malloc fails.
149 //char* Message::Copy_payload( ){
150 std::unique_ptr<unsigned char> Message::Copy_payload( ){
151 unsigned char* new_payload = NULL;
154 new_payload = (unsigned char *) malloc( sizeof( unsigned char ) * mbuf->len );
155 memcpy( new_payload, mbuf->payload, mbuf->len );
158 return std::unique_ptr<unsigned char>( new_payload );
162 Makes a copy of the MEID and returns a smart pointer to it.
164 std::unique_ptr<unsigned char> Message::Get_meid(){
165 unsigned char* m = NULL;
167 m = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_MEID );
168 rmr_get_meid( mbuf, m );
170 return std::unique_ptr<unsigned char>( m );
174 Return the total size of the payload (the amount that can be written to
175 as opposed to the portion of the payload which is currently in use.
176 If mbuf isn't valid (nil, or message has a broken header) the return
179 int Message::Get_available_size(){
180 return rmr_payload_size( mbuf ); // rmr can handle a nil pointer
183 int Message::Get_mtype(){
184 int rval = INVALID_MTYPE;
194 Makes a copy of the source field and returns a smart pointer to it.
196 std::unique_ptr<unsigned char> Message::Get_src(){
197 unsigned char* m = NULL;
199 m = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_SRC );
200 memset( m, 0, sizeof( unsigned char ) * RMR_MAX_SRC );
203 rmr_get_src( mbuf, m );
206 return std::unique_ptr<unsigned char>( m );
209 int Message::Get_state( ){
210 int state = INVALID_STATUS;
219 int Message::Get_subid(){
220 int rval = INVALID_SUBID;
230 Return the amount of the payload (bytes) which is used. See
231 Get_available_size() to get the total usable space in the payload.
233 int Message::Get_len(){
244 This returns a smart (unique) pointer to the payload portion of the
245 message. This provides the user application with the means to
246 update the payload in place to avoid multiple copies. The
247 user programme is responsible to determing the usable payload
248 length by calling Message:Get_available_size(), and ensuring that
249 writing beyond the indicated size does not happen.
251 Msg_component Message::Get_payload(){
253 return std::unique_ptr<unsigned char, unfreeable>( mbuf->payload );
259 void Message::Set_meid( std::shared_ptr<unsigned char> new_meid ) {
261 rmr_str2meid( mbuf, (unsigned char *) new_meid.get() );
265 void Message::Set_mtype( int new_type ){
267 mbuf->mtype = new_type;
271 void Message::Set_len( int new_len ){
272 if( mbuf != NULL && new_len >= 0 ) {
277 void Message::Set_subid( int new_subid ){
279 mbuf->sub_id = new_subid;
284 // -------------- send functions ---------------------------------
287 This assumes that the contents of the mbuf were set by either a send attempt that
288 failed with a retry and thus is ready to be processed by RMR.
289 Exposed to the user, but not expected to be frequently used.
291 bool Message::Send( ) {
295 mbuf = rmr_send_msg( mrc, mbuf ); // send and pick up new mbuf
296 state = mbuf->state == RMR_OK; // overall state for caller
303 Similar to Send(), this assumes that the message is already set up and this is a retry.
304 Exposed to the user, but not expected to be frequently used.
306 bool Message::Reply( ) {
310 mbuf = rmr_rts_msg( mrc, mbuf ); // send and pick up new mbuf
311 state = mbuf->state == RMR_OK; // state for caller based on send
319 This will setup the message (type etc.) ensure the message payload space is
320 large enough and copy in the payload (if a new payload is given), then will
321 either send or rts the message based on the stype parm.
323 If payload is nil, then we assume the user updated the payload in place and
326 This is public, but most users should use Send_msg or Send_response functions.
328 bool Message::Send( int mtype, int subid, int payload_len, unsigned char* payload, int stype ) {
332 if( mtype != NO_CHANGE ) {
335 if( subid != NO_CHANGE ) {
336 mbuf->sub_id = subid;
339 if( payload_len != NO_CHANGE ) {
340 mbuf->len = payload_len;
343 if( payload != NULL ) { // if we have a payload, ensure msg has room, realloc if needed, then copy
344 mbuf = rmr_realloc_payload( mbuf, payload_len, RMR_NO_COPY, RMR_NO_CLONE ); // ensure message is large enough
349 memcpy( mbuf->payload, payload, mbuf->len );
352 if( stype == RESPONSE ) {
353 mbuf = rmr_rts_msg( mrc, mbuf );
355 mbuf = rmr_send_msg( mrc, mbuf );
358 state = mbuf->state == RMR_OK;
365 Send a response to the endpoint that sent the original message.
367 Response can be null and the assumption will be that the message payload
368 was updated in place and no additional copy is needed before sending the message.
370 The second form of the call allows for a stack allocated buffer (e.g. char foo[120]) to
371 be passed as the payload.
373 bool Message::Send_response( int mtype, int subid, int response_len, std::shared_ptr<unsigned char> response ) {
374 return Send( mtype, subid, response_len, response.get(), RESPONSE );
377 bool Message::Send_response( int mtype, int subid, int response_len, unsigned char* response ) {
378 return Send( mtype, subid, response_len, response, RESPONSE );
382 These allow a response message to be sent without changing the mtype/subid.
384 bool Message::Send_response( int response_len, std::shared_ptr<unsigned char> response ) {
385 return Send( NO_CHANGE, NO_CHANGE, response_len, response.get(), RESPONSE );
388 bool Message::Send_response( int response_len, unsigned char* response ) {
389 return Send( NO_CHANGE, NO_CHANGE, response_len, response, RESPONSE );
394 Send a message based on message type routing.
396 Payload can be null and the assumption will be that the message payload
397 was updated in place and no additional copy is needed before sending the message.
399 Return is a new mbuf suitable for sending another message, or the original buffer with
400 a bad state sent if there was a failure.
402 bool Message::Send_msg( int mtype, int subid, int payload_len, std::shared_ptr<unsigned char> payload ) {
403 return Send( mtype, subid, payload_len, payload.get(), MESSAGE );
406 bool Message::Send_msg( int mtype, int subid, int payload_len, unsigned char* payload ) {
407 return Send( mtype, subid, payload_len, payload, MESSAGE );
411 Similar send functions that allow the message type/subid to remain unchanged
413 bool Message::Send_msg( int payload_len, std::shared_ptr<unsigned char> payload ) {
414 return Send( NO_CHANGE, NO_CHANGE, payload_len, payload.get(), MESSAGE );
417 bool Message::Send_msg( int payload_len, unsigned char* payload ) {
418 return Send( NO_CHANGE, NO_CHANGE, payload_len, payload, MESSAGE );