📄 ttcpproxy.cpp
字号:
{
TTCP_ExitTestOnWSAError( pTBlk, "setsockopt: SO_SNDBUF" );
}
TTCP_LogMsg( " SO_SNDBUF : %d\n", pTBlk->m_Cmd.m_nSockOptBufSize );
}
TTCP_InitStatistics( pTBlk );
errno = 0;
if( pTBlk->m_Cmd.m_nOptWriteDelay )
{
TTCP_LogMsg( " Write Delay : %d milliseconds\n",
pTBlk->m_Cmd.m_nOptWriteDelay
);
}
if( pTBlk->m_Cmd.m_bSinkMode )
{
TTCP_FillPattern( pTBlk );
TTCP_Nwrite( pTBlk, UDP_GUARD_BUFFER_LENGTH ); /* rcvr start */
if( pTBlk->m_Cmd.m_bOptContinuous )
{
TTCP_LogMsg( " Send Mode : Send Pattern CONTINUOUS\n" );
while (TTCP_Nwrite( pTBlk, pTBlk->m_Cmd.m_nBufferSize) == pTBlk->m_Cmd.m_nBufferSize)
pTBlk->m_nbytes += pTBlk->m_Cmd.m_nBufferSize;
}
else
{
TTCP_LogMsg( " Send Mode : Send Pattern; Number of Buffers: %d\n",
pTBlk->m_Cmd.m_nNumBuffersToSend
);
while (pTBlk->m_Cmd.m_nNumBuffersToSend--
&& TTCP_Nwrite( pTBlk, pTBlk->m_Cmd.m_nBufferSize) == pTBlk->m_Cmd.m_nBufferSize)
pTBlk->m_nbytes += pTBlk->m_Cmd.m_nBufferSize;
}
TTCP_Nwrite( pTBlk, UDP_GUARD_BUFFER_LENGTH ); /* rcvr end */
}
else
{
register int cnt;
TTCP_LogMsg( " Send Mode : Read from STDIN\n" );
//
// Read From stdin And Write To Remote
//
while( ( cnt = read(0, pTBlk->m_pBuf,pTBlk->m_Cmd.m_nBufferSize ) ) > 0
&& TTCP_Nwrite( pTBlk, cnt) == cnt
)
{
pTBlk->m_nbytes += cnt;
}
}
if(errno)
TTCP_ExitTestOnCRTError( pTBlk, "IO" );
TTCP_LogStatistics( pTBlk );
//
// Pause To Allow Receiver To Flush Receive Buffers
// ------------------------------------------------
// PCATTCP Version 2.01.01.06 and prior (as well as the original TTCP
// application)were subject to failure at various points. This was due
// to the fact that UDP has no flow control, so a UDP transfer overwhelms
// the receiving computer. The reason it was failing was that the end marker
// of the data transfer was getting lost in the network while the receiving
// computer was being overwhelmed with data. This would cause the receiving
// computer to hang, waiting for more data, but the transmitting computer
// had already finished sending all the data along with the end markers.
//
// The folks at Clarkson University identified a simple fix for this
// weakness which PCAUSA has adopted in V2.01.01.07. See the URL:
//
// http://www.clarkson.edu/projects/itl/HOWTOS/mcnair_summer2002/Paper/User_Manual_PCATTCP_Controller_1.00.htm
//
// A simple pause by the transmitter before the end markers were sent would
// allow the receiving computer time to free its internal receiving buffers
// and obtain an end marker.
//
Sleep( 1000 );
TTCP_Nwrite( pTBlk, UDP_GUARD_BUFFER_LENGTH ); // rcvr end
TTCP_Nwrite( pTBlk, UDP_GUARD_BUFFER_LENGTH ); // rcvr end
TTCP_Nwrite( pTBlk, UDP_GUARD_BUFFER_LENGTH ); // rcvr end
TTCP_Nwrite( pTBlk, UDP_GUARD_BUFFER_LENGTH ); // rcvr end
TTCP_FreeTestBlock( pTBlk );
return( 0 );
}
/////////////////////////////////////////////////////////////////////////////
//// TTCP_ReceiveTCP
//
// Purpose
// TTCP TCP stream receiver.
//
// Parameters
// pCmdBlk - Pointer to CMD_BLOCK that contains options and other
// configuration information to be used to receive on
// the stream.
// conn_fd - The connection socket, which returned from a call to
// accept which is made in TTCP_ListenTCP.
//
// Return Value
// Returns zero(0) for normal return. Non-zero otherwise.
//
// Remarks
// The TTCP_ListenTCP routine listens for connections on the TTCP port.
// When a connection is accepted in TTCP_ListenTCP it then calls this
// function to perform the TCP receive test on the connection socket.
//
// Ownership of the conn_fd socket is passed to this routine, which is
// responsible for eventually closing it.
//
DWORD WINAPI TTCP_ReceiveTCP( PCMD_BLOCK pCmdBlk )
{
PTEST_BLOCK pTBlk = NULL;
//
// Allocate Test Instance Data
// ---------------------------
// Allocate a TEST_BLOCK for this specific instance. The TEST_BLOCK
// contains a copy of the calleer's CMD_BLOCK as well as additional
// members that are used to perform this test.
//
pTBlk = TTCP_AllocateTestBlock( pCmdBlk );
if( !pTBlk )
{
closesocket( pCmdBlk->m_ExtraSocket );
TTCP_ExitTestOnCRTError( NULL, "malloc" );
return( 1 );
}
//
// Save The Connection Socket
//
pTBlk->m_Socket_fd = pCmdBlk->m_ExtraSocket;
pTBlk->m_Cmd.m_Protocol = IPPROTO_TCP;
//
// Allocate The Buffer Send/Receive Data
//
if( !TTCP_AllocateBuffer( pTBlk ) )
{
TTCP_ExitTestOnCRTError( pTBlk, "malloc" );
return( 1 );
}
TTCP_InitStatistics( pTBlk );
errno = 0;
TCP_ORIGINAL_INFO OriginalInfo;
if( TcpRedirector_GetOriginalDestination( &OriginalInfo, sizeof( OriginalInfo ), IPPORT_TTCP_PROXY ) == TRUE )
{
struct in_addr in_temp;
in_temp.S_un.S_addr = OriginalInfo.RemoteAddress;
TTCP_LogMsg( " Original : TCP <- %s:%d from %s (%d)\n",
inet_ntoa( in_temp ),
OriginalInfo.RemotePort,
OriginalInfo.OriginatorProcessName,
OriginalInfo.OriginatorProcessId
);
}
if( pTBlk->m_Cmd.m_bSinkMode )
{
register int cnt;
//
// Discard Received Data
//
TTCP_LogMsg( " Receive Mode: Sinking (discarding) Data\n" );
while( (cnt=TTCP_Nread( pTBlk, pTBlk->m_Cmd.m_nBufferSize) ) > 0)
{
pTBlk->m_nbytes += cnt;
}
}
else
{
register int cnt;
//
// Read From Remote And Write To stdout
//
TTCP_LogMsg( " Receive Mode: Writing Received Data To STDOUT\n" );
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" );
TTCP_LogStatistics( pTBlk );
TTCP_FreeTestBlock( pTBlk );
return( 0 );
}
/////////////////////////////////////////////////////////////////////////////
//// TTCP_ListenTCP
//
// Purpose
// TTCP TCP connection listener.
//
// Parameters
// pCmdBlk - Pointer to CMD_BLOCK that contains options and other
// configuration information to be used to listen for
// connections.
//
// Return Value
// Returns zero(0) for normal return. Non-zero otherwise.
//
// Remarks
// The TTCP_ListenTCP routine listens for connections on the TTCP port.
//
// When a connection is accepted TTCP_ListenTCP calls TTCP_ReceiveTCP
// function to perform the actual TCP receive test.
//
// Ownership of the conn_fd socket is passed to TTCP_ReceiveTCP routine,
// which is responsible for eventually closing conn_fd.
//
DWORD WINAPI TTCP_ListenTCP( PCMD_BLOCK pCmdBlk )
{
PTEST_BLOCK pTBlk = NULL;
SOCKET conn_fd;
BOOLEAN bDoAccept = TRUE;
CHAR szLocalHostName[ 128 ];
TTCP_LogMsg( "TCP Receive Test\n" );
//
// Allocate Test Instance Data
// ---------------------------
// Allocate a TEST_BLOCK for this specific instance. The TEST_BLOCK
// contains a copy of the calleer's CMD_BLOCK as well as additional
// members that are used to perform this test.
//
pTBlk = TTCP_AllocateTestBlock( pCmdBlk );
if( !pTBlk )
{
TTCP_ExitTestOnCRTError( NULL, "malloc" );
return( 1 );
}
sprintf( szLocalHostName, "Unknown" );
gethostname( szLocalHostName, 128 );
TTCP_LogMsg( " Local Host : %s\n", szLocalHostName );
//
// Setup Local IP Addresses For Test
//
pTBlk->m_Cmd.m_LocalAddress.sin_family = AF_INET;
pTBlk->m_Cmd.m_LocalAddress.sin_port = htons( pTBlk->m_Cmd.m_Port );
//
// Open Listening Socket
//
if( (pTBlk->m_Socket_fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == INVALID_SOCKET )
{
TTCP_ExitTestOnWSAError( pTBlk, "socket" );
}
//
// Bind Socket With Local Address
//
if( bind(
pTBlk->m_Socket_fd,
(PSOCKADDR )&pTBlk->m_Cmd.m_LocalAddress,
sizeof(pTBlk->m_Cmd.m_LocalAddress)
) == SOCKET_ERROR
)
{
TTCP_ExitTestOnWSAError( pTBlk, "bind" );
}
if( pTBlk->m_Cmd.m_bUseSockOptBufSize )
{
if( setsockopt(
pTBlk->m_Socket_fd,
SOL_SOCKET,
SO_RCVBUF,
(char * )&pTBlk->m_Cmd.m_nSockOptBufSize,
sizeof pTBlk->m_Cmd.m_nSockOptBufSize
) == SOCKET_ERROR
)
{
TTCP_ExitTestOnWSAError( pTBlk, "setsockopt: SO_RCVBUF" );
}
TTCP_LogMsg( " SO_RCVBUF : %d\n", pTBlk->m_Cmd.m_nSockOptBufSize );
}
//
// Start TCP Connections
// ---------------------
// We Are The Server.
//
listen( pTBlk->m_Socket_fd, 0 ); // allow a queue of 0
if( pTBlk->m_Cmd.m_bSockOptDebug )
{
if( setsockopt(
pTBlk->m_Socket_fd,
SOL_SOCKET,
SO_DEBUG,
(PCHAR )&one, // Boolean
sizeof(one)
) == SOCKET_ERROR
)
{
TTCP_ExitTestOnWSAError( pTBlk, "setsockopt: SO_DEBUG" );
}
}
pTBlk->m_Cmd.m_nRemoteAddrLen = sizeof( pTBlk->m_Cmd.m_RemoteAddr );
while( bDoAccept )
{
DWORD tid; // Thread ID
TTCP_LogMsg( "**************\n" );
TTCP_LogMsg( " Listening...: On port %d\n", pTBlk->m_Cmd.m_Port );
if( ( conn_fd = accept( pTBlk->m_Socket_fd, (PSOCKADDR )&pTBlk->m_Cmd.m_RemoteAddr,
&pTBlk->m_Cmd.m_nRemoteAddrLen) ) == SOCKET_ERROR)
{
TTCP_ExitTestOnWSAError( pTBlk, "accept" );
}
else
{
SOCKADDR_IN peer;
int peerlen = sizeof(peer);
if (getpeername( conn_fd, (PSOCKADDR ) &peer,
&peerlen) == SOCKET_ERROR)
{
TTCP_ExitTestOnWSAError( pTBlk, "getpeername" );
}
pCmdBlk->m_RemoteAddr.sin_addr.s_addr = peer.sin_addr.s_addr;
pCmdBlk->m_RemoteAddr.sin_port = peer.sin_port;
TTCP_LogMsg( "\n Accept : TCP <- %s:%d\n",
inet_ntoa( pCmdBlk->m_RemoteAddr.sin_addr ),
htons( pCmdBlk->m_RemoteAddr.sin_port ) );
}
pTBlk->m_Cmd.m_ExtraSocket = conn_fd;
if( pCmdBlk->m_bOptMultiReceiver )
{
CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE )TTCP_ReceiveTCP,
&pTBlk->m_Cmd,
0,
&tid
);
}
else
{
TTCP_ReceiveTCP( &pTBlk->m_Cmd );
}
if( !pTBlk->m_Cmd.m_bOptContinuous )
{
bDoAccept = FALSE;
}
}
TTCP_FreeTestBlock( pTBlk );
return( 0 );
}
/////////////////////////////////////////////////////////////////////////////
//// TTCP_ReceiveUDP
//
// Purpose
// TTCP UDP datagram receiver.
//
// Parameters
// pCmdBlk - Pointer to CMD_BLOCK that contains options and other
// configuration information.
//
// Return Value
// Returns zero(0) for normal return. Non-zero otherwise.
//
// Remarks
// The TTCP_ReceiveUDP routine performs the TTCP UDP receive test.
//
DWORD WINAPI TTCP_ReceiveUDP( PCMD_BLOCK pCmdBlk )
{
PTEST_BLOCK pTBlk = NULL;
BOOLEAN bContinue = TRUE;
TTCP_LogMsg( "UDP Receive Test\n" );
//
// Allocate Test Instance Data
// ---------------------------
// Allocate a TEST_BLOCK for this specific instance. The TEST_BLOCK
// contains a copy of the calleer's CMD_BLOCK as well as additional
// members that are used to perform this test.
//
pTBlk = TTCP_AllocateTestBlock( pCmdBlk );
if( !pTBlk )
{
TTCP_ExitTestOnCRTError( NULL, "malloc" );
return( 1 );
}
TTCP_LogMsg( " Protocol : UDP\n" );
TTCP_LogMsg( " Port : %d\n", pTBlk->m_Cmd.m_Port );
//
// Setup Local IP Addresses For Test
//
pTBlk->m_Cmd.m_LocalAddress.sin_family = AF_INET;
pTBlk->m_Cmd.m_LocalAddress.sin_port = htons( pTBlk->m_Cmd.m_Port );
//
// Setup Buffer Configuration
//
if( pTBlk->m_Cmd.m_nBufferSize <= UDP_GUARD_BUFFER_LENGTH
)
{
pTBlk->m_Cmd.m_nBufferSize = UDP_GUARD_BUFFER_LENGTH + 1; // send more than the sentinel size
}
//
// Allocate The Buffer Send/Receive Data
//
if( !TTCP_AllocateBuffer( pTBlk ) )
{
TTCP_ExitTestOnCRTError( pTBlk, "malloc" );
}
//
// Open Socket For Test
//
if( (pTBlk->m_Socket_fd = socket( AF_INET, SOCK_DGRAM, 0 ) ) == INVALID_SOCKET )
{
TTCP_ExitTestOnWSAError( pTBlk, "socket" );
}
//
// Bind Socket With Local Address
//
if( bind(
pTBlk->m_Socket_fd,
(PSOCKADDR )&pTBlk->m_Cmd.m_LocalAddress,
sizeof(pTBlk->m_Cmd.m_LocalAddress)
) == SOCKET_ERROR
)
{
TTCP_ExitTestOnWSAError( pTBlk, "bind" );
}
if( pTBlk->m_Cmd.m_bUseSockOptBufSize )
{
if( setsockopt(
pTBlk->m_Socket_fd,
SOL_SOCKET,
SO_RCVBUF,
(char * )&pTBlk->m_Cmd.m_nSockOptBufSize,
sizeof pTBlk->m_Cmd.m_nSockOptBufSize
) == SOCKET_ERROR
)
{
TTCP_ExitTestOnWSAError( pTBlk, "setsockopt: SO_RCVBUF" );
}
TTCP_LogMsg( " SO_RCVBUF : %d\n", pTBlk->m_Cmd.m_nSockOptBufSize );
}
while( bContinue )
{
TTCP_InitStatistics( pTBlk );
errno = 0;
memset(
&pTBlk->m_Cmd.m_RemoteAddr,
0x00,
sizeof( IN_ADDR )
);
if( pTBlk->m_Cmd.m_bSinkMode )
{
register int cnt;
int going = 0;
BOOLEAN bIsFirst = TRUE;
while( (cnt=TTCP_Nread( pTBlk, pTBlk->m_Cmd.m_nBufferSize)) > 0 )
{
if( cnt <= UDP_GUARD_BUFFER_LENGTH )
{
if( going )
{
going = 0;
break; /* "EOF" */
}
going = 1;
TTCP_InitStatistics( pTBlk );
}
else
{
if( bIsFirst )
{
TTCP_LogMsg( " recvfrom : UDP <- %s:%d\n",
inet_ntoa( pTBlk->m_Cmd.m_RemoteAddr.sin_addr ),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -