VR-Link API Documentation for DIS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DIS Netdump Example

This is a simple program that prints all received PDUs.


/****************************************************************************
* Copyright (c) 2015 VT MAK
* All rights reserved.
****************************************************************************/
#if DtDIS
#include <vlutil/vlTime.h>
#include <vl/unknownPdu.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> netmaskString("N","netmaskString", "DIS Net Mask 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[] )
{
// Used for error handling
DtINIT_MINIDUMPER( "DIS-Netdump" );
signal( SIGFPE, SIG_IGN );
DtInfo << "Using VR-Link version " << VR_LINK_VERSION_STRING << std::endl;
DtInfo << "Built on " << DtOperatingSystem() << " with " << DtCompiler() << " - " <<
#if defined( DT_HAVE_64BIT_LONGS ) || defined( _WIN64 )
"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(netmaskString);
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
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;
}
}
DtInetEndpoint endpoint;
endpoint.setPort(disPort);
DtInetAddr destAddr(destAddrString.getValue());
if (netmaskString.isSet())
{
destAddr = DtInetAddr(destAddrString.getValue(), netmaskString.getValue());
}
if (destAddrString.isSet())
{
// The user set a destination address, use it.
endpoint.setAddress(destAddr);
}
else
{
// Use the primary broadcast address
if (bcastAddr)
{
endpoint.setAddress(*bcastAddr);
}
else
{
DtFatalError("Cannot obtain primary broadcast address.\n");
}
DtDELETE(bcastAddr);
}
DtInetUdpSocket* skt = new DtDisSocket(endpoint, 0, netDeviceToUse);
if (skt->isOk())
{
DtWarn << "Netdump socket OK to: " << skt->destination().toDtString() << std::endl;
}
else
{
DtFatalError("Cannot construct a socket to: %s\n",
}
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)
{
}
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;
unsigned int pktVersion = ( (DtNetPduHeader*)packet )->version;
bool isCoupling = ((DtU8)((DtNetPduHeader*)packet)->pduStatus) & 0x8;
DtU8 pduVersion = (DtU8)((DtNetPduHeader*)packet)->version;
DtNetU8 pduStatus = (DtU8)((DtNetPduHeader*)packet)->pduStatus;
if ( size != pktSize && pktVersion >= 7 && !isCoupling)
{
DtWarn << "#### WARNING: Size mismatch: Received("<< size
<<"), DIS Header(" << pktSize << ") ####\n";
if ( errorChecking )
{
DtWarn << " Will not attempt to print this PDU." << std::endl;
return 1;
}
}
if ( printRaw )
{
DtInfo( "%s%s******** PDU #%-6d \t\t %13.3f secs ********\n%s",
clearScreen, vb, n++, vrClock->elapsedRealTime(), vb );
DtUnknownPdu unkPdu( (DtNetPacket*)packet, (DtBufferPtr)packet );
unkPdu.printHeader();
int pduSize = unkPdu.length();
for ( int k = 0; k < pduSize; k += 4 )
{
DtInfo("%04x\t%08x\n", k, *(DtU32 *)(unkPdu.netRep() + k));
}
DtInfo << std::endl;
}
if (pduVersion >= 7 && (((pduStatus >> 3) & 0x1) == 0x1))
{
// This is an error check to ensure there is sufficient space for the Attribute PDU
unsigned int couplingPadding = alignedPadding(pktSize, 8);
unsigned int minimumSizeForAttibutePdu = pktSize + couplingPadding + sizeof(DtNetAttributePdu);
if (!(size >= minimumSizeForAttibutePdu))
{
// There is not enough room for the minimum size of the Attribute PDU
// We will change it so the Coupled Extension Indicator is off
DtWarn << "Turning off Coupled Extension Indicator in Bad PDU due to packet having insufficient space" << std::endl;
DtU8 val = pduStatus;
// When Not Coupled, set bit to 0
DtPDU_STATUS_SET_INDICATOR_ONE_BIT(CoupledExtensionIndicator, NotCoupled);
((DtNetPduHeader*)packet)->pduStatus = val;
}
else
{
// This is the common case, where a PDU has the coupled extension PDU indicator on, and there is sufficient room in the packet
}
}
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 )
{
DtInfo( "%s%s******** PDU #%-6d \t\t %13.3f secs ********\n%s",
clearScreen, vb, n++, vrClock->elapsedRealTime(), vb );
DtInfo("SourceInetAddr:\t %s\n", fromAddress.address().toDtString().c_str());
pdu->print();
DtInfo << std::endl;
}
DtDELETE( pdu );
}
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 Thu Feb 22 04:26:36 EST 2018 from SVN revision 186468
Copyright © 2005-2016 VT MÄK. All Rights Reserved (www.mak.com)