📄 udpecho.c
字号:
//
// Remarks
// For non-error cases, this function saves the number of bytes which TDI
// has copied into the buffer and then queues the UDPS_Packet in the
// ReceivedUdpPacketList. It then calls a routine which can send the packet
// back to the originator.
//
NTSTATUS
UDPS_TransferDataCallback(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PVOID pContext
)
{
PUDPS_PACKET pUDPS_Packet;
PNDIS_BUFFER pNdisBuffer;
ULONG nDataSize, nBufferCount;
NTSTATUS nFinalStatus = pIrp->IoStatus.Status;
ULONG nByteCount = pIrp->IoStatus.Information;
#if DBG
DbgPrint( "UDPS_TransferDataCallback: FinalStatus: %d; Bytes Transfered: %d\n",
nFinalStatus, nByteCount );
#endif
pUDPS_Packet = (PUDPS_PACKET )pContext;
//
// Sanity Checks
//
ASSERT( pUDPS_Packet );
if( !pUDPS_Packet )
{
IoFreeIrp( pIrp );
return( STATUS_MORE_PROCESSING_REQUIRED );
}
//
// 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_TransferDataCallback: Invalid Packet Signature\n" );
#endif
IoFreeIrp( pIrp );
return( STATUS_MORE_PROCESSING_REQUIRED );
}
//
// Handle Transfer Failure
//
if( !NT_SUCCESS( nFinalStatus ) )
{
//
// Recycle The Packet And Buffers
//
UDPS_FreePacketAndBuffers( pUDPS_Packet );
// ATTENTION!!! Update Statistics???
IoFreeIrp( pIrp );
return( STATUS_MORE_PROCESSING_REQUIRED );
}
// ATTENTION!!! Update Statistics???
//
// Query The NDIS_PACKET
// ---------------------
// NdisQueryPacket is called to locate the NDIS_BUFFER to be passed to
// TdiSend(). The nDataSize will be the unmodified original size of
// the buffer - *NOT* the amount of data which was transfered to the
// buffer by TDI.
//
NdisQueryPacket(
(PNDIS_PACKET )pUDPS_Packet,
(PULONG )NULL,
(PULONG )&nBufferCount,
&pNdisBuffer,
&nDataSize
);
ASSERT( pNdisBuffer );
if( !pNdisBuffer )
{
//
// Recycle The Packet And Buffers
//
UDPS_FreePacketAndBuffers( pUDPS_Packet );
IoFreeIrp( pIrp );
return( STATUS_MORE_PROCESSING_REQUIRED );
}
//
// Save The Byte Count
// -------------------
// In this implementation, the NDIS_BUFFER Length field is adjusted
// to the amount of data that was copied into the buffer. This has
// the added benefit of insuring that when the packet is sent later
// the NDIS_BUFFER Length field and the length parameter passed to
// TdiSend are the same.
//
NdisAdjustBufferLength( pNdisBuffer, nByteCount );
// ATTENTION!!! Check Flags???
IoFreeIrp( pIrp ); // Don't Access pIrp Any More...
//
// Put The Packet In The Received UDP PacketList
//
InsertTailList(
&g_ReceivedUdpPacketList,
&pUDPS_Packet->Reserved.m_ListElement
);
//
// Possibly Send Another Packet
//
UDPS_EchoUdpPackets( FALSE );
return( STATUS_MORE_PROCESSING_REQUIRED );
}
/////////////////////////////////////////////////////////////////////////////
//// UDPS_ReceiveDatagramEventHandler
//
// Purpose
//
// Parameters
//
// Return Value
//
// Remarks
//
NTSTATUS
UDPS_ReceiveDatagramEventHandler(
IN PVOID TdiEventContext, // Context From SetEventHandler
IN LONG SourceAddressLength, // length of the originator of the datagram
IN PVOID SourceAddress, // string describing the originator of the datagram
IN LONG OptionsLength, // options for the receive
IN PVOID Options, //
IN ULONG ReceiveDatagramFlags, //
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.
)
{
PUDPS_PACKET pUDPS_Packet;
NDIS_STATUS nNdisStatus;
PNDIS_BUFFER pNdisBuffer;
PDEVICE_OBJECT pUDPDeviceObject;
PTRANSPORT_ADDRESS pTransAddr = (PTRANSPORT_ADDRESS )SourceAddress;
BOOLEAN bIsCompleteTsdu = FALSE;
#if DBG
DbgPrint( "UDPS_ReceiveDatagramEventHandler Entry...\n" );
DbgPrint( "BytesIndicated: %d, BytesAvailable: %d; ReceiveFlags: 0x%X\n",
BytesIndicated, BytesAvailable, ReceiveDatagramFlags );
DEBUG_DumpTransportAddress( pTransAddr );
#endif
//
// Determine Whether Tsdu Contains A Full TSDU
// -------------------------------------------
// We could check (ReceiveDatagramFlags & TDI_RECEIVE_ENTIRE_MESSAGE).
// However, checking (BytesIndicated == BytesAvailable) seems more
// reliable.
//
if( BytesIndicated == BytesAvailable )
{
bIsCompleteTsdu = TRUE;
}
//
// 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 )pUDPS_Packet,
g_hPacketPool
);
if( nNdisStatus != NDIS_STATUS_SUCCESS || !pUDPS_Packet )
{
// ATTENTION!!! Update Statistics???
#if DBG
DbgPrint( "UDPS_ReceiveDatagramEventHandler Could Not Allocate Packet\n" );
#endif
//
// Tell TDI That No Data Was Taken
// -------------------------------
// TDI will attempt to buffer the data for later consumption or
// the data will be retransmitted. Special steps may be needed to
// force the TDI driver to indicate the data not taken at a later
// time when resources become available.
//
*BytesTaken = 0;
return( STATUS_SUCCESS );
}
//
// Initialize The Packet Signature
//
pUDPS_Packet->Reserved.m_Signature = UDPS_PACKET_SIGN;
//
// Save Remote Address
//
NdisMoveMemory(
&pUDPS_Packet->Reserved.m_RemoteAddress,
SourceAddress,
sizeof( TA_IP_ADDRESS )
);
//
// Save Remote Connection Info In Packet Reserved Area
//
NdisZeroMemory(
&pUDPS_Packet->Reserved.m_RemoteConnectionInfo,
sizeof( TDI_CONNECTION_INFORMATION )
);
pUDPS_Packet->Reserved.m_RemoteConnectionInfo.RemoteAddress = &pUDPS_Packet->Reserved.m_RemoteAddress;
pUDPS_Packet->Reserved.m_RemoteConnectionInfo.RemoteAddressLength = sizeof( TA_IP_ADDRESS );
//
// Save Bytes Taken In Internal Buffer
// -----------------------------------
// In this sample the data is saved in an internal buffer that is a
// field in the UDPS_PACKET structure.
//
// ATTENTION!!! Note that *BytesTaken is set in the following statement.
//
if( BytesIndicated <= UDPS_BUFFER_SIZE )
{
*BytesTaken = BytesIndicated;
}
else
{
*BytesTaken = UDPS_BUFFER_SIZE;
}
NdisMoveMemory(
pUDPS_Packet->Reserved.m_DataBuffer,
Tsdu,
*BytesTaken
);
//
// Allocate An NDIS Buffer Descriptor For The Receive Data
//
NdisAllocateBuffer(
&nNdisStatus,
&pNdisBuffer,
g_hBufferPool,
pUDPS_Packet->Reserved.m_DataBuffer, // Private Buffer
*BytesTaken
);
if( nNdisStatus != NDIS_STATUS_SUCCESS || !pNdisBuffer )
{
// ATTENTION!!! Update Statistics???
NdisFreePacket( (PNDIS_PACKET )pUDPS_Packet );
#if DBG
DbgPrint( "UDPS_ReceiveDatagramEventHandler Could Not Allocate Buffer\n" );
#endif
//
// Tell TDI That No Data Was Taken
// -------------------------------
// TDI will attempt to buffer the data for later consumption or
// the data will be retransmitted. Special steps may be needed to
// force the TDI driver to indicate the data not taken at a later
// time when resources become available.
//
*BytesTaken = 0;
return( STATUS_SUCCESS );
}
NdisChainBufferAtFront( (PNDIS_PACKET )pUDPS_Packet, pNdisBuffer );
//
// Put The Packet In The Received UDP PacketList
//
InsertTailList(
&g_ReceivedUdpPacketList,
&pUDPS_Packet->Reserved.m_ListElement
);
//
// Determine Whether Tsdu Contains A Full TSDU
// -------------------------------------------
// We could check (ReceiveDatagramFlags & TDI_RECEIVE_ENTIRE_MESSAGE).
// However, checking (BytesIndicated == BytesAvailable) seems more
// reliable.
//
if( *BytesTaken == BytesAvailable )
{
//
// Possibly Send Another Packet
//
UDPS_EchoUdpPackets( FALSE );
return( STATUS_SUCCESS );
}
//
// Allocate Another 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 )pUDPS_Packet,
g_hPacketPool
);
if( nNdisStatus != NDIS_STATUS_SUCCESS || !pUDPS_Packet )
{
// ATTENTION!!! Update Statistics???
#if DBG
DbgPrint( "UDPS_ReceiveDatagramEventHandler Could Not Allocate Packet\n" );
#endif
return( STATUS_SUCCESS );
}
//
// Initialize The Packet Signature
//
pUDPS_Packet->Reserved.m_Signature = UDPS_PACKET_SIGN;
//
// Save Remote Address
//
NdisMoveMemory(
&pUDPS_Packet->Reserved.m_RemoteAddress,
SourceAddress,
sizeof( TA_IP_ADDRESS )
);
//
// Save Remote Connection Info In Packet Reserved Area
//
NdisZeroMemory(
&pUDPS_Packet->Reserved.m_RemoteConnectionInfo,
sizeof( TDI_CONNECTION_INFORMATION )
);
pUDPS_Packet->Reserved.m_RemoteConnectionInfo.RemoteAddress = &pUDPS_Packet->Reserved.m_RemoteAddress;
pUDPS_Packet->Reserved.m_RemoteConnectionInfo.RemoteAddressLength = sizeof( TA_IP_ADDRESS );
//
// Allocate An NDIS Buffer Descriptor For The Receive Data
//
NdisAllocateBuffer(
&nNdisStatus,
&pNdisBuffer,
g_hBufferPool,
pUDPS_Packet->Reserved.m_DataBuffer, // Private Buffer
BytesAvailable - *BytesTaken
);
if( nNdisStatus != NDIS_STATUS_SUCCESS || !pNdisBuffer )
{
// ATTENTION!!! Update Statistics???
NdisFreePacket( (PNDIS_PACKET )pUDPS_Packet );
#if DBG
DbgPrint( "UDPS_ReceiveDatagramEventHandler Could Not Allocate Buffer\n" );
#endif
return( STATUS_SUCCESS );
}
NdisChainBufferAtFront( (PNDIS_PACKET )pUDPS_Packet, pNdisBuffer );
//
// Allocate Resources To Call TDI To Transfer Received Data
//
pUDPDeviceObject = IoGetRelatedDeviceObject(
g_KS_Address.m_pFileObject
);
pUDPS_Packet->Reserved.m_pReceiveIrp = IoAllocateIrp(
pUDPDeviceObject->StackSize,
FALSE
);
ASSERT( pUDPS_Packet->Reserved.m_pReceiveIrp );
if( !pUDPS_Packet->Reserved.m_pReceiveIrp )
{
UDPS_FreePacketAndBuffers( pUDPS_Packet );
return( STATUS_SUCCESS );
}
TdiBuildReceiveDatagram(
pUDPS_Packet->Reserved.m_pReceiveIrp, // IRP
pUDPDeviceObject, // Pointer To TDI Device Object
g_KS_Address.m_pFileObject, // Address File Object
UDPS_TransferDataCallback, // CompletionRoutine
pUDPS_Packet, // Context
pNdisBuffer, // MdlAddress
BytesAvailable - *BytesTaken, // ReceiveLen
&pUDPS_Packet->Reserved.m_RemoteConnectionInfo, // ReceiveDatagramInfo
NULL, // ReturnInfo
TDI_RECEIVE_NORMAL // InFlags
);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -