RealtimeCompLab2
Dependencies: mbed
Fork of PPP-Blinky by
Diff: main.cpp
- Revision:
- 38:ab582987926e
- Parent:
- 37:2e6689f8b181
- Child:
- 39:b90183d35f1e
--- a/main.cpp Thu Jan 05 10:37:48 2017 +0000 +++ b/main.cpp Thu Jan 05 17:12:57 2017 +0000 @@ -47,25 +47,21 @@ // a structure to keep all our ppp globals in struct pppType { - int online; - int ident; - int sync; - unsigned int seq; - int crc; - int ledState; - int oldFlags; + int online; // we hunt for a PPP connection if this is zero + int ident; // our IP ident value + unsigned int seq; // our TCP sequence number + int crc; // for calculating IP and TCP CRCs + int ledState; // state of LED1 struct { char * buf; volatile int head; volatile int tail; - int total; - } rx; // serial port buffer + } rx; // serial port objects struct { - int id; - int len; - int crc; - char * buf; - } pkt; // ppp buffer + int len; // number of bytes in buffer + int crc; // PPP CRC (frame check) + char * buf; // the actual buffer + } pkt; // ppp buffer objects }; pppType ppp; // our global - definitely not thread safe @@ -77,14 +73,11 @@ ppp.rx.buf=rxbuf; ppp.rx.tail=0; ppp.rx.head=0; - ppp.rx.total=0; ppp.pkt.buf=frbuf; ppp.pkt.len=0; ppp.ident=0; - ppp.sync=0; ppp.seq=1000; ppp.ledState=0; - ppp.oldFlags=0; } void crcReset() @@ -142,11 +135,9 @@ } else return -1; } -void scanForConnectString(); // scan for connect attempts from pc - void processFrame(int start, int end) // process received frame { - led1Toggle(); // change led1 state when frames are received + led1Toggle(); // change led1 state on every frame we receive if(start==end) { pc.putc(0x7e); return; @@ -184,9 +175,9 @@ } } -// Note - the hex output of dumpframe can be imported into WireShark -// Copy the frame's hex output from your terminal program and save as a text file -// In WireShark, use "Import Hex File". Options are No Offset, protocol=PPP. +// Note - the hex output of dumpFrame() can be imported into WireShark +// Capture the frame's hex output in your terminal program and save as a text file +// In WireShark, use "Import Hex File". Options are: Offset=None, Protocol=PPP. void dumpFrame() { for(int i=0; i<ppp.pkt.len; i++) debug(("%02x ", ppp.pkt.buf[i])); @@ -197,13 +188,13 @@ { if ( (ch<0x20) || (ch==0x7d) || (ch==0x7e) ) { pc.putc(0x7d); - pc.putc(ch^0x20); + pc.putc(ch^0x20); // three characters need special handling } else { pc.putc(ch); } } -void sendFrame() +void sendFrame() // send one PPP frame in HDLC format { int crc = crcBuf(ppp.pkt.buf, ppp.pkt.len-2); // update crc ppp.pkt.buf[ ppp.pkt.len-2 ] = (~crc>>0); // fcs lo (crc) @@ -303,7 +294,7 @@ int sum=0; int placeHolder; if (len&1) { - placeHolder = ptr[len-1]; // when length is odd zero stuff + placeHolder = ptr[len-1]; // when length is odd stuff in a zero byte ptr[len-1]=0; } for (int i=0; i<len/2; i++) { @@ -438,8 +429,8 @@ snprintf(srcIP,16, "%d.%d.%d.%d", srcAdr[0],srcAdr[1],srcAdr[2],srcAdr[3]); char dstIP [16]; snprintf(dstIP,16, "%d.%d.%d.%d", dstAdr[0],dstAdr[1],dstAdr[2],dstAdr[3]); - debug(("IP %s %s v%d h%d d%d e%d L%d ",srcIP,dstIP,versionIP,headerSizeIP,dscpIP,ecnIP,packetLength)); - if (v1) debug(("i%04x f%d t%d p%d C%04x\n",identIP,flagsIP,ttlIP,protocolIP,checksumIP)); + if (v0) debug(("IP %s %s v%d h%d d%d e%d L%d ",srcIP,dstIP,versionIP,headerSizeIP,dscpIP,ecnIP,packetLength)); + if (v0) debug(("i%04x f%d t%d p%d C%04x\n",identIP,flagsIP,ttlIP,protocolIP,checksumIP)); } void dumpHeaderTCP() @@ -512,27 +503,35 @@ #define TCP_FLAG_RST (1<<2) #define TCP_FLAG_FIN (1<<0) - // A sparse TCP flag interpreter that implements basic TCP connections from a single source + // A sparse TCP flag interpreter that implements simple TCP connections from a single source + // Clients are allowed ONE push packet, after which the link is closed with a FIN flag in the ACK packet + // This strategy allows web browsers, netcat and curl to work ok while keeping the state machine simple int dataLen = 0; // most of our responses will have zero TCP data, only a header - int flagsOut = TCP_FLAG_ACK; // the default case is an ack - int fastResponse = 0; // normally we wait 200ms before sending but this can make it faster + int flagsOut = TCP_FLAG_ACK; // the default case is an ACK packet + int fastResponse = 0; // normally you wait 200ms before sending a packet but this can make it faster + + if (ppp.seq != ack) { + ppp.seq = ack; // if their sequence number is different than our calculation we adopt their version + } if ( ((flagsTCP & ~TCP_FLAG_ACK) == 0) && ((flagsTCP & TCP_FLAG_ACK) != 0) ) { - if (incomingLen == 0) return; // no new data - } else if ( (flagsTCP & TCP_FLAG_FIN) != 0 ) { // got FIN - if ((ppp.oldFlags & TCP_FLAG_FIN) !=0) return; - seq++; // increase sequence by 1 for FIN and SYNC - } else if ( (flagsTCP & TCP_FLAG_SYN) != 0 ) { // got SYN + if (incomingLen == 0) { // ignore - just an empty ack packet + return; + } + } else if ( (flagsTCP & TCP_FLAG_SYN) != 0 ) { // got SYN flag flagsOut = TCP_FLAG_SYN | TCP_FLAG_ACK; // do a syn-ack - seq++; // increase sequency by for FIN and SYN - } else if ( (flagsTCP & TCP_FLAG_PSH) != 0 ) { // they are pushing data - fastResponse = 1; // we can response fast to a push - // It's a push - let's check the data for an HTTP home page GET request + seq++; // for SYN flag we have to increase sequence by 1 + } else if ( (flagsTCP & TCP_FLAG_FIN) != 0 ) { // got FIN flag + seq++; // for FIN flag we have to increase sequence by 1 + } else if ( (flagsTCP & TCP_FLAG_PSH) != 0 ) { // got PSH flag (push) + flagsOut = TCP_FLAG_ACK | TCP_FLAG_FIN; // for every push we answer once AND close the link + fastResponse = 1; // we can respond fast to a push + // It's a push, so let's check the incoming data for an HTTP GET request if ( strncmp(dataStart, "GET / HTTP/1.1", 14) == 0) { dataLen = 15*32; // this block has to hold the web page below, but keep it under 1k - memset(dataStart,'x', dataLen ); // initialize the block - int n=1; // number of bytes we have printed so far + memset(dataStart,'x', dataLen ); // initialize the data block + int n=0; // number of bytes we have printed so far n=n+sprintf(n+dataStart,"HTTP/1.1 200 OK\r\nServer: PPP-Blinky\r\n"); // http header n=n+sprintf(n+dataStart,"Content-Length: 376\r\n"); // http header n=n+sprintf(n+dataStart,"Content-Type: text/html; charset=us-ascii\r\n\r\n"); // http header @@ -547,11 +546,11 @@ if (v0) { debug(("HTTP GET dataLen %d*32=%d Header %d Content-Length %d Total %d Margin %d\n",dataLen/32,dataLen,nHeader,contentLength,n,dataLen-n)); } - } else if ( strncmp(dataStart, "GET /", 4) == 0) { // all other files get 404 not found - dataLen = 5*32; // this block has to hold the web page below, but keep it under 1k - memset(dataStart,'x', dataLen ); // initialize the block - int n=0; - n=n+sprintf(n+dataStart,"HTTP/1.1 200 OK\r\nServer: PPP-Blinky\r\n"); // http header + } else if ( strncmp(dataStart, "GET /", 4) == 0) { // all other HTTP GET requests get 404 Not Found response + dataLen = 5*32; // block size for File not found webpage + memset(dataStart,'x', dataLen ); // initialize the data block + int n=0; // number of bytes we have printed so far + n=n+sprintf(n+dataStart,"HTTP/1.1 400 Not Found\r\nServer: PPP-Blinky\r\n"); // http header n=n+sprintf(n+dataStart,"Content-Length: 58\r\n"); // http header n=n+sprintf(n+dataStart,"Content-Type: text/html; charset=us-ascii\r\n\r\n"); // http header int nHeader=n; // byte total of all headers @@ -563,80 +562,80 @@ debug(("HTTP GET dataLen %d*32=%d Header %d Content-Length %d Total %d Margin %d\n",dataLen/32,dataLen,nHeader,contentLength,n,dataLen-n)); } } else { - dataLen=0; + dataLen=0; // we did not find a valid HTTP request, so just ACK with zero data } } else { - dataLen=0; + dataLen=0; // it's not any TCP Flag Combo that needs special handling } - // All the flag checking is now donw - - ppp.oldFlags = flagsTCP; // remember the flags for the next round - - // Now we have to recalculate all the header sizes + // All the TCP flag handling is now done - ack = seq + incomingLen; // acknowledge the number of bytes they sent by adding it to seq - seq = ppp.seq; + // Now we have to recalculate all the header sizes, swap IP address/port source and destination, and do the IP and TCP checksums - char src[4]; - char dst[4]; + char src[4]; // temp hold + char dst[4]; // temp hold memcpy(src, srcAdr,4); memcpy(dst, dstAdr,4); memcpy(srcAdr, dst,4); memcpy(dstAdr, src,4); // swap ip address source/dest - char psrc[2]; - char pdst[2]; + + char psrc[2]; // temp hold + char pdst[2]; // temp hold memcpy(psrc, srctcp,2); memcpy(pdst, dsttcp,2); memcpy(srctcp, pdst,2); memcpy(dsttcp, psrc,2); // swap ip port source/dest - int newPacketSize = headerSizeIP + headerSizeTCP + dataLen; + ack = seq + incomingLen; // acknowledge the number of bytes that they sent by adding it to "our" sequence number + seq = ppp.seq; // set up the sequence number we have to respond with + + acktcp[0]=ack>>24; + acktcp[1]=ack>>16; + acktcp[2]=ack>>8; + acktcp[3]=ack>>0; // save ack + + seqtcp[0]=seq>>24; + seqtcp[1]=seq>>16; + seqtcp[2]=seq>>8; + seqtcp[3]=seq>>0; // save seq + + flagbitstcp[1] = flagsOut; // set up the new flags + + int newPacketSize = headerSizeIP + headerSizeTCP + dataLen; // calculate size of the outgoing packet pktLen[0] = (newPacketSize>>8); pktLen[1]=newPacketSize; // ip total packet size ppp.pkt.len = newPacketSize+6; // ppp packet length tcpSize = headerSizeTCP + dataLen; // tcp packet size - flagbitstcp[1] = flagsOut; // set up the new flags - - acktcp[0]=ack>>24; - acktcp[1]=ack>>16; - acktcp[2]=ack>>8; - acktcp[3]=ack>>0; // save ack - seqtcp[0]=seq>>24; - seqtcp[1]=seq>>16; - seqtcp[2]=seq>>8; - seqtcp[3]=seq>>0; // save seq - - - // redo all the header stuff + // the header is all set up, now do the IP and TCP checksums headercheck[0]=0; headercheck[1]=0; headerCheckSum(); // redo the ip header checksum - char pseudoHeader[12]; + + char pseudoHeader[12]; // we are building a fake TCP header int sum; - char temp[12]; // for the terrible pseudoheader checksum memcpy( pseudoHeader+0, srcAdr, 8); // source and destination addresses. pseudoHeader[8]=0; pseudoHeader[9]=protocol[0]; pseudoHeader[10]=tcpSize>>8; pseudoHeader[11]=tcpSize; - memcpy(temp, s-12, 12); // keep a copy - memcpy( s-12, pseudoHeader, 12); // put the header on the tcp packet + char temp[12]; // temporary storage for the 12 bytes that are in the way + memcpy(temp, s-12, 12); // save the 12 bytes that are in the way + memcpy( s-12, pseudoHeader, 12); // copy in the fake header checksumtcp[0]=0; checksumtcp[1]=0; - sum=dataCheckSum(s-12,tcpSize+12); // update TCP checksum + sum=dataCheckSum(s-12,tcpSize+12); // calculate the TCP checksum checksumtcp[0]=sum>>8; checksumtcp[1]=sum; - memcpy( s-12, temp, 12); // overwrite the pseudoheader + memcpy( s-12, temp, 12); // restore the 12 bytes that the fake header overwrote if (fastResponse==1) { fastResponse=0; // reset and skip 200 ms wait } else { - wait(0.2); // wait 200 ms before sending packet + wait(0.2); // normally, you wait 200 ms before sending a TCP packet } - sendFrame(); // return the TCP packet - ppp.seq = ppp.seq + dataLen; // increase OUR sequence by outgoing data length - for the next round + sendFrame(); // All done! Send the TCP packet + ppp.seq = ppp.seq + dataLen; // increase OUR sequence by the outgoing data length - for the next round } void dumpDataTCP()