blob: 11254b831a1438dc5264dfaa08e617cd16979f7b [file] [log] [blame]
// :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 <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <fcntl.h>
#include <rmr/rmr.h>
/*
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, "<ECHO> 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, "<ECHO> 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, "<ECHO> waiting for RMr to show ready\n" );
sleep( 1 );
if( time( NULL ) > timeout ) {
fprintf( stderr, "<ECHO> giving up\n" );
exit( 1 );
}
}
fprintf( stderr, "<ECHO> 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.
}