/* Copyright 2000 (c) by David Schweikert, Swiss Federal Institute of Technology, Computer Engineering and Networks Laboratory. TOPSY -- A Teachable Operating System. Implementation of a tiny and simple micro kernel for teaching purposes. For further information, please visit http://www.tik.ee.ethz.ch/~topsy This software is provided under the terms of the GNU General Public Licence. A full copy of the GNU GPL is provided in the file COPYING found in the development root of Topsy. */ /* File: $Source: /usr/drwho/vault/cvs/topsy/Topsy/Net/UDP/NetUDP.c,v $ Author(s): Affiliation: ETH Zuerich, TIK Version: $Revision: 1.1 $ Creation Date: Last Date of Change: $Date: 2000/03/31 17:50:40 $ by: $Author: gfa $ $Log: NetUDP.c,v $ Revision 1.1 2000/03/31 17:50:40 gfa Merged with /Net from several term projects */ #include #include #include #include #include #include #include #include #include #include /* needed for NETIP_PROTOCOL_UDP */ #include void netudpRead(ThreadId id, unsigned long int length); static void netudpMain(ThreadArg arg); static void netudpUp(NetBuf buf, NetAttrs attrs); static void netudpDown(NetBuf buf, NetAttrs attrs); static void netudpListen(ThreadId thread, NetAttrs attrs, long value); static void netudpClose(NetAttrs attrs, long value); ThreadId netudp_ports[NETUDP_MAXPORTNR+1]; /* Should be done with a hash-table... */ void netudpInit() { ThreadId netudpId; int i; netudp_ports[0]=NETUDP_FIRST_USER_PORT; for(i=1; ilen)) goto error; /* checksum (facultative) */ if(hdr->checksum) { if(netudpChecksum(buf,attrs,len)) { netdbgDisplay(NETDEBUG_UDP, "netudp: Checksum error.\n"); goto error; } } sport = ntohs(hdr->sport); dport = ntohs(hdr->dport); /* source and destination port */ netattrSet(attrs, NETATTR_UDP_FROM, sport); netattrSet(attrs, NETATTR_UDP_TO, dport); if(!(thread = netudpLookup(dport))) { netdbgPrintf(NETDEBUG_UDP, "netudp: Nobody listens to port %d.\n", dport); goto error; } /* remove header */ buf->start+=sizeof(NetUDPHdr); netmodSendUpThread(thread,buf,attrs); return; error: netdbgPrintf(NETDEBUG_UDP, "netudp: Discarding upcoming packet.\n"); netbufFree(buf); netattrFree(attrs); } static void netudpDown(NetBuf buf, NetAttrs attrs) { NetUDPHdr *hdr; unsigned short tmp, len; netdbgDisplay(NETDEBUG_UDP, "netudp: Received downgoing packet\n"); if(!netbufAddHead(&buf,sizeof(NetUDPHdr))) goto error; hdr = (NetUDPHdr *) NETBUF_DATA(buf); /* source port, dest port */ if(!netattrGet(attrs,NETATTR_UDP_FROM,&tmp)) goto error; hdr->sport = htons(tmp); if(!netattrGet(attrs,NETATTR_UDP_TO,&tmp)) goto error; hdr->dport = htons(tmp); /* length */ len = netbufLen(buf); hdr->len = htons(len); /* UDP BRAINDAMAGE: I DON'T KNOW THE SOURCE IP ADDRESS YET, SO * I CAN'T CALCULATE THE CHECKSUM!!!!!!!!!!! */ #if 0 if(!netattrGet(attrs,NETATTR_UDP_NOCHECKSUM,&tmp)) { if((tmp=netudpChecksum(buf,attrs,len))==0) tmp=0xFFFF; } else { tmp=0; } #endif tmp=0; hdr->checksum = tmp; netattrSet(attrs, NETATTR_IP_PROTOCOL, NETIP_PROTOCOL_UDP); /* Send down packet */ netcfgSendNextDown(NETMODULE_UDP, buf, attrs); return; error: netbufFree(buf); netattrFree(attrs); } static void netudpListen(ThreadId thread, NetAttrs attrs, long port) { /* We don't need attributes... */ netattrFree(attrs); if(port<0 || port>NETUDP_MAXPORTNR) { netdbgDisplay(NETDEBUG_UDP, "netudp: Invalid port number.\n"); return; } /* port nr. 0 is special: allocate a free port yourself */ /* netudp_ports[pos] (should) contains the first free port */ if(port==0) { port = netudp_ports[0]; if(netudp_ports[port]) { while(portNETUDP_MAXPORTNR) { netdbgDisplay(NETDEBUG_UDP, "netudp: Invalid port number.\n"); return; } if(port >= NETUDP_FIRST_USER_PORT && netudp_ports[0]>port) netudp_ports[0]=port; netudp_ports[port]=0; }