Fix block of dynamic route table load
[ric-plt/lib/rmr.git] / examples / msg_echo.c
1 // :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 */
53 static 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
74 int 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