Address sonar complaints about the listener
[ric-app/mc.git] / sidecars / listener / src / rdc_replay.c
1
2 /*
3         Mnemonic:       rdc_replay.c
4         Abstract:       This reads raw data from an RDC file generated by the mc_listener
5                                 builds RMR messages which mimic the original message that the
6                                 listener received, and then writes those messages.  The assumption
7                                 is that a dummy route table is in place that causes one or more message
8                                 types to be routed to the mc_listener for "replay" into the mc-core
9                                 application.
10
11
12                                 The RDC file format is expected to be:
13                                         @RDC<mtype><len> or as depicted in hex:
14
15
16                                         0000000 40 52 44 43                                     << delim == @RDC
17                                                                                 30 30 31 30 30 35 30 2a  << mtype
18                                                                                                                                 30 30 30 30 << msg len
19                                         0000020 30 37 34 00
20                                                                                 40 4d 43 4c 30 30 30 30 30 34 36 00 << raw message
21                                                         :
22                                                         :
23
24                                 This is a very quick and dirty thing, so it might be flakey.
25
26                                 Parms from command line are file to read, and the msg type to extract.
27                                 If mtype given is 0, then message type of each record is written to
28                                 stdout (can be sorted -u for a list of messages in the file).
29
30
31         Date:           19 November 2019
32         Author:         E. Scott Daniels
33 */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <fcntl.h>
38 #include <errno.h>
39 #include <unistd.h>
40 #include <string.h>
41
42 #include "mcl.h"
43
44 /*
45         Write a scathing message to let the user know they buggered it!
46 */
47 static void invalid_arg( char* arg ) {
48         fprintf( stderr, "%s is not a valid option, or requires an additional parameter which was omitted\n", arg );
49 }
50
51 int main( int argc, char** argv ) {
52         char rbuf[1024 * 5];
53         int state;                                      // processing state
54         int fd;                                         // input file des
55         int mtype;                                      // msg type for current buffer
56         int mlen;                                       // len of raw data
57         char*   nxt;                            // pointer at next bytes to process
58         int     remain = 0;                             // number of bytes remaining to parse
59         int     need = 20;                              // number of bytes needed before having enough to work with
60         int desired = -1;                       // all mtypes; -t overrides and susses out one type
61         int     wlen = 0;
62         void*   mcl_ctx;                        // mcl library context
63         long    ok_count = 0;
64         long    err_count = 0;
65         char*   fifo_path = "/tmp/mcl_replay/fifos";    // directory where we create fifos; -d overrieds
66         char*   input_file = NULL;                                              // -f to set; stdin is default if nil
67         char*   arg;
68         int             i;
69
70         i = 1;
71         while( i < argc ) {
72                 arg = argv[i];
73                 if( *arg != '-' ) {
74                         break;
75                 }
76
77                 switch( *(arg+1) ) {
78                         case 'd':
79                                 if( i < argc-1 ) {
80                                         fifo_path = argv[i+1];
81                                         i++;
82                                 } else {
83                                         invalid_arg( arg );
84                                         err_count++;
85                                 }
86                                 break;
87
88                         case 'f':
89                                 if( i < argc-1 ) {
90                                         input_file = argv[i+1];
91                                         i++;
92                                 } else {
93                                         invalid_arg( arg );
94                                         err_count++;
95                                 }
96                                 break;
97
98                         case 't':
99                                 if( i < argc-1 ) {
100                                         desired = atoi( argv[i+1] );
101                                         i++;
102                                 } else {
103                                         invalid_arg( arg );
104                                         err_count++;
105                                 }
106                                 break;
107
108                         default:
109                                 fprintf( stderr, "unrecognised option: %s\n", arg );
110                                 err_count++;
111                                 break;
112                 }
113
114                 i++;
115         }
116
117         if( err_count ) {
118                 fprintf( stderr, "usage: %s [-d fifo-dir] [-f input-file] [-t msg-type]\n", argv[0] );
119                 fprintf( stderr, "if -f not given, then standard input is read\n" );
120                 exit( 1 );
121         }
122
123
124         if( input_file == NULL ) {
125                 fd = 0;
126         } else {
127                 if( (fd = open( input_file, O_RDONLY )) < 0 ) {
128                         fprintf( stderr, "abort: cant open: %s: %s\n", input_file, strerror(errno) );
129                         exit( 1 );
130                 }
131         }
132
133         mcl_ctx = mcl_mk_context( fifo_path );
134         mcl_set_sigh();                                                 // ignore pipe related signals
135
136         remain = read( fd, rbuf, sizeof( rbuf ) );
137         nxt = rbuf;
138         while( remain > 0 ) {
139                 if( remain < 20 ) {                                     // not enough stuff
140                         memcpy( rbuf, nxt, remain );    // copy remaining up front
141                         nxt = rbuf;
142                         remain += read( fd, nxt + remain, sizeof( rbuf ) - remain );
143                 }
144
145                 if( remain < 20 ) {                                     // truncated or a record > rbuf
146                         fprintf( stderr, "abort: @header check, truncated file, or record > read buffer size\n" );
147                         exit( 1 );
148                 }
149
150                 if( strncmp( nxt, "@RDC", 4 ) == 0 ) {
151                         mtype = atoi( nxt+4 );
152                         mlen = atoi( nxt+12 );
153                         nxt += 20;
154                         remain -= 20;
155
156                         if( remain < mlen ) {                           // not enough stuff
157                                 memcpy( rbuf, nxt, remain );    // copy remaining up front
158                                 nxt = rbuf;
159                                 remain += read( fd, nxt + remain, sizeof( rbuf ) - remain );
160                         }
161
162                         if( remain < mlen ) {                           // truncated or a record > rbuf
163                                 fprintf( stderr, "abort: truncated file, or record > read buffer size\n" );
164                                 exit( 1 );
165                         }
166
167                         if( desired < 0 || mtype == desired ) {                         // all mtypes, or specific
168                                 state = mcl_fifo_one( mcl_ctx, nxt, mlen, mtype );
169                                 if( state ) {
170                                         ok_count++;
171                                 } else {
172                                         err_count++;
173                                 }
174                         }
175
176                         nxt += mlen;
177                         remain -= mlen;
178                 } else {
179                         fprintf( stderr, "abort: didn't find rdc header!?! @ %ld\n", (long) (nxt - rbuf) );
180                         exit( 1 );
181                 }
182         }
183
184         fprintf( stderr, "done, captured %ld messages; %ld errors\n", ok_count, err_count );
185         close( fd );
186 }
187