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

📄 miniweb.c

📁 嵌入式TCPIP协议
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright (c) 2001, Adam Dunkels. All rights reserved. * * Redistribution or modification is prohibited. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.   * */#define STATEFUL#include "dev.h"#include "miniweb.h"/* These are kept in CPU registers. */static unsigned char a, x, y, c;/* These are kept in RAM. */static unsigned char ipaddr[4];static unsigned char srcport[2];static unsigned char port;static unsigned char seqno[4];static struct tcpip_header *stateptr;static unsigned char chksum[2];static unsigned short len;static unsigned char *tmpptr;#ifdef STATEFULstatic struct tcpip_header *tmpstateptr;static unsigned char cwnd;static unsigned char tcpstate;static unsigned char inflight;#endif /* STATEFUL *//* These actually only need four bits each. */static unsigned char timer, txtime, nrtx;/* Only two bits of state needed here. */static unsigned char chksumflags;#define CHKSUMFLAG_BYTE 2#define CHKSUMFLAG_CARRY 1/* This is just a declaration, and does not use RAM. */extern struct tcpip_header *pages[];extern struct tcpip_header reset;static void tcpip_output(void);#define NULL (void *)0#define Y_NORESPONSE 0#define Y_RESPONSE 1#define Y_NEWDATA 2/* a + c << 8 = a + x + c *//*#define ADC(a, c, x) do { \                        unsigned short __tmp; \			__tmp = a + (x) + c; \			a = __tmp & 0xff; \			c = __tmp >> 8; \			} while(0)*/#define ADD_CHK1(x) ADC(chksum[0], c, x);#define ADD_CHK2(x) ADC(chksum[1], c, x); /*#define ADD_CHK(x) do { \		       if(!(chksumflags & CHKSUMFLAG_BYTE)) { \			 ADD_CHK1(x); \                         chksumflags = chksumflags | CHKSUMFLAG_BYTE; \		       } else { \			 ADD_CHK2(x); \                         chksumflags = chksumflags & ~CHKSUMFLAG_BYTE; \		       } \                    } while(0)#define DEV_GETC(x) do { \                       DEV_GET(x); \                       ADD_CHK(x); \		       } while(0) */#define ADC(a, c, x) adc(&(a), &(c), x)#define ADD_CHK(x)  add_chk(x)#define DEV_GETC(x) x = dev_getc()#define DEV_WAITC(x) DEV_WAIT(x); ADD_CHK(x)/*-----------------------------------------------------------------------------------*/static voidadc(unsigned char *a, unsigned char *c, unsigned char x){  unsigned short tmp;    tmp = *a + x + *c;   *a = tmp & 0xff;  *c = tmp >> 8; }/*-----------------------------------------------------------------------------------*/static voidadd_chk(unsigned char x){  ADC(chksum[(chksumflags & CHKSUMFLAG_BYTE) >> 1], c, x);  chksumflags ^= CHKSUMFLAG_BYTE;}/*-----------------------------------------------------------------------------------*/static unsigned chardev_getc(void){  unsigned char x;  DEV_GET(x);  ADD_CHK(x);  return x;}/*-----------------------------------------------------------------------------------*/voidminiweb_init(void){  nrtx = 0;#ifdef STATEFUL  tcpstate = LISTEN;  cwnd = 1;  inflight = 0;#endif /* STATEFUL */}/*-----------------------------------------------------------------------------------*/voidminiweb_main_loop(void)     {  while(1) {  drop:    DEV_DROP();#ifdef STATEFUL    /* The content of the y register signals whether we should send       out a new packet once the input processing is done. y = 0 means       that we should not send out a packet and y != 0 means that we       should send out a packet. */    y = Y_NORESPONSE;#endif /* STATEFUL */    chksum[0] = chksum[1] = 0;    chksumflags = 0;    /* Get first byte of IP packet, which is the IP version number and       IP header length. */    DEV_WAITC(a);        /* We discard every packet that isn't IP version 4 and that has IP       options. */    if(a != 0x45) {      printf("Packet dropped due to options or version mismatch\n");      goto drop;    }    /* IP Type of Service field, discard. */    DEV_GETC(a);    /* IP packet length. */    DEV_GETC(a);    len = a << 8;    DEV_GETC(a);    len |= a;        /* IP ID, discard. */    DEV_GETC(a);  DEV_GETC(a);        /* Fragmentation offset. */    DEV_GETC(a);    if((a & 0x20) || (a & 0x1f) != 0) {      printf("Got IP fragment, dropping\n");      goto drop;    }    DEV_GETC(a);    if(a != 0) {      printf("Got IP fragment, dropping\n");      goto drop;    }        /* TTL, discard. */    DEV_GETC(a);        /* Get the IP protocol field. If this isn't a TCP packet, we drop       it. */    DEV_GETC(a);    if(a != IP_PROTO_TCP) {      printf("Not a TCP packet, dropping\n");      goto drop;    }        /* Get the IP checksum field, and discard it. */    DEV_GETC(a);  DEV_GETC(a);    /* Get the source address of the packet, which we will use as the       destination address for our replies. */    DEV_GETC(a);    ipaddr[0] = a;    DEV_GETC(a);    ipaddr[1] = a;    DEV_GETC(a);    ipaddr[2] = a;    DEV_GETC(a);    ipaddr[3] = a;    /* And we discard the destination IP address. */    DEV_GETC(a);  DEV_GETC(a);  DEV_GETC(a);  DEV_GETC(a);          /* Check the computed IP header checksum. If it fails, we go ahead       and drop the packet. */    while(c) {      ADD_CHK(0);    }    if(chksum[0] != 0xff || chksum[1] != 0xff) {      printf("Failed IP header checksum, dropping\n");      goto drop;    }        /* Thus the IP processing is done with, and we carry on with the       TCP layer. */    chksum[0] = chksum[1] = 0;    c = 0;    chksumflags = 0;    /* Get the source TCP port and store it for our replies. */#ifdef STATEFUL    DEV_GETC(a);    if(tcpstate == LISTEN || tcpstate == TIME_WAIT) {      srcport[0] = a;    } else if(srcport[0] != a) {      printf("Got new port and not in LISTEN or TIME_WAIT, dropping packet\n");      goto drop;    }    DEV_GETC(a);    if(tcpstate == LISTEN || tcpstate == TIME_WAIT) {      srcport[1] = a;    } else if(srcport[1] != a) {      printf("Got new port and not in LISTEN or TIME_WAIT, dropping packet\n");      goto drop;    }#else /* STATEFUL */    DEV_GETC(a);    srcport[0] = a;    DEV_GETC(a);    srcport[1] = a;#endif /* STATEFUL */        /* Get the TCP destination port. */    DEV_GETC(a);    DEV_GETC(a);#ifdef STATEFUL    if(tcpstate == LISTEN || tcpstate == TIME_WAIT) {      port = a;    }#else /* STATEFUL */    port = a;#endif /* STATEFUL */    if(port < PORTLOW || port >= PORTHIGH) {      printf("Port outside range %d\n", port);      goto drop;    }    /* Get the TCP sequence number. */    DEV_GETC(a);    seqno[0] = a;    DEV_GETC(a);    seqno[1] = a;    DEV_GETC(a);    seqno[2] = a;    DEV_GETC(a);    seqno[3] = a;    /* Next, check the acknowledgement. If it acknowledges outstanding       data, we move the state pointer upwards. (This has room for       massive assembler optimizations.) Since we never send out any       sequence numbers that wrap, we can use standard arithmetic       here. */#ifndef STATEFUL       stateptr = pages[port - PORTLOW];#endif /* STATEFUL */#ifdef STATEFUL    if(tcpstate != LISTEN) {#endif /* STATEFUL */    for(x = 0; x < 4; x ++) {      DEV_GETC(a);      while(stateptr != NULL && a > stateptr->seqno[x]) {	stateptr = stateptr->next;#ifdef STATEFUL        y = Y_RESPONSE;        inflight--;#endif /* STATEFUL */

⌨️ 快捷键说明

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