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

📄 netbuf.c

📁 ucos操作系统下TCPIP实现代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
* netbuf.c - Network Buffers program file.
*
* Copyright (c) 1998 by Global Election Systems Inc.  All rights reserved.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice and the following disclaimer are included verbatim in any 
* distributions. No written agreement, license, or royalty fee is required
* for any of the authorized uses.
*
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
* REVISION HISTORY
*
* 98-01-30 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
*	Original based on BSD codes.
******************************************************************************
* PROGRAMMER NOTES
*
* FREE BUFFER MARK
*	Free buffers have nextChain pointing back to themselves.
*
* CRITICAL SECTIONS
*	Only queue operations are protected from corruption from other tasks and
* interrupts.  It is assumed that only one task at a time operates on a buffer
* chain but multiple tasks will share queues.
*
* BUFFER QUEUES
*	The buffer queue structure's primary purpose is to minimize the overhead
* of adding a new chain to the queue.  A side benefit is that if packets
* span more than one nBuf, then the overhead to seek to a particular offset
* in the queue is reduced.  A queue is required to maintain boundaries of 
* incoming UDP datagrams if UDP support were added.
*****************************************************************************/

#include "typedefs.h"
#include "avconfig.h"
#include "string.h"
#include "stdio.h"				// Required by debug.h
#include "avos.h"

#include "netbuf.h"

#include "debug.h"


/*************************/
/*** LOCAL DEFINITIONS ***/
/*************************/
#define MAXNBUFS 32					/* The number of nBufs allocated. */

                                                                    
/******************************/
/*** PUBLIC DATA STRUCTURES ***/
/******************************/
NBuf *topNBuf;
#if STATS_SUPPORT > 0
NBufStats nBufStats;
#else
u_int curFreeBufs;
#endif


/*****************************/
/*** LOCAL DATA STRUCTURES ***/
/*****************************/
/* The free list of buffers. */
static NBuf nBufs[MAXNBUFS];


/***********************************/
/*** PUBLIC FUNCTION DEFINITIONS ***/
/***********************************/
/* Initialize the memory buffer subsytem. */
void nBufInit (void)
{
	int i;
	
	topNBuf = &nBufs[0];
	for (i = 0; i < MAXNBUFS; i++) {
		nBufs[i].nextBuf = &nBufs[i + 1];
		nBufs[i].nextChain = &nBufs[i];
	}
	nBufs[MAXNBUFS - 1].nextBuf = NULL;
	
#if STATS_SUPPORT > 0
	memset(&nBufStats, 0, sizeof(nBufStats));
	nBufStats.headLine.fmtStr    = "\t\tNETWORK BUFFERS\r\n";
	nBufStats.curFreeBufs.fmtStr = "\tCURRENT FREE: %5lu\r\n";
	nBufStats.curFreeBufs.val = MAXNBUFS;
	nBufStats.minFreeBufs.fmtStr = "\tMINIMUM FREE: %5lu\r\n";
	nBufStats.minFreeBufs.val = MAXNBUFS;
	nBufStats.maxFreeBufs.fmtStr = "\tMAXIMUM FREE: %5lu\r\n";
	nBufStats.maxFreeBufs.val = MAXNBUFS;
	nBufStats.maxChainLen.fmtStr = "\tMAX CHAIN SZ: %5lu\r\n";
#else
	curFreeBufs = MAXNBUFS;
#endif
}

/*
 * nFree - Free a single nBuf and associated external storage.
 * Return the next nBuf in the chain, if any.
 */
NBuf *nFree(NBuf *n)
{
	NBuf *n0;
	
	nFREE(n, n0)
	return n0;
}


/*
 * nFreeChain - Free all nBufs in a chain.  
 * Return the next chain in the queue, if any.
 */
NBuf *nFreeChain(NBuf *n)
{
	NBuf *n0, *n1;
	
	if (n) {
		if (n->nextChain == n)
			panic("nFreeChain");
		else {
			n0 = n;
			n = n->nextChain;
			while (n0) {
				nFREE(n0, n1);
				n0 = n1;
			}
		}
	}
	
	return n;
}


/*
 * nPrepend - Prepend plen bytes to nBuf n and load from s if non-null.
 * A new nBuf is always allocated but if allocation fails, the
 * original nBuf chain is freed.  The chain size is updated.  This assumes
 * that the chain is not in a queue.
 * Return the new nBuf chain on success, NULL on failure.
 */
NBuf *nPrepend(
	NBuf	*n,					/* Destination nBuf chain. */
	const char *s,				/* The data to prepend. */
	u_int	plen				/* The length of the data to prepend. */
)
{
	NBuf *n0;
	
	if (n) {
		nGET(n0);
		while (n0) {
			n0->nextBuf = n;
			if (plen > NBUFSZ) {
				n0->len = NBUFSZ;
#if STATS_SUPPORT > 0
				if ((n0->chainLen = n->chainLen + NBUFSZ) > nBufStats.maxChainLen.val)
					nBufStats.maxChainLen.val = n0->chainLen;
#else
				n0->chainLen = n->chainLen + NBUFSZ;
#endif
				if (s) {
					memcpy(n0->data, s + plen - NBUFSZ, NBUFSZ);
				}
				plen -= NBUFSZ;
				n = n0;
				nGET(n0);
			} else {
				n0->len = plen;
#if STATS_SUPPORT > 0
				if ((n0->chainLen = n->chainLen + plen) > nBufStats.maxChainLen.val)
					nBufStats.maxChainLen.val = n0->chainLen;
#else
				n0->chainLen = n->chainLen + plen;
#endif
				n0->data = n0->body + NBUFSZ - plen;
				if (s) {
					memcpy(n0->data, s, plen);
				}
				plen = 0;
				n = n0;
				/*** We're done, skip the test.
				n0 = NULL;
				***/
				break;
			}
		}
		if (plen) {
			NBUFDEBUG((LOG_ERR, "nPrepend: No free buffers"));
			(void)nFreeChain(n);
			n = NULL;
		}
	}
	return n;
}


/*
 * nAppend - Append slen bytes to the nBuf chain n and load from s if non-null.
 * Note that the chain length is updated but the chain is assumed to not be in
 * a queue.
 * Return the number of bytes appended.
 */
u_int nAppend(NBuf *n, const char *s, u_int sLen)
{
	u_int copied = 0, i;
	NBuf *n0 = n;	

	if (n0 && sLen) {
		/* Find the last nBuf on the chain. */
		for (; n0->nextBuf; n0 = n0->nextBuf);
		/* If there's space, append what we can. */
		if ((i = (u_int)nTRAILINGSPACE(n0)) > 0) {
			if (i > sLen)
				i = sLen;
			n0->len += i;
#if STATS_SUPPORT > 0
			if ((n->chainLen += i) > nBufStats.maxChainLen.val)
				nBufStats.maxChainLen.val = n->chainLen;
#else
			n->chainLen += i;
#endif
			if (s) {
				memcpy(n0->data, s, i);
				s += i;
			}
			copied = i;
			sLen -= i;
		}
		if (sLen) {
			nGET(n0->nextBuf);
			n0 = n0->nextBuf;
		}
	}
	/* Append new buffers until s is consumed or we fail to allocate. */
	while (n0 && sLen) {
		if (sLen > NBUFSZ) {
			n0->len = NBUFSZ;
#if STATS_SUPPORT > 0
			if ((n->chainLen += NBUFSZ) > nBufStats.maxChainLen.val)
				nBufStats.maxChainLen.val = n->chainLen;
#else
			n->chainLen += NBUFSZ;
#endif
			if (s) {
				memcpy(n0->data, s, NBUFSZ);
				s += NBUFSZ;
			}
			sLen -= NBUFSZ;
			copied += NBUFSZ;
		} else {
			n0->len = sLen;
#if STATS_SUPPORT > 0
			if ((n->chainLen += sLen) > nBufStats.maxChainLen.val)
				nBufStats.maxChainLen.val = n->chainLen;
#else
			n->chainLen += sLen;
#endif
			if (s) {
				memcpy(n0->data, s, sLen);
			}
			copied += sLen;
			break;	/* We're done, skip the test. */
		}
		nGET(n0->nextBuf);
		n0 = n0->nextBuf;
	}
	return copied;
}


/*
 * nAppendBuf - Append data from buffer chain n1 starting from the offset
 * onto the end of the chain n0.  
 * Return the number of characters appended.
 */
u_int nAppendBuf(
	NBuf *nDst,					/* The destination chain. */
	NBuf *nSrc,					/* The source chain. */
	u_int off0, 				/* The starting offset into the source. */
	u_int len					/* The maximum bytes to copy. */
)
{
	u_int st = 0, copySz;
	NBuf *nTop = nDst, *nTmp;
	
	if (!nDst)
		return 0;
		
	/* Find the end of the destination chain. */
	nTop = nDst;
	for (; nDst->nextBuf; nDst = nDst->nextBuf)
		;
		
	/* Find the starting position in the source chain. */
	for (; nSrc && off0 > nSrc->len; nSrc = nSrc->nextBuf)
		off0 -= nSrc->len;
	
	if (nSrc) {
		while (nDst && len) {
			/* Compute how much to copy from the current source buffer. */
			copySz = min(len, nSrc->len - off0);

			/* Do we need to append another destination buffer? */
			/* 
			 * Note that we don't attempt to fill small spaces at the
			 * end of the current destination buffer since on average,
			 * we don't expect that it would reduce the number of
			 * buffers used and it would complicate and slow the 
			 * operation.
			 */
			if (nTRAILINGSPACE(nDst) < copySz) {
				nGET(nTmp);
				if (!nTmp) {
					NBUFDEBUG((LOG_ERR, "nBufCopy: No free buffers"));
					nDst = NULL;
					break;
				}
				nDst->nextBuf = nTmp;
				nDst = nTmp;
			}
				
			/* Copy it and advance to the next source buffer if needed. */
			memcpy(&nDst->data[nDst->len], &nSrc->data[off0], copySz);
#if STATS_SUPPORT > 0
			if ((nTop->chainLen += copySz) > nBufStats.maxChainLen.val)
				nBufStats.maxChainLen.val = nTop->chainLen;
#else
			nTop->chainLen += copySz;
#endif
			nDst->len += copySz;
			st += copySz;
			len -= copySz;
			off0 = 0;
			nSrc = nSrc->nextBuf;
		}
	}
	
	return st;
}


/*
 * nAppendFromQ - Append data from a source queue starting from the offset
 * onto the end of the destination chain.
 * Return the number of characters appended.
 */
u_int nAppendFromQ(
	NBuf *nDst,					/* The destination chain. */
	NBufQHdr *nSrcQ,			/* The source queue. */
	u_int off0, 				/* The starting offset into the source. */
	u_int len					/* The maximum bytes to copy. */
)
{
	u_int st = 0, copySz;
	NBuf *nDstTop, *nSrc, *nSrcTop, *nTmp;
	
	/* Validate parameters. */
	if (!nDst || !nSrcQ)
		return 0;
	
	/* Find the end of the destination chain. */
	nDstTop = nDst;
	while (nDst->nextBuf)
		nDst = nDst->nextBuf;
		
	/* Find the starting chain in the source queue. */
	for (nSrc = nSrcQ->qHead; nSrc && off0 >= nSrc->chainLen; nSrc = nSrc->nextChain) {
		off0 -= nSrc->chainLen;
	}
	nSrcTop = nSrc;
	
	/* Find the starting position in the source chain. */
	for (; nSrc && off0 >= nSrc->len; nSrc = nSrc->nextBuf) {
		off0 -= nSrc->len;
	}

	while (nSrc && nDst && len) {
		/* 
		 * Compute how much to copy from the current source buffer. 
		 * Note that since we copy from a single source buffer at a
		 * time, we don't have to check that the copy size fits in
		 * a single buffer.
		 */
		copySz = min(len, nSrc->len - off0);

		/* Append another destination buffer if needed. */
		/* 
		 * Note that we don't attempt to fill small spaces at the
		 * end of the current destination buffer since on average,
		 * we don't expect that it would reduce the number of
		 * buffers used and it would complicate and slow the 
		 * operation.
		 */
		if (nTRAILINGSPACE(nDst) < copySz) {
			nGET(nTmp);
			if (!nTmp) {
				NBUFDEBUG((LOG_ERR, "nAppendFromQ: No free buffers"));
				nDst = NULL;
				break;
			}
			nDst->nextBuf = nTmp;
			nDst = nTmp;
		}
			
		/* Copy it and advance to the next source buffer if needed. */
		memcpy(&nDst->data[nDst->len], &nSrc->data[off0], copySz);
#if STATS_SUPPORT > 0
		if ((nDstTop->chainLen += copySz) > nBufStats.maxChainLen.val)
			nBufStats.maxChainLen.val = nDstTop->chainLen;
#else
		nDstTop->chainLen += copySz;
#endif
		nDst->len += copySz;
		st += copySz;
		len -= copySz;
		off0 = 0;
		if ((nSrc = nSrc->nextBuf) == NULL)
			nSrc = nSrcTop = nSrcTop->nextChain;

⌨️ 快捷键说明

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