⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udpecho.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 3 页
字号:
// 
// 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 + -