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

📄 tcpecho.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 4 页
字号:
   //
   NdisAdjustBufferLength( pNdisBuffer, nByteCount );

   // ATTENTION!!! Check Flags???

   IoFreeIrp( pIrp );   // Don't Access pIrp Any More...

   //
   // Put The Packet In The Connection's Received TCP PacketList
   //
   InsertTailList(
      &pConnection->m_ReceivedTcpPacketList,
      &pTCPS_Packet->Reserved.m_ListElement
      );

   //
   // Possibly Send Another Packet
   //
   TCPS_EchoTcpPackets( pConnection );

   return( STATUS_MORE_PROCESSING_REQUIRED );
}


/////////////////////////////////////////////////////////////////////////////
//// TCPS_ReceiveEventHandler
//
// Purpose
// Called by the TDI when incomming data arrives on the connection.
//
// Parameters
//
// Return Value
// 
// Remarks
// This handler is NOT called if there is an outstanding TdiReceive or
// we have not accepted all previously indicated data.
//
// Although some data (perhaps all) is available at pReceivedData, it is
// best to handle received data as a two-step operation - which actually
// parallels the two-step reception operation of the underlying protocol
// driver.
//
// The first step in reception is when the received data is "indicated"
// here at the TCPS_ReceiveEventHandler. Here the data at Tsdu and
// the associated ReceiveFlags can be examined to determine if the data
// is of further interest.
//
// If the data is of interest, then resources should be allocated and
// the ??? setup to have the underlying TDI driver transfer
// the data. When transfer is complete, the TCPS_ReceiveCompletion
// callback will ba called.
//
// In the TCPS_ReceiveCompletion the data, which we will then own,
// can be processed further. In the case of the ECHO client, it can be
// sent back to the remote network client.
//
//   ***** TDI Client (US) *****    * TDI Protocol Driver (MSTCP) *
//   TCPS_ReceiveEventHandler       ReceiveHandler
//   TCPS_TransferDataCallback      TransferDataComplete
//

NTSTATUS
TCPS_ReceiveEventHandler(
   IN PVOID TdiEventContext,                 // Context From SetEventHandler
   IN CONNECTION_CONTEXT ConnectionContext,  // Contect From Accept
   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.
   )
{
   PTCPS_Connection   pConnection;
   PTCPS_PACKET      pTCPS_Packet;
   NDIS_STATUS         nNdisStatus;
   PNDIS_BUFFER      pNdisBuffer;
   PDEVICE_OBJECT    pTCPDeviceObject;

#if DBG
   DbgPrint( "TCPS_ReceiveEventHandler Entry...\n" );
   DbgPrint( "BytesIndicated: %d, BytesAvailable: %d; ReceiveFlags: 0x%X\n",
      BytesIndicated, BytesAvailable, ReceiveFlags );
#endif

   pConnection = (PTCPS_Connection )ConnectionContext;

   //
   // Check On State
   //
   if( !pConnection->m_bIsConnected || pConnection->m_bIsDisconnecting  )
   {
      //
      // Tell TDI That All Data Was Taken
      //
      *BytesTaken = BytesIndicated;
      return( STATUS_SUCCESS );
   }

   //
   // 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_ReceiveEventHandler 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
   //
   pTCPS_Packet->Reserved.m_Signature = TCPS_PACKET_SIGN;

   //
   // Save Connection Pointer For Use In Callback Routine
   //
   pTCPS_Packet->Reserved.m_pConnection = pConnection;

   //
   // Save Bytes Taken In Internal Buffer
   // -----------------------------------
   // In this sample the data is saved in an internal buffer that is a
   // field in the TCPS_PACKET structure.
   //
   // ATTENTION!!! Note that *BytesTaken is set in the following statement.
   //
   if( BytesIndicated <= TCPS_BUFFER_SIZE )
   {
      *BytesTaken = BytesIndicated;
   }
   else
   {
      *BytesTaken = TCPS_BUFFER_SIZE;
   }

   NdisMoveMemory(
      pTCPS_Packet->Reserved.m_DataBuffer,
      Tsdu,
      *BytesTaken
      );

   //
   // Allocate An NDIS Buffer Descriptor For The Receive Data
   //
   NdisAllocateBuffer(
      &nNdisStatus,
      &pNdisBuffer,
      g_hBufferPool,
      pTCPS_Packet->Reserved.m_DataBuffer,   // Private Buffer
      *BytesTaken
      );

   if( nNdisStatus != NDIS_STATUS_SUCCESS || !pNdisBuffer )
   {
      // ATTENTION!!! Update Statistics???

      NdisFreePacket( (PNDIS_PACKET )pTCPS_Packet );

#if DBG
      DbgPrint( "TCPS_ReceiveEventHandler 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 )pTCPS_Packet, pNdisBuffer );

   //
   // Put The Packet In The Connection's Received TCP PacketList
   //
   InsertTailList(
      &pConnection->m_ReceivedTcpPacketList,
      &pTCPS_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
      //
      TCPS_EchoTcpPackets( pConnection );

      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 )pTCPS_Packet,
      g_hPacketPool
      );

   if( nNdisStatus != NDIS_STATUS_SUCCESS || !pTCPS_Packet )
   {
      // ATTENTION!!! Update Statistics???

#if DBG
      DbgPrint( "TCPS_ReceiveEventHandler Could Not Allocate Packet\n" );
#endif

      return( STATUS_SUCCESS );
   }

   //
   // 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;

   //
   // Process Partial TSDU
   // --------------------
   // One could check (ReceiveDatagramFlags & TDI_RECEIVE_COPY_LOOKAHEAD) to
   // determine whether copying the BytesIndicated lookahead data is
   // required or not. However, since the case where lookahead data must
   // be copied must be dealt with anyway, it seems simpler to just go ahead
   // and always copy the lookahead data here in the handler.

   //
   // Allocate An NDIS Buffer Descriptor For The Receive Data
   //
   NdisAllocateBuffer(
      &nNdisStatus,
      &pNdisBuffer,
      g_hBufferPool,
      pTCPS_Packet->Reserved.m_DataBuffer,   // Private Buffer
      BytesAvailable - *BytesTaken
      );

   if( nNdisStatus != NDIS_STATUS_SUCCESS || !pNdisBuffer )
   {
      // ATTENTION!!! Update Statistics???

      NdisFreePacket( (PNDIS_PACKET )pTCPS_Packet );

#if DBG
      DbgPrint( "TCPS_ReceiveEventHandler Could Not Allocate Buffer\n" );
#endif

      return( STATUS_SUCCESS );
   }

   NdisChainBufferAtFront( (PNDIS_PACKET )pTCPS_Packet, pNdisBuffer );

   //
   // Allocate Resources To Call TDI To Transfer Received Data
   //
   pTCPDeviceObject = IoGetRelatedDeviceObject(
                        pConnection->m_KS_Endpoint.m_pFileObject
                        );

   pTCPS_Packet->Reserved.m_pReceiveIrp = IoAllocateIrp(
                                 pTCPDeviceObject->StackSize,
                                 FALSE
                                 );

   ASSERT( pTCPS_Packet->Reserved.m_pReceiveIrp );

   if( !pTCPS_Packet->Reserved.m_pReceiveIrp )
   {
      TCPS_FreePacketAndBuffers( pTCPS_Packet );

      return( STATUS_SUCCESS );
   }

   TdiBuildReceive(
      pTCPS_Packet->Reserved.m_pReceiveIrp, // IRP
      pTCPDeviceObject,                  // Pointer To TDI Device Object
      pConnection->m_KS_Endpoint.m_pFileObject,   // Connection Endpoint File Object
      TCPS_TransferDataCallback,         // CompletionRoutine
      pTCPS_Packet,                     // Context
      pNdisBuffer,                     // MdlAddress
      0,                                 // ReceiveFlags
      BytesAvailable - *BytesTaken     // ReceiveLength
      );

   //
   // Make the next stack location current.  Normally IoCallDriver would
   // do this, but for this IRP it has been bypassed.
   //
   IoSetNextIrpStackLocation( pTCPS_Packet->Reserved.m_pReceiveIrp );

   //
   // Tell TDI To Transfer The Data
   //
   *IoRequestPacket = pTCPS_Packet->Reserved.m_pReceiveIrp;

   return( STATUS_MORE_PROCESSING_REQUIRED );
}

#else

/////////////////////////////////////////////////////////////////////////////
//// TCPS_ReceiveCompletion
//
// Purpose
//
// Parameters
//
// Return Value
// 
// Remarks
//

VOID
TCPS_ReceiveCompletion(
   PVOID UserCompletionContext,
   PIO_STATUS_BLOCK IoStatusBlock,
   ULONG Reserved
   )
{
   PTCPS_Connection   pConnection;
   PTCPS_PACKET      pTCPS_Packet;
   PNDIS_BUFFER      pNdisBuffer;
   ULONG             nDataSize, nBufferCount;
   NTSTATUS          nFinalStatus = IoStatusBlock->Status;
   ULONG             nByteCount = IoStatusBlock->Information;

#if DBG
   DbgPrint( "TCPS_ReceiveCompletion: FinalStatus: 0x%8.8x; Bytes Transfered: %d\n",
      nFinalStatus, nByteCount );
#endif

   pTCPS_Packet = (PTCPS_PACKET )UserCompletionContext;

   //
   // Sanity Check On Passed Parameters
   //
   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_ReceiveCompletion: Invalid Packet Signature\n" );
#endif

      return;
   }

   pConnection = pTCPS_Packet->Reserved.m_pConnection;

   //
   // Check On State
   //
   if( !pConnection->m_bIsConnected || pConnection->m_bIsDisconnecting  )
   {
      //
      // Recycle The Packet And Buffers
      //
      TCPS_FreePacketAndBuffers( pTCPS_Packet );

      return;
   }

   //
   // Handle Transfer Failure
   //
   if( !NT_SUCCESS( nFinalStatus ) )
   {
      //
      // Recycle The Packet And Buffers
      //
      TCPS_FreePacketAndBuffers( pTCPS_Packet );

      // ATTENTION!!! Update Statistics???

      return;
   }

   // ATTENTION!!! Update Statistics???

   //
   // Query The NDIS_PACKET
   //
   NdisQueryPacket(
      (PNDIS_PACKET )pTCPS_Packet,
      (PULONG )NULL,
      (PULONG )&nBufferCount,
      &pNdisBuffer,
      &nDataSize
      );

   ASSERT( pNdisBuffer );

   if( !pNdisBuffer )
   {
      //
      // Recycle The Packet And Buffers
      //
      TCPS_FreePacketAndBuffers( pTCPS_Packet );

      return;
   }

   //
   // 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???

   //
   // Put The Packet In The Connection's Received TCP PacketList
   //
   InsertTailList(
      &pConnection->m_ReceivedTcpPacketList,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -