Fix CMake to reference unit test in correct dir
[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
71         for( i = 1; i < argc; i++ ) {
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         
115         if( err_count ) {
116                 fprintf( stderr, "usage: %s [-d fifo-dir] [-f input-file] [-t msg-type]\n", argv[0] );
117                 fprintf( stderr, "if -f not given, then standard input is read\n" );
118                 exit( 1 );
119         }
120
121         
122         if( input_file == NULL ) {
123                 fd = 0;
124         } else {
125                 if( (fd = open( input_file, O_RDONLY )) < 0 ) {
126                         fprintf( stderr, "abort: cant open: %s: %s\n", input_file, strerror(errno) );
127                         exit( 1 );
128                 }
129         }
130
131         mcl_ctx = mcl_mk_context( fifo_path );
132         mcl_set_sigh();                                                 // ignore pipe related signals
133
134         remain = read( fd, rbuf, sizeof( rbuf ) );
135         nxt = rbuf;
136         while( remain > 0 ) {
137                 if( remain < 20 ) {                                     // not enough stuff
138                         memcpy( rbuf, nxt, remain );    // copy remaining up front
139                         nxt = rbuf;
140                         remain += read( fd, nxt + remain, sizeof( rbuf ) - remain );
141                 }
142
143                 if( remain < 20 ) {                                     // truncated or a record > rbuf
144                         fprintf( stderr, "abort: @header check, truncated file, or record > read buffer size\n" );
145                         exit( 1 );
146                 }
147         
148                 if( strncmp( nxt, "@RDC", 4 ) == 0 ) {
149                         mtype = atoi( nxt+4 );
150                         mlen = atoi( nxt+12 );
151                         nxt += 20;
152                         remain -= 20;
153
154                         if( remain < mlen ) {                           // not enough stuff
155                                 memcpy( rbuf, nxt, remain );    // copy remaining up front
156                                 nxt = rbuf;
157                                 remain += read( fd, nxt + remain, sizeof( rbuf ) - remain );
158                         }
159
160                         if( remain < mlen ) {                           // truncated or a record > rbuf
161                                 fprintf( stderr, "abort: truncated file, or record > read buffer size\n" );
162                                 exit( 1 );
163                         }
164                         
165                         if( desired < 0 || mtype == desired ) {                         // all mtypes, or specific
166                                 state = mcl_fifo_one( mcl_ctx, nxt, mlen, mtype );
167                                 if( state ) {
168                                         ok_count++;
169                                 } else {
170                                         err_count++;
171                                 }
172                         }
173
174                         nxt += mlen;
175                         remain -= mlen;
176                 } else {
177                         fprintf( stderr, "abort: didn't find rdc header!?! @ %ld\n", (long) (nxt - rbuf) );
178                         exit( 1 );
179                 }
180         }
181
182         fprintf( stderr, "done, captured %ld messages; %ld errors\n", ok_count, err_count );
183         close( fd );
184 }
185