?? netbuff.cpp
字號:
//***********************************************************************/
// Author : Garry
// Original Date : Aug,06 2005
// Module Name : NETBUFF.CPP
// Module Funciton :
// This module countains net buffer's
// implementation code.
// Last modified Author :
// Last modified Date :
// Last modified Content :
// 1.
// 2.
// Lines number :
//***********************************************************************/
#ifndef __STDAFX_H__
#include "..\Kernel\StdAfx.h"
#endif
#ifndef __DEFINES_H__
#include "DEFINES.H"
#endif
#ifndef __NETBUFF_H__
#include "NETBUFF.H"
#endif
/*--------------- ** Some important hints about net buffer object ** -------------------
The net buffer object is used by network entity,such as IP kernel thread,net interface
card,to store data or packets.When you use the net buffer object,the following rules must
be obeied:
1. When you transfer a net buffer object as a parameter to another kernel thread,you
must first increment the reference counter by calling NetBufferGet routine;
2. When you finished to use a net buffer object,you must call NetBufferFree routine to
release the memory or decrement the reference counter,if the net buffer object is created
by yourself,if the object is not created by your self,but is transfered by another
kernel thread,you must call NetBufferFree routine too;
3. All net buffer operations are interrupt safe,so you can call the operations anywhere.
---------------------------------------------------------------------------------------*/
//
//The implementation of net buffer queue.
//This is a FIFO queue,can be used by any entity,such as IP kernel thread.
//
//
//The implementation of InsertIntoQueue.
//This routine adds the net buffer object to the end of the queue.
//If the current element number is not exceed the max number,then insert it,and
//returns TRUE,otherwise,returns FALSE.
//
static BOOL InsertIntoQueue(__NET_BUFFER_QUEUE* lpQueue,__NET_BUFFER* lpNetBuffer)
{
DWORD dwFlags = 0L;
__ENTER_CRITICAL_SECTION(NULL,dwFlags); //The following operation should not be
//interrupted.
if(lpQueue->dwQueueNum == lpQueue->dwMaxNum) //The queue is full.
{
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
return FALSE;
}
//
//The following code insert the net buffer object into queue's tail.
//
if(NULL == lpQueue->lpQueueTail) //There is not any element in the queue.
{
lpQueue->lpQueueHdr = lpNetBuffer;
lpQueue->lpQueueTail = lpNetBuffer;
lpNetBuffer->lpNext = NULL;
lpNetBuffer->lpPrev = NULL;
lpQueue->dwQueueNum ++;
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
return TRUE;
}
else //The queu is not empty.
{
lpQueue->lpQueueTail->lpNext = lpNetBuffer;
lpNetBuffer->lpPrev = lpQueue->lpQueueTail;
lpNetBuffer->lpNext = NULL;
lpQueue->lpQueueTail = lpNetBuffer;
lpQueue->dwQueueNum ++;
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
return TRUE;
}
return TRUE;
}
//
//The implementation of DeleteFromQueue.
//This routine first check if the object is in the queue,if not,returns FALSE,
//else,deletes it and returns TRUE.
//
static BOOL DeleteFromQueue(__NET_BUFFER_QUEUE*,__NET_BUFFER*)
{
BOOL bResult = FALSE;
return bResult;
}
//
//The implementation of GetFromQueue.This routine gets the first element of this queue.
//
static __NET_BUFFER* GetFromQueue(__NET_BUFFER_QUEUE* lpQueue)
{
__NET_BUFFER* lpNetBuffer = NULL;
DWORD dwFlags = 0L;
if(NULL == lpQueue) //Parameter check.
return NULL;
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
if(NULL == lpQueue->lpQueueHdr) //The current queue is empty.
{
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
return NULL;
}
if(lpQueue->lpQueueHdr == lpQueue->lpQueueTail) //There is only one element in the queue.
{
lpNetBuffer = lpQueue->lpQueueHdr;
lpQueue->lpQueueHdr = NULL;
lpQueue->lpQueueTail = NULL;
lpNetBuffer->lpPrev = NULL;
lpNetBuffer->lpNext = NULL;
lpQueue->dwQueueNum--;
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
return lpNetBuffer;
}
else //There are at least two elements in the current queue.
{
lpNetBuffer = lpQueue->lpQueueHdr;
lpQueue->lpQueueHdr = lpNetBuffer->lpNext;
lpQueue->lpQueueHdr->lpPrev = NULL;
lpQueue->dwQueueNum --;
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
return lpNetBuffer;
}
return NULL; //This instruction should never be executed.
}
//
//The implementation of GetQueueLength.
//
static DWORD GetQueueLen(__NET_BUFFER_QUEUE* lpQueue)
{
if(NULL == lpQueue)
return 0L;
return lpQueue->dwQueueNum;
}
//
//The implementation of SetMaxLen.
//
static VOID SetMaxLen(__NET_BUFFER_QUEUE* lpQueue,DWORD dwMaxLen)
{
DWORD dwFlags = 0L;
if(NULL == lpQueue) //Parameter check.
return;
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
lpQueue->dwMaxNum = dwMaxLen;
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
return;
}
//
//The implementation of Initialize.
//
static VOID QueueInitialize(__NET_BUFFER_QUEUE* lpQueue)
{
if(NULL == lpQueue)
return;
lpQueue->lpQueueHdr = NULL;
lpQueue->lpQueueTail = NULL;
lpQueue->dwQueueNum = 0L;
lpQueue->dwMaxNum = 0L;
lpQueue->Initialize = QueueInitialize;
lpQueue->SetMaxLen = SetMaxLen;
lpQueue->GetQueueLen = GetQueueLen;
lpQueue->GetFromQueue = GetFromQueue;
lpQueue->DeleteFromQueue = DeleteFromQueue;
lpQueue->InsertIntoQueue = InsertIntoQueue;
return;
}
BOOL NetBufferQueueInit(__NET_BUFFER_QUEUE* lpQueue) //Global routine.
{
if(NULL == lpQueue)
return FALSE;
QueueInitialize(lpQueue);
return TRUE;
}
//--------------------------------------------------------------------------------------
//
//The implementation of net buffer manager.
//
//
//Pre-declaration of routines.
//
static VOID NetBufferFreeData(__NET_BUFFER_MANAGER*,__NET_BUFFER*);
//
//A helper routine,used to get a free net buffer from free list.
//
static __NET_BUFFER* __GetFreeNetBuffer(__NET_BUFFER_MANAGER* lpMgr)
{
__NET_BUFFER* lpNetBuffer = NULL;
lpNetBuffer = ALLOC_BUFF_MEMORY(sizeof(__NET_BUFFER));
if(NULL == lpNetBuffer)
return NULL;
#define SET(member,value) lpNetBuffer->member = value //This macro initializes a member.
SET(lpPrev, NULL);
SET(lpNext, NULL);
SET(lpSocket, NULL);
SET(Time, NULL);
SET(lpNetDevice, NULL);
SET(TransLayerHdr.lpTransLayerData, NULL);
SET(NetLayerHdr.lpNetLayerData, NULL);
SET(LinkLayerHdr.lpLinkLayerData, NULL);
SET(dwDataLen, 0L);
SET(dwTotalLen, 0L);
SET(dwCheckSum, 0L);
SET(dwPktType, PACKET_TYPE_UNKNOWN);
SET(bCloned, FALSE);
SET(ucProtocol, PACKET_PROTOCOL_UNKNOWN);
SET(ucReserved1, 0);
SET(ucReserved2, 0);
SET(ucReserved3, 0);
SET(lpBufferHdr, NULL);
SET(lpBufferEnd, NULL);
SET(lpDataHdr, NULL);
SET(lpDataEnd, NULL);
#undef SET //Finish to initialize the net buffer allocated just now.
__INIT_ATOMIC(lpNetBuffer->Users);
AtomicSet(&lpNetBuffer->Users,1);
return lpNetBuffer;
}
//
//A helper routine,used to free a net buffer object.
//
static VOID __FreeNetBuffer(__NET_BUFFER_MANAGER* lpMgr,__NET_BUFFER* lpNetBuffer)
{
if(NULL == lpNetBuffer) //Parameter check.
return;
FREE_BUFF_MEMORY(lpNetBuffer); //Release the net buffer memory.
return;
}
//
//The implementation of NetBufferAlloc.
//
static __NET_BUFFER* NetBufferAlloc(__NET_BUFFER_MANAGER* lpManager,DWORD dwBuffLen)
{
__NET_BUFFER* lpNetBuffer = NULL;
DWORD dwFlags = 0L;
UCHAR* lpDataBuff = NULL;
__FRAG_DATA* lpFragData = NULL;
if((NULL == lpManager) || (0 == dwBuffLen)) //Parameter check.
return NULL;
lpNetBuffer = __GetFreeNetBuffer(lpManager);
if(NULL == lpNetBuffer) //Can not get a net buffer object,no memory may be the
//most reasonable reason.
return NULL;
lpDataBuff = ALLOC_DATA_MEMORY(dwBuffLen);
if(NULL == lpDataBuff) //Can not allocate memory to hold data.
{
__FreeNetBuffer(lpManager,lpNetBuffer);
return NULL;
}
//
//We have get a net buffer object and allocate a data buffer successfully,then,
//we should initialize the net buffer object according to data buffer.
//
lpNetBuffer->lpBufferHdr = lpDataBuff;
lpNetBuffer->lpBufferEnd = lpDataBuff + dwBuffLen;
lpNetBuffer->lpDataHdr = lpDataBuff;
lpNetBuffer->lpDataEnd = lpDataBuff;
lpFragData = NET_BUFFER_FRAG_DATA(lpNetBuffer); //Get the fragment data.
NetBufferQueueInit(&lpFragData->FragQueue); //Initialize the frag data queue.
__INIT_ATOMIC(lpFragData->SharedCounter); //Initialize the shared counter.
AtomicSet(&lpFragData->SharedCounter,1); //Set the shared counter to 1.
return lpNetBuffer;
}
//
//The implementation of NetBufferFree.
//This routine decrement the reference counter of net buffer object,if the reference
//counter hits zero,then release the net buffer object and it's data buffer,else,
//only return.
//
static VOID NetBufferFree(__NET_BUFFER_MANAGER* lpManager,__NET_BUFFER* lpNetBuffer)
{
if((NULL == lpManager) || (NULL == lpNetBuffer)) //parameter check.
return;
if(AtomicDec(&lpNetBuffer->Users)) //The reference counter hit zero.
{
NetBufferFreeData(lpManager,lpNetBuffer); //Release the data buffer.
__FreeNetBuffer(lpManager,lpNetBuffer); //Release the net buffer object.
}
else //The reference counter does not hit zero,it means,that there also some other
//entities are using the net buffer object.
return;
}
//
//The implementation of NetBufferFreeData.
//
static VOID NetBufferFreeData(__NET_BUFFER_MANAGER* lpMgr,__NET_BUFFER* lpNetBuffer)
{
__FRAG_DATA* lpFragData = NULL;
__NET_BUFFER* lpNetBuff = NULL;
if((NULL == lpMgr) || (NULL == lpNetBuffer)) //Parameter check.
return;
lpFragData = NET_BUFFER_FRAG_DATA(lpNetBuffer);
if(AtomicDec(&lpFragData->SharedCounter)) //Share counter hits zero,should release
//all data.
{
lpNetBuff = lpFragData->FragQueue.GetFromQueue(&lpFragData->FragQueue);
while(lpNetBuff) //There is fragment data.
{
NetBufferFree(lpMgr,lpNetBuff); //Release the fragment data.
lpNetBuff = lpFragData->FragQueue.GetFromQueue(&lpFragData->FragQueue);
}
//__FreeNetBuffer(lpMgr,lpNetBuff); //Release the memory the data buffer occupied.
FREE_DATA_MEMORY(lpNetBuffer->lpBufferHdr); //Release the data buffer.
}
else //The shared counter is not zero,it means there is other entity is using the data
//buffer.
{
DWORD dwLoop = lpFragData->FragQueue.GetQueueLen(&lpFragData->FragQueue);
for(DWORD i = 0;i < dwLoop;i ++) //Decrement the reference counter of all fragment.
//The reference counter of all fragments should
//never less than the reference counter of data
//buffer.
//This can be ensure by NetBufferClone routine,
//this routine will increment the reference counter
//of data buffer and all fragments.
//So,NetBufferFree routine only decrement the
//reference counter of all fragments.
{
lpNetBuff = lpFragData->FragQueue.GetFromQueue(&lpFragData->FragQueue);
NetBufferFree(lpMgr,lpNetBuff);
lpFragData->FragQueue.InsertIntoQueue(&lpFragData->FragQueue,lpNetBuff);
}
}
return;
}
//
//The implementation of NetBufferGet.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -