Move listener src into subdir for easier testing
[ric-app/mc.git] / sidecars / listener / src / rdc_replay.c
diff --git a/sidecars/listener/src/rdc_replay.c b/sidecars/listener/src/rdc_replay.c
new file mode 100644 (file)
index 0000000..cd50f66
--- /dev/null
@@ -0,0 +1,185 @@
+
+/*
+       Mnemonic:       rdc_replay.c
+       Abstract:       This reads raw data from an RDC file generated by the mc_listener
+                               builds RMR messages which mimic the original message that the
+                               listener received, and then writes those messages.  The assumption
+                               is that a dummy route table is in place that causes one or more message
+                               types to be routed to the mc_listener for "replay" into the mc-core
+                               application. 
+
+
+                               The RDC file format is expected to be:
+                                       @RDC<mtype><len> or as depicted in hex:
+
+
+                                       0000000 40 52 44 43                             << delim == @RDC
+                                                                               30 30 31 30 30 35 30 2a  << mtype
+                                                                                                                               30 30 30 30 << msg len
+                                       0000020 30 37 34 00 
+                                                                               40 4d 43 4c 30 30 30 30 30 34 36 00 << raw message
+                                                       :
+                                                       :
+
+                               This is a very quick and dirty thing, so it might be flakey.
+
+                               Parms from command line are file to read, and the msg type to extract.
+                               If mtype given is 0, then message type of each record is written to
+                               stdout (can be sorted -u for a list of messages in the file).
+
+
+       Date:           19 November 2019
+       Author:         E. Scott Daniels
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "mcl.h"
+
+/*
+       Write a scathing message to let the user know they buggered it!
+*/
+static void invalid_arg( char* arg ) {
+       fprintf( stderr, "%s is not a valid option, or requires an additional parameter which was omitted\n", arg );
+}
+
+int main( int argc, char** argv ) {
+       char rbuf[1024 * 5];
+       int state;                                      // processing state
+       int fd;                                         // input file des
+       int mtype;                                      // msg type for current buffer
+       int mlen;                                       // len of raw data
+       char*   nxt;                            // pointer at next bytes to process
+       int     remain = 0;                             // number of bytes remaining to parse
+       int     need = 20;                              // number of bytes needed before having enough to work with
+       int desired = -1;                       // all mtypes; -t overrides and susses out one type
+       int     wlen = 0;
+       void*   mcl_ctx;                        // mcl library context
+       long    ok_count = 0;
+       long    err_count = 0;
+       char*   fifo_path = "/tmp/mcl_replay/fifos";    // directory where we create fifos; -d overrieds
+       char*   input_file = NULL;                                              // -f to set; stdin is default if nil
+       char*   arg;
+       int     i;
+
+
+       for( i = 1; i < argc; i++ ) {
+               arg = argv[i];
+               if( *arg != '-' ) {
+                       break;
+               }
+
+               switch( *(arg+1) ) {
+                       case 'd':
+                               if( i < argc-1 ) {
+                                       fifo_path = argv[i+1];
+                                       i++;
+                               } else {
+                                       invalid_arg( arg );
+                                       err_count++;
+                               }
+                               break;
+
+                       case 'f':
+                               if( i < argc-1 ) {
+                                       input_file = argv[i+1];
+                                       i++;
+                               } else {
+                                       invalid_arg( arg );
+                                       err_count++;
+                               }
+                               break;
+
+                       case 't':
+                               if( i < argc-1 ) {
+                                       desired = atoi( argv[i+1] );
+                                       i++;
+                               } else {
+                                       invalid_arg( arg );
+                                       err_count++;
+                               }
+                               break;
+
+                       default:
+                               fprintf( stderr, "unrecognised option: %s\n", arg );
+                               err_count++;
+                               break;  
+               }
+       }
+       
+       if( err_count ) {
+               fprintf( stderr, "usage: %s [-d fifo-dir] [-f input-file] [-t msg-type]\n", argv[0] );
+               fprintf( stderr, "if -f not given, then standard input is read\n" );
+               exit( 1 );
+       }
+
+       
+       if( input_file == NULL ) {
+               fd = 0;
+       } else {
+               if( (fd = open( input_file, O_RDONLY )) < 0 ) {
+                       fprintf( stderr, "abort: cant open: %s: %s\n", input_file, strerror(errno) );
+                       exit( 1 );
+               }
+       }
+
+       mcl_ctx = mcl_mk_context( fifo_path );
+       mcl_set_sigh();                                                 // ignore pipe related signals
+
+       remain = read( fd, rbuf, sizeof( rbuf ) );
+       nxt = rbuf;
+       while( remain > 0 ) {
+               if( remain < 20 ) {                                     // not enough stuff
+                       memcpy( rbuf, nxt, remain );    // copy remaining up front
+                       nxt = rbuf;
+                       remain += read( fd, nxt + remain, sizeof( rbuf ) - remain );
+               }
+
+               if( remain < 20 ) {                                     // truncated or a record > rbuf
+                       fprintf( stderr, "abort: @header check, truncated file, or record > read buffer size\n" );
+                       exit( 1 );
+               }
+       
+               if( strncmp( nxt, "@RDC", 4 ) == 0 ) {
+                       mtype = atoi( nxt+4 );
+                       mlen = atoi( nxt+12 );
+                       nxt += 20;
+                       remain -= 20;
+
+                       if( remain < mlen ) {                           // not enough stuff
+                               memcpy( rbuf, nxt, remain );    // copy remaining up front
+                               nxt = rbuf;
+                               remain += read( fd, nxt + remain, sizeof( rbuf ) - remain );
+                       }
+
+                       if( remain < mlen ) {                           // truncated or a record > rbuf
+                               fprintf( stderr, "abort: truncated file, or record > read buffer size\n" );
+                               exit( 1 );
+                       }
+                       
+                       if( desired < 0 || mtype == desired ) {                         // all mtypes, or specific
+                               state = mcl_fifo_one( mcl_ctx, nxt, mlen, mtype );
+                               if( state ) {
+                                       ok_count++;
+                               } else {
+                                       err_count++;
+                               }
+                       }
+
+                       nxt += mlen;
+                       remain -= mlen;
+               } else {
+                       fprintf( stderr, "abort: didn't find rdc header!?! @ %ld\n", (long) (nxt - rbuf) );
+                       exit( 1 );
+               }
+       }
+
+       fprintf( stderr, "done, captured %ld messages; %ld errors\n", ok_count, err_count );
+       close( fd );
+}
+