Lab2_web / Mbed 2 deprecated webserverBlinky

Dependencies:   mbed

Fork of webserverBlinky by RealTimeCompLab2

Revision:
4:a469050d5b80
Parent:
3:bcc66de0bdcd
Child:
5:27624c02189f
diff -r bcc66de0bdcd -r a469050d5b80 main.cpp
--- a/main.cpp	Tue Dec 27 18:38:49 2016 +0000
+++ b/main.cpp	Thu Dec 29 04:21:29 2016 +0000
@@ -2,59 +2,179 @@
 
 // Proof-of-concept for TCP/IP using Windows 7/8/10 Dial Up Networking over MBED USB Virtual COM Port
 
-// Toggles LED1 every time the PC tries to establish a Dial-up Networking Connection
+// Toggles LED1 every time the PC sends an IP packet over the PPP link
+
+// Note - turn off all authentication, passwords, compression etc. Simplest link possible.
 
 Serial pc(USBTX, USBRX); // The USB com port - Set this up as a Dial-Up Modem
+Serial xx(PC_10, PC_11); // debug port - use a second USB serial port to monitor
 
-DigitalOut myled(LED1);
+DigitalOut led1(LED1);
+
+#define FRAME_7E (0x7e)
+#define BUFLEN (1<<14)
+char rxbuf[BUFLEN];
+char frbuf[3000]; // buffer for ppp frame
 
-#define BUFLEN (1<<12)
-char rxbuf[BUFLEN];
+struct {
+    int online; 
+    struct {
+        char * buf;
+        int head; 
+        int tail; 
+    } rx; // serial port buffer
+    struct {
+        int len;
+        int crc;
+        char * buf;
+    } pkt; // ppp buffer
+} ppp;
 
-int headPointer = 0; // head of receive buffer
-int tailPointer = 0; // tail of receive buffer
+void pppInitStruct(){ ppp.online=0; ppp.rx.buf=rxbuf; ppp.rx.tail=0; ppp.rx.head=0; ppp.pkt.buf=frbuf; ppp.pkt.len=0;}
+
+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
+void crcReset(){crcG=0xffff;} // crc restart
 
 void rxHandler() // serial port receive interrupt handler
 {
-    rxbuf[headPointer]=pc.getc(); // insert in buffer
+    ppp.rx.buf[ppp.rx.head]=pc.getc(); // insert in buffer
     __disable_irq();
-    headPointer=(headPointer+1)&(BUFLEN-1);
+    ppp.rx.head=(ppp.rx.head+1)&(BUFLEN-1);
     __enable_irq();
 }
 
 int pc_readable() // check if buffer has data
 {
-    return (headPointer==tailPointer) ? 0 : 1 ;
+    return (ppp.rx.head==ppp.rx.tail) ? 0 : 1 ;
 }
 
 int pc_getBuf() // get one character from the buffer
 {
     if (pc_readable()) {
-        int x = rxbuf[tailPointer];
-        tailPointer=(tailPointer+1)&(BUFLEN-1);
+        int x = ppp.rx.buf[ ppp.rx.tail ];
+        ppp.rx.tail=(ppp.rx.tail+1)&(BUFLEN-1);
         return x;
     }
     return -1;
 }
 
-// ppp frame start/end flag
-#define FRAME_START_END 0x7e
+
+void scanForConnectString(); // scan for connect attempts from pc
 
 int main()
 {
     pc.baud(115200);
+    xx.baud(115200); 
+    xx.puts("\x1b[2J\x1b[H"); // VT100 terminal control code for screen clear/home
+    
+    pppInitStruct(); // structure containing all the PPP stuff
+
     pc.attach(&rxHandler,Serial::RxIrq); // activate the receive interrupt handler
-    int flagCount=0;
+
+    int frameStartIndex, frameEndIndex;
+    int frameBusy=0;
+
     while(1) {
         while ( pc_readable() ) {
             int rx = pc_getBuf();
-            if (rx == FRAME_START_END) flagCount++;
-            char * clientFound = strstr( rxbuf, "CLIENTCLIENT" ); // look for string
-            if( clientFound ) {
-                strcpy( clientFound, "FOUND!FOUND!" ); // overwrite found string
-                pc.printf("CLIENTSERVER"); // respond to PC
+            if (frameBusy) { 
+                if (rx==FRAME_7E) {
+                    frameBusy=0; // done gathering frame
+                    frameEndIndex=ppp.rx.tail-1; // remember where frame ends
+                    void processFrame(int start, int end); // process a received frame
+                    processFrame(frameStartIndex, frameEndIndex);
+                }
+            } 
+            else {
+                if (rx==FRAME_7E) {
+                    frameBusy=1; // start gathering frame
+                    frameStartIndex=ppp.rx.tail; // remember where frame starts
+                }
             }
-            if ( flagCount>0 ) myled = ((flagCount/2)%2); // toggle on PPP frame found
+        }
+        if (ppp.online==0) scanForConnectString(); // try to connect
+    }
+}
+
+void processFrame(int start, int end) {
+    crcReset();
+    char * dest = ppp.pkt.buf;
+    ppp.pkt.len=0;
+    int special=0;
+    for (int i=start; i<end; i++) {
+        if (special==0) {
+            if (rxbuf[i]==0x7d) special=1; 
+            else { *dest++ = rxbuf[i]; ppp.pkt.len++; crcDo(rxbuf[i]);}
+        } else {
+            *dest++ = rxbuf[i]-32; ppp.pkt.len++; crcDo(rxbuf[i]-32);
+            special=0;
         }
     }
+    ppp.pkt.crc = crcG;
+    ppp.rx.head=0; // reuse rxbuf
+    ppp.rx.tail=0; // reuse rxbuf
+    void determinePacketType(); // declare early
+    determinePacketType();
 }
+
+void sendFrame(){
+    crcReset(); for(int i=0;i<ppp.pkt.len-2;i++) crcDo(ppp.pkt.buf[i]);
+    ppp.pkt.buf[ ppp.pkt.len-2 ] = ((~crcG)>>0)&0xff; // update crc lo
+    ppp.pkt.buf[ ppp.pkt.len-1 ] = ((~crcG)>>8)&0xff; // update crc hi
+    pc.putc(0x7e);
+    for(int i=0;i<ppp.pkt.len;i++) {
+        unsigned int cc = (unsigned int)ppp.pkt.buf[i];
+        if (cc>32) pc.putc(cc);
+        else { 
+            pc.putc(0x7d); pc.putc(cc+32);
+        }
+    } 
+    pc.putc(0x7e);    
+}
+
+void LCPrequestFrame() {
+      ppp.pkt.buf[4]=2; // change to an ACK packet
+      sendFrame(); // return their request
+      ppp.pkt.buf[4]=1; // change back to a request
+      ppp.pkt.buf[5] = ppp.pkt.buf[5]+1; // take the next id
+      ppp.pkt.buf[16] = ppp.pkt.buf[16] ^ 0x33; // modify magic number
+      ppp.pkt.buf[17] = ppp.pkt.buf[16] ^ 0x33; // modify magic number
+      sendFrame(); // send our request
+}
+    
+void LCPackFrame() {
+    xx.printf("== PPP is up ==\n");
+}    
+
+void generalFrame() {
+    xx.printf("== General Frame ==\n");
+    for(int i=0;i<ppp.pkt.len;i++) xx.printf("%02x ", ppp.pkt.buf[i]);
+    xx.printf(" C %02x %02x L=%d\n", ppp.pkt.crc&0xff, (ppp.pkt.crc>>8)&0xff, ppp.pkt.len);
+}    
+
+void iPcpFrame() {
+    xx.printf("== IPCP Frame ==\n");
+    for(int i=0;i<ppp.pkt.len;i++) xx.printf("%02x ", ppp.pkt.buf[i]);
+    xx.printf(" C %02x %02x L=%d\n", ppp.pkt.crc&0xff, (ppp.pkt.crc>>8)&0xff, ppp.pkt.len);
+    led1 = ppp.pkt.buf[3] & 1; // This is the sequence number so the led blinks on packets
+}    
+
+void determinePacketType() {
+    char pktLCPReqType  [] = { 0xff, 3, 0xc0, 0x21, 1 }; // LCP requeswt  packet
+    char pktLCPAckType  [] = { 0xff, 3, 0xc0, 0x21, 2 }; // LCP ack packet
+    char pktIPCPtype    [] = { 0x80, 0x21, 1          }; // ip control packet
+    if(0);
+    else if (0==memcmp( ppp.pkt.buf,pktLCPReqType,5)) LCPrequestFrame(); 
+    else if (0==memcmp( ppp.pkt.buf,pktLCPAckType,5)) LCPackFrame(); 
+    else if (0==memcmp( ppp.pkt.buf,pktIPCPtype,3  )) iPcpFrame(); 
+    else generalFrame(); // default handler
+}    
+
+void scanForConnectString(){
+    char * clientFound = strstr( rxbuf, "CLIENTCLIENT" ); // look for PC string
+    if( clientFound ) { 
+        strcpy( clientFound, "FOUND!FOUND!" ); // overwrite so we don't get fixated
+        pc.printf("CLIENTSERVER"); // respond to PC
+    }
+}