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 -----------------------------------------------
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 );
73 // --- getters/setters -----------------------------------------------------
75 Copy the payload bytes, and return a smart pointer (unique) to it.
76 If the application needs to update the payload in place for a return
77 to sender call, or just to access the payload in a more efficent manner
78 (without the copy), the Get_payload() function should be considered.
80 This function will return a NULL pointer if malloc fails.
82 //char* Message::Copy_payload( ){
83 std::unique_ptr<unsigned char> Message::Copy_payload( ){
84 unsigned char* new_payload = NULL;
87 new_payload = (unsigned char *) malloc( sizeof( unsigned char ) * mbuf->len );
88 memcpy( new_payload, mbuf->payload, mbuf->len );
91 return std::unique_ptr<unsigned char>( new_payload );
95 Makes a copy of the MEID and returns a smart pointer to it.
97 std::unique_ptr<unsigned char> Message::Get_meid(){
98 unsigned char* m = NULL;
100 m = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_MEID );
101 rmr_get_meid( mbuf, m );
103 return std::unique_ptr<unsigned char>( m );
107 Return the total size of the payload (the amount that can be written to
108 as opposed to the portion of the payload which is currently in use.
109 If mbuf isn't valid (nil, or message has a broken header) the return
112 int Message::Get_available_size(){
113 return rmr_payload_size( mbuf ); // rmr can handle a nil pointer
116 int Message::Get_mtype(){
117 int rval = INVALID_MTYPE;
127 Makes a copy of the source field and returns a smart pointer to it.
129 std::unique_ptr<unsigned char> Message::Get_src(){
130 unsigned char* m = NULL;
132 m = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_SRC );
133 memset( m, 0, sizeof( unsigned char ) * RMR_MAX_SRC );
136 rmr_get_src( mbuf, m );
139 return std::unique_ptr<unsigned char>( m );
142 int Message::Get_state( ){
147 return INVALID_STATUS;
150 int Message::Get_subid(){
151 int rval = INVALID_SUBID;
161 Return the amount of the payload (bytes) which is used. See
162 Get_available_size() to get the total usable space in the payload.
164 int Message::Get_len(){
175 This returns a smart (unique) pointer to the payload portion of the
176 message. This provides the user application with the means to
177 update the payload in place to avoid multiple copies. The
178 user programme is responsible to determing the usable payload
179 length by calling Message:Get_available_size(), and ensuring that
180 writing beyond the indicated size does not happen.
182 Msg_component Message::Get_payload(){
184 return std::unique_ptr<unsigned char, unfreeable>( mbuf->payload );
190 void Message::Set_meid( std::shared_ptr<unsigned char> new_meid ) {
192 rmr_str2meid( mbuf, (unsigned char *) new_meid.get() );
196 void Message::Set_mtype( int new_type ){
198 mbuf->mtype = new_type;
202 void Message::Set_len( int new_len ){
203 if( mbuf != NULL && new_len >= 0 ) {
208 void Message::Set_subid( int new_subid ){
210 mbuf->sub_id = new_subid;
215 // -------------- send functions ---------------------------------
218 This assumes that the contents of the mbuf were set by either a send attempt that
219 failed with a retry and thus is ready to be processed by RMR.
220 Exposed to the user, but not expected to be frequently used.
222 bool Message::Send( ) {
227 mbuf = rmr_send_msg( mrc, mbuf );
228 return mbuf->state == RMR_OK;
232 Similar to Send(), this assumes that the message is already set up and this is a retry.
233 Exposed to the user, but not expected to be frequently used.
235 bool Message::Reply( ) {
240 mbuf = rmr_rts_msg( mrc, mbuf );
241 return mbuf->state == RMR_OK;
246 This will setup the message (type etc.) ensure the message payload space is
247 large enough and copy in the payload (if a new payload is given), then will
248 either send or rts the message based on the stype parm.
250 If payload is nil, then we assume the user updated the payload in place and
253 This is public, but most users should use Send_msg or Send_response functions.
255 bool Message::Send( int mtype, int subid, int payload_len, unsigned char* payload, int stype ) {
261 if( mtype != NO_CHANGE ) {
264 if( subid != NO_CHANGE ) {
265 mbuf->sub_id = subid;
268 if( payload_len != NO_CHANGE ) {
269 mbuf->len = payload_len;
272 if( payload != NULL ) { // if we have a payload, ensure msg has room, realloc if needed, then copy
273 mbuf = rmr_realloc_payload( mbuf, payload_len, RMR_NO_COPY, RMR_NO_CLONE ); // ensure message is large enough
278 memcpy( mbuf->payload, payload, mbuf->len );
281 if( stype == RESPONSE ) {
282 mbuf = rmr_rts_msg( mrc, mbuf );
284 mbuf = rmr_send_msg( mrc, mbuf );
287 return mbuf->state == RMR_OK;
291 Send a response to the endpoint that sent the original message.
293 Response can be null and the assumption will be that the message payload
294 was updated in place and no additional copy is needed before sending the message.
296 The second form of the call allows for a stack allocated buffer (e.g. char foo[120]) to
297 be passed as the payload.
299 bool Message::Send_response( int mtype, int subid, int response_len, std::shared_ptr<unsigned char> response ) {
300 return Send( mtype, subid, response_len, response.get(), RESPONSE );
303 bool Message::Send_response( int mtype, int subid, int response_len, unsigned char* response ) {
304 return Send( mtype, subid, response_len, response, RESPONSE );
308 These allow a response message to be sent without changing the mtype/subid.
310 bool Message::Send_response( int response_len, std::shared_ptr<unsigned char> response ) {
311 return Send( NO_CHANGE, NO_CHANGE, response_len, response.get(), RESPONSE );
314 bool Message::Send_response( int response_len, unsigned char* response ) {
315 return Send( NO_CHANGE, NO_CHANGE, response_len, response, RESPONSE );
320 Send a message based on message type routing.
322 Payload can be null and the assumption will be that the message payload
323 was updated in place and no additional copy is needed before sending the message.
325 Return is a new mbuf suitable for sending another message, or the original buffer with
326 a bad state sent if there was a failure.
328 bool Message::Send_msg( int mtype, int subid, int payload_len, std::shared_ptr<unsigned char> payload ) {
329 return Send( mtype, subid, payload_len, payload.get(), MESSAGE );
332 bool Message::Send_msg( int mtype, int subid, int payload_len, unsigned char* payload ) {
333 return Send( mtype, subid, payload_len, payload, MESSAGE );
337 Similar send functions that allow the message type/subid to remain unchanged
339 bool Message::Send_msg( int payload_len, std::shared_ptr<unsigned char> payload ) {
340 return Send( NO_CHANGE, NO_CHANGE, payload_len, payload.get(), MESSAGE );
343 bool Message::Send_msg( int payload_len, unsigned char* payload ) {
344 return Send( NO_CHANGE, NO_CHANGE, payload_len, payload, MESSAGE );