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

📄 tcpecho.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 4 页
字号:
   ASSERT( pConnection );

   if( !pConnection )
   {
      return( STATUS_INSUFFICIENT_RESOURCES );
   }

   pTCPDeviceObject = IoGetRelatedDeviceObject(
                        pConnection->m_KS_Endpoint.m_pFileObject
                        );

   //
   // Save Remote Client Address
   //
   NdisMoveMemory(
      &pConnection->m_RemoteAddress,
      RemoteAddress,
      sizeof( TA_IP_ADDRESS )
      );

#if DBG
   DEBUG_DumpTransportAddress(
      (PTRANSPORT_ADDRESS )&pConnection->m_RemoteAddress
      );
#endif

   //
   // Allocate Resources To Call TDI To Accept
   //
   pConnection->m_pAcceptIrp = IoAllocateIrp(
                                 pTCPDeviceObject->StackSize,
                                 FALSE
                                 );

   ASSERT( pConnection->m_pAcceptIrp );

   if( !pConnection->m_pAcceptIrp )
      return( STATUS_INSUFFICIENT_RESOURCES );

   //
   // Build The Accept Request
   //
   pConnection->m_RemoteConnectionInfo.UserDataLength = 0;
   pConnection->m_RemoteConnectionInfo.UserData = NULL;

   pConnection->m_RemoteConnectionInfo.OptionsLength = 0;
   pConnection->m_RemoteConnectionInfo.Options = NULL;

   pConnection->m_RemoteConnectionInfo.RemoteAddressLength = sizeof( TA_IP_ADDRESS );
   pConnection->m_RemoteConnectionInfo.RemoteAddress = &pConnection->m_RemoteAddress;

   TdiBuildAccept(
      pConnection->m_pAcceptIrp,          // IRP
      pTCPDeviceObject,                   // Pointer To TDI Device Object
      pConnection->m_KS_Endpoint.m_pFileObject,   // Connection Endpoint File Object
      TCPS_ConnectedCallback,
      pConnection,
      &pConnection->m_RemoteConnectionInfo,
      &pConnection->m_RemoteConnectionInfo
      );

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

   //
   // Place The New Connection In The Open Connection List
   //
   InsertTailList(
      &g_OpenConnectionList,
      &pConnection->m_ListElement
      );

   *hAcceptIrp = pConnection->m_pAcceptIrp;
   *ConnectionContext = pConnection;

   return( STATUS_MORE_PROCESSING_REQUIRED );   // Accept The Connection
}


/////////////////////////////////////////////////////////////////////////////
//                          S E N D  R O U T I N E S                       //
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//// TCPS_EchoTcpPackets
//
// Purpose
// Call to handle packets queued on the ReceivedTcpPacketList.
//
// Parameters
//
// Return Value
// 
// Remarks
//

VOID
TCPS_EchoTcpPackets(
   PTCPS_Connection pConnection
   )
{
   //
   // Echo TCP Packets
   //
   while( !IsListEmpty( &pConnection->m_ReceivedTcpPacketList ) )
   {
      PLIST_ENTRY    linkage;
      PTCPS_PACKET   pTCPS_Packet;
      PNDIS_BUFFER   pNdisBuffer = NULL;
      ULONG          nDataSize, nByteCount, nBufferCount;
      TDI_STATUS     nTdiStatus;

      //
      // Find The Oldest Packet
      //
      linkage = RemoveHeadList( &pConnection->m_ReceivedTcpPacketList );

      pTCPS_Packet = CONTAINING_RECORD(
                     linkage,
                     TCPS_PACKET,
                     Reserved.m_ListElement
                     );

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

         continue;
      }

      //
      // 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 )pTCPS_Packet,
         (PULONG )NULL,
         (PULONG )&nBufferCount,
         &pNdisBuffer,
         &nDataSize
         );

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

         return;
      }

      nTdiStatus = KS_SendOnEndpoint(
                        &pConnection->m_KS_Endpoint,
                        NULL,          // User Completion Event
                        TCPS_SendCompletion,  // User Completion Routine
                        pTCPS_Packet,   // User Completion Context
                        &pTCPS_Packet->Reserved.m_PacketIoStatus,
                        pNdisBuffer,   // MdlAddress
                        0              // Send Flags
                        );

      if( !NT_SUCCESS( nTdiStatus ) )
      {
         break;
      }
   }
}


/////////////////////////////////////////////////////////////////////////////
//// TCPS_SendCompletion
//
// Purpose
// Called by TDI when the send operation completes.
//
// Parameters
//
// Return Value
// 
// Remarks
//

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

#if DBG
   DbgPrint( "TCPS_SendCompletion: FinalStatus: %d; BytesSent: %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_SendCompletion: Invalid Packet Signature\n" );
#endif

      return;
   }

   pConnection = pTCPS_Packet->Reserved.m_pConnection;


   if( !NT_SUCCESS( nFinalStatus ) )
   {
      // ATTENTION!!! Update Statistics???
   }

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

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

   if( !pNdisBuffer )
   {
      //
      // Recycle The Packet And Buffers
      //
      TCPS_FreePacketAndBuffers( pTCPS_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, TCPS_BUFFER_SIZE );

#ifdef USE_RECEIVE_EVENT_HANDLER

   //
   // Recycle The Packet And Buffers
   //
   TCPS_FreePacketAndBuffers( pTCPS_Packet );

#else

   //
   // Check On State
   //
   if( !pConnection->m_bIsConnected || pConnection->m_bIsDisconnecting  )
   {
      //
      // Recycle The Packet And Buffers
      //
      TCPS_FreePacketAndBuffers( pTCPS_Packet );
   }
   else
   {
      //
      // Start Another Receive On Same Buffer
      //
      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;
}


/////////////////////////////////////////////////////////////////////////////
//                      R E C E I V E  R O U T I N E S                     //
/////////////////////////////////////////////////////////////////////////////


#ifdef USE_RECEIVE_EVENT_HANDLER

/////////////////////////////////////////////////////////////////////////////
//// TCPS_TransferDataCallback
//
// Purpose
// Called by TDI when the receive data transfer initiated by ClientEventReceive
// or TdiReceive completes.
//
// Parameters
//
// Return Value
// 
// Remarks
// For non-error cases, this function saves the number of bytes which TDI
// has copied into the buffer and then queues the TCPS_Packet in the 
// ReceivedTcpPacketList. It then calls a routine which can send the packet
// back to the originator.
//

NTSTATUS
TCPS_TransferDataCallback(
   IN PDEVICE_OBJECT pDeviceObject,
   IN PIRP pIrp,
   IN PVOID pContext
   )
{
   PTCPS_Connection   pConnection;
   PTCPS_PACKET      pTCPS_Packet;
   PNDIS_BUFFER      pNdisBuffer;
   ULONG               nDataSize, nBufferCount;
   NTSTATUS            nFinalStatus = pIrp->IoStatus.Status;
   ULONG               nByteCount = pIrp->IoStatus.Information;

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

   pTCPS_Packet = (PTCPS_PACKET )pContext;

   //
   // Sanity Checks
   //
   ASSERT( pTCPS_Packet );

   if( !pTCPS_Packet )
   {
      IoFreeIrp( pIrp );

      return( STATUS_MORE_PROCESSING_REQUIRED );
   }

   //
   // 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_TransferDataCallback: Invalid Packet Signature\n" );
#endif

      IoFreeIrp( pIrp );

      return( STATUS_MORE_PROCESSING_REQUIRED );
   }

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

      IoFreeIrp( pIrp );

      return( STATUS_MORE_PROCESSING_REQUIRED );
   }

   //
   // Handle Transfer Failure
   //
   if( !NT_SUCCESS( nFinalStatus ) )
   {
      //
      // Recycle The Packet And Buffers
      //
      TCPS_FreePacketAndBuffers( pTCPS_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 )pTCPS_Packet,
      (PULONG )NULL,
      (PULONG )&nBufferCount,
      &pNdisBuffer,
      &nDataSize
      );

   ASSERT( pNdisBuffer );

   if( !pNdisBuffer )
   {
      //
      // Recycle The Packet And Buffers
      //
      TCPS_FreePacketAndBuffers( pTCPS_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.

⌨️ 快捷键说明

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