// :vim ts=4 sw=4 noet: /* ================================================================================== Copyright (c) 2019 Nokia Copyright (c) 2018-2019 AT&T Intellectual Property. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================================================== */ /* Mnemonic: msg_echo.c Abstract: This is a simple message receiver which will echo the received message back to the sender using an RMR return to sender call. All of the message will be left unchanged, though the message type may be changed by supplying it on the command line as the first positional parameter. Because this process uses the rts call in RMR, it does not need a route table. However, RMR needs to have at least an empty table in order to work properly. To avoid having the user make a dummy table, we will create an empty one in /tmp and set the needed environment var so the RMR initialisation process finds it. Date: 9 August 2019 Author: E. Scott Daniels */ #include #include #include #include #include #include #include #include /* Create an empty route table and set an environment var for RMR to find. This must be called before initialising RMR. */ static void mk_rt( ) { int fd; char fnb[128]; char* contents = "newrt|start\nnewrt|end\n"; snprintf( fnb, sizeof( fnb ), "/tmp/msg_echo.rt" ); fd = open( fnb, O_CREAT | O_WRONLY, 0664 ); if( fd < 0 ) { fprintf( stderr, "[FAIL] could not create dummy route table: %s %s\n", fnb, strerror( errno ) ); return; } write( fd, contents, strlen( contents ) ); if( (close( fd ) < 0 ) ) { fprintf( stderr, "[FAIL] couldn't close dummy route table: %s: %s\n", fnb, strerror( errno ) ); return; } setenv( "RMR_SEED_RT", fnb, 0 ); // set it, but don't overwrite it } int main( int argc, char** argv ) { void* mrc; // msg router context rmr_mbuf_t* msg = NULL; // message received int i; int state; int errors = 0; char* listen_port = "4560"; long timeout = 0; char* data; // pointer at env data we sussed out char wbuf[1024]; // we'll pull trace data into here, and use as general working buffer char sbuf[128]; // short buffer int mtype = -1; // if set on command line, we'll add to msg before rts int ai = 1; // argument index data = getenv( "RMR_RTG_SVC" ); if( data == NULL ) { setenv( "RMR_RTG_SVC", "19289", 1 ); // set one that won't collide with the sender if on same host } // ---- simple arg parsing ------ while( ai < argc ) { if( *argv[ai] == '-' ) { switch( argv[ai][1] ) { case 'p': // timeout ai++; listen_port = argv[ai]; break; case 't': // rts message type ai++; mtype = atoi( argv[ai] ); break; default: fprintf( stderr, "[FAIL] unrecognised option: %s\n", argv[ai] ); fprintf( stderr, "\nusage: %s [-p port] [-t msg-type]\n", argv[0] ); exit( 1 ); } ai++; } else { break; // not an option, leave with a1 @ first positional parm } } fprintf( stderr, " listening on port: %s will return messages with type: %d\n", listen_port, mtype ); mk_rt(); // make an empty rt mrc = rmr_init( listen_port, RMR_MAX_RCV_BYTES, RMRFL_NONE ); // start your engines! if( mrc == NULL ) { fprintf( stderr, " ABORT: unable to initialise RMr\n" ); exit( 1 ); } timeout = time( NULL ) + 20; while( ! rmr_ready( mrc ) ) { // wait for RMr to configure the route table fprintf( stderr, " waiting for RMr to show ready\n" ); sleep( 1 ); if( time( NULL ) > timeout ) { fprintf( stderr, " giving up\n" ); exit( 1 ); } } fprintf( stderr, " rmr now shows ready, listening begins\n" ); while( 1 ) { // listen until the cows come home, pigs fly... msg = rmr_rcv_msg( mrc, msg ); if( msg && msg->state == RMR_OK ) { if( mtype >= 0 ) { msg->mtype = mtype; msg->sub_id = RMR_VOID_SUBID; } msg = rmr_rts_msg( mrc, msg ); } } return 0; // unreachable, but some compilers swak if this isn't here. }