VR-Link API Documentation for DIS
DIS Netdump Example

This is a simple program that prints all received PDUs.


/*******************************************************************************
** Copyright (c) 1992-2010 VT MAK
** All rights reserved.
*******************************************************************************/

#if DtDIS

#include <vlutil/vlTime.h>
#include <vlutil/vlInetUdpSocket.h>
#include <vlutil/vlInetDevice.h>
#include <vlutil/vlProcessControl.h>
#include <vlutil/vlKeyboard.h>
#include <vlutil/vlInetInterfaceUtils.h>
#include <vlutil/vlInetPlatformUtils.h>
#include <cmdLine/cmdLine.h>
#include <vl/exerciseConn.h>
#include <vl/disPduFactory.h>
#include <vl/unknownPdu.h>
#include <vlutil/vlPrintUtil.h>
#include <vcPdu.h>

#include <signal.h>
#include <stdio.h>
#include <iostream>
#include <vector>


// Returns -1 if user entered q or Q, 0 otherwise
int keybrdTick( void );

// Reads and prints a PDU.  Returns 0 if there were none to be read.
int readAndProcess( DtInetUdpSocket* skt );


// Globals
char* vb = 0;
char* clearScreen = (char *)"";
int numBetweenStdinChecks = 100;

#if defined(_WIN32) || defined(__solaris__)
unsigned int defaultReceiveBufferSize(DtInetUtils::getMaxPacketBufferSize());
#else
unsigned int defaultReceiveBufferSize(UINT_MAX);
#endif

DtCmdLine::ValueArg<DtString> destAddrString("A","destAddrString", "DIS Destination Address String", false, "0.0.0.0", "IP Address");
DtCmdLine::ValueArg<DtString> deviceAddrString("","deviceAddress", "DIS Device Address String", false, "0.0.0.0", "IP Address");
DtCmdLine::ValueArg<int>      disPort("P", "disPort", "DIS Port", false, 3000, "integer");
DtCmdLine::SwitchArg          verbose("", "verbose", "Enable Verbose Output", false);
DtCmdLine::SwitchArg          useIpv6("", "useIpv6", "Use IPv6", false);
DtCmdLine::SwitchArg          errorChecking("", "errorChecking", "Enable Error Checking", false);
DtCmdLine::SwitchArg          clearScreenFlag("c", "clrScreen", "Clear Screen Between PDUs", false);
DtCmdLine::ValueArg<int>      receiveBufferSize("", "receiveBufferSize", "Receive Buffer Size", false, defaultReceiveBufferSize, "integer");
DtCmdLine::MultiArg<DtString> mcastAddrs("S", "mcastAddr", "Multicast Address", false, "IP Address");
DtCmdLine::SwitchArg          printRaw("r", "raw", "Print Raw Data", false);


DtPduFactory* pduFactory;
DtClock* vrClock = new DtClock();

#if VXWORKS
#define main realMain
DT_VXWORKS_APP(netdump)
#endif

int main( int argc, char** argv )
{
   signal( SIGFPE, SIG_IGN );

   DtInfo << "Using VR-Link version " <<  VR_LINK_VERSION_STRING << std::endl;
   DtInfo << "Built on " << DtOperatingSystem() << " with " << DtCompiler() << " - " << 
#if DT_HAVE_64BIT_LONGS
      "64bit"
#else
      "32bit"
#endif
      << std::endl;
    
#ifndef _GT_
    /* this increases speed of output, since dumpPdu will fflush */
    setvbuf( stdout, NULL, _IOFBF, BUFSIZ );
#endif

   DtCmdLine::CmdLine cmdLine("DIS Netdump", ' ', DtExerciseConn::vrlinkVersion().c_str());
   cmdLine.add(destAddrString);
   cmdLine.add(deviceAddrString);
   cmdLine.add(disPort);
   cmdLine.add(verbose);
   cmdLine.add(useIpv6);
   cmdLine.add(errorChecking);
   cmdLine.add(receiveBufferSize);
   cmdLine.add(clearScreenFlag);
   cmdLine.add(mcastAddrs);
   cmdLine.add(printRaw);
   cmdLine.parse(argc, argv);

   if (clearScreenFlag)
   {
      clearScreen = (char *)"\033[H\033[2J"; 
   }

   // Initialize the socket

   DtInetEndpoint endpoint;
   endpoint.setProtocol(DtInetProtocol_UDP);
   endpoint.setPort(disPort);

   if (destAddrString.isSet())
   {
      // The user set a destination address, use it.
      endpoint.setAddress(destAddrString.getValue());
   }
   else
   {
      // Use the primary broadcast address
      DtInetAddr* bcastAddr = DtInetUtils::getPrimaryBroadcastAddress(useIpv6);
      if (bcastAddr)
      {
         endpoint.setAddress(*bcastAddr);
      }
      else
      {
         DtFatalError("Cannot obtain primary broadcast address.\n");
      }
      DtDELETE(bcastAddr);
   }

   DtInetDevice* netDeviceToUse = 0;
   DtInetDevice netDevice(DtInetAddr(deviceAddrString.getValue()));
   if (deviceAddrString.isSet())
   {
      if (netDevice.isOk())
      {
         netDeviceToUse = &netDevice;
      }
      else
      {
         DtWarn << "Invalid device address: \"" << deviceAddrString.getValue() << "\" Using default." << std::endl;
      }
   }

   DtInetUdpSocket* skt = new DtInetUdpSocket(endpoint, 0, netDeviceToUse);
   skt->setNonBlockingOption(true);
   if (skt->isOk())
   {
      DtWarn << "Netdump socket OK to: " << skt->destination().toDtString() << std::endl;
   }
   else
   {
      DtFatalError("Cannot construct a socket to: %s\n",
         skt->destination().toDtString().c_str());
   }

   if (receiveBufferSize.isSet())
   {
      // User changed the receive buffer size.
      if (receiveBufferSize <= 0)
      {
         DtWarn << "Invalid receive buffer size: " << receiveBufferSize.getValue() << " must be > 0." << std::endl;
         DtWarn << "Using default: " << skt->getReceiveBufferSize() << std::endl;
      }
      else
      {
         skt->setReceiveBufferSize(receiveBufferSize);
      }
   }
   
   std::vector <DtString>::const_iterator pos = mcastAddrs.getValue().begin();
   for (; pos != mcastAddrs.getValue().end(); ++pos)
   {
      skt->joinMulticastGroup(DtInetAddr(*pos));
   }

   DtDisPduFactory fact;
   pduFactory = &fact;
   pduFactory->DtADD_PDU_CREATOR(ViewControl);
   
   fflush( stdout );
   
   if ( verbose )
   {
      vb =(char *)"************************************************************\n"; 
   }
   else
   {
      vb = (char *)"";
   }

   int forever = 1; // to keep cfront quiet
   while( forever )
   {
      // Keep reading and processing as long as there is stuff to read.
      // Check for keyboard input every numBetweenStdinChecks reads.
      int numBeforeStdinCheck = 0;
      do
      {
         if ( numBeforeStdinCheck == 0 )
         {
            numBeforeStdinCheck = numBetweenStdinChecks;
            if ( keybrdTick() == -1 )
            {
               return 0;
            }
         }
         else
         {
            --numBeforeStdinCheck;
         }
      } while( readAndProcess( skt ) );
   }

   return 0;
}


int readAndProcess( DtInetUdpSocket* skt )
{
   static int n = 1;

   char packet[15000];
   DtInetEndpoint fromAddress;
   DtInetSockRcvStatus status = skt->recvFrom((caddr_t)packet, 15000, fromAddress);
   int size = status;

   if ( !status )
   {
      return 0;
   }

   int pktSize = ( (DtNetPduHeader*)packet )->DtLength;
   if ( size != pktSize )
   {
      std::cout <<  "#### WARNING: Size mismatch: Received("<< size 
         <<"), DIS Header(" << pktSize << ") ####\n";
      if ( errorChecking )
      {  
         std::cout << "  Will not attempt to print this PDU."<< std::endl;
         return 1;
      }
   }

   DtPdu* pdu;
   int version = ( (DtNetPduHeader*)packet )->version;
   if ( version >= DtProtocolVersionToRecvMin &&
        version <= DtProtocolVersionToRecvMax )
   {
      pdu = pduFactory->createPdu( (DtNetPacket*)packet, (DtBufferPtr)packet );
   }
   else
   {
      pdu = new DtUnknownPdu( (DtNetPacket*)packet, (DtBufferPtr)packet );
   }

   if ( pdu )
   {
      if (printRaw)
      {
         printf( "%s%s******** PDU #%-6d \t\t %13.3f secs ********\n%s",
            clearScreen, vb, n++, vrClock->elapsedRealTime(), vb );
         pdu->printHeader();
         int pduSize = pdu->length();
         for (int k = 0; k < pduSize; k += 4)
         {
            printf("%04x\t%08x\n", k, *(DtU32 *)(pdu->netRep() + k));
         }
         printf("\n");
         fflush(stdout);
      }
      else
      {
         printf( "%s%s******** PDU #%-6d \t\t %13.3f secs ********\n%s",
            clearScreen, vb, n++, vrClock->elapsedRealTime(), vb );

         printf("SourceInetAddr:\t %s\n", fromAddress.address().toDtString().c_str());
         pdu->print();
         printf( "\n" );
         delete pdu;
         fflush( stdout );
      }
   }

   return 1;
}


int keybrdTick()
{
   char* keyPtr = DtPollBlockingInputLine();
   if ( !keyPtr )
   {
      return 0;  // no input
   }
    
   switch( *keyPtr )
   {
      case 'q':
      case 'Q':
      {
         return -1;
      }
      default:
      {
         std::cout << "Unrecognized command key <" << *keyPtr << ">" 
            << std::endl;
         break;
      }
   }
   return 0;
}

#endif


Document ID: Generated on Mon May 14 08:06:18 EDT 2012 from SVN revision 114750
Copyright © 2005-2012 VT MÄK Inc. All Rights Reserved (www.mak.com)