blob: 11254b831a1438dc5264dfaa08e617cd16979f7b [file] [log] [blame]
E. Scott Daniels8761b5d2019-08-09 15:37:48 -04001// :vim ts=4 sw=4 noet:
2/*
3==================================================================================
4 Copyright (c) 2019 Nokia
5 Copyright (c) 2018-2019 AT&T Intellectual Property.
6
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
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
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==================================================================================
19*/
20
21/*
22 Mnemonic: msg_echo.c
23 Abstract: This is a simple message receiver which will echo the received
24 message back to the sender using an RMR return to sender call.
25 All of the message will be left unchanged, though the message type
26 may be changed by supplying it on the command line as the first
27 positional parameter.
28
29 Because this process uses the rts call in RMR, it does not need
30 a route table. However, RMR needs to have at least an empty table
31 in order to work properly. To avoid having the user make a dummy
32 table, we will create an empty one in /tmp and set the needed
33 environment var so the RMR initialisation process finds it.
34
35 Date: 9 August 2019
36 Author: E. Scott Daniels
37*/
38
39#include <unistd.h>
40#include <errno.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <time.h>
44#include <string.h>
45#include <fcntl.h>
46
47#include <rmr/rmr.h>
48
49/*
50 Create an empty route table and set an environment var for RMR to find.
51 This must be called before initialising RMR.
52*/
53static void mk_rt( ) {
54 int fd;
55 char fnb[128];
56 char* contents = "newrt|start\nnewrt|end\n";
57
58 snprintf( fnb, sizeof( fnb ), "/tmp/msg_echo.rt" );
59 fd = open( fnb, O_CREAT | O_WRONLY, 0664 );
60 if( fd < 0 ) {
61 fprintf( stderr, "[FAIL] could not create dummy route table: %s %s\n", fnb, strerror( errno ) );
62 return;
63 }
64
65 write( fd, contents, strlen( contents ) );
66 if( (close( fd ) < 0 ) ) {
67 fprintf( stderr, "[FAIL] couldn't close dummy route table: %s: %s\n", fnb, strerror( errno ) );
68 return;
69 }
70
71 setenv( "RMR_SEED_RT", fnb, 0 ); // set it, but don't overwrite it
72}
73
74int main( int argc, char** argv ) {
75 void* mrc; // msg router context
76 rmr_mbuf_t* msg = NULL; // message received
77 int i;
78 int state;
79 int errors = 0;
80 char* listen_port = "4560";
81 long timeout = 0;
82 char* data; // pointer at env data we sussed out
83 char wbuf[1024]; // we'll pull trace data into here, and use as general working buffer
84 char sbuf[128]; // short buffer
85 int mtype = -1; // if set on command line, we'll add to msg before rts
86 int ai = 1; // argument index
87
88 data = getenv( "RMR_RTG_SVC" );
89 if( data == NULL ) {
90 setenv( "RMR_RTG_SVC", "19289", 1 ); // set one that won't collide with the sender if on same host
91 }
92
93 // ---- simple arg parsing ------
94 while( ai < argc ) {
95 if( *argv[ai] == '-' ) {
96 switch( argv[ai][1] ) {
97 case 'p': // timeout
98 ai++;
99 listen_port = argv[ai];
100 break;
101
102 case 't': // rts message type
103 ai++;
104 mtype = atoi( argv[ai] );
105 break;
106
107 default:
108 fprintf( stderr, "[FAIL] unrecognised option: %s\n", argv[ai] );
109 fprintf( stderr, "\nusage: %s [-p port] [-t msg-type]\n", argv[0] );
110 exit( 1 );
111 }
112
113 ai++;
114 } else {
115 break; // not an option, leave with a1 @ first positional parm
116 }
117 }
118
119 fprintf( stderr, "<ECHO> listening on port: %s will return messages with type: %d\n", listen_port, mtype );
120
121 mk_rt(); // make an empty rt
122
123 mrc = rmr_init( listen_port, RMR_MAX_RCV_BYTES, RMRFL_NONE ); // start your engines!
124 if( mrc == NULL ) {
125 fprintf( stderr, "<ECHO> ABORT: unable to initialise RMr\n" );
126 exit( 1 );
127 }
128
129 timeout = time( NULL ) + 20;
130 while( ! rmr_ready( mrc ) ) { // wait for RMr to configure the route table
131 fprintf( stderr, "<ECHO> waiting for RMr to show ready\n" );
132 sleep( 1 );
133
134 if( time( NULL ) > timeout ) {
135 fprintf( stderr, "<ECHO> giving up\n" );
136 exit( 1 );
137 }
138 }
139 fprintf( stderr, "<ECHO> rmr now shows ready, listening begins\n" );
140
141 while( 1 ) { // listen until the cows come home, pigs fly...
142 msg = rmr_rcv_msg( mrc, msg );
143
144 if( msg && msg->state == RMR_OK ) {
145 if( mtype >= 0 ) {
146 msg->mtype = mtype;
147 msg->sub_id = RMR_VOID_SUBID;
148 }
149
150 msg = rmr_rts_msg( mrc, msg );
151 }
152 }
153
154 return 0; // unreachable, but some compilers swak if this isn't here.
155}
156