Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Revision:
3:24c5f0f50bf1
Parent:
2:e67f7c158087
Child:
6:6f002d202f59
--- a/Websocket.cpp	Tue Jul 24 02:07:23 2012 +0000
+++ b/Websocket.cpp	Tue Jul 31 04:59:16 2012 +0000
@@ -1,8 +1,11 @@
 #include "Websocket.h"
 #include <string>
 
+#include "SnBase64.h"
+
 //#define DEBUG
 
+const bool Websocket::kUseB64 = true;
 
 #ifdef TARGET_LPC1768
 Websocket::Websocket(char * url) {
@@ -15,7 +18,7 @@
     new_msg = false;
     fillFields(url);
     
-    memset(eth_rx, 0, 1024);
+    memset(eth_rx, 0, RX_BUF_SIZE);
     
     eth = new EthernetNetIf(
         IpAddr(128,195,204,148), //IP Address
@@ -158,10 +161,10 @@
         while (true) {
             Net::poll();
             if (time(0) > timeout) {
-                /*
+                
                 printf("connect timeout %u > %u\r\n",
                     time(0), timeout);
-                */
+                
                 return false;
             }
             if (tmr.read() > 0.05) {
@@ -286,7 +289,7 @@
     }
 }
 
-void Websocket::send(char * str) 
+void Websocket::send(const char * str) 
 {
 #ifdef DEBUG
     printf("SEND(%s)\r\n",str);
@@ -320,8 +323,87 @@
 #endif //target
 }
 
-bool Websocket::sendBinary(const char* hbuf, const uint32_t hlen,
-                           char* str, const uint32_t len) 
+bool Websocket::sendBinary(const char* hbuf, const uint32_t hlen, 
+                           FILE* f, const uint32_t nbytes,
+                           char* const bbuf) {
+    if (kUseB64) {
+        return sendBinaryB64txt(hbuf, hlen, f, nbytes, bbuf);
+    } else {
+        return sendBinaryDirect(hbuf, hlen, f, nbytes);
+    }
+}
+
+bool Websocket::sendBinaryB64txt(const char* hbuf, const uint32_t hlen,
+                                 FILE* f, const uint32_t nbytes,
+                                 char* const bbuf) {
+#ifdef DEBUG
+    printf("SENDbinaryB64txt(%s)\r\n",str);
+#endif
+/* Opcode:  4 bits
+      The opcode denotes the frame type of the WebSocket frame
+      Defines the interpretation of the payload data.  If an unknown
+      opcode is received, the receiving endpoint MUST _Fail the
+      WebSocket Connection_.  The following values are defined.
+      *  %x0 denotes a continuation frame
+      *  %x1 denotes a text frame
+      *  %x2 denotes a binary frame
+      *  %x3-7 are reserved for further non-control frames
+      *  %x8 denotes a connection close
+      *  %x9 denotes a pingg
+      *  %xA denotes a pong
+      *  %xB-F are reserved for further control frames
+      
+      */
+    sendOpcode(0x01);
+    sendLength(BASE64ENC_LEN(nbytes));
+    sendMask();
+
+#ifdef TARGET_LPC1768
+   //M: else if (netif == ETH) {
+    if (netif == ETH) 
+    {
+        Net::poll();
+        //sock->send(str, strlen(str));
+        // read 3 bytes at a time
+        static const uint8_t cbytes = 3; // must be multiple of 3
+        static const uint32_t clen = BASE64ENC_LEN(cbytes)+1;
+        char chunk[clen];
+        char fbuf[cbytes];
+        const uint32_t nchunks = nbytes / cbytes;
+        for (uint32_t i=0; i<nchunks; i++) {
+            fread(fbuf, cbytes, 1, f);
+            B64::modp_b64_encode(fbuf, cbytes, chunk);
+            sock->send(chunk, clen-1);
+        }
+        // now the remainder
+        const uint32_t rem = nbytes-(nchunks*cbytes);
+        if (rem>0) {
+            fread(fbuf, rem, 1, f);
+            B64::modp_b64_encode(fbuf, rem, chunk);
+            sock->send(chunk, strlen(chunk));
+        }
+    }
+#endif //target
+    return true;
+}
+
+bool Websocket::sendBinary(const char* str, const uint32_t len,
+                           char* const bbuf) {
+    if (kUseB64) {
+        return sendBinaryB64txt(str, len, bbuf);
+    } else {
+        return sendBinaryDirect(str, len);
+    }
+}
+
+bool Websocket::sendBinaryB64txt(const char* str, const uint32_t len,
+                                 char* const bbuf) {
+    B64::modp_b64_encode(str, len, bbuf);
+    send(bbuf);
+    return true;
+}
+
+bool Websocket::sendBinaryDirect(const char* str, const uint32_t len) 
 {
     // CJR: add function for sending binary
     // force header info to be sent on each call
@@ -343,6 +425,7 @@
       *  %xB-F are reserved for further control frames
       
       */
+    printf("send binary: 0x02 %u 0\r\n", len);
     sendOpcode(0x02);
     sendLength(len);
     sendMask();
@@ -352,17 +435,22 @@
     if (netif == ETH) 
     {
         Net::poll();
+        /*
         // first send the header
         const char* hh = hbuf;
         for (uint32_t j=0; j<hlen; j++, hh++) {
             sendChar(*hh);
+            printf("%02x ",*hh);
         }
+        */
         // now send the message
         uint32_t nbytes=0;
-        char* s = str;
-        for (uint32_t i=0; i<len; i++, s++) {
-            nbytes += sendChar(*s);
+        const char* ss = str;
+        for (uint32_t i=0; i<len; i++, ss++) {
+            nbytes += sendChar(*ss);
+            printf("%02x ",*ss);
         }
+        printf("\r\n");
         //const int32_t nbytes = sock->send(str, len);
         return nbytes==len;
     }
@@ -370,8 +458,8 @@
     return false;
 }
 
-bool Websocket::sendBinary(const char* hbuf, const uint32_t hlen,
-                           FILE* f, const uint32_t nbytes) 
+bool Websocket::sendBinaryDirect(const char* hbuf, const uint32_t hlen,
+                                 FILE* f, const uint32_t nbytes) 
 {
 #ifdef DEBUG
     printf("SENDBINARY(FILE*)\r\n");
@@ -426,7 +514,9 @@
     return true;
 }
 
-bool Websocket::read(char * message, uint32_t& len_msg, const uint32_t timeout) 
+bool Websocket::read(char * message, uint32_t& len_msg, const uint32_t maxlen,
+                     const uint32_t timeout,
+                     char* const bbuf, const uint32_t bbsize) 
 {
 #ifdef DEBUG
     printf("READ()\r\n");
@@ -456,7 +546,7 @@
                         time(0), timeout);
                     wait(2);
                     return false;
-                } else if (index>=1024) {
+                } else if (index>=RX_BUF_SIZE) {
                     index=0;
                     continue;
                 }
@@ -474,13 +564,14 @@
             // and a race-condition occurred
             int32_t ix=0;
             const char* erx = eth_rx;
-            for (ix=0; ix<1024; ix++, erx++) { // 1024 or 512? (since sock->read is called with 512)
+            for (ix=0; ix<RX_BUF_SIZE; ix++, erx++) { // 1024 or 512? (since sock->read is called with 512)
                 if ( (*erx==0x81) || (*erx==0x82) ) {
                     index = ix+1;
+                    opcode = *erx;
                     break;
                 }
             }
-            if (ix==1024) {
+            if (ix==RX_BUF_SIZE) {
                 // some new non-websocket message came in during the redoing of the search?
                 // anyway opcode not found
                 printf("opcode re-search failed\r\n");
@@ -488,7 +579,7 @@
             }
 //#ifdef DEBUG
             printf("opcode: 0x%X @ index=%u\r\n", opcode, index-1);
-            for (int i=0; i<1024; i++) {
+            for (int i=0; i<RX_BUF_SIZE; i++) {
                 printf("%02x ",eth_rx[i]);
             }
             printf("\r\n");
@@ -501,7 +592,7 @@
             {
                 len_msg += eth_rx[index++] << 8;                        
                 len_msg = eth_rx[index++];                                  
-             printf("len message is greater than 126 %d\r\n", len_msg);     
+                printf("len message is greater than 126 %d\r\n", len_msg);     
             } 
             else if (len_msg == 127) 
             {              
@@ -514,6 +605,8 @@
             if(len_msg == 0) 
             {  
                 return false;
+            } else if (len_msg>=maxlen) {
+                return false;
             }
 //#ifdef DEBUG
             printf("length: %d\r\n", len_msg);
@@ -524,37 +617,53 @@
                 for (int j = 0; j < 4; j++){
                     mask[j] = eth_rx[index++];
                     printf(" mask index %i is %i, ", j, mask[j]); 
-                    }                   
+                }                   
             }
-           // for (int i = 0; i < 4; i++)
-           //{
-           //         mask[i] = 0; 
-           //} 
-         /*   for (int i = 0; i < 4; i++)
-            {
-                 printf(" mask index %i is %i, ", i, mask[i]); 
-            }*/   
             printf("\r\n");
+            
+            // read the actual message
             for (int i = 0; i < len_msg; i++) 
             {             
-         //      printf("%c", eth_rx[i]);
-        //       message[i-8] = eth_rx[i];            
-          //      message[i] = eth_rx[index++] ^ mask[i % 4];    
-          if (len_msg < 126)
-                message[i] = eth_rx[i+2];                      
-          else
-                message[i] = eth_rx[i+4];                              
-             //   printf("message is %s\r\n", message);            
+                if (len_msg < 126) {
+                    message[i] = eth_rx[i+2];                      
+                } else {
+                    message[i] = eth_rx[i+4];
+                }
             }            
             message[len_msg] = 0;
             
+            if ( kUseB64 && ((opcode & 0x01)!=0) ) {
+                // decode the message
+                printf("need to b64decode\r\n");
+                const uint8_t pads = len_msg%4;
+                if ((len_msg+pads+1)<maxlen) {
+                    char* mm = message+len_msg;
+                    for (uint8_t k=0; k<pads; k++, mm++) {
+                        *mm = CHARPAD;
+                    }
+                    *mm=0;
+                    if (BASE64ENC_LEN(len_msg+pads)<bbsize) {
+                        len_msg = B64::modp_b64_decode(message, len_msg+pads, bbuf);
+                        if (len_msg<maxlen) {
+                            memcpy(message, bbuf, len_msg);
+                        } else {
+                            return false;
+                        }
+                    } else {
+                        return false;
+                    }
+                } else {
+                    return false;
+                }
+            }
+            
             for (int i=0; i<len_msg; i++) {
                 printf("%02x ",message[i]);
             }
             printf("\r\n");
             
-             new_msg = false;                
-           return true;
+            new_msg = false;                
+            return true;
         }//if new message
         //printf("no new message!\r\n");
         return false;
@@ -623,7 +732,7 @@
 #ifdef DEBUG
         printf("TCPSOCKET_READABLE\r\n");
 #endif
-        int len = sock->recv(eth_rx, 512);       
+        const int len = sock->recv(eth_rx, RX_RECV_BYTES);
         eth_rx[len] = 0;
         new_msg = true;
         printf("sock recv len %d\r\n",len);