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

📄 udpecho.c

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

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

#include "UDPEcho.H"
#include "TDIEcho.h"

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


#define UDPS_PACKET_SIGN   (UINT)0x45434845    /* ECHO */
#define UDPS_BUFFER_SIZE   4096

typedef
struct _UDPS_PACKET_RESERVED
{
   UINT              m_Signature;      // UDPS_PACKET_SIGN

   LIST_ENTRY        m_ListElement;

   UCHAR             m_DataBuffer[ UDPS_BUFFER_SIZE ];

   IO_STATUS_BLOCK   m_PacketIoStatus;

   PIRP              m_pReceiveIrp;

   TDI_CONNECTION_INFORMATION m_RemoteConnectionInfo;
   TA_IP_ADDRESS              m_RemoteAddress;

   ULONG             m_nPackingInsurance;   // Spare. Do Not Use.
}
   UDPS_PACKET_RESERVED, *PUDPS_PACKET_RESERVED;


/* The UDPS_PACKET Structure
----------------------------
 * This is an NDIS_PACKET structure which has been extended to include
 * additional fields (i.e., UDPS_PACKET_RESERVED) specific to this
 * implementation of the ECHO UDP server.
 */
typedef
struct _UDPS_PACKET
{
   NDIS_PACKET          Packet;
   UDPS_PACKET_RESERVED   Reserved;
}
   UDPS_PACKET, *PUDPS_PACKET;

#define   UDPS_PACKET_POOL_SIZE      32
#define   UDPS_BUFFER_POOL_SIZE      UDPS_PACKET_POOL_SIZE

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

//
// UDPS Global Variables
//
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

LIST_ENTRY           g_ReceivedUdpPacketList;

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

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

#ifdef USE_RECEIVE_EVENT_HANDLER

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

#else

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

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

VOID
UDPS_FreePacketAndBuffers(
   PUDPS_PACKET pUDPS_Packet
   )
{
   ULONG          nDataSize, nBufferCount;
   PNDIS_BUFFER   pNdisBuffer;

   //
   // Sanity Check On Arguments
   //
   ASSERT( pUDPS_Packet );

   if( !pUDPS_Packet )
   {
      return;
   }

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

      return;
   }

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

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


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

/////////////////////////////////////////////////////////////////////////////
//// UDPS_EchoUdpPackets
//
// Purpose
// Call to handle packets queued on the ReceivedUdpPacketList.
//
// Parameters
//
// Return Value
// 
// Remarks
//

VOID
UDPS_EchoUdpPackets( BOOLEAN bShutdown )
{
   //
   // Echo UDP Packets
   //
   while( !IsListEmpty( &g_ReceivedUdpPacketList ) )
   {
      PLIST_ENTRY    linkage;
      PUDPS_PACKET   pUDPS_Packet;
      PNDIS_BUFFER   pNdisBuffer = NULL;
      ULONG          nDataSize, nByteCount, nBufferCount;
      TDI_STATUS     nTdiStatus = STATUS_SUCCESS;

      //
      // Find The Oldest Packet
      //
      linkage = RemoveHeadList( &g_ReceivedUdpPacketList );

      pUDPS_Packet = CONTAINING_RECORD(
                     linkage,
                     UDPS_PACKET,
                     Reserved.m_ListElement
                     );

      if( bShutdown )
      {
         //
         // Recycle The Packet And Buffers
         //
         UDPS_FreePacketAndBuffers( pUDPS_Packet );

         continue;
      }

      //
      // Query The NDIS_PACKET
      // ---------------------
      // NdisQueryPacket is called to locate the NDIS_BUFFER to be passed to
      // TdiSend().
      //
      NdisQueryPacket(
         (PNDIS_PACKET )pUDPS_Packet,
         (PULONG )NULL,
         (PULONG )&nBufferCount,
         &pNdisBuffer,
         &nDataSize
         );

      if( !pNdisBuffer )
      {
         //
         // Recycle The Packet And Buffers
         //
         UDPS_FreePacketAndBuffers( pUDPS_Packet );

         return;
      }

      nTdiStatus = KS_SendDatagramOnAddress(
                        &g_KS_Address,
                        NULL,          // User Completion Event
                        UDPS_SendDatagramCompletion,  // User Completion Routine
                        pUDPS_Packet,   // User Completion Context
                        &pUDPS_Packet->Reserved.m_PacketIoStatus,
                        pNdisBuffer,   // MdlAddress
                        &pUDPS_Packet->Reserved.m_RemoteConnectionInfo
                        );

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


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

VOID
UDPS_SendDatagramCompletion(
   PVOID UserCompletionContext,
   PIO_STATUS_BLOCK IoStatusBlock,
   ULONG Reserved
   )
{
   PUDPS_PACKET      pUDPS_Packet;
   TDI_STATUS        nTdiStatus;
   PNDIS_BUFFER      pNdisBuffer;
   ULONG             nDataSize, nBufferCount;
   NTSTATUS          nFinalStatus = IoStatusBlock->Status;
   ULONG             nByteCount = IoStatusBlock->Information;

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

   pUDPS_Packet = (PUDPS_PACKET )UserCompletionContext;

   //
   // Sanity Check On Passed Parameters
   //
   ASSERT( pUDPS_Packet );

   if( !pUDPS_Packet )
   {
      return;
   }

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

      return;
   }

   ASSERT( NT_SUCCESS( nFinalStatus ) );

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

   //
   // Possibly Send Another Packet
   //
   UDPS_EchoUdpPackets( FALSE );

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

   if( !pNdisBuffer )
   {
      //
      // Recycle The Packet And Buffers
      //
      UDPS_FreePacketAndBuffers( pUDPS_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, UDPS_BUFFER_SIZE );

#ifdef USE_RECEIVE_EVENT_HANDLER

   //
   // Recycle The Packet And Buffers
   //
   UDPS_FreePacketAndBuffers( pUDPS_Packet );

#else

   //
   // Start Another Receive On Same Buffer
   //
   KS_ReceiveDatagramOnAddress(
      &g_KS_Address,
      NULL,       // User Completion Event
      UDPS_ReceiveDatagramCompletion,// User Completion Routine
      pUDPS_Packet,   // User Completion Context
      &pUDPS_Packet->Reserved.m_PacketIoStatus,
      pNdisBuffer,   // MdlAddress
      NULL,          // ReceiveDatagramInfo
      &pUDPS_Packet->Reserved.m_RemoteConnectionInfo, // ReturnInfo
      TDI_RECEIVE_NORMAL   // InFlags
      );

#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

/////////////////////////////////////////////////////////////////////////////
//// UDPS_TransferDataCallback
//
// Purpose
// Called by TDI when the receive data transfer initiated by ClientEventReceive
// or TdiReceive completes.
//
// Parameters
//
// Return Value

⌨️ 快捷键说明

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