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

📄 netudp.c

📁 基于东南大学开发的SEP3203的ARM7中的所有驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/**

 * UDP Protocol Support for uC/IP.

 *

 * Copyright (c) 2001 by Intelligent Systems Software (UK) Ltd.  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

 *

 * 02-02-2001 Craig Graham <c_graham@hinge.mistral.co.uk>,Intelligent Systems Software (UK) Ltd

 *  First Version. Not based on anything really except RFC 768 (and Guy Lancaster's TCP

 *      protocol implementation as a basis for the checksum stuff).

 *(yyyy-mm-dd)

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

 *      Added support for static array of UDP_QUEUE* removing dependancy on 

 *      malloc and free for all the usual reasons.

 * 2001-09-10 Mads Lind Christiansen <mc@voxtream.com>, Partner Voxtream

 *      Fixed UDP checksum problems and more.

 *      The UDP module should now be up and running.

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

 * NOTES

 *  This probably isn't very good, but it does work (at least well enough to support DNS lookups,

 *  which is what I wanted it for).

 *

 */

#include <string.h>

#include "netconf.h"

#include "net.h"

#include "nettimer.h"

#include "netbuf.h"

#include "netrand.h"

#include "netip.h"

#include "netiphdr.h"

#include "netudp.h"

#include "neticmp.h"



#include "netdebug.h"

#include "os.h"

#include "devio.h"



/*#pragma warning (push)

#pragma warning (disable: 4761) // integral size mismatch in argument; conversion supplied

#pragma warning (disable: 4244) // 'function' : conversion from 'short ' to 'unsigned char ', possible loss of data

#pragma warning (disable: 4018) // signed/unsigned mismatch*/

////////////////////////////////////////////////////////////////////////////////



/** Maximum number of udp connections at one time */

#define MAXUDP          4

#define FUDP_OPEN       1

#define FUDP_CONNECTED  2

#define FUDP_LISTEN     4

#define MAXUDPQUEUES    20



/*

#ifdef DEBUG_UDP

#define UDPDEBUG(A) printf A

#else

#define UDPDEBUG(A)

#endif

 */



/** Dump an nBuf chain */

#define DUMPCHAIN(A) {\
        NBuf* p;\
        int i; \
        for (p = (A); p; p = p->nextBuf) {\
            for (i = 0; i < p->len; i++) {\
                if ((i & 3)==0)\
                    UDPDEBUG(("\n[%d]:",i));\
                    UDPDEBUG(("%x,",p->data[i]));\
            }\
        }\
        UDPDEBUG(("\n"));\
    }











UDPCB udps[MAXUDP];

static UDP_QUEUE udpqs[MAXUDPQUEUES];

static UDP_QUEUE* udp_free_list;



/** Port number auto-assigned by udpConnect if you've not already bound the socket when you connect it */

static int randPort = 0x0507;



UDP_QUEUE* alloc_udp_q(void)

{

//    return (UDP_QUEUE*)malloc(sizeof(UDP_QUEUE));

    UDP_QUEUE* q = NULL;

    if (udp_free_list != NULL) {

        q = udp_free_list;

        udp_free_list = udp_free_list->next;

    }

    return q;

}



void free_udp_q(UDP_QUEUE* q)

{

//    free(q);

    q->srcPort = 0;

    q->next = udp_free_list;

    udp_free_list = q;

}



void udpInit(void)

{

    int i;

    UDPDEBUG(("udpInit()\n"));

    for (i = 0; i < MAXUDP; i++) {

        udps[i].flags = 0;

        udps[i].sem = OSSemCreate(0);

    }

    udp_free_list = NULL;

    for (i = MAXUDPQUEUES; i--; ) {

        free_udp_q(&udpqs[i]);

    }

}







#if ONETASK_SUPPORT > 0

int udpOpen(void (*receiveEvent)(int ud, u_int16_t bytes))

#else

int udpOpen(void)

#endif

{

    int i;

    UDPDEBUG(("udpOpen()\n"));

    OS_ENTER_CRITICAL();

    for (i = 0; (i < MAXUDP) && (udps[i].flags & FUDP_OPEN); i++);

    if (i == MAXUDP) {

        OS_EXIT_CRITICAL();

        return -1;

    }

    udps[i].flags |= FUDP_OPEN;

    udps[i].ourPort = udps[i].theirPort = 0;

    udps[i].theirAddr.s_addr = 0xffffffff;

    udps[i].acceptFromAddr.s_addr = 0xffffffff;   /* Default to not accepting any address stuff */

    udps[i].head = udps[i].tail = NULL;

	

	#if ONETASK_SUPPORT > 0

	udps[i].receiveEvent = receiveEvent;

	#endif



    OS_EXIT_CRITICAL();

    return i;

}



int udpClose(int ud)

{

    if (!(udps[ud].flags & FUDP_OPEN)) return -1;

    udps[ud].flags = 0;

    return 0;

}



int udpConnect(u_int ud, const struct sockaddr_in *remoteAddr, u_char tos)

{

    if (!(udps[ud].flags & FUDP_OPEN)) return -1;

    udps[ud].acceptFromAddr = udps[ud].theirAddr = remoteAddr->sin_addr;

    udps[ud].theirPort = htons(remoteAddr->sin_port);

    udps[ud].tos = tos;

    if (udps[ud].ourPort == 0)

        udps[ud].ourPort = htons((unsigned short)(randPort++));

    udps[ud].flags |= FUDP_CONNECTED;

    return 0;

}



int udpListen(u_int ud, int backLog)

{

    if (!(udps[ud].flags & FUDP_OPEN)) return -1;

    udps[ud].flags |= FUDP_LISTEN;

    return 0;

}



int udpBind(u_int ud, struct sockaddr_in* peerAddr)

{

    UDPDEBUG(("udpBind(%d,%lx)\n",ud,peerAddr));

    if (!(udps[ud].flags & FUDP_OPEN)) return -1;

    udps[ud].acceptFromAddr.s_addr = peerAddr->sin_addr.s_addr;

    udps[ud].acceptFromAddr.s_addr = 0xD34130B6UL;

    

//work out whether we should do the htons on the client ???    

    udps[ud].ourPort = peerAddr->sin_port;

	udps[ud].ourPort = 0X1F90;

//    udps[ud].ourPort = htons(peerAddr->sin_port);

    return 0;

}



int udpRead(u_int ud, void* buf, long len)

{

    unsigned char* d;

    int rtn;

    NBuf* b;

    UDP_QUEUE* q;

    struct in_addr fromAddr;

    u_int8 err;



    if (!(udps[ud].flags & FUDP_OPEN)) return -1;

    d = (unsigned char*)buf;

    rtn = 0;

    //OSSemPend(udps[ud].sem, 0, &err);

	OSSemPend(udps[ud].sem, 0, &err);

    if (udps[ud].head == NULL) {

        return -1;

    }

    fromAddr = udps[ud].theirAddr = udps[ud].head->srcAddr;

    udps[ud].theirPort = udps[ud].head->srcPort;



	UDPDEBUG(("fromAddr.s_addr = %08X,   udps[ud].head->srcAddr.s_addr = %08X\n", fromAddr.s_addr, udps[ud].head->srcAddr.s_addr));



    while ((udps[ud].head) && (len) && (fromAddr.s_addr == udps[ud].head->srcAddr.s_addr)) {

        // Get next nBuf

        b = udps[ud].head->nBuf;

		// While we have more buffer to copy out to AND

		// We have a queued nBuf

        while ((len) && (b)) {

			// While we have more buffer space to copy to AND

			// nBuf is not empty

//            while ((len) && (b->data != &b->body[b->len])) {

			while ( (len) && (b->len) )	{

				// Copy one byte

                *d++ = *b->data++;

				b->len--; 

                len--;

                rtn++;

            }

			// If nBuf is empty

//            if (b->data == &b->body[b->len]) {

			if (!b->len) {

				// Free it!

                OS_ENTER_CRITICAL();

                b = udps[ud].head->nBuf = nFree(b);

                OS_EXIT_CRITICAL();

            }

        }

		// If nBuf was freed (we need another one if any)

        if (b == NULL) {

			// Get next nBuf in queue

            q = udps[ud].head;

            OS_ENTER_CRITICAL();

            udps[ud].head = q->next;

            OS_EXIT_CRITICAL();

            free_udp_q(q);

			#if ONETASK_SUPPORT > 0

			#else

            if (udps[ud].head)

                OSSemPend(udps[ud].sem, 0, &err);

			#endif

        } else {

			#if ONETASK_SUPPORT > 0

			// nBuf was not freed but we have filled our buffer (buf) 

			return rtn;

			#else

            OSSemPost(udps[ud].sem);

			#endif

        }

    }

    if (udps[ud].head == NULL)

        udps[ud].tail = NULL;

    return rtn;

}



#if 1



int udpWrite(u_int ud, const void* buf, long len)

{

    NBuf* pNBuf;

    IPHdr* ipHdr;

    UDPHdr* udpHdr;



    long rtn = 0;

	long copied;

    u_int mtu;



    UDPDEBUG(("udpWrite()\n"));

    if (!(udps[ud].flags & FUDP_OPEN)) return -1;

    mtu = ipMTU(htonl(udps[ud].theirAddr.s_addr));

    if (!mtu) {

        UDPDEBUG(("no route to host\n"));

        return -1;

    }

    while (len) {

        pNBuf = NULL;

#if ONETASK_SUPPORT > 0

		// We can't do a loop forever in a onetask OS

        nGET(pNBuf);

		// No more nBuf buffers available, should return what we have copied so far

		if (!pNBuf) return rtn;

#else

		// BUSY WAITING! (not nice)

        do {

            nGET(pNBuf);

        } while (pNBuf == NULL);

#endif

		// Reserve room for headers 

		pNBuf->len = pNBuf->chainLen = sizeof(IPHdr) + sizeof(UDPHdr);



		// Add payload

		copied = nAppend(pNBuf, &((unsigned char *)buf)[rtn], MIN(mtu - sizeof(IPHdr) - sizeof(UDPHdr), (unsigned)len));

		if (copied && pNBuf) {

			len -= copied;

			rtn += copied;



			// Setup IP header and prepare it so we can compute the UDP checksum

			// Use the IP header as UDP pseudo header

			ipHdr = nBUFTOPTR(pNBuf, IPHdr *);

			ipHdr->ip_src.s_addr = htonl(localHost);

			ipHdr->ip_dst.s_addr = udps[ud].theirAddr.s_addr;

			ipHdr->ip_ttl = 0;

			ipHdr->ip_p = IPPROTO_UDP;

	        ipHdr->ip_sum = htons((unsigned short)(copied + sizeof(UDPHdr)));



			// Build the UDP header 

			udpHdr = (void *)(ipHdr + 1);

			udpHdr->srcPort = udps[ud].ourPort;

			udpHdr->dstPort = udps[ud].theirPort;

			udpHdr->checksum = 0;

            udpHdr->length = ipHdr->ip_sum;



			// Compute UDP header checksum

	        udpHdr->checksum = inChkSum(pNBuf, (unsigned short)(pNBuf->chainLen - 8), 8);



			// Build IP header 

			ipHdr->ip_v = 4;

			ipHdr->ip_hl = sizeof(IPHdr) >> 2;

			ipHdr->ip_tos =(unsigned char)(udps[ud].tos);

	        ipHdr->ip_len = copied + sizeof(IPHdr) + sizeof(UDPHdr);

			ipHdr->ip_id = IPNEWID();

			ipHdr->ip_off = 0;

	        ipHdr->ip_ttl = UDPTTL;

			ipHdr->ip_sum = 0;

			ipHdr->ip_sum = inChkSum(pNBuf, sizeof(IPHdr), 0);

		} else {

			// Nothing copied ?!? This can only happen if nBuf size is eq. to sizeof(IPHdr) + sizeof(UDPHdr)

			// AND there are no more buffers free

			// This situation isn't actually handled! But we will free nBuf anyway

			nFreeChain(pNBuf);

		}



        UDPDEBUG(("-src=%s port %ld dest=%s port=%ld\n", \

            ip_ntoa(/*htonl*/(ipHdr->ip_src.s_addr)),   \

            htons(udpHdr->srcPort),                     \

            ip_ntoa2(/*htonl*/(ipHdr->ip_dst.s_addr)),  \

            htons(udpHdr->dstPort)                      \

            ));



        // Pass the datagram to IP and we're done. 

				if (pNBuf) ipRawOut(pNBuf);

    }

    return rtn;

}



#else



int udpWrite(u_int ud, const void* buf, long len)

{

    NBuf* pNBuf;
    NBuf* pNBufTail;

    IPHdr* ipHdr;

    UDPHdr* udpHdr;

    long rtn = len;

⌨️ 快捷键说明

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