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

📄 tcpecho.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 4 页
字号:
/////////////////////////////////////////////////////////////////////////////
//// INCLUDE FILES

#include "ndis.h"
#include "TDI.H"
#include "TDIKRNL.H"
//#include "KSTcpEx.h"
#include "KSUtil.h"

#include "TCPEcho.H"
#include "TDIEcho.h"

// Copyright And Configuration Management ----------------------------------
//
//               TDI TCP Echo Server Implementation - TCPEcho.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 ---------------------------------------------------------------------

typedef
struct _TCPS_Connection
{
   LIST_ENTRY                    m_ListElement;

   BOOLEAN                       m_bIsConnectionObjectValid;
   KS_ENDPOINT                 m_KS_Endpoint;

   BOOLEAN                       m_bIsConnected;
   BOOLEAN                       m_bIsDisconnecting;

   LIST_ENTRY                    m_ReceivedTcpPacketList;

   TA_IP_ADDRESS                 m_RemoteAddress;
   TDI_CONNECTION_INFORMATION    m_RemoteConnectionInfo;

   PIRP                          m_pAcceptIrp;
   PIRP                          m_pDisconnectIrp;
   PKEVENT                       m_pWaitEvent;
}
   TCPS_Connection, *PTCPS_Connection;

#define   MAX_CONNECTIONS   8

#define TCPS_PACKET_SIGN   (UINT)0x45434845    /* ECHO */
#define TCPS_BUFFER_SIZE   4096

typedef
struct _TCPS_PACKET_RESERVED
{
   UINT               m_Signature;      // TCPS_PACKET_SIGN

   LIST_ENTRY         m_ListElement;

   PTCPS_Connection   m_pConnection;

   UCHAR               m_DataBuffer[ TCPS_BUFFER_SIZE ];

   IO_STATUS_BLOCK   m_PacketIoStatus;

   PIRP              m_pReceiveIrp;

   TA_IP_ADDRESS                  m_RemoteAddress;
   TDI_CONNECTION_INFORMATION      m_RemoteConnectionInfo;

   ULONG               m_nPackingInsurance;   // Spare. Do Not Use.
}
   TCPS_PACKET_RESERVED, *PTCPS_PACKET_RESERVED;


/* The TCPS_PACKET Structure
----------------------------
 * This is an NDIS_PACKET structure which has been extended to include
 * additional fields (i.e., TCPS_PACKET_RESERVED) specific to this
 * implementation of the ECHO TCP server.
 */
typedef
struct _TCPS_PACKET
{
   NDIS_PACKET          Packet;
   TCPS_PACKET_RESERVED   Reserved;
}
   TCPS_PACKET, *PTCPS_PACKET;

#define   TCPS_PACKET_POOL_SIZE      32
#define   TCPS_BUFFER_POOL_SIZE      TCPS_PACKET_POOL_SIZE

//
// Notes On Receiving
// ------------------
// The TDIECHO sample illustrates two different methods for receiving TCP
// data:
//
//   TdiReceive Requests
//   TdiReceive Events
//
// The method used for receiving TCP data is determined at compile time by
// the USE_RECEIVE_EVENT_HANDLER preprocessor directive.
//
//   USE_RECEIVE_EVENT_HANDLER not defined
//      Receive TCP data by making explicit calls to TdiReceive.
//
//   USE_RECEIVE_EVENT_HANDLER defined
//      Receive TCP data as it is indicated to the TDI_EVENT_RECEIVE event
//      handler.
//
//#define USE_RECEIVE_EVENT_HANDLER

//
// TCPS Global Variables
//
int                  g_nTCPS_UseCount = 0;

TCPS_Connection      g_ConnectionSpace[MAX_CONNECTIONS];

LIST_ENTRY           g_FreeConnectionList;
LIST_ENTRY           g_OpenConnectionList;

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

static BOOLEAN         g_bAddressOpen = FALSE;
static KS_ADDRESS    g_KS_Address;
static TA_IP_ADDRESS g_LocalAddress;

//
// Local Procedure Prototypes
//
VOID
TCPS_SendCompletion(
    PVOID UserCompletionContext,
    PIO_STATUS_BLOCK IoStatusBlock,
    ULONG Reserved
    );

#ifdef USE_RECEIVE_EVENT_HANDLER

NTSTATUS
TCPS_TransferDataCallback(
   IN PDEVICE_OBJECT pDeviceObject,
   IN PIRP pIrp,
   IN PVOID pContext
   );

#else

VOID
TCPS_ReceiveCompletion(
   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                    //
/////////////////////////////////////////////////////////////////////////////

PTCPS_Connection
TCPS_AllocConnection( void )
{
   PTCPS_Connection pConnection;

   //
   // Fetch A TCPS_Connection Structure From The Free List
   //
   if( IsListEmpty( &g_FreeConnectionList ) )
   {
      return( (PTCPS_Connection )NULL );
   }

   pConnection = (PTCPS_Connection )RemoveHeadList( &g_FreeConnectionList );

   if( !pConnection )
   {
      return( (PTCPS_Connection )NULL );
   }

   //
   // Sanity Checks
   //
   ASSERT( pConnection->m_bIsConnectionObjectValid );

   if( !pConnection->m_bIsConnectionObjectValid )
   {
      return( (PTCPS_Connection )NULL );
   }

   //
   // Set Connection State
   //
   pConnection->m_bIsConnected = FALSE;
   pConnection->m_bIsDisconnecting = FALSE;

   ASSERT( IsListEmpty( &pConnection->m_ReceivedTcpPacketList ) );

   return( pConnection );
}


VOID
TCPS_FreeConnection(
   PTCPS_Connection pConnection
   )
{
   //
   // Set Connection State
   //
   pConnection->m_bIsConnected = FALSE;
   pConnection->m_bIsDisconnecting = FALSE;

   //
   // Return Connection To Free List
   //
   InsertTailList(
      &g_FreeConnectionList,
      &pConnection->m_ListElement
      );
}


/////////////////////////////////////////////////////////////////////////////
//// TCPS_FreePacketAndBuffers
//
// Purpose
// Free the NDIS_PACKET and associated NDIS_BUFFER's associated with the
// specified TCPS_PACKET.
//
// Parameters
//
// Return Value
// 
// Remarks
//

VOID
TCPS_FreePacketAndBuffers(
   PTCPS_PACKET pTCPS_Packet
   )
{
   ULONG          nDataSize, nBufferCount;
   PNDIS_BUFFER   pNdisBuffer;

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

      return;
   }

   //
   // Invalidate The Signature
   //
   pTCPS_Packet->Reserved.m_Signature = 0;      // Zap The Signature

   //
   // Recycle The Packet
   //
   KS_FreePacketAndBuffers( (PNDIS_PACKET )pTCPS_Packet );
}


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

NTSTATUS
TCPS_ConnectedCallback(
   IN PDEVICE_OBJECT pDeviceObject,
   IN PIRP pIrp,
   IN PVOID Context
   )
{
   PTCPS_Connection   pConnection = (PTCPS_Connection )Context;
   NTSTATUS          nFinalStatus = pIrp->IoStatus.Status;
   PTCPS_PACKET      pTCPS_Packet;
   NDIS_STATUS       nNdisStatus;
   PNDIS_BUFFER      pNdisBuffer;

#if DBG
   DbgPrint( "TCPS_ConnectedCallback: FinalStatus: %d\n", nFinalStatus );
#endif

   if( NT_SUCCESS( nFinalStatus ) )
   {
      pConnection->m_bIsConnected = TRUE;
   }
   else
   {
      pConnection->m_bIsConnected = FALSE;
      pConnection->m_bIsDisconnecting = FALSE;

      //
      // Remove From Open Connection List
      //
      RemoveEntryList( &pConnection->m_ListElement );

      //
      // Return Connection To Free List
      //
      TCPS_FreeConnection( pConnection );
   }

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

   if( !NT_SUCCESS( nFinalStatus ) )
   {
      return( STATUS_MORE_PROCESSING_REQUIRED );
   }


#ifndef USE_RECEIVE_EVENT_HANDLER

   //
   // 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_ConnectedCallback Could Not Allocate Packet\n" );
#endif

      return( STATUS_MORE_PROCESSING_REQUIRED );
   }

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

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

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

      NdisFreePacket( (PNDIS_PACKET )pTCPS_Packet );

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

      return( STATUS_MORE_PROCESSING_REQUIRED );
   }

   NdisChainBufferAtFront( (PNDIS_PACKET )pTCPS_Packet, pNdisBuffer );

   //
   // Start A Receive On The Connection
   //
   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( STATUS_MORE_PROCESSING_REQUIRED );
}


/////////////////////////////////////////////////////////////////////////////
//// TCPS_ConnectEventHandler
//
// Purpose
// Called by the TDI to indicate that a connection request has been received
// from a remote client.
//
// Parameters
//   TdiEventContext
//   RemoteAddressLength
//   RemoteAddress
//   UserDataLength
//   UserData
//   OptionsLength
//   Options
//   ConnectionContext
//   hAcceptIrp
//
// Return Value
// 
// Remarks
//

NTSTATUS
TCPS_ConnectEventHandler(
   IN PVOID TdiEventContext,     // Context From SetEventHandler
   IN LONG RemoteAddressLength,
   IN PVOID RemoteAddress,
   IN LONG UserDataLength,       // Unused for MSTCP
   IN PVOID UserData,            // Unused for MSTCP
   IN LONG OptionsLength,
   IN PVOID Options,
   OUT CONNECTION_CONTEXT *ConnectionContext,
   OUT PIRP *hAcceptIrp
   )
{
   PTCPS_Connection   pConnection = NULL;
   TDI_STATUS        nTdiStatus;
   PDEVICE_OBJECT    pTCPDeviceObject;

#if DBG
   DbgPrint( "TCPS_ConnectEventHandler Entry...\n" );
#endif

   //
   // Allocate A Connection
   //
   pConnection = TCPS_AllocConnection();

⌨️ 快捷键说明

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