+/*
+ Rtc_parse_msg parses a single message from the route manager. We allow multiple, newline terminated,
+ records in each message; it is required that the last record in the message be complete (we do not
+ reconstruct records split over multiple messages). For each record, we call the record parser
+ to parse and add the information to the table being built.
+
+ This function was broken from the main rtc() function in order to be able to unit test it. Without
+ this as a standalone funciton, it was impossible to simulate a message arriving on the RTC's private
+ context.
+
+ To reduce malloc/free cycles, we allocate a static work buffer and expand it when needed; in other
+ words, this is not thread safe but it shouldn't need to be.
+*/
+static void rtc_parse_msg( uta_ctx_t *ctx, uta_ctx_t* pvt_cx, rmr_mbuf_t* msg, int vlevel, int* flags ) {
+ static unsigned char* pbuf = NULL;
+ static int pbuf_size = 0;
+
+ unsigned char* payload;
+ unsigned char* curr;
+ unsigned char* nextr;
+ int mlen;
+
+ payload = msg->payload;
+ mlen = msg->len; // usable bytes in the payload
+
+ if( DEBUG > 1 || (vlevel > 0) ) rmr_vlog( RMR_VL_DEBUG, "rmr_rtc: received rt message type=%d len=%d\n", msg->mtype, (int) mlen );
+ switch( msg->mtype ) {
+ case RMRRM_TABLE_DATA:
+ if( (*flags & RTCFL_HAVE_UPDATE) == 0 ) {
+ *flags |= RTCFL_HAVE_UPDATE;
+ rmr_vlog( RMR_VL_INFO, "message flow from route manager starts\n" );
+ }
+
+ if( pbuf_size <= mlen ) {
+ if( pbuf ) {
+ free( pbuf );
+ }
+ if( mlen < 512 ) {
+ pbuf_size = 1024;
+ } else {
+ pbuf_size = mlen * 2;
+ }
+ pbuf = (char *) malloc( sizeof( char ) * pbuf_size );
+ }
+ memcpy( pbuf, payload, mlen );
+ pbuf[mlen] = 0; // don't depend on sender making this a legit string
+ if( vlevel > 1 ) {
+ rmr_vlog_force( RMR_VL_DEBUG, "rmr_rtc: rt message: (%s)\n", pbuf );
+ }
+
+ curr = pbuf;
+ while( curr ) { // loop over each record in the buffer
+ nextr = strchr( (char *) curr, '\n' ); // allow multiple newline records, find end of current and mark
+
+ if( nextr ) {
+ *(nextr++) = 0;
+ }
+
+ if( vlevel > 1 ) {
+ rmr_vlog_force( RMR_VL_DEBUG, "rmr_rtc: processing (%s)\n", curr );
+ }
+ parse_rt_rec( ctx, pvt_cx, curr, vlevel, msg ); // parse record and add to in progress table; ack using rts to msg
+
+ curr = nextr;
+ }
+
+ msg->len = 0; // force back into the listen loop
+ break;
+
+ default:
+ rmr_vlog( RMR_VL_WARN, "rmr_rtc: invalid message type=%d len=%d\n", msg->mtype, (int) msg->len );
+ break;
+ }
+}
+