📄 ttcpproxy.cpp
字号:
htons( pTBlk->m_Cmd.m_RemoteAddr.sin_port ) );
bIsFirst = FALSE;
}
pTBlk->m_nbytes += cnt;
}
}
}
else
{
register int cnt;
//
// Read From Remote And Write To stdout
//
while( ( cnt = TTCP_Nread( pTBlk, pTBlk->m_Cmd.m_nBufferSize ) ) > 0
&& write(1, pTBlk->m_pBuf,cnt) == cnt
)
{
pTBlk->m_nbytes += cnt;
}
}
if(errno)
TTCP_ExitTestOnCRTError( pTBlk, "IO" );
if( pTBlk->m_nbytes > 0 )
{
TTCP_LogStatistics( pTBlk );
}
if( !pTBlk->m_Cmd.m_bOptContinuous )
{
bContinue = FALSE;
}
}
TTCP_FreeTestBlock( pTBlk );
return( 0 );
}
//
// Usage Message
//
char Usage[] = "\
Usage: pcattcp -t [-options] host [ < in ]\n\
pcattcp -r [-options > out]\n\
Common options:\n\
-l ## length of bufs read from or written to network (default 8192)\n\
-u use UDP instead of TCP\n\
-p ## port number to send to or listen at (default 5001)\n\
-s toggle sinkmode (enabled by default)\n\
sinkmode enabled:\n\
-t: source (transmit) fabricated pattern\n\
-r: sink (discard) all received data\n\
sinkmode disabled:\n\
-t: reads data to be transmitted from stdin\n\
-r: writes received data to stdout\n\
-A align the start of buffers to this modulus (default 16384)\n\
-O start buffers at this offset from the modulus (default 0)\n\
-v verbose: print more statistics\n\
-d set SO_DEBUG socket option\n\
-b ## set socket buffer size (if supported)\n\
-f X format for rate: k,K = kilo{bit,byte}; m,M = mega; g,G = giga\n\
-c -t: send continuously\n\
-r: accept multiple connections sequentially\n\
-R concurrent TCP/UDP multithreaded receiver\n\
Options specific to -t:\n\
-n ## number of source bufs written to network (default 2048)\n\
-D don't buffer TCP writes (sets TCP_NODELAY socket option)\n\
-w ## milliseconds of delay before each write (default 0)\n\
Options specific to -r:\n\
-B for -s, only output full blocks as specified by -l (for TAR)\n\
-T \"touch\": access each byte as it's read\n\
";
/////////////////////////////////////////////////////////////////////////////
//// TTCP_ParseCommandLine
//
// Purpose
// Parse the console application command-line arguments and setup the
// CMD_BLOCK/
//
// Parameters
// pCmdBlk - Pointer to CMD_BLOCK to be filled with parsed option
// information.
//
// Return Value
// Returns zero(0) for normal return. Non-zero otherwise.
//
// Remarks
//
int TTCP_ParseCommandLine( PCMD_BLOCK pCmdBlk, int argc, char **argv )
{
int c;
if (argc < 2)
{
fprintf( stderr, Usage );
return( !0 );
}
while (optind != argc)
{
c = getopt(argc, argv, "cdrstuvBDRTb:f:l:n:p:A:O:w:" );
switch (c)
{
case EOF:
optarg = argv[optind];
optind++;
break;
case 'B':
b_flag = 1;
break;
case 't':
pCmdBlk->m_bTransmit = TRUE;
break;
case 'r':
pCmdBlk->m_bTransmit = FALSE;
break;
case 'c':
pCmdBlk->m_bOptContinuous = TRUE;
break;
case 'd':
pCmdBlk->m_bSockOptDebug = 1;
break;
case 'D':
pCmdBlk->m_nSockOptNoDelay = 1;
break;
case 'R':
pCmdBlk->m_bOptContinuous = TRUE;
pCmdBlk->m_bTransmit = FALSE;
pCmdBlk->m_bOptMultiReceiver = TRUE;
break;
case 'n':
pCmdBlk->m_nNumBuffersToSend = atoi(optarg);
break;
case 'l':
pCmdBlk->m_nBufferSize = atoi(optarg);
break;
case 's':
pCmdBlk->m_bSinkMode = !pCmdBlk->m_bSinkMode;
break;
case 'p':
pCmdBlk->m_Port = atoi(optarg);
break;
case 'u':
pCmdBlk->m_Protocol = IPPROTO_UDP;
break;
case 'v':
verbose = 1;
break;
case 'A':
pCmdBlk->m_nBufAlign = atoi(optarg);
break;
case 'O':
pCmdBlk->m_nBufOffset = atoi(optarg);
break;
case 'b':
pCmdBlk->m_bUseSockOptBufSize = TRUE;
pCmdBlk->m_nSockOptBufSize = atoi(optarg);
if( pCmdBlk->m_nSockOptBufSize < 0 )
{
pCmdBlk->m_nSockOptBufSize = 0;
}
break;
case 'f':
fmt = *optarg;
break;
case 'T':
pCmdBlk->m_bTouchRecvData = 1;
break;
case 'w':
pCmdBlk->m_nOptWriteDelay = atoi(optarg);
break;
default:
fprintf( stderr, Usage );
return( !0 );
}
}
return( 0 );
}
/////////////////////////////////////////////////////////////////////////////
//// MAIN Program Entry Point
//
int _tmain(int argc, _TCHAR* argv[])
{
CMD_BLOCK cmdBlock;
//
// Say Hello
//
TTCP_LogMsg( "PCAUSA TTCP Proxy V%s\n", PCATTCP_VERSION );
//
// Fetch Command/Options For This Test
//
TTCP_SetConfigDefaults( &cmdBlock );
if( TTCP_ParseCommandLine( &cmdBlock, argc, argv ) != 0 )
{
return( 0 );
}
if (!TcpRedirector_Startup())
{
printf( "%s Driver Not Loaded\n", TDIREDIR_BASE_NAME );
return 0;
}
else
printf( "%s Driver Loaded\n", TDIREDIR_BASE_NAME );
//
// Start Winsock 2
//
if( WSAStartup( MAKEWORD(0x02,0x00), &g_WsaData ) == SOCKET_ERROR )
{
fprintf( stderr, Usage );
TTCP_ExitTestOnWSAError( NULL, "WSAStartup" );
}
PTCP_REDIR_RULE_BUFFER pRuleBuffer = NULL;
// Allocate the Redirection Rule Buffer
pRuleBuffer = TcpRedirector_AllocateRuleBuffer();
if( pRuleBuffer == NULL )
{
printf( "Redirection Rule Buffer Allocation Failed\n" );
// Cleanup
TcpRedirector_Shutdown();
WSACleanup();
return 0;
}
// 192.168.1.20 - 192.168.1.100:5001 -> 127.0.0.1:5002
// Redirect Any Process Except "TTCPPROXY.EXE"
pRuleBuffer = TcpRedirector_AddPortRule(
pRuleBuffer,
inet_addr( "192.168.1.20" ), // RemoteAddressRangeStart
inet_addr( "192.168.1.100" ), // RemoteAddressRangeEnd
inet_addr( "255.255.255.0" ), // RemoteNetMask
IPPORT_TTCP, // RemotePort
NULL,
"ttcpproxy.exe",
(HANDLE )GetCurrentProcessId(),
inet_addr( "127.0.0.1" ), // RedirectToAddress
IPPORT_TTCP_PROXY // RedirectToPort
);
// Crude Rule Dumper for Debug...
DumpRuleBuffer( pRuleBuffer );
// Pass Redirection Rules to Driver
TcpRedirector_SetRedirectRules( pRuleBuffer, pRuleBuffer->TotalBufferSize );
//
// Set The Ctrl-C Handler
//
SetConsoleCtrlHandler( CtrlHandler, TRUE );
if( cmdBlock.m_bOptMultiReceiver )
{
TTCP_LogMsg( " Threading : Multithreaded\n" );
}
//
// Dispatch To Specialized Procedues
//
if( cmdBlock.m_bTransmit )
{
DWORD nResult;
if( cmdBlock.m_Protocol == IPPROTO_UDP )
{
nResult = TTCP_TransmitUDP( &cmdBlock, argv[argc - 1] );
}
else
{
nResult = TTCP_TransmitTCP( &cmdBlock, argv[argc - 1] );
}
}
else
{
DWORD nResult;
if( cmdBlock.m_bOptMultiReceiver )
{
if( cmdBlock.m_Protocol == IPPROTO_UDP )
{
nResult = TTCP_ReceiveUDP( &cmdBlock );
}
else
{
HANDLE RxThreadHandles[ 2 ]; // Thread Handles
DWORD tid[2]; // Thread IDs
//
// Run TCP Connection Listener In New Thread
//
cmdBlock.m_Protocol = IPPROTO_TCP;
RxThreadHandles[0] = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE )TTCP_ListenTCP,
&cmdBlock,
0,
&tid[0]
);
//cmdBlock.m_Protocol = IPPROTO_UDP;
//nResult = TTCP_ReceiveUDP( &cmdBlock );
}
}
else
{
if( cmdBlock.m_Protocol == IPPROTO_UDP )
{
nResult = TTCP_ReceiveUDP( &cmdBlock );
}
else
{
nResult = TTCP_ListenTCP( &cmdBlock );
}
}
}
// Cleanup
TcpRedirector_ClearRedirectRules();
TcpRedirector_Shutdown();
WSACleanup();
return( 0 );
}
/*
* N R E A D
*/
int TTCP_Nread( PTEST_BLOCK pTBlk, int count )
{
SOCKADDR_IN from;
int len = sizeof(from);
register int cnt;
if( pTBlk->m_Cmd.m_Protocol == IPPROTO_UDP )
{
cnt = recvfrom( pTBlk->m_Socket_fd,
pTBlk->m_pBuf, count, 0,
(PSOCKADDR )&from,
&len
);
pTBlk->m_Cmd.m_RemoteAddr.sin_addr.s_addr = from.sin_addr.s_addr;
pTBlk->m_Cmd.m_RemoteAddr.sin_port = from.sin_port;
pTBlk->m_numCalls++;
}
else
{
if( b_flag )
{
cnt = TTCP_mread( pTBlk, count ); /* fill buf */
}
else
{
cnt = recv( pTBlk->m_Socket_fd, pTBlk->m_pBuf, count, 0 );
if( cnt == SOCKET_ERROR )
{
int nError = WSAGetLastError();
}
pTBlk->m_numCalls++;
}
}
if( pTBlk->m_Cmd.m_bTouchRecvData && cnt > 0 )
{
register int c = cnt, sum;
register char *b = pTBlk->m_pBuf;
sum = 0;
while (c--)
sum += *b++;
}
return(cnt);
}
/*
* N W R I T E
*/
int TTCP_Nwrite( PTEST_BLOCK pTBlk, int count )
{
register int cnt;
//
// Introduce Write Delay After First Write Call
//
if( pTBlk->m_Cmd.m_nOptWriteDelay && pTBlk->m_numCalls > 0 )
{
Sleep( pTBlk->m_Cmd.m_nOptWriteDelay );
}
if( pTBlk->m_Cmd.m_Protocol == IPPROTO_UDP )
{
again:
cnt = sendto( pTBlk->m_Socket_fd, pTBlk->m_pBuf, count, 0,
(PSOCKADDR )&pTBlk->m_Cmd.m_RemoteAddr,
sizeof(pTBlk->m_Cmd.m_RemoteAddr)
);
pTBlk->m_numCalls++;
if( cnt == SOCKET_ERROR && WSAGetLastError() == WSAENOBUFS )
{
delay(18000);
errno = 0;
goto again;
}
}
else
{
cnt = send( pTBlk->m_Socket_fd, pTBlk->m_pBuf, count, 0 );
pTBlk->m_numCalls++;
}
return(cnt);
}
void delay( int us )
{
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = us;
select( 1, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
}
/*
* M R E A D
*
* This function performs the function of a read(II) but will
* call read(II) multiple times in order to get the requested
* number of characters. This can be necessary because
* network connections don't deliver data with the same
* grouping as it is written with. Written by Robert S. Miles, BRL.
*/
int TTCP_mread( PTEST_BLOCK pTBlk, unsigned n)
{
char *bufp = pTBlk->m_pBuf;
register unsigned count = 0;
register int nread;
do
{
nread = recv( pTBlk->m_Socket_fd, bufp, n-count, 0);
pTBlk->m_numCalls++;
if(nread < 0) {
perror("ttcp_mread");
return(-1);
}
if(nread == 0)
return((int)count);
count += (unsigned)nread;
bufp += nread;
}
while(count < n);
return((int)count);
}
#define END(x) {while(*x) x++;}
char *outfmt( double b )
{
static char obuf[50];
switch (fmt) {
case 'G':
sprintf(obuf, "%.2f GB", b / 1024.0 / 1024.0 / 1024.0);
break;
default:
case 'K':
sprintf(obuf, "%.2f KB", b / 1024.0);
break;
case 'M':
sprintf(obuf, "%.2f MB", b / 1024.0 / 1024.0);
break;
case 'g':
sprintf(obuf, "%.2f Gbit", b * 8.0 / 1024.0 / 1024.0 / 1024.0);
break;
case 'k':
sprintf(obuf, "%.2f Kbit", b * 8.0 / 1024.0);
break;
case 'm':
sprintf(obuf, "%.2f Mbit", b * 8.0 / 1024.0 / 1024.0);
break;
}
return obuf;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -