3 ==================================================================================
4 Copyright (c) 2020 Nokia
5 Copyright (c) 2020 AT&T Intellectual Property.
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
11 http://www.apache.org/licenses/LICENSE-2.0
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 ==================================================================================
22 Mnemonic: rmr_dump.cpp
23 Abstract: This is a sample xapp which will behave somewhat like tcpdump
24 as it receives rmr messages. The list of message types which should
25 be processed are given on the command line, following any flag
26 options (e.g. -p port). Any of those messages received are reported
27 on by the application. The verbosity level may be used to increase
28 the amount of detail given for the tracked messages.
30 This writes to the TTY which is slow, so do not expect it to be able
31 to process and report on a high rate of messages. Also, forwarded
32 messages will reach the intended target, however if the target
33 attempts to send a response the response will come back to THIS
34 application, and not the message origination; this cannot be a bit
35 of middleware in it's current form.
38 Author: E. Scott Daniels
45 #include "ricxfcpp/xapp.hpp"
48 Information that the callback needs outside
49 of what is given to it via parms on a call
53 int vlevel; // verbosity level
54 bool forward; // if true, message is forwarded
55 int stats_freq; // header/stats after n messages
56 std::atomic<long> pcount; // messages processed
57 std::atomic<long> icount; // messages ignored
58 std::atomic<int> hdr; // number of messages before next header
61 // ----------------------------------------------------------
66 void dump( unsigned const char* buf, int len ) {
71 fprintf( stdout, "<RD> 0000 | " );
73 for( i = 0; i < len; i++ ) {
74 cheater[j++] = isprint( buf[i] ) ? buf[i] : '.';
75 fprintf( stdout, "%02x ", buf[i] );
79 fprintf( stdout, " | %s\n<RD> %04x | ", cheater, i+1 );
87 fprintf( stdout, " " );
90 fprintf( stdout, " | %s\n", cheater );
95 generate stats when the hdr count reaches 0. Only one active
96 thread will ever see it be exactly 0, so this is thread safe.
98 void stats( cb_info_t& cbi ) {
99 int curv; // current stat trigger value
103 if( curv == 0 ) { // stats when we reach 0
104 fprintf( stdout, "ignored: %ld processed: %ld\n",
105 cbi.icount.load(), cbi.pcount.load() );
106 if( cbi.vlevel > 0 ) {
107 fprintf( stdout, "\n %5s %5s %2s %5s\n",
108 "MTYPE", "SUBID", "ST", "PLLEN" );
111 cbi.hdr = cbi.stats_freq; // reset must be last
115 void cb1( Message& mbuf, int mtype, int subid, int len,
116 Msg_component payload, void* data ) {
120 if( (cbi = (cb_info_t *) data) == NULL ) {
125 stats( *cbi ); // gen stats & header if needed
127 if( cbi->vlevel > 0 ) {
128 fprintf( stdout, "<RD> %-5d %-5d %02d %-5d \n",
129 mtype, subid, mbuf.Get_state(), len );
131 if( cbi->vlevel > 1 ) {
132 dump( payload.get(), len > 64 ? 64 : len );
137 // forward with no change to len or payload
138 mbuf.Send_msg( Message::NO_CHANGE, NULL );
143 registered as the default callback; it counts the
144 messages that we aren't giving details about.
146 void cbd( Message& mbuf, int mtype, int subid, int len,
147 Msg_component payload, void* data ) {
150 if( (cbi = (cb_info_t *) data) == NULL ) {
158 // forward with no change to len or payload
159 mbuf.Send_msg( Message::NO_CHANGE, NULL );
163 int main( int argc, char** argv ) {
164 std::unique_ptr<Xapp> x;
165 char* port = (char *) "4560";
166 int ai = 1; // arg processing index
168 int ncb = 0; // number of callbacks registered
172 cbi = (cb_info_t *) malloc( sizeof( *cbi ) );
175 cbi->stats_freq = 10;
178 // very simple flag parsing (no error/bounds checking)
180 if( argv[ai][0] != '-' ) { // break on first non-flag
184 // very simple arg parsing; each must be separate -x -y not -xy.
185 switch( argv[ai][1] ) {
186 case 'f': // enable packet forwarding
190 case 'p': // define port
195 case 's': // stats frequency
196 cbi->stats_freq = atoi( argv[ai+1] );
197 if( cbi->stats_freq < 5 ) { // enforce sanity
203 case 't': // thread count
204 nthreads = atoi( argv[ai+1] );
211 case 'v': // simple verbose bump
215 case 'V': // explicit verbose level
216 cbi->vlevel = atoi( argv[ai+1] );
221 fprintf( stderr, "unrecognised option: %s\n", argv[ai] );
222 fprintf( stderr, "usage: %s [-f] [-p port] [-s stats-freq] [-t thread-count] [-v | -V n] msg-type1 ... msg-typen\n", argv[0] );
223 fprintf( stderr, "\tstats frequency is in number of messages received\n" );
224 fprintf( stderr, "\tverbose levels (-V) 0 counts only, 1 message info 2 payload dump\n" );
231 cbi->hdr = cbi->stats_freq;
232 fprintf( stderr, "<RD> listening on port: %s\n", port );
234 // create xapp, wait for route table if forwarding
235 x = std::unique_ptr<Xapp>( new Xapp( port, cbi->forward ) );
237 // register callback for each type on the command line
239 mtype = atoi( argv[ai] );
241 fprintf( stderr, "<RD> capturing messages for type %d\n", mtype );
242 x->Add_msg_cb( mtype, cb1, cbi );
247 fprintf( stderr, "<RD> no message types specified on the command line\n" );
251 x->Add_msg_cb( x->DEFAULT_CALLBACK, cbd, cbi ); // register default cb
253 fprintf( stderr, "<RD> starting driver\n" );
256 // return from run() is not expected, but some compilers might
257 // compilain if there isn't a return value here.