📄 tcpecho.c
字号:
/////////////////////////////////////////////////////////////////////////////
//// INCLUDE FILES
#include "ndis.h"
#include "TDI.H"
#include "TDIKRNL.H"
//#include "KSTcpEx.h"
#include "KSUtil.h"
#include "TCPEcho.H"
#include "TDIEcho.h"
// Copyright And Configuration Management ----------------------------------
//
// TDI TCP Echo Server Implementation - TCPEcho.c
//
// Network Development Framework (NDF)
// For
// Windows 95 And Windows NT
//
// Copyright (c) 1997-2000, Printing Communications Associates, Inc.
//
// Thomas F. Divine
// 4201 Brunswick Court
// Smyrna, Georgia 30080 USA
// (770) 432-4580
// tdivine@pcausa.com
//
// End ---------------------------------------------------------------------
typedef
struct _TCPS_Connection
{
LIST_ENTRY m_ListElement;
BOOLEAN m_bIsConnectionObjectValid;
KS_ENDPOINT m_KS_Endpoint;
BOOLEAN m_bIsConnected;
BOOLEAN m_bIsDisconnecting;
LIST_ENTRY m_ReceivedTcpPacketList;
TA_IP_ADDRESS m_RemoteAddress;
TDI_CONNECTION_INFORMATION m_RemoteConnectionInfo;
PIRP m_pAcceptIrp;
PIRP m_pDisconnectIrp;
PKEVENT m_pWaitEvent;
}
TCPS_Connection, *PTCPS_Connection;
#define MAX_CONNECTIONS 8
#define TCPS_PACKET_SIGN (UINT)0x45434845 /* ECHO */
#define TCPS_BUFFER_SIZE 4096
typedef
struct _TCPS_PACKET_RESERVED
{
UINT m_Signature; // TCPS_PACKET_SIGN
LIST_ENTRY m_ListElement;
PTCPS_Connection m_pConnection;
UCHAR m_DataBuffer[ TCPS_BUFFER_SIZE ];
IO_STATUS_BLOCK m_PacketIoStatus;
PIRP m_pReceiveIrp;
TA_IP_ADDRESS m_RemoteAddress;
TDI_CONNECTION_INFORMATION m_RemoteConnectionInfo;
ULONG m_nPackingInsurance; // Spare. Do Not Use.
}
TCPS_PACKET_RESERVED, *PTCPS_PACKET_RESERVED;
/* The TCPS_PACKET Structure
----------------------------
* This is an NDIS_PACKET structure which has been extended to include
* additional fields (i.e., TCPS_PACKET_RESERVED) specific to this
* implementation of the ECHO TCP server.
*/
typedef
struct _TCPS_PACKET
{
NDIS_PACKET Packet;
TCPS_PACKET_RESERVED Reserved;
}
TCPS_PACKET, *PTCPS_PACKET;
#define TCPS_PACKET_POOL_SIZE 32
#define TCPS_BUFFER_POOL_SIZE TCPS_PACKET_POOL_SIZE
//
// Notes On Receiving
// ------------------
// The TDIECHO sample illustrates two different methods for receiving TCP
// data:
//
// TdiReceive Requests
// TdiReceive Events
//
// The method used for receiving TCP data is determined at compile time by
// the USE_RECEIVE_EVENT_HANDLER preprocessor directive.
//
// USE_RECEIVE_EVENT_HANDLER not defined
// Receive TCP data by making explicit calls to TdiReceive.
//
// USE_RECEIVE_EVENT_HANDLER defined
// Receive TCP data as it is indicated to the TDI_EVENT_RECEIVE event
// handler.
//
//#define USE_RECEIVE_EVENT_HANDLER
//
// TCPS Global Variables
//
int g_nTCPS_UseCount = 0;
TCPS_Connection g_ConnectionSpace[MAX_CONNECTIONS];
LIST_ENTRY g_FreeConnectionList;
LIST_ENTRY g_OpenConnectionList;
static BOOLEAN g_bPacketPoolAllocated = FALSE;
static NDIS_HANDLE g_hPacketPool = NULL; // NDIS Packet Pool
static BOOLEAN g_bBufferPoolAllocated = FALSE;
static NDIS_HANDLE g_hBufferPool = NULL; // NDIS Buffer Pool
static BOOLEAN g_bAddressOpen = FALSE;
static KS_ADDRESS g_KS_Address;
static TA_IP_ADDRESS g_LocalAddress;
//
// Local Procedure Prototypes
//
VOID
TCPS_SendCompletion(
PVOID UserCompletionContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG Reserved
);
#ifdef USE_RECEIVE_EVENT_HANDLER
NTSTATUS
TCPS_TransferDataCallback(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PVOID pContext
);
#else
VOID
TCPS_ReceiveCompletion(
PVOID UserCompletionContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG Reserved
);
#endif // USE_RECEIVE_EVENT_HANDLER
/////////////////////////////////////////////////////////////////////////////
// U T I L I T Y R O U T I N E S //
/////////////////////////////////////////////////////////////////////////////
PTCPS_Connection
TCPS_AllocConnection( void )
{
PTCPS_Connection pConnection;
//
// Fetch A TCPS_Connection Structure From The Free List
//
if( IsListEmpty( &g_FreeConnectionList ) )
{
return( (PTCPS_Connection )NULL );
}
pConnection = (PTCPS_Connection )RemoveHeadList( &g_FreeConnectionList );
if( !pConnection )
{
return( (PTCPS_Connection )NULL );
}
//
// Sanity Checks
//
ASSERT( pConnection->m_bIsConnectionObjectValid );
if( !pConnection->m_bIsConnectionObjectValid )
{
return( (PTCPS_Connection )NULL );
}
//
// Set Connection State
//
pConnection->m_bIsConnected = FALSE;
pConnection->m_bIsDisconnecting = FALSE;
ASSERT( IsListEmpty( &pConnection->m_ReceivedTcpPacketList ) );
return( pConnection );
}
VOID
TCPS_FreeConnection(
PTCPS_Connection pConnection
)
{
//
// Set Connection State
//
pConnection->m_bIsConnected = FALSE;
pConnection->m_bIsDisconnecting = FALSE;
//
// Return Connection To Free List
//
InsertTailList(
&g_FreeConnectionList,
&pConnection->m_ListElement
);
}
/////////////////////////////////////////////////////////////////////////////
//// TCPS_FreePacketAndBuffers
//
// Purpose
// Free the NDIS_PACKET and associated NDIS_BUFFER's associated with the
// specified TCPS_PACKET.
//
// Parameters
//
// Return Value
//
// Remarks
//
VOID
TCPS_FreePacketAndBuffers(
PTCPS_PACKET pTCPS_Packet
)
{
ULONG nDataSize, nBufferCount;
PNDIS_BUFFER pNdisBuffer;
//
// Sanity Check On Arguments
//
ASSERT( pTCPS_Packet );
if( !pTCPS_Packet )
{
return;
}
//
// Verify The Packet Signature
//
ASSERT( pTCPS_Packet->Reserved.m_Signature == TCPS_PACKET_SIGN );
if( pTCPS_Packet->Reserved.m_Signature != TCPS_PACKET_SIGN )
{
#if DBG
DbgPrint( "TCPS_FreePacketAndBuffers: Invalid Packet Signature\n" );
#endif
return;
}
//
// Invalidate The Signature
//
pTCPS_Packet->Reserved.m_Signature = 0; // Zap The Signature
//
// Recycle The Packet
//
KS_FreePacketAndBuffers( (PNDIS_PACKET )pTCPS_Packet );
}
/////////////////////////////////////////////////////////////////////////////
// C O N N E C T R O U T I N E S //
/////////////////////////////////////////////////////////////////////////////
NTSTATUS
TCPS_ConnectedCallback(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PVOID Context
)
{
PTCPS_Connection pConnection = (PTCPS_Connection )Context;
NTSTATUS nFinalStatus = pIrp->IoStatus.Status;
PTCPS_PACKET pTCPS_Packet;
NDIS_STATUS nNdisStatus;
PNDIS_BUFFER pNdisBuffer;
#if DBG
DbgPrint( "TCPS_ConnectedCallback: FinalStatus: %d\n", nFinalStatus );
#endif
if( NT_SUCCESS( nFinalStatus ) )
{
pConnection->m_bIsConnected = TRUE;
}
else
{
pConnection->m_bIsConnected = FALSE;
pConnection->m_bIsDisconnecting = FALSE;
//
// Remove From Open Connection List
//
RemoveEntryList( &pConnection->m_ListElement );
//
// Return Connection To Free List
//
TCPS_FreeConnection( pConnection );
}
IoFreeIrp( pIrp ); // Don't Access pIrp Any More...
if( !NT_SUCCESS( nFinalStatus ) )
{
return( STATUS_MORE_PROCESSING_REQUIRED );
}
#ifndef USE_RECEIVE_EVENT_HANDLER
//
// Allocate The Receive Packet Descriptor
// --------------------------------------
// Use of this structure is adopted from it's use in lower-level
// NDIS protocol drivers. It is simply a convienient way to allocate
// the space needed to handle packet reception.
//
NdisAllocatePacket(
&nNdisStatus,
&(PNDIS_PACKET )pTCPS_Packet,
g_hPacketPool
);
if( nNdisStatus != NDIS_STATUS_SUCCESS || !pTCPS_Packet )
{
// ATTENTION!!! Update Statistics???
#if DBG
DbgPrint( "TCPS_ConnectedCallback Could Not Allocate Packet\n" );
#endif
return( STATUS_MORE_PROCESSING_REQUIRED );
}
//
// Initialize The Packet Signature
//
pTCPS_Packet->Reserved.m_Signature = TCPS_PACKET_SIGN;
//
// Save Connection Pointer For Use In Callback Routine
//
pTCPS_Packet->Reserved.m_pConnection = pConnection;
//
// Allocate An NDIS Buffer Descriptor For The Receive Data
//
NdisAllocateBuffer(
&nNdisStatus,
&pNdisBuffer,
g_hBufferPool,
pTCPS_Packet->Reserved.m_DataBuffer, // Private Buffer
TCPS_BUFFER_SIZE // Private Buffer's Size
);
if( nNdisStatus != NDIS_STATUS_SUCCESS || !pNdisBuffer )
{
// ATTENTION!!! Update Statistics???
NdisFreePacket( (PNDIS_PACKET )pTCPS_Packet );
#if DBG
DbgPrint( "TCPS_ConnectedCallback Could Not Allocate Buffer\n" );
#endif
return( STATUS_MORE_PROCESSING_REQUIRED );
}
NdisChainBufferAtFront( (PNDIS_PACKET )pTCPS_Packet, pNdisBuffer );
//
// Start A Receive On The Connection
//
KS_ReceiveOnEndpoint(
&pConnection->m_KS_Endpoint,
NULL, // User Completion Event
TCPS_ReceiveCompletion, // User Completion Routine
pTCPS_Packet, // User Completion Context
&pTCPS_Packet->Reserved.m_PacketIoStatus,
pNdisBuffer, // MdlAddress
0 // Flags
);
#endif // USE_RECEIVE_EVENT_HANDLER
return( STATUS_MORE_PROCESSING_REQUIRED );
}
/////////////////////////////////////////////////////////////////////////////
//// TCPS_ConnectEventHandler
//
// Purpose
// Called by the TDI to indicate that a connection request has been received
// from a remote client.
//
// Parameters
// TdiEventContext
// RemoteAddressLength
// RemoteAddress
// UserDataLength
// UserData
// OptionsLength
// Options
// ConnectionContext
// hAcceptIrp
//
// Return Value
//
// Remarks
//
NTSTATUS
TCPS_ConnectEventHandler(
IN PVOID TdiEventContext, // Context From SetEventHandler
IN LONG RemoteAddressLength,
IN PVOID RemoteAddress,
IN LONG UserDataLength, // Unused for MSTCP
IN PVOID UserData, // Unused for MSTCP
IN LONG OptionsLength,
IN PVOID Options,
OUT CONNECTION_CONTEXT *ConnectionContext,
OUT PIRP *hAcceptIrp
)
{
PTCPS_Connection pConnection = NULL;
TDI_STATUS nTdiStatus;
PDEVICE_OBJECT pTCPDeviceObject;
#if DBG
DbgPrint( "TCPS_ConnectEventHandler Entry...\n" );
#endif
//
// Allocate A Connection
//
pConnection = TCPS_AllocConnection();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -