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

📄 netbuf.c

📁 基于东南大学开发的SEP3203的ARM7中的所有驱动
💻 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.

* 2001-05-18 Mads Christiansen <mads@mogi.dk>, Partner Voxtream 

*       Small bugfix in nSplit.

* 2001-04-05 Robert Dickenson <odin@pnc.com.au>, Cognizant Pty Ltd.

*       Updated in various ways.

******************************************************************************

* 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 "netconf.h"

#include "netbuf.h"



#include <string.h>

#include <stdio.h>

#include "netdebug.h"

#include "os.h"

//#include "nettypes.h"





/*************************/

/*** LOCAL DEFINITIONS ***/

/*************************/

#define MAXNBUFS 48					/* The number of nBufs allocated. */



                                                                    

/******************************/

/*** PUBLIC DATA STRUCTURES ***/

/******************************/

NBuf *topNBuf;

#if STATS_SUPPORT > 0

NBufStats nBufStats;

u_int curFreeBufs;  // added by robert to make build

#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 = NULL;

	

	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;

	NBuf* n1 = NULL;

	

	if (n) {

		if (n->nextChain == n)

			netpanic("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;

#if STATS_SUPPORT > 0

			if ((n->chainLen += i) > nBufStats.maxChainLen.val)

				nBufStats.maxChainLen.val = n->chainLen;

#else

			n->chainLen += i;

#endif

			if (s) {

				// BUGFIX, replaced n0->data with n0->data + n0->len  and moved a line   /mogi

				memcpy( n0->data + n0->len , s, i);

				s += i;

			}

			// Moved this line here /mogi

			n0->len += 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 (nSrc && nDst && len) {

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

			

	}

	

	return st;

}





/*

 * nBufCopy - Return a new nBuf chain containing a copy of up to len bytes of

 * an nBuf chain starting "off0" bytes from the beginning.

 * Return the new chain on success, otherwise NULL. 

 */

NBuf *nBufCopy(

	NBuf *nSrc,					/* Top of nBuf chain to be copied. */

	u_int off0, 				/* Offset into the nBuf chain's data. */

	u_int len					/* Maximum bytes to copy. */

)

{

	u_int i;

	NBuf *nTop = NULL, *nDst, *nTmp;

	

	/* Find the starting position in the source chain. */

	for (; nSrc && off0 > nSrc->len; nSrc = nSrc->nextBuf)

		off0 -= nSrc->len;

	

	if (nSrc) {

		nGET(nDst);

		nTop = nDst;

		

		while (nDst && len) {

			/* Compute how much to copy from the current source buffer. */

			i = nSrc->len - off0;

			if (i > len)

				i = len;

			

			/* Copy it and advance to the next buffer if needed. */

			memcpy(nDst->data, &nSrc->data[off0], i);

#if STATS_SUPPORT > 0

			if ((nTop->chainLen += i) > nBufStats.maxChainLen.val)

				nBufStats.maxChainLen.val = nTop->chainLen;

#else

			nTop->chainLen += i;

#endif

			nDst->len = i;

			len -= i;

			off0 = 0;

			nSrc = nSrc->nextBuf;

			if (len && nSrc) {

				nGET(nTmp);

				if (nTmp) {

					nDst->nextBuf = nTmp;

					nDst = nTmp;

				} else {

					NBUFDEBUG((LOG_ERR, "nBufCopy: No free buffers"));

					(void)nFreeChain(nTop);

					nTop = NULL;

				}

			} else {

				/*** Let's just break out...

				nDst = NULL;

				***/

				break;
			}

⌨️ 快捷键说明

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