RealtimeCompLab2

Dependencies:   mbed

Fork of PPP-Blinky by Nicolas Nackel

Revision:
28:1aa629be05e7
Parent:
27:78d194dd8799
Child:
29:30de79d658f6
--- a/main.cpp	Tue Jan 03 03:19:47 2017 +0000
+++ b/main.cpp	Wed Jan 04 02:20:06 2017 +0000
@@ -16,8 +16,8 @@
 // https://en.wikibooks.org/wiki/Serial_Programming/IP_Over_Serial_Connections
 // http://pingtester.net/ - nice tool for high rate ping testing
 
-Serial pc(USBTX, USBRX); // The USB com port - Set this up as a Dial-Up Modem on your pc
-Serial xx(PC_10, PC_11); // debug((((( port - use an additional USB serial port to monitor this
+Serial xx(USBTX, USBRX); // The USB com port - Set this up as a Dial-Up Modem on your pc
+Serial pc(PC_10, PC_11); // debug((((( port - use an additional USB serial port to monitor this
 
 // the second #define below gets rid of all the debug printfs
 #define debug(x) xx.printf x
@@ -33,6 +33,8 @@
 struct {
     int online; 
     int ident;
+    int sync;
+    int seq;
     struct {
         char * buf;
         volatile int head; 
@@ -56,7 +58,7 @@
 tcpType tcp;
     
 
-void pppInitStruct(){ ppp.online=0; 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;}
+void pppInitStruct(){ ppp.online=0; 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=77;}
 
 int crcG; // frame check sequence (CRC) holder
 void crcDo(int x){for (int i=0;i<8;i++){crcG=((crcG&1)^(x&1))?(crcG>>1)^0x8408:crcG>>1;x>>=1;}} // crc calculator
@@ -140,7 +142,6 @@
 }
 
 void sendFrame(){
-    ppp.ident++;
     int crc = crcBuf(ppp.pkt.buf, ppp.pkt.len-2); // update crc
     ppp.pkt.buf[ ppp.pkt.len-2 ] = (~crc>>0); // fcs lo (crc)
     ppp.pkt.buf[ ppp.pkt.len-1 ] = (~crc>>8); // fcs hi (crc)
@@ -295,7 +296,6 @@
     char * pktLen =     ipPkt+2; // 2 bytes
     char * ident =      ipPkt+4; // 2 bytes
     char * flags =      ipPkt+6; // 2 bits
-    //char * fragment =   ipPkt+6; // 14 bits
     char * ttl =        ipPkt+8; // 1 byte
     char * protocol =   ipPkt+9; // 1 byte
     char * headercheck= ipPkt+10; // 2 bytes 
@@ -309,39 +309,25 @@
     int packetLength = (pktLen[0]<<8)|pktLen[1]; // ip total packet length
     int identIP = (ident[0]<<8)|ident[1];
     int flagsIP = flags[0]>>14&3;
-    //int fragmentIP = ((fragment[0]&0x3f)<<8)|fragment[1];
     int ttlIP = ttl[0];
     int protocolIP = protocol[0];
     int checksumIP = (headercheck[0]<<8)|headercheck[1];
     char srcIP [16]; 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));
-    debug(("i%04x f%d t%d p%d C%04x\n",identIP,flagsIP,ttlIP,protocolIP,checksumIP));
+    if(0) { debug(("i%04x f%d t%d p%d C%04x\n",identIP,flagsIP,ttlIP,protocolIP,checksumIP)); }
 }    
 
 void dumpHeaderTCP() {
     int ipHdrLen     = (ppp.pkt.buf[4]&0xf)*4; // overall length of ip packet
     
     char * s             = ppp.pkt.buf+4+ipHdrLen; // start of tcp packet
-    //char * srctcp        = s + 0;  // 2 bytes
-    //char * dsttcp        = s + 2;  // 2 bytes
     char * seqtcp        = s + 4;  // 4 bytes
     char * acktcp        = s + 8;  // 4 bytes
-    //char * offset        = s + 12; // 4 bits
     char * flagbitstcp   = s + 12; // 9 bits
-    //char * winsizetcp    = s + 14; // 2 bytes
-    //char * checksumtcp   = s + 16; // 2 bytes
-    //char * urgentpointer = s + 18; // 2 bytes
-
-    //int srcPort = (srctcp[0]<<8)|srctcp[1];
-    //int dstPort = (dsttcp[0]<<8)|dsttcp[1];
     int seq = (seqtcp[0]<<24)|(seqtcp[1]<<16)|(seqtcp[2]<<8)|(seqtcp[3]);
     int ack = (acktcp[0]<<24)|(acktcp[1]<<16)|(acktcp[2]<<8)|(acktcp[3]);
-    //int tcpHdrSize = ((offset[0]>>4)&0x0f)*4; // size of tcp header only
     int flags = ((flagbitstcp[0]&1)<<8)|flagbitstcp[1];
-    //int winsize = (winsizetcp[0]<<8)|winsizetcp[1];
-    //int checkTCP = (checksumtcp[0]<<8)|checksumtcp[1];
-    //int urgentTCP = (urgentpointer[0]<<8)|urgentpointer[1];
     
     int idx = 0; char flagInfo [40];
     if (flags & (1<<0)) idx=snprintf(flagInfo+idx,40, "FIN "); if (flags & (1<<1)) idx=snprintf(flagInfo+idx,40, "SYN ");
@@ -350,8 +336,7 @@
     if (flags & (1<<6)) idx=snprintf(flagInfo+idx,40, "ECE "); if (flags & (1<<7)) idx=snprintf(flagInfo+idx,40, "CWR ");
     if (flags & (1<<8)) idx=snprintf(flagInfo+idx,40, "NS ");
     
-    debug(("Flag %s Seq %08x Ack %08x ", flagInfo, seq, ack));
-    
+    if(0) { debug(("Flag %s Seq %08x Ack %08x ", flagInfo, seq, ack)); }
 }    
 
 void tcpHandler() {
@@ -362,7 +347,7 @@
     char * ihl =        ipPkt;    // bottom 4 bits
     char * ident =      ipPkt+4;  // 2 bytes
     char * pktLen =     ipPkt+2;  // 2 bytes
-    char * protocol =   ipPkt+9; // 1 byte
+    char * protocol =   ipPkt+9;  // 1 byte
     char * srcAdr =     ipPkt+12; // 4 bytes
     char * dstAdr =     ipPkt+16; // 4 bytes = total of 20 bytes
     
@@ -371,61 +356,102 @@
 
     ident[0] = ppp.ident>>8; ident[1] = ppp.ident>>0; // stuff in our ident
     
-    char src[4]; char dst[4]; memcpy(src, srcAdr,4); memcpy(dst, dstAdr,4);
-    memcpy(srcAdr, dst,4); memcpy(dstAdr, src,4); // swap ip address source/dest
-    headercheck[0]=0; headercheck[1]=0; headerCheckSum(); // redo the tcp header checksum
-    
-    headercheck[0]=0; headercheck[1]=0; headerCheckSum(); // redo the tcp header checksum
-
-    int ipHdrLen     = (ppp.pkt.buf[4]&0xf)*4; // length of ip header
+    int ipHdrLen         = (ppp.pkt.buf[4]&0xf)*4; // length of ip header
     char * s             = ppp.pkt.buf+4+ipHdrLen; // start of tcp packet
     char * srctcp        = s + 0;  // 2 bytes
     char * dsttcp        = s + 2;  // 2 bytes
+    char * seqtcp        = s + 4;  // 4 bytes
+    char * acktcp        = s + 8;  // 4 bytes
+    char * offset        = s + 12; // 4 bits
     char * flagbitstcp   = s + 12; // 9 bits
     char * checksumtcp   = s + 16; // 2 bytes
 
     int tcpSize = packetLength - headerSizeIP;
+    int tcpHeaderLen = ((offset[0]>>4)&0x0f)*4; // size of tcp header only
+    int dataLen = tcpSize - tcpHeaderLen; // data is what's left after the header
+    
+    int seq = (seqtcp[0]<<24)|(seqtcp[1]<<16)|(seqtcp[2]<<8)|(seqtcp[3]);
+    int ack = (acktcp[0]<<24)|(acktcp[1]<<16)|(acktcp[2]<<8)|(acktcp[3]);
+    
+    char * dataStart = s + tcpHeaderLen; // start of data
+    
     int flagsTCP = ((flagbitstcp[0]&1)<<8)|flagbitstcp[1];
+
+    #define TCP_FLAG_ACK (1<<4) 
+    #define TCP_FLAG_SYN (1<<1)
+    #define TCP_FLAG_PSH (1<<3)
+    #define TCP_FLAG_RST (1<<2)
+    #define TCP_FLAG_FIN (1<<0)
     
-    int syncFound = 0;
-    #define TCP_FLAG_SYN 2
-    if ((flagsTCP & TCP_FLAG_SYN)!=0) syncFound=1;
+    // a simple state machine to emulate basie TCP states (e.g. webserver)
+
+    int dataLenOld = dataLen; // we are updating data len but still need to use it
+    dataLen = 0; // reset the data length to prep for a short response
+
+    if ( ((flagsTCP & ~TCP_FLAG_ACK) == 0) && ((flagsTCP & TCP_FLAG_ACK) != 0) ) {
+       if (dataLenOld > 0) {  // they sent data in the ack
+          ack = seq + dataLenOld; // we update to show we know
+          seq = ppp.seq;
+       } 
+       else {
+          if (ack <= ppp.seq) return; // just an empty ack
+          ppp.seq = ack; // update our count
+          ack = seq;
+          seq = ppp.seq;
+       }
+    }  
+    else if ( (flagsTCP & TCP_FLAG_FIN) != 0 ) { // got FIN
+        flagbitstcp[1] |= TCP_FLAG_ACK; // do a syn-ack
+        ack = seq;
+        seq = ppp.seq;
+    } 
+    else if ( (flagsTCP & TCP_FLAG_SYN) != 0 ) { // got SYN
+        flagbitstcp[1] |= TCP_FLAG_ACK; // do a syn-ack
+        ack = seq + 1;
+        seq = ppp.seq-1;
+    } 
+    else if ( (flagsTCP & TCP_FLAG_PSH) != 0 ) { // respond to push with ack
+        flagbitstcp[1] = TCP_FLAG_ACK; 
+        int temp = ack;
+        ack = seq + dataLenOld;
+        ppp.seq = temp;
+        seq = temp;
+        if ( strncmp(dataStart, "GET / HTTP/1.1", 14) == 0) { // check for web client
+            dataLen = 3*32; // extend the data
+            memset(dataStart,0, dataLen ); 
+            sprintf(dataStart,"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked; charset=utf-8\r\nF\r\nmbed-PPP-Blinky\r\n\r\n0\r\n\r\n"); 
+        }     
+    }
+       
+   // now we have to redo all the header sizes       
+   
+    int newPacketSize = headerSizeIP + tcpHeaderLen + dataLen;
+    pktLen[0] = (newPacketSize>>8); pktLen[1]=newPacketSize;   // ip total packet size
+    ppp.pkt.len = newPacketSize+6; // ppp packet length
+    tcpSize = tcpHeaderLen + dataLen; // tcp packet size
     
-    #define TCP_FLAG_ACK (1<<4) 
-    flagbitstcp[1] = TCP_FLAG_ACK; // change any flag to an ACK
+    // redo all the header stuff
+    
+    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
 
+    char src[4]; char dst[4]; 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]; memcpy(psrc, srctcp,2); memcpy(pdst, dsttcp,2);
     memcpy(srctcp, pdst,2); memcpy(dsttcp, psrc,2); // swap ip port source/dest
-
+    
+    headercheck[0]=0; headercheck[1]=0; headerCheckSum(); // redo the ip header checksum
     char pseudoHeader[12]; 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
     checksumtcp[0]=0; checksumtcp[1]=0; 
-    sum=dataCheckSum(s-12,tcpSize+12); // update TCP checksum
+    sum=dataCheckSum(s-12,tcpSize+12);                      // update TCP checksum
     checksumtcp[0]=sum>>8; checksumtcp[1]=sum;
     memcpy( s-12, temp, 12); // overwrite the pseudoheader
-    
     sendFrame(); // return the TCP packet
-    
-    if (syncFound==0) return;
-    
-    flagbitstcp[1] = TCP_FLAG_SYN; // change the ACK to our SYN
-    
-    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
-    checksumtcp[0]=0; checksumtcp[1]=0; 
-    sum=dataCheckSum(s-12,tcpSize+12); // update TCP checksum
-    checksumtcp[0]=sum>>8; checksumtcp[1]=sum;
-    memcpy( s-12, temp, 12); // overwrite the pseudoheader
-
-    sendFrame(); // send our request as a response to a SYN
 }    
 
 void dumpDataTCP() {
@@ -433,11 +459,8 @@
     int ipHeaderLen  = (ppp.pkt.buf[4]&0xf)*4; // length of ip header
     int tcpHeaderLen = ((ppp.pkt.buf[4+ipHeaderLen+12]>>4)&0xf)*4;; // length of tcp header
     int dataLen = ipPktLen - ipHeaderLen - tcpHeaderLen; // data is what's left after the two headers
-    //debug(("TCP %d ipHeader %d tcpHeader %d Data %d\n", ipPktLen, ipHeaderLen, tcpHeaderLen, dataLen));
-    if (dataLen > 0) {
-          debug(("%s\n",ppp.pkt.buf+4+ipHeaderLen+tcpHeaderLen));
-    }
-
+    if(0) { debug(("TCP %d ipHeader %d tcpHeader %d Data %d\n", ipPktLen, ipHeaderLen, tcpHeaderLen, dataLen)); } // 1 for more verbose
+    if (dataLen > 0) { debug(("%s\n",ppp.pkt.buf+4+ipHeaderLen+tcpHeaderLen)); } // show the data
 }    
 
 void TCPpacket(){
@@ -469,7 +492,7 @@
     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));
     debug(("i%04x f%d t%d p%d C%04x\n",identIP,flagsIP,ttlIP,protocolIP,checksumIP));
-    //dumpHeaderTCP();
+    dumpHeaderTCP();
     dumpDataTCP();
     tcpHandler();
 }
@@ -485,7 +508,6 @@
         case    6: TCPpacket();   break;
         default: otherProtocol();
     }        
-    //debug((("IP frame proto %3d len %4d %d.%d.%d.%d  %d.%d.%d.%d\n", ppp.pkt.buf[13],(ppp.pkt.buf[6]<<8)+ppp.pkt.buf[7],ppp.pkt.buf[16],ppp.pkt.buf[17],ppp.pkt.buf[18],ppp.pkt.buf[19],ppp.pkt.buf[20],ppp.pkt.buf[21],ppp.pkt.buf[22],ppp.pkt.buf[23] );
 }    
 
 void LCPconfReq() {