Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
Diff: Websocket.cpp
- 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);