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

📄 udp.cc

📁 南京航空航天大学开发的一个类Unix和Linux的操作系统,好不好看看就知道了,
💻 CC
字号:
#include "root.h" #include <lib/errno.h>#include <init/ctor.h>#include <mm/allockm.h>#include <mm/layout.h>#include "udp.h"#include "ip.h"static Q(all, udpsock_t) allq;typedef Q(hash, udpsock_t) hashq_t;static int hsize, hmask;static hashq_t *hashtab;static inline hashq_t * hashfunc(u16_t lport){	return hashtab + (ntohs(lport) & hmask);}__ctor(PRINET, SUBANY, initudphash){	construct(&allq);	hsize = min(32, nphysmeg);	hmask = hsize - 1;	hashtab = (hashq_t*) allocbm(hsize * sizeof(hashq_t));	construct(hashtab, hsize);}static bool exist(u32_t laddr, u16_t lport){	hashq_t * hashq = hashfunc(lport);	udpsock_t * s;	foreach (s, *hashq) {		if ((s->laddr == INADDRANY || laddr == INADDRANY || s->laddr == laddr) &&		    (s->lport == lport))			return true;	}	return false;}static u16_t newudpport(){	/* well known ports ranges from 0 to 1023 */	static u16_t begin = USERSOCK;	while (exist(INADDRANY, begin))		if (!++begin) /* overflow */			begin = USERSOCK;	return htons(begin);}void udpinput(pkt_t *pkt){	iphdr_t * ih = (iphdr_t*) pkt->data;	udphdr_t * uh = (udphdr_t*) (pkt->data + ih->headlen());	if (uh->chksum && udpchksum(ih->saddr, ih->daddr, ih->datalen(), ih->data)) {		printd("udp check sum failed\n");		delpkt(pkt);		return;	}	hashq_t * hashq = hashfunc(uh->dport);        udpsock_t *s;	/* demultiplex the packet */	foreach (s, *hashq) {		bool localmatch = (s->laddr == INADDRANY || s->laddr == ih->daddr) &&			          (s->lport == uh->dport);		if (!localmatch)			continue;		/* if s is not connected, ignore ih->saddr, uh->sport */		if ((s->faddr == INADDRANY) ||  		    (s->faddr == ih->saddr && s->fport == uh->sport)) {			s->input(pkt);			return;		}				}	printd("no udp socket accept this packet(saddr=%s sport=%d daddr=%s dport=%d\n",         inetntoa(ih->saddr), ntohs(uh->sport), inetntoa(ih->daddr), ntohs(uh->dport));	delpkt(pkt);}void udpsock_t::dump(){	printf("laddr = %s, lport = %d, faddr = %s, fport = %d\n", 	       inetntoa(laddr), ntohs(lport), inetntoa(faddr), ntohs(fport));}udpsock_t::udpsock_t(){	backlog = 8;	mss = ETHMTU - LINKIPUDPHLEN;	laddr = INADDRANY;	lport = newudpport();	faddr = INADDRANY;	fport = 0;	nextall = prevall = nexthash = prevhash = NULL;	allq.enqtail(this);	hashfunc(lport)->enqtail(this);}void udpsock_t::input(pkt_t *pkt){	recvq.enqtail(pkt);	waitq.broadcast();}udpsock_t::~udpsock_t(){	allq.unlink(this);	unlinkhash();}int udpsock_t::bind(sockaddr_t * me_, socklen_t socklen){	sockaddrin_t * me = (sockaddrin_t *) me_;	int e = verw(me, sizeof(sockaddrin_t));	if (e < 0)		return e;	if (ntohs(me->port) < USERSOCK && !suser())		return EACCES;	if (exist(me->addr, me->port))		return EADDRINUSE;#warning "need check me->addr is one of the NIC's praddr"	unlinkhash();	laddr = me->addr;	lport = me->port;	hashfunc(lport)->enqtail(this);	return 0;}int udpsock_t::connect(sockaddr_t * serv_, socklen_t socklen){	sockaddrin_t * serv = (sockaddrin_t *) serv_;	int e = verr(serv, sizeof(*serv));	if (e < 0)		return e;	faddr = serv->addr;	fport = serv->port;	return 0;}int udpsock_t::listen(int backlog_){	backlog = backlog_;	return 0;}int udpsock_t::accept(sockaddr_t * client, socklen_t * addrlen){	return EOPNOTSUPP;}int udpsock_t::getname(sockaddr_t * name, socklen_t * namelen, int peer){	int e;	if (e = verw(namelen, sizeof(socklen_t))) 		return e;	if (*namelen < sizeof(sockaddrin_t))		return EINVAL;	if (e = verw(name, sizeof(sockaddr_t))) 		return e;	sockaddrin_t * sin = (sockaddrin_t*) name;	sin->family = AFINET;	if (peer) {		sin->port = fport;		sin->addr = faddr;	} else {		sin->port = lport;		sin->addr = laddr;	}	*namelen = sizeof(sockaddrin_t);	return 0;}int udpsock_t::getsockname(sockaddr_t * name, socklen_t * namelen){	return getname(name, namelen, 0);}int udpsock_t::getpeername(sockaddr_t * name, socklen_t * namelen){	return getname(name, namelen, 1);}/* laddr maybe equal INADDRANY, we compute the chksum after routing */int udpsock_t::output(pkt_t * pkt, u32_t daddr, u16_t dport){	udphdr_t * uh = (udphdr_t*)pkt->addhead(sizeof(udphdr_t));	uh->sport = lport;	uh->dport = dport; 	uh->totlen = htons(pkt->datalen);	uh->chksum = 0;        return ipoutput(pkt, IPPROTOUDP, laddr, daddr, &uh->chksum);}int udpsock_t::send(void * buf, size_t buflen, int flags){        if (faddr == INADDRANY)                return EINVAL;        return 0;}int udpsock_t::sendto(void * buf, size_t buflen, int flags, sockaddr_t * to_,            socklen_t tolen){	sockaddrin_t * to = (sockaddrin_t*) to_;        while (buflen) {                size_t once = min(mss, buflen);                pkt_t * pkt = newpkt(AUSER, LINKIPUDPHLEN, once);		if (!pkt)			return ENOMEM;		memcpy(pkt->data, buf, once);		int e;                if (e = output(pkt, to->addr, to->port)) {			delpkt(pkt);			return e;		}                buf += once;                buflen -= once;        }        return 0;}int udpsock_t::sendmsg(const msghdr_t *mh, int flags){        return 0;}int udpsock_t::recv(void * buf, size_t len, int flags){        return recvfrom(buf, len, flags, NULL, NULL);}int udpsock_t::recvfrom(void * buf, size_t len, int flags,         sockaddr_t *from_, socklen_t *fromlen){        sockaddrin_t * from = (sockaddrin_t*) from_;        while (recvq.empty())		WAIT(waitq);        pkt_t * pkt = recvq.deqhead();	iphdr_t * ih = (iphdr_t*) pkt->data;	pkt->delhead(ih->headlen());	udphdr_t * uh = (udphdr_t*) pkt->data;	pkt->delhead(sizeof(udphdr_t));        int once = min(len, pkt->datalen);        memcpy(buf, pkt->data, once);         if (from) {                from->family = AFINET;                from->addr = ih->saddr;                from->port = uh->sport;        }        if (flags & MSGPEEK)                recvq.enqhead(pkt);        return once; }int udpsock_t::recvmsg(msghdr_t *mh, int flags){	return 0;}int udpsock_t::shutdown(int how){	return 0;}int udpsock_t::setsockopt(int level, int optname, void* optval, socklen_t optlen){	return 0;}int udpsock_t::getsockopt(int level, int optname, void* optval, socklen_t* optlen){	return 0;}

⌨️ 快捷键说明

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