Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
Diff: Websocket.cpp
- Revision:
- 0:664899e0b988
- Child:
- 1:e392595b4b76
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Websocket.cpp Sat Jun 30 02:03:51 2012 +0000 @@ -0,0 +1,578 @@ +#include "Websocket.h" +#include <string> + +//#define DEBUG + + +#ifdef TARGET_LPC1768 +Websocket::Websocket(char * url) { + server_ip = NULL; + netif = ETH; + eth_writeable = false; + eth_readable = false; + eth_connected = false; + response_server_eth = false; + new_msg = false; + fillFields(url); + + eth = new EthernetNetIf( + IpAddr(128,195,204,148), //IP Address + IpAddr(255,255,255,0), //Network Mask + IpAddr(128,195,204,1), //Gateway + IpAddr(128,200,1,201) //DNS + ); + sock = new TCPSocket(); + + EthernetErr ethErr = eth->setup(); +#ifdef DEBUG + if (ethErr) { + printf("\r\nERROR %d in setup.\r\n", ethErr); + } +#endif + + //we must use dnsresolver to find the ip address + if (server_ip == NULL) { + DNSResolver dr; + server_ip = new IpAddr(); + *server_ip = dr.resolveName(ip_domain.c_str()); +#ifdef DEBUG + printf("\r\nserver with dns=%d.%d.%d.%d\r\n", (*server_ip)[0], (*server_ip)[1], (*server_ip)[2], (*server_ip)[3]); +#endif + + } + + IpAddr ipt = eth->getIp(); +#ifdef DEBUG + printf("\r\nmbed IP Address is %d.%d.%d.%d\r\n", ipt[0], ipt[1], ipt[2], ipt[3]); +#endif + + sock->setOnEvent(this, &Websocket::onTCPSocketEvent); +} +#endif //target + + +void Websocket::fillFields(char * url) +{ + printf("FILLFIELDS\r\n"); + char *res = NULL; + char *res1 = NULL; + + char buf[50]; + strcpy(buf, url); + printf("\r\nBuf is:"); + for(int i=0;i<50;i++) + { + printf("%d", buf[i]); + } + printf("\r\n"); + res = strtok(buf, ":"); + if (strcmp(res, "ws")) + { +#ifdef DEBUG + printf("\r\nFormat error: please use: \"ws://ip-or-domain[:port]/path\"\r\n\r\n"); +#endif + } + else + { + //ip_domain and port + res = strtok(NULL, "/"); + + //path + res1 = strtok(NULL, " "); + if (res1 != NULL) + { + path = res1; + } + + //ip_domain + res = strtok(res, ":"); + + //port + res1 = strtok(NULL, " "); + //port + if (res1 != NULL) + { + port = res1; + } else + { + port = "80"; + } + + if (res != NULL) + { + ip_domain = res; + + //if we use ethernet, we must decode ip address or use dnsresolver +#ifdef TARGET_LPC1768 + if (netif == ETH) { + strcpy(buf, res); + //we try to decode the ip address + if (buf[0] >= '0' && buf[0] <= '9') { + res = strtok(buf, "."); + int i = 0; + int ip[4]; + while (res != NULL) { + ip[i] = atoi(res); + res = strtok(NULL, "."); + i++; + } + server_ip = new IpAddr(ip[0], ip[1], ip[2], ip[3]); +#ifdef DEBUG + printf("server without dns=%i.%i.%i.%i\n",(*server_ip)[0],(*server_ip)[1],(*server_ip)[2],(*server_ip)[3]); +#endif + } + } +#endif //target + } + } +} + + +bool Websocket::connect(Timer* stop, const uint32_t timeout) +{ + // printf("CONNECT() Function\r\n"); + char cmd[50]; +#ifdef TARGET_LPC1768 + //M: else if (netif == ETH) + if (netif == ETH) + { + Host server (*server_ip, atoi(port.c_str())); + sock->close(); + TCPSocketErr bindErr = sock->connect(server); + if (bindErr) + { +#ifdef DEBUG + printf("\r\nERROR binderr: %d\r\n", bindErr); +#endif + return false; + } + Timer tmr; + tmr.start(); + Timer myStop; + if (stop==0) { + stop = &myStop; + } + int i = 0; + printf("I: %d\r\n", i); + while (true) { + Net::poll(); + if (stop->read() > timeout) + return false; + if (tmr.read() > 0.05) { + tmr.reset(); + if (eth_connected) { + switch (i) { + case 0: + sprintf(cmd, "GET /%s HTTP/1.1\r\n", path.c_str()); + sock->send(cmd, strlen(cmd)); + i++; + break; + case 1: + sprintf(cmd, "Host: %s:%s\r\n", ip_domain.c_str(), port.c_str()); + sock->send(cmd, strlen(cmd)); + i++; + break; + case 2: + sprintf(cmd, "Upgrade: WebSocket\r\n"); + sock->send(cmd, strlen(cmd)); + i++; + break; + case 3: + sprintf(cmd, "Origin: null\r\n"); + sock->send(cmd, strlen(cmd)); + i++; + break; + case 4: + sprintf(cmd, "Connection: Upgrade\r\n"); + sock->send(cmd, strlen(cmd)); + i++; + break; + case 5: + sprintf(cmd, "Sec-WebSocket-Key: L159VM0TWUzyDxwJEIEzjw==\r\n"); + sock->send(cmd, strlen(cmd)); + i++; + break; + case 6: + sprintf(cmd, "Sec-WebSocket-Version: 13\r\n\r\n"); + sock->send(cmd, strlen(cmd)); + i++; + break; + case 7: + if (response_server_eth) + i++; + else + break; + + default: + break; + } + } + if (i==8) { +#ifdef DEBUG + printf("\r\nip_domain: %s\r\npath: /%s\r\nport: %s\r\n\r\n",this->ip_domain.c_str(), this->path.c_str(), this->port.c_str()); +#endif + return true; + } + } + } + } +#endif //target + //the program shouldn't be here + return false; +} + +void Websocket::sendLength(uint32_t len) +{ + //printf("SENDLENGTH(), Send Length: %d\r\n", len); + if (len < 126) + { + sendChar(len | (1<<7)); + } + else if (len < 65535) + { // use 2 bytes + sendChar(126 | (1<<7)); + //M: reverce these two lines + sendChar((len >> 8) & 0xff); //2 + sendChar(len & 0xff); //1 + // sendChar((len >> 8) & 0xff); //2 + } + else + { + sendChar(127 | (1<<7)); + for (int i = 0; i < 8; i++) + { + sendChar((len >> i*8) & 0xff); + } + } +} + +int Websocket::sendChar(uint8_t c) +{ +#ifdef TARGET_LPC1768 + if (netif == ETH) { + Net::poll(); + return sock->send((const char *)&c, 1); + // printf("SENDCHAR(), Sendchar %d \r\n", c); + } +#endif + return 0; +} + +void Websocket::sendOpcode(uint8_t opcode) +{ +// printf("SENDOPCODE()\r\n"); + sendChar(0x80 | (opcode & 0x0f)); +// printf("SendOpcode: 0x%X\r\n", opcode); +} + +/*Masking-key: 0 or 4 bytes + All frames sent from the client to the server are masked by a 32- + bit value that is contained within the frame. This field is + present if the mask bit is set to 1, and is absent if the mask bit + is set to 0. +*/ +void Websocket::sendMask() +{ +// printf("SENDMASK()\r\n"); + for (int i = 0; i < 4; i++) { + sendChar(0); //no frame masking + } +} + +void Websocket::send(char * str) +{ + //printf("SEND()\r\n"); +/* 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(strlen(str)); + sendMask(); + +#ifdef TARGET_LPC1768 + //M: else if (netif == ETH) { + if (netif == ETH) + { + Net::poll(); + sock->send(str, strlen(str)); + } +#endif //target +} + +bool Websocket::sendBinary(char* str, const uint32_t len) +{ + // CJR: add function for sending binary + + //printf("SEND()\r\n"); +/* 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(0x02); + sendLength(len); + sendMask(); + +#ifdef TARGET_LPC1768 + //M: else if (netif == ETH) { + if (netif == ETH) + { + Net::poll(); + uint32_t nbytes=0; + char* s = str; + for (uint32_t i=0; i<len; i++, s++) { + nbytes += sendChar(*s); + } + //const int32_t nbytes = sock->send(str, len); + return nbytes==len; + } +#endif //target + return false; +} + +bool Websocket::sendBinary(FILE* f, const uint32_t nbytes) +{ + // CJR: add function for sending binary + // return false if EOF or file error before nbytes sent + + //printf("SEND()\r\n"); +/* 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(0x02); + sendLength(nbytes); + sendMask(); + +#ifdef TARGET_LPC1768 + //M: else if (netif == ETH) { + if (netif == ETH) + { + Net::poll(); + uint8_t c; + // conserve mbed memory by reading byte-by-byte + for (uint32_t i=0; i<nbytes; i++) { + fread(&c, 1, 1, f); + if ((feof(f)==0) && (ferror(f)==0)) { + sendChar(c); + } else { + return false; + } + } + + } +#endif //target + return true; +} + +bool Websocket::read(char * message, Timer* timer, const uint32_t timeout) +{ + //printf("READ()\r\n"); + uint32_t len_msg; //32 bit size + char opcode = 0; //continuation frame + char mask[4] = {0, 0, 0, 0}; //no mask + Timer myTimer; + if (timer==0) { + timer = &myTimer; + } +#ifdef TARGET_LPC1768 + if (netif == ETH) + { + // printf("Current opcode in read() 0x%X\r\n", opcode); + uint32_t index = 0; + Net::poll(); + if (new_msg) //from webserver + { + printf("There is new message from webserver\r\n"); + // read the opcode + while (true) + { + if (timer->read() > timeout) + { + return false; + } + opcode = eth_rx[index++]; + printf("new opcode in read() func: 0x%X\r\n", opcode); //0x81 + if (opcode == 0x81) + { + break; + } + }// end of while(true) +#ifdef DEBUG + // printf("opcode: 0x%X\r\n", opcode); +#endif + len_msg = eth_rx[index++] & 0x7f; + printf("length_message2 : %d\r\n", len_msg); // + if (len_msg == 126) + { + len_msg += eth_rx[index++] << 8; + len_msg = eth_rx[index++]; + printf("len message is greater than 126 %d\r\n", len_msg); + } + else if (len_msg == 127) + { + len_msg = 0; + for (int i = 0; i < 8; i++) + { + len_msg += eth_rx[index++] << i*8; + } + } + if(len_msg == 0) + { + return false; + } +#ifdef DEBUG + // printf("length: %d\r\n", len_msg); +#endif + if ((len_msg & 0x80)) + { + printf("print mask bit %d\r\n", len_msg & 0x80); + 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"); + 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); + } + message[len_msg] = 0; + + //M: add : + // if (new_msg) + // {new_msg = true;} + //else + new_msg = false; + return true; + }//if new message + printf("no new message!\r\n"); + return false; + }//end of if(eth) +#endif //target +//the program shouldn't be here + return false; +} // end of read func + +bool Websocket::close() +{ + // printf("COSE()\r\n"); +#ifdef TARGET_LPC1768 + if (netif == ETH) + { + if (sock->close()) + return false; + return true; + } +#endif //target + //the program shouldn't be here + return false; +} + +bool Websocket::connected() { + // printf("CONNECTED()\r\n"); + +#ifdef TARGET_LPC1768 + + if (netif == ETH) + { + return eth_connected; + } +#endif //target + //the program shouldn't be here + return false; +} + +std::string Websocket::getPath() +{ + return path; +} + +#ifdef TARGET_LPC1768 +void Websocket::onTCPSocketEvent(TCPSocketEvent e) +{ + // printf("TCPSocketEvent is "); + if (e == TCPSOCKET_CONNECTED) + { + eth_connected = true; +#ifdef DEBUG + // printf("TCP Socket Connected\r\n"); +#endif + } + else if (e == TCPSOCKET_WRITEABLE) { + // printf("TCPSOCKET_WRITEABLE\r\n"); + } + else if (e == TCPSOCKET_READABLE) + { + // printf("TCPSOCKET_READABLE\r\n"); + int len = sock->recv(eth_rx, 512); + eth_rx[len] = 0; + new_msg = true; + if (!response_server_eth) + { + string checking; + size_t found = string::npos; + checking = eth_rx; + found = checking.find("DdLWT/1JcX+nQFHebYP+rqEx5xI="); + if (found != string::npos) + response_server_eth = true; + } + } + else + { +#ifdef DEBUG + printf("TCP Socket Fail\r\n"); +#endif + eth_connected = false; + } +} +#endif //target +