⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ttcpproxy.cpp

📁 Complete PCAUSA samples including various kernel mode TDI code, TDI filters/redirectors and NDIS fil
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// TTCPProxy.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <io.h>
#include "getopt.h" 


/*
 *  T T C P . C
 *
 * Test TCP connection.  Makes a connection on port 5001
 * and transfers fabricated buffers or data copied from stdin.
 *
 * Usable on 4.2, 4.3, and 4.1a systems by defining one of
 * BSD42 BSD43 (BSD41a)
 * Machines using System V with BSD sockets should define SYSV.
 *
 * Modified for operation under 4.2BSD, 18 Dec 84
 *      T.C. Slattery, USNA
 * Minor improvements, Mike Muuss and Terry Slattery, 16-Oct-85.
 * Modified in 1989 at Silicon Graphics, Inc.
 *  catch SIGPIPE to be able to print stats when receiver has died 
 *  for tcp, don't look for sentinel during reads to allow small transfers
 *  increased default buffer size to 8K, g_nNumBuffersToSend to 2K to transfer 16MB
 *  moved default port to 5001, beyond IPPORT_USERRESERVED
 *  make sinkmode default because it is more popular, 
 *      -s now means don't sink/source.
 *       in sink/source mode use pattern generator to fill send
 *       buffer (once at init time). received data is tossed.
 *  count number of read/write system calls to see effects of 
 *      blocking from full socket buffers
 *  for tcp, -D option turns off buffered writes (sets TCP_NODELAY sockopt)
 *  buffer alignment options, -A and -O
 *  print stats in a format that's a bit easier to use with grep & awk
 *  for SYSV, mimic BSD routines to use most of the existing timing code
 * Modified by Steve Miller of the University of Maryland, College Park
 *  -b sets the socket buffer size (SO_SNDBUF/SO_RCVBUF)
 * Modified Sept. 1989 at Silicon Graphics, Inc.
 *  restored -s sense at request of tcs@brl
 * Modified Oct. 1991 at Silicon Graphics, Inc.
 *  use getopt(3) for option processing, add -f and -T options.
 *  SGI IRIX 3.3 and 4.0 releases don't need #define SYSV.
 *
 * PCAUSA Version 1.00.00.01 - Modified April, 1999 at Printing
 * Communications Assoc., Inc. (PCAUSA) PCAUSA. Initial port to Winsock.
 *
 * PCAUSA Version 1.00.00.02 - Modified January, 2000 at Printing
 * Communications Assoc., Inc. (PCAUSA) to fix setting of setsockopt call
 * for TCP_NODELAY.
 *
 * PCAUSA Version 2.01.01.04 - Modified May, 2002 at Printing
 * Communications Assoc., Inc. (PCAUSA). Incorporates substantial rework
 * suit the author's style and purpose (as a sockets programming learning
 * program and a TCP/IP exploration tool).
 *
 * Although the functionality has been extended, the application is
 * backwards-compatible with previous PCAUSA releases.
 *
 * PCAUSA Version 2.01.01.05 - Modified May, 2002 at PCAUSA. Modification
 * to allow SO_RVCBUF and SO_SNDBUF values of zero(0) to be handled.
 *
 * PCAUSA Version 2.01.01.06 - Modified April, 2003 at PCAUSA. Fixed minor
 * bug in TTCP transmitter. PCAUSA PCATTCP preamble was not inserted
 * correctly when building transmit buffer.
 * 
 * PCAUSA Version 2.01.01.07 - Modified November, 2003 at PCAUSA.
 * Incorporated fix identified by Clarkson University that reduces
 * hangs when ending the UDP transmitter test. See additional comments
 * in TTCP_TransmitUDP module.
 * 
 * Distribution Status -
 *      Public Domain.  Distribution Unlimited.
 */

#define  PCATTCP_VERSION   "2.02.06.15"

/////////////////////////////////////////////////////////////////////////////
//// GLOBAL VARIABLES
//

extern int errno;

BOOL     g_bShutdown = FALSE;               // Set by Ctrl-C Handler
WSADATA  g_WsaData;

#ifndef IPPORT_TTCP
#define IPPORT_TTCP          5001
#endif

#define IPPORT_TTCP_PROXY    5002

typedef
struct _CMD_BLOCK
{
   //
   // Test Command/Configuration Data
   //
   BOOLEAN     m_bTransmit;
   USHORT      m_Protocol;

   SOCKADDR_IN m_RemoteAddr;        // Host Byte Order
   int         m_nRemoteAddrLen;

   SOCKADDR_IN m_LocalAddress;      // Host Byte Order

   USHORT      m_Port;              // Host Byte Order

   BOOLEAN     m_bOptContinuous;
   int         m_nOptWriteDelay;    // milliseconds of delay before each write

   BOOLEAN     m_bOptMultiReceiver;

   BOOLEAN     m_bTouchRecvData;

   BOOLEAN     m_bSinkMode;         // FALSE = normal I/O, TRUE = sink/source mode

   int         m_nNumBuffersToSend; // number of buffers to send in sinkmode

   int         m_nBufferSize;       // length of buffer
   int         m_nBufOffset;        // align buffer to this
   int         m_nBufAlign;         //modulo this

   BOOLEAN     m_bUseSockOptBufSize;
   int         m_nSockOptBufSize;   // socket buffer size to use

   int         m_nSockOptNoDelay;   // set TCP_NODELAY socket option

   BOOLEAN     m_bSockOptDebug;     // TRUE = set SO_DEBUG socket option

   SOCKET      m_ExtraSocket;
}
   CMD_BLOCK, *PCMD_BLOCK;

typedef
struct _TEST_BLOCK
{
   //
   // Command/Configuration Data
   //
   CMD_BLOCK   m_Cmd;

   //
   // Instance Data
   //
   PCHAR       m_pBufBase;          // ptr to dynamic buffer (base)
   PCHAR       m_pBuf;              // ptr to dynamic buffer (aligned)

   SOCKET      m_Socket_fd;         // fd of network send/receive socket

   //
   // Statistics
   //
   DWORD          m_tStart;
   DWORD          m_tFinish;

   unsigned long  m_numCalls;          // # of I/O system calls
   double         m_nbytes;         // bytes on net
}
   TEST_BLOCK, *PTEST_BLOCK;

int b_flag = 0;      // use mread()
int one = 1;         // for 4.3 BSD style setsockopt()
int zero = 0;        // for 4.3 BSD style setsockopt()

int verbose = 0;     // 0=print basic info, 1=print cpu rate, proc
                         // resource usage.

char fmt = 'K';      // output format:
                     // k = kilobits, K = kilobytes,
                     // m = megabits, M = megabytes, 
                     // g = gigabits, G = gigabytes

#define  UDP_GUARD_BUFFER_LENGTH  4

//
// Forward Procedure Prototypes
//
void TTCP_ExitTest( PTEST_BLOCK pTBlk, BOOLEAN bExitProcess );
void TTCP_ExitTestOnWSAError( PTEST_BLOCK pTBlk, PCHAR pFnc );
void TTCP_ExitTestOnCRTError( PTEST_BLOCK pTBlk, PCHAR pFnc );

int TTCP_Nread( PTEST_BLOCK pTBlk, int count );
int TTCP_Nwrite( PTEST_BLOCK pTBlk, int count );
int TTCP_mread( PTEST_BLOCK pTBlk, unsigned n );

char *outfmt(double b);

void delay( int us );

/////////////////////////////////////////////////////////////////////////////
//// Miscellaneous Support Routines
//

void DumpRuleBuffer( PTCP_REDIR_RULE_BUFFER pRuleBuffer )
{
    ULONG    i;
    struct in_addr  in_temp;

    if( pRuleBuffer == NULL )
    {
        printf( "Rule Buffer is NULL\n" );
    }

    printf( "Dumping %d Rules\n\n", pRuleBuffer->RuleCount );

    for( i = 0; i < pRuleBuffer->RuleCount; ++i )
    {
        if( pRuleBuffer->RuleArray[ i ].RemoteAddressRangeStart == 0 )
        {
            printf( "Any Remote Address" );
        }
        else
        {
            if( pRuleBuffer->RuleArray[ i ].RemoteAddressRangeStart
                == pRuleBuffer->RuleArray[ i ].RemoteAddressRangeEnd
                )
            {
                in_temp.S_un.S_addr = pRuleBuffer->RuleArray[ i ].RemoteAddressRangeStart;

                printf( "%s", inet_ntoa( in_temp ) );
            }
            else
            {
                in_temp.S_un.S_addr = pRuleBuffer->RuleArray[ i ].RemoteAddressRangeStart;

                printf( "%s - ", inet_ntoa( in_temp ) );

                in_temp.S_un.S_addr = pRuleBuffer->RuleArray[ i ].RemoteAddressRangeEnd;
                printf( "%s", inet_ntoa( in_temp ) );
            }
        }

        printf( ":%d -> ", pRuleBuffer->RuleArray[ i ].RemotePort );

        in_temp.S_un.S_addr = pRuleBuffer->RuleArray[ i ].RedirectToAddress;
        printf( "%s:%d\n", inet_ntoa( in_temp ), pRuleBuffer->RuleArray[ i ].RedirectToPort );

        if( *pRuleBuffer->RuleArray[ i ].ProcessNameToRedirect == 0 )
        {
            printf( "   Redirect Any Process " );
        }
        else
        {
            printf( "   Redirect Process \042%s\042 ", pRuleBuffer->RuleArray[ i ].ProcessNameToRedirect);
        }

        if( pRuleBuffer->RuleArray[ i ].ProcessIdToIgnore == 0 )
        {
            if( *pRuleBuffer->RuleArray[ i ].ProcessNameToIgnore == 0 )
            {
                printf( "\n" );
            }
            else
            {
                printf( "Except \042%s\042\n", pRuleBuffer->RuleArray[ i ].ProcessNameToIgnore);
            }
        }
        else
        {
            printf( "Except Process %d\n", pRuleBuffer->RuleArray[ i ].ProcessIdToIgnore);
        }

        printf( "\n" );
    }

    printf( "\n" );
}

void TTCP_LogMsg( const char *format, ... )
{
//   FILE *logfd = NULL;
   FILE *logfd = stderr;

   char  szBuffer[ 256 ];
   va_list  marker;

   if( !logfd )
   {
//      LogOpen();
   }

   if( !logfd )
   {
      return;
   }

   va_start( marker, format );

   vsprintf( szBuffer, format, marker );

   fprintf( logfd, szBuffer );
}


void TTCP_InitStatistics( PTEST_BLOCK pTBlk )
{
   pTBlk->m_numCalls = 0;       // # of I/O system calls
   pTBlk->m_nbytes = 0;      // bytes on net

   pTBlk->m_tStart = GetTickCount();
}


void TTCP_LogStatistics( PTEST_BLOCK pTBlk )
{
   double realt;                 // user, real time (seconds)

   pTBlk->m_tFinish = GetTickCount();

   realt = ((double )pTBlk->m_tFinish - (double )pTBlk->m_tStart)/1000;

   if( pTBlk->m_Cmd.m_Protocol == IPPROTO_UDP )
   {
      if( pTBlk->m_Cmd.m_bTransmit )
      {
         TTCP_LogMsg( "  Statistics  : UDP -> %s:%d\n",
            inet_ntoa( pTBlk->m_Cmd.m_RemoteAddr.sin_addr ),
            pTBlk->m_Cmd.m_Port );
      }
      else
      {
         TTCP_LogMsg( "  Statistics  : UDP <- %s:%d\n",
            inet_ntoa( pTBlk->m_Cmd.m_RemoteAddr.sin_addr ),
            htons( pTBlk->m_Cmd.m_RemoteAddr.sin_port ) );
      }
   }
   else
   {
      if( pTBlk->m_Cmd.m_bTransmit )
      {
         TTCP_LogMsg( "  Statistics  : TCP -> %s:%d\n",
            inet_ntoa( pTBlk->m_Cmd.m_RemoteAddr.sin_addr ),
            pTBlk->m_Cmd.m_Port
            );
      }
      else
      {
         TTCP_LogMsg( "  Statistics  : TCP <- %s:%d\n",
            inet_ntoa( pTBlk->m_Cmd.m_RemoteAddr.sin_addr ),
            htons( pTBlk->m_Cmd.m_RemoteAddr.sin_port ) );
      }
   }

   TTCP_LogMsg( 
      "%.0f bytes in %.2f real seconds = %s/sec +++\n",
      pTBlk->m_nbytes,
      realt,
      outfmt(pTBlk->m_nbytes/realt)
      );

   TTCP_LogMsg( "numCalls: %d; msec/call: %.2f; calls/sec: %.2f\n",
      pTBlk->m_numCalls,
      1024.0 * realt/((double )pTBlk->m_numCalls),
      ((double )pTBlk->m_numCalls)/realt
      );
}

/////////////////////////////////////////////////////////////////////////////
//// TEST_BLOCK Support Routines
//
// Remarks
// A TEST_BLOCK structure is allocated for each TTCP primary test routine:
//
//    TTCP_TransmitTCP
//    TTCP_TransmitUDP
//    TTCP_ReceiveTCP
//    TTCP_ListenTCP
//    TTCP_ReceiveUDP
//
// The TEST_BLOCK is a private "instance data" structure that contains
// all of the information necessary to perform the function. It includes
// a copy of the CMD_BLOCK parameters that control the test's operation
// as well as other members to keep track of SOCKETs, buffers and
// statistics associated with the test function.
//
// Each TTCP primary test function allocates its own TEST_BLOCK and is
// responsible for eventually freeing it.
//
// In the blocking single-threaded PCATTCP version use of this mechanism
// is certainly overkill, and serves no truly useful purpose. Global
// data would have been just as effective.
//
// HOWEVER, this approach was taken in anticipation of eventually enhancing
// the test to be multi-threaded - which will actually be trivial.
//

PTEST_BLOCK
TTCP_AllocateTestBlock( PCMD_BLOCK pCmdBlk )
{
   PTEST_BLOCK pTBlk = NULL;

   pTBlk = (PTEST_BLOCK )malloc( sizeof( TEST_BLOCK ) );

   if( !pTBlk )
   {
      TTCP_ExitTestOnCRTError( NULL, "malloc" );

      return( NULL );
   }

   memset( pTBlk, 0x00, sizeof( TEST_BLOCK ) );

   memcpy( &pTBlk->m_Cmd, pCmdBlk, sizeof( CMD_BLOCK ) );

   pTBlk->m_Socket_fd = INVALID_SOCKET; // fd of network send/receive socket

   return( pTBlk );
}


void TTCP_FreeTestBlock( PTEST_BLOCK pTBlk )
{
   if( !pTBlk )
   {
      return;
   }

   if( pTBlk->m_pBufBase )
   {
      free( pTBlk->m_pBufBase );
   }

   pTBlk->m_pBufBase = NULL;

   if( pTBlk->m_Socket_fd != INVALID_SOCKET )
   {
      closesocket( pTBlk->m_Socket_fd );

      pTBlk->m_Socket_fd = INVALID_SOCKET;
   }

   pTBlk->m_Socket_fd = INVALID_SOCKET;

   free( pTBlk );
}


/////////////////////////////////////////////////////////////////////////////
//// TTCP Exit Routines
//
// Remarks
// The TTCP tests exit by calling one of 
//
//  TTCP_ExitTest           - Call for normal exit.
//  TTCP_ExitTestOnWSAError - Call to exit when Winsock error is encountered.
//  TTCP_ExitTestOnCRTError - Call to exit when OS/DOS error is encountered.
//
// The exit routines systematically free the TEST_BLOCK resources and the
// TEST_BLOCK structure itself.
//
// They exit by calling ExitThread or ExitProcess. Understand that in
// the single-threaded version a call to ExitThread simply exits the
// main program thread. That is: it is equivalent to calling ExitProcess.
//

void TTCP_ExitTest( PTEST_BLOCK pTBlk, BOOLEAN bExitProcess )
{
    if( pTBlk )
    {
        TTCP_FreeTestBlock( pTBlk );
    }

    if( bExitProcess )
    {
        WSACleanup();

        TcpRedirector_ClearRedirectRules();
        TcpRedirector_Shutdown();

        ExitProcess( 1 );
    }

    ExitThread( 1 );
}


void TTCP_ExitTestOnWSAError( PTEST_BLOCK pTBlk, PCHAR pFnc )
{
   int nError = WSAGetLastError();

   TTCP_LogMsg( "*** Winsock Error: %s Failed; Error: %d (0x%8.8X)\n",
      pFnc, nError, nError );

   TTCP_ExitTest( pTBlk, TRUE );
}


void TTCP_ExitTestOnCRTError( PTEST_BLOCK pTBlk, PCHAR pFnc )
{
   TTCP_LogMsg( "*** CRT Error: %s Failed; Error: %d (0x%8.8X)\n",
      pFnc, errno, errno );

   TTCP_ExitTest( pTBlk, TRUE );
}


/////////////////////////////////////////////////////////////////////////////
//// CtrlHandler
//
// Purpose
// Console Ctrl-C handler.
//
// Parameters
//
// Return Value
//
// Remarks
//

BOOL WINAPI CtrlHandler( DWORD dwCtrlType )
{
   //
   // Sanity Checks
   //

   switch( dwCtrlType )
   {
      case CTRL_C_EVENT:
         TTCP_LogMsg( "Ctrl+C Event\n" );
         TTCP_LogMsg( "TTCP shutting down...\n" );
         g_bShutdown = TRUE;

         //
         // Flush Logged Messages
         // ---------------------
         // This allows redirected console output to be saved OK.
         //
         fflush( stderr );
         fflush( stdout );

         ExitProcess(1);
         return( TRUE );

      case CTRL_BREAK_EVENT:
      case CTRL_CLOSE_EVENT:
      case CTRL_SHUTDOWN_EVENT:
      default:
         return( FALSE );
   }

   return( FALSE );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -