📄 udpecho.c
字号:
/////////////////////////////////////////////////////////////////////////////
//// INCLUDE FILES
#include "ndis.h"
#include "TDI.H"
#include "TDIKRNL.H"
#include "KSUtil.h"
#include "UDPEcho.H"
#include "TDIEcho.h"
// Copyright And Configuration Management ----------------------------------
//
// TDI UDP Echo Server Implementation - UDPEcho.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 ---------------------------------------------------------------------
#define UDPS_PACKET_SIGN (UINT)0x45434845 /* ECHO */
#define UDPS_BUFFER_SIZE 4096
typedef
struct _UDPS_PACKET_RESERVED
{
UINT m_Signature; // UDPS_PACKET_SIGN
LIST_ENTRY m_ListElement;
UCHAR m_DataBuffer[ UDPS_BUFFER_SIZE ];
IO_STATUS_BLOCK m_PacketIoStatus;
PIRP m_pReceiveIrp;
TDI_CONNECTION_INFORMATION m_RemoteConnectionInfo;
TA_IP_ADDRESS m_RemoteAddress;
ULONG m_nPackingInsurance; // Spare. Do Not Use.
}
UDPS_PACKET_RESERVED, *PUDPS_PACKET_RESERVED;
/* The UDPS_PACKET Structure
----------------------------
* This is an NDIS_PACKET structure which has been extended to include
* additional fields (i.e., UDPS_PACKET_RESERVED) specific to this
* implementation of the ECHO UDP server.
*/
typedef
struct _UDPS_PACKET
{
NDIS_PACKET Packet;
UDPS_PACKET_RESERVED Reserved;
}
UDPS_PACKET, *PUDPS_PACKET;
#define UDPS_PACKET_POOL_SIZE 32
#define UDPS_BUFFER_POOL_SIZE UDPS_PACKET_POOL_SIZE
//
// Notes On Receiving
// ------------------
// The TDIECHO sample illustrates two different methods for receiving UDP
// data:
//
// TdiReceive Requests
// TdiReceive Events
//
// The method used for receiving UDP data is determined at compile time by
// the USE_RECEIVE_EVENT_HANDLER preprocessor directive.
//
// USE_RECEIVE_EVENT_HANDLER not defined
// Receive UDP data by making explicit calls to TdiReceive.
//
// USE_RECEIVE_EVENT_HANDLER defined
// Receive UDP data as it is indicated to the TDI_EVENT_RECEIVE event
// handler.
//
//#define USE_RECEIVE_EVENT_HANDLER
//
// UDPS Global Variables
//
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
LIST_ENTRY g_ReceivedUdpPacketList;
static BOOLEAN g_bAddressOpen = FALSE;
static KS_ADDRESS g_KS_Address;
static TA_IP_ADDRESS g_LocalAddress;
//
// Local Procedure Prototypes
//
VOID
UDPS_SendDatagramCompletion(
PVOID UserCompletionContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG Reserved
);
#ifdef USE_RECEIVE_EVENT_HANDLER
NTSTATUS
UDPS_TransferDataCallback(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PVOID pContext
);
#else
VOID
UDPS_ReceiveDatagramCompletion(
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 //
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//// UDPS_FreePacketAndBuffers
//
// Purpose
// Free the NDIS_PACKET and associated NDIS_BUFFER's associated with the
// specified UDPS_PACKET.
//
// Parameters
//
// Return Value
//
// Remarks
//
VOID
UDPS_FreePacketAndBuffers(
PUDPS_PACKET pUDPS_Packet
)
{
ULONG nDataSize, nBufferCount;
PNDIS_BUFFER pNdisBuffer;
//
// Sanity Check On Arguments
//
ASSERT( pUDPS_Packet );
if( !pUDPS_Packet )
{
return;
}
//
// Verify The Packet Signature
//
ASSERT( pUDPS_Packet->Reserved.m_Signature == UDPS_PACKET_SIGN );
if( pUDPS_Packet->Reserved.m_Signature != UDPS_PACKET_SIGN )
{
#if DBG
DbgPrint( "UDPS_FreePacketAndBuffers: Invalid Packet Signature\n" );
#endif
return;
}
//
// Invalidate The Signature
//
pUDPS_Packet->Reserved.m_Signature = 0; // Zap The Signature
//
// Recycle The Packet
//
KS_FreePacketAndBuffers( (PNDIS_PACKET )pUDPS_Packet );
}
/////////////////////////////////////////////////////////////////////////////
// S E N D R O U T I N E S //
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//// UDPS_EchoUdpPackets
//
// Purpose
// Call to handle packets queued on the ReceivedUdpPacketList.
//
// Parameters
//
// Return Value
//
// Remarks
//
VOID
UDPS_EchoUdpPackets( BOOLEAN bShutdown )
{
//
// Echo UDP Packets
//
while( !IsListEmpty( &g_ReceivedUdpPacketList ) )
{
PLIST_ENTRY linkage;
PUDPS_PACKET pUDPS_Packet;
PNDIS_BUFFER pNdisBuffer = NULL;
ULONG nDataSize, nByteCount, nBufferCount;
TDI_STATUS nTdiStatus = STATUS_SUCCESS;
//
// Find The Oldest Packet
//
linkage = RemoveHeadList( &g_ReceivedUdpPacketList );
pUDPS_Packet = CONTAINING_RECORD(
linkage,
UDPS_PACKET,
Reserved.m_ListElement
);
if( bShutdown )
{
//
// Recycle The Packet And Buffers
//
UDPS_FreePacketAndBuffers( pUDPS_Packet );
continue;
}
//
// Query The NDIS_PACKET
// ---------------------
// NdisQueryPacket is called to locate the NDIS_BUFFER to be passed to
// TdiSend().
//
NdisQueryPacket(
(PNDIS_PACKET )pUDPS_Packet,
(PULONG )NULL,
(PULONG )&nBufferCount,
&pNdisBuffer,
&nDataSize
);
if( !pNdisBuffer )
{
//
// Recycle The Packet And Buffers
//
UDPS_FreePacketAndBuffers( pUDPS_Packet );
return;
}
nTdiStatus = KS_SendDatagramOnAddress(
&g_KS_Address,
NULL, // User Completion Event
UDPS_SendDatagramCompletion, // User Completion Routine
pUDPS_Packet, // User Completion Context
&pUDPS_Packet->Reserved.m_PacketIoStatus,
pNdisBuffer, // MdlAddress
&pUDPS_Packet->Reserved.m_RemoteConnectionInfo
);
if( !NT_SUCCESS( nTdiStatus ) )
{
break;
}
}
}
/////////////////////////////////////////////////////////////////////////////
//// UDPS_SendDatagramCompletion
//
// Purpose
// Called by TDI when the send operation completes.
//
// Parameters
//
// Return Value
//
// Remarks
//
VOID
UDPS_SendDatagramCompletion(
PVOID UserCompletionContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG Reserved
)
{
PUDPS_PACKET pUDPS_Packet;
TDI_STATUS nTdiStatus;
PNDIS_BUFFER pNdisBuffer;
ULONG nDataSize, nBufferCount;
NTSTATUS nFinalStatus = IoStatusBlock->Status;
ULONG nByteCount = IoStatusBlock->Information;
#if DBG
DbgPrint( "UDPS_SendDatagramCompletion: FinalStatus: %d; BytesSent: %d\n", nFinalStatus, nByteCount );
#endif
pUDPS_Packet = (PUDPS_PACKET )UserCompletionContext;
//
// Sanity Check On Passed Parameters
//
ASSERT( pUDPS_Packet );
if( !pUDPS_Packet )
{
return;
}
//
// Verify The Packet Signature
//
ASSERT( pUDPS_Packet->Reserved.m_Signature == UDPS_PACKET_SIGN );
if( pUDPS_Packet->Reserved.m_Signature != UDPS_PACKET_SIGN )
{
#if DBG
DbgPrint( "UDPS_SendDatagramCompletion: Invalid Packet Signature\n" );
#endif
return;
}
ASSERT( NT_SUCCESS( nFinalStatus ) );
if( !NT_SUCCESS( nFinalStatus ) )
{
// ATTENTION!!! Update Statistics???
}
//
// Possibly Send Another Packet
//
UDPS_EchoUdpPackets( FALSE );
//
// Query The NDIS_PACKET
//
NdisQueryPacket(
(PNDIS_PACKET )pUDPS_Packet,
(PULONG )NULL,
(PULONG )&nBufferCount,
&pNdisBuffer,
&nDataSize
);
if( !pNdisBuffer )
{
//
// Recycle The Packet And Buffers
//
UDPS_FreePacketAndBuffers( pUDPS_Packet );
return;
}
//
// Reset pNdisBuffer->Length
// -------------------------
// When the packet was received on this NDIS_BUFFER, the Length field
// was adjusted to the amount of data copied into the buffer. Here
// the Length field is reset to indicate the size of the buffer.
//
NdisAdjustBufferLength( pNdisBuffer, UDPS_BUFFER_SIZE );
#ifdef USE_RECEIVE_EVENT_HANDLER
//
// Recycle The Packet And Buffers
//
UDPS_FreePacketAndBuffers( pUDPS_Packet );
#else
//
// Start Another Receive On Same Buffer
//
KS_ReceiveDatagramOnAddress(
&g_KS_Address,
NULL, // User Completion Event
UDPS_ReceiveDatagramCompletion,// User Completion Routine
pUDPS_Packet, // User Completion Context
&pUDPS_Packet->Reserved.m_PacketIoStatus,
pNdisBuffer, // MdlAddress
NULL, // ReceiveDatagramInfo
&pUDPS_Packet->Reserved.m_RemoteConnectionInfo, // ReturnInfo
TDI_RECEIVE_NORMAL // InFlags
);
#endif // USE_RECEIVE_EVENT_HANDLER
return;
}
/////////////////////////////////////////////////////////////////////////////
// R E C E I V E R O U T I N E S //
/////////////////////////////////////////////////////////////////////////////
#ifdef USE_RECEIVE_EVENT_HANDLER
/////////////////////////////////////////////////////////////////////////////
//// UDPS_TransferDataCallback
//
// Purpose
// Called by TDI when the receive data transfer initiated by ClientEventReceive
// or TdiReceive completes.
//
// Parameters
//
// Return Value
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -