Lab2_web / Mbed 2 deprecated webserverBlinky

Dependencies:   mbed

Fork of webserverBlinky by RealTimeCompLab2

Revision:
184:4133f557d4d4
Parent:
183:6d3ba874b267
Child:
185:4cd8f91e9d49
--- a/PPP-Blinky/ppp-blinky.cpp	Mon Sep 11 18:00:26 2017 +0000
+++ b/PPP-Blinky/ppp-blinky.cpp	Mon Sep 11 23:33:27 2017 +0000
@@ -797,9 +797,9 @@
 }
 
 /// Encode a buffer in base-64
+const static char lut [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
 void enc64(char * in, char * out, int len)
 {
-    const static char lut [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
     int i,j,a,b,c;
     i=0;
     j=0;
@@ -828,20 +828,27 @@
 int webSocketHandler(char * dataStart)
 {
     int n=0; // byte counter
-    char * key = strstr(dataStart, "Sec-WebSocket-Key: "); // search for the key in the payload
+    char * key = strstr(dataStart, "Sec-WebSocket-Key:"); // search for the key in the payload
     if (key != NULL) {
+        key = key + 18; // skip over the key ident string "Sec-WebSocket-Key:"
         if (v0) putsWhileCheckingInput("WebSocket Request\n");
-        char challenge [70];
-        strncpy(challenge,key+19,70); // a local buffer
-        *strchr(challenge,'\r')=0; // insert null so we can use sprintf
-        strncat(challenge,"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",70); // append websocket gui code
+        while ( strchr(lut, *key) == NULL) key++; // skip non-valid base-64 characters (whitespace)
+        char challenge [80];
+        int i=0;
+        char * copyTo = challenge;
+        while (strchr(lut, *key) != NULL) { // copy while we see valid base-64 characters
+            if (i++ >40) break; // prevent buffer overflow
+            *copyTo++ = *key++; // copy next valid base-64 character
+        }
+        strcpy(copyTo,"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); // append websocket gui code
+        if (0) debugPrintf("Challenge is %s\n", challenge); // the string we hash for the challenge
         char shaOutput [20]; // sha1 output
-        sha1( shaOutput, challenge, strlen(challenge));
+        sha1( shaOutput, challenge, strlen(challenge)); // hash the challenge
         char encOut[50];
-        enc64( shaOutput, encOut, 20);
+        enc64( shaOutput, encOut, 20); // base-64 encode
         char * versionstring = strstr(dataStart, "Sec-WebSocket-Version:");
         char * version = challenge;
-        strncpy(version, versionstring,70); // copy version string
+        strncpy(version, versionstring,70); // copy their version string
         *strchr(version,'\r')=0; // null terminate so we can sprintf it
         memset(dataStart,0,500); // blank out old data befor send the websocket response header
         n=n+sprintf(dataStart+n, "HTTP/1.1 101 Switching Protocols\r\n");
@@ -942,7 +949,9 @@
         n=2; // our close command is only two bytes long because we don't use the four mask bytes
         dataStart[1]=0; // we don't have mask bytes on
     } else {
-        if (v1) putsWhileCheckingInput("TCP data received\n"); // all other tcp push packets
+        if ( len > 1 ) { // we assume a length of 1 is a keep-alive or push packet
+            if (v1) putsWhileCheckingInput("TCP data received\n"); // all other tcp push packets
+        }
     }
     return n; // total byte size of our response
 }
@@ -965,7 +974,7 @@
         n=n+sprintf(pbuf+n, outGoing ? "\x1b[34m" : "\x1b[30m" ); // VT100 color code, print black for incoming, blue for outgoing headers
         checkPc();
         n=n+sprintf(pbuf+n, "IP:%d ipHeader:%d tcpHeader:%d tcpData:%d\n", packetLengthIp, headerSizeIp, headerSizeTcp, tcpDataSize);    // 1 for more verbose
-        if (n>70) putsWhileCheckingInput("n>pbuf in dumpDataTCP()\n");
+        if (n>70) putsWhileCheckingInput("n>pbuf overflow in dumpDataTCP()\n");
         checkPc();
         putsWhileCheckingInput( pbuf );
         if (tcpDataSize > 0) {
@@ -1008,19 +1017,19 @@
     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 packet
 
-    ppp.tcp->windowR = __REV16( 700 ); // set tcp window size to 700 bytes
+    ppp.tcp->windowR = __REV16( 1200 ); // set tcp window size to 120 bytes
 
     // A sparse TCP flag interpreter that implements stateless TCP connections
 
     switch ( ppp.tcp->flag.All ) {
-        case TCP_FLAG_ACK: // handle ack messages by ignoring them
-            return;
         case TCP_FLAG_SYN:
             flagsOut = TCP_FLAG_SYN | TCP_FLAG_ACK; // something wants to connect - acknowledge it
             seq_out = seq_in+0x10000000U; // create a new sequence number using their sequence as a starting point, increase the highest digit
             ack_out++; // for SYN flag we have to increase the sequence by 1
             break;
+        case TCP_FLAG_ACK:
         case TCP_FLAG_ACK | TCP_FLAG_PSH:
+            if ( (ppp.tcp->flag.All == TCP_FLAG_ACK) && (tcpDataSize == 0)) return; // handle zero-size ack messages by ignoring them
             if ( (strncmp(tcpDataIn, "GET /", 5) == 0) ) { // check for an http GET command
                 flagsOut = TCP_FLAG_ACK | TCP_FLAG_PSH; // we have data, set the PSH flag
                 dataLen = httpResponse(tcpDataOut); // send an http response
@@ -1254,7 +1263,10 @@
 void initializePpp()
 {
     debugBaudRate(115200); // baud rate for (optional) debug serial port
-    debugPrintf("\x1b[2J\x1b[H\x1b[30mmbed PPP-Blinky HTTP & WebSocket server ready :)\n"); // VT100 codes for clear_screen, home, black_text - Tera Term is a handy VT100 terminal
+    debugPrintf("\x1b[2J\x1b[H\x1b[30m");
+    wait_ms(200); // a brief wait so a human can see the reset event
+    debugPrintf("mbed PPP-Blinky HTTP & WebSocket server ready :)\n"); // VT100 codes for clear_screen, home, black_text - Tera Term is a handy VT100 terminal
+    
     pppInitStruct(); // initialize all the variables/properties/buffers
     pc.baud(115200); // pc serial port acting as a dial-up modem - for PPP traffic
     pc.attach(&pppReceiveHandler, RawSerial::RxIrq); // set up serial port receive interrupt handler