📄 tcpclient.c
字号:
//
NTSTATUS TCPC_ReceiveEventHandler(
IN PVOID TdiEventContext, // Context From SetEventHandler
IN CONNECTION_CONTEXT ConnectionContext,
IN ULONG ReceiveFlags,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG *BytesTaken,
IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes
OUT PIRP *IoRequestPacket // TdiReceive IRP if MORE_PROCESSING_REQUIRED.
)
{
// KdPrint(("TCPC_ReceiveEventHandler: Entry...\n") );
KdPrint((" Bytes Indicated: %d; BytesAvailable: %d; Flags: 0x%8.8x\n",
BytesIndicated, BytesAvailable, ReceiveFlags));
return( STATUS_SUCCESS );
}
/////////////////////////////////////////////////////////////////////////////
//// TCPC_ReceiveExpeditedEventHandler
//
// Purpose
//
// Parameters
// TdiEventContext - Pointer to TCPC_SESSION structure for the session.
//
// Return Value
//
// Remarks
// This indication is delivered if expedited data is received on the connection.
// This will only occur in providers that support expedited data.
//
NTSTATUS TCPC_ReceiveExpeditedEventHandler(
IN PVOID TdiEventContext, // Context From SetEventHandler
IN CONNECTION_CONTEXT ConnectionContext,
IN ULONG ReceiveFlags, //
IN ULONG BytesIndicated, // number of bytes in this indication
IN ULONG BytesAvailable, // number of bytes in complete Tsdu
OUT ULONG *BytesTaken, // number of bytes used by indication routine
IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes
OUT PIRP *IoRequestPacket // TdiReceive IRP if MORE_PROCESSING_REQUIRED.
)
{
KdPrint(("TCPC_ReceiveExpeditedEventHandler: Entry...\n") );
KdPrint((" Bytes Indicated: %d; BytesAvailable: %d; Flags: 0x%8.8x\n",
BytesIndicated, BytesAvailable, ReceiveFlags));
return( STATUS_SUCCESS );
}
VOID
TCPC_SendCompletion(
PVOID UserCompletionContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG Reserved
)
{
PTCPC_SESSION pSession = (PTCPC_SESSION )UserCompletionContext;
NTSTATUS Status = STATUS_SUCCESS;
if( NT_SUCCESS( IoStatusBlock->Status ) )
{
// KdPrint(( "TCPC_SendBuffer: Sent %d Bytes\n", IoStatusBlock->Information ));
}
else
{
KdPrint(( "TCPC_SendBuffer: Status 0x%8.8X\n", IoStatusBlock->Status ));
KeSetEvent( &pSession->m_FinalSendEvent, 0, FALSE );
return;
}
--pSession->m_nNumBuffersToSend; // Sent One
if( pSession->m_nNumBuffersToSend )
{
// ATTENTION!!!
// ------------
// Do not call KS_SendOnEndpoint (which eventually calls
// IoCallDriver) directly from this completion routine. Use a
// worker thread, running at IRQL = PASSIVE_LEVEL, to make the
// call.
//
//
// Start Another Asynchronous Send On The Connection
//
(pSession->m_pPatternMdl)->Next = NULL; // IMPORTANT!!!
Status = KS_SendOnEndpoint(
&pSession->m_KS_Endpoint,
NULL, // User Completion Event
TCPC_SendCompletion, // User Completion Routine
pSession, // User Completion Context
&pSession->m_PatternIoStatus,
pSession->m_pPatternMdl,
0 // Send Flags
);
if( !NT_SUCCESS( Status ) )
{
if( Status != STATUS_PENDING )
{
KdPrint(( "TCPC_SendBuffer: Status 0x%8.8X\n", IoStatusBlock->Status ));
KeSetEvent( &pSession->m_FinalSendEvent, 0, FALSE );
return;
}
}
}
else
{
KeSetEvent( &pSession->m_FinalSendEvent, 0, FALSE );
}
}
/////////////////////////////////////////////////////////////////////////////
//// DoQueryAddressInfoTest
//
// Purpose
// Demonstrate TD_ADDRESS_INFO TDI Query
//
// Parameters
//
// Return Value
//
// Remarks
//
VOID
DoQueryAddressInfoTest(
PTCPC_SESSION pSession
)
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG nInfoBufferSize = sizeof( pSession->m_InfoBuffer );
//
// Query TDI Address Info On Transport Address
//
Status = KS_QueryAddressInfo(
pSession->m_KS_Address.m_pFileObject, // Address Object
pSession->m_InfoBuffer,
&nInfoBufferSize
);
KdPrint(( "Query Address Info Status: 0x%8.8x\n", Status ));
if( NT_SUCCESS( Status ) )
{
DEBUG_DumpAddressInfo( (PTDI_ADDRESS_INFO )pSession->m_InfoBuffer );
}
//
// Query TDI Address Info On Connection Endpoint
//
Status = KS_QueryAddressInfo(
pSession->m_KS_Endpoint.m_pFileObject, // Connection Object
pSession->m_InfoBuffer,
&nInfoBufferSize
);
KdPrint(( "Query Address Info Status: 0x%8.8x\n", Status ));
if( NT_SUCCESS( Status ) )
{
DEBUG_DumpAddressInfo( (PTDI_ADDRESS_INFO )pSession->m_InfoBuffer );
}
}
/////////////////////////////////////////////////////////////////////////////
//// DoQueryConnectionInfoTest
//
// Purpose
// Demonstrate TD_CONNECTION_INFO TDI Query
//
// Parameters
//
// Return Value
//
// Remarks
//
VOID
DoQueryConnectionInfoTest(
PTCPC_SESSION pSession
)
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG nInfoBufferSize = sizeof( pSession->m_InfoBuffer );
//
// Query TDI Connection Info
//
Status = KS_QueryConnectionInfo(
&pSession->m_KS_Endpoint, // Connection Endpoint
pSession->m_InfoBuffer,
&nInfoBufferSize
);
KdPrint(( "Query Connection Info Status: 0x%8.8x\n", Status ));
if( NT_SUCCESS( Status ) )
{
DEBUG_DumpConnectionInfo( (PTDI_CONNECTION_INFO )pSession->m_InfoBuffer );
}
}
/////////////////////////////////////////////////////////////////////////////
//// TCPC_TestThread
//
// Purpose
//
// Parameters
//
// Return Value
//
// Remarks
//
VOID
TCPC_TestThread(
IN PVOID pContext
)
{
NTSTATUS Status = STATUS_SUCCESS;
NDIS_STATUS nNdisStatus;
PTTCP_TEST_START_CMD pStartCmd = NULL;
PTCPC_SESSION pSession = (PTCPC_SESSION )pContext;
LARGE_INTEGER DelayTime;
IO_STATUS_BLOCK IoStatusBlock;
KdPrint(("TCPC_TestThread: Starting...\n") );
//
// Initialize Default Settings
//
Status = STATUS_SUCCESS; // Always Indicate I/O Success
//
// Locate Test Session Parameter Buffer
//
pSession = (PTCPC_SESSION )pContext;
//
// Allocate The Pattern Buffer
//
pSession->m_PatternBufferSize = pSession->m_TestParams.m_nBufferSize;
pSession->m_nNumBuffersToSend = pSession->m_TestParams.m_nNumBuffersToSend;
nNdisStatus = NdisAllocateMemory(
&pSession->m_pPatternBuffer,
pSession->m_PatternBufferSize,
0, // Allocate non-paged system-space memory
HighestAcceptableMax
);
if( !NT_SUCCESS( nNdisStatus ) )
{
pSession->m_pPatternBuffer = NULL;
goto ExitTheThread;
}
TDITTCP_FillPatternBuffer(
pSession->m_pPatternBuffer,
pSession->m_PatternBufferSize
);
pSession->m_pPatternMdl = KS_AllocateAndProbeMdl(
pSession->m_pPatternBuffer, // Virtual Address
pSession->m_PatternBufferSize,
FALSE,
FALSE,
NULL
);
if( !pSession->m_pPatternMdl )
{
goto ExitTheThread;
}
//
// Setup Local TDI Address
//
KS_InitIPAddress(
&pSession->m_LocalAddress,
INADDR_ANY, // Any Local Address
0 // Any Local Port
);
//
// Open Transport Address
//
Status = KS_OpenTransportAddress(
TCP_DEVICE_NAME_W,
(PTRANSPORT_ADDRESS )&pSession->m_LocalAddress,
&pSession->m_KS_Address
);
if( !NT_SUCCESS( Status ) )
{
//
// Address Object Could Not Be Created
//
goto ExitTheThread;
}
//
// Create The Connection Endpoint
//
Status = KS_OpenConnectionEndpoint(
TCP_DEVICE_NAME_W,
&pSession->m_KS_Address,
&pSession->m_KS_Endpoint,
&pSession->m_KS_Endpoint // Context
);
if( !NT_SUCCESS( Status ) )
{
//
// Connection Endpoint Could Not Be Created
//
KS_CloseConnectionEndpoint( &pSession->m_KS_Endpoint );
KS_CloseTransportAddress( &pSession->m_KS_Address );
goto ExitTheThread;
}
KdPrint(("TCPC_TestThread: Created Local TDI Connection Endpoint\n") );
KdPrint((" pSession: 0x%8.8X; pAddress: 0x%8.8X; pConnection: 0x%8.8X\n",
(ULONG )pSession,
(ULONG )&pSession->m_KS_Address,
(ULONG )&pSession->m_KS_Endpoint
));
//
// Setup Event Handlers On The Address Object
//
Status = KS_SetEventHandlers(
&pSession->m_KS_Address,
pSession, // Event Context
NULL, // ConnectEventHandler
TCPC_DisconnectEventHandler,
TCPC_ErrorEventHandler,
TCPC_ReceiveEventHandler,
NULL, // ReceiveDatagramEventHandler
TCPC_ReceiveExpeditedEventHandler
);
if( !NT_SUCCESS( Status ) )
{
//
// Event Handlers Could Not Be Set
//
KS_CloseConnectionEndpoint( &pSession->m_KS_Endpoint );
KS_CloseTransportAddress( &pSession->m_KS_Address );
goto ExitTheThread;
}
KdPrint(("TCPC_TestThread: Set Event Handlers On The Address Object\n") );
//
// Setup Remote TDI Address
//
KS_InitIPAddress(
&pSession->m_RemoteAddress,
pSession->m_TestParams.m_RemoteAddress.s_addr,
pSession->m_TestParams.m_Port
);
//
// Request Connection To Remote Node
//
Status = KS_Connect(
&pSession->m_KS_Endpoint,
(PTRANSPORT_ADDRESS )&pSession->m_RemoteAddress
);
KdPrint(( "Connect Status: 0x%8.8x\n", Status ));
if( NT_SUCCESS( nNdisStatus ) )
{
//
// Specify NODELAY Send Option On The Connection Endpoint
// ------------------------------------------------------
// Returns successfully, BUT does not appear to effect TCP stream.
//
if( pSession->m_TestParams.m_nNoDelay )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -