Simple websocket client based on the original with a few added features such as: - setBaud() - set the baud rate for the communication - Initialize() - mimics the constructor - chaged read() to readmsg() to avoid confusion with other functions - Added SerialCommPort

Fork of WebSocketClient by Damien Frost

Committer:
defrost
Date:
Wed Aug 23 10:59:19 2017 +0000
Revision:
30:0b5a84149a79
Parent:
29:33d77a538611
- Fixed bug in receiveBytes, it now works

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 3:9589afa4712e 1 #include "Websocket.h"
samux 3:9589afa4712e 2
samux 7:4567996414a5 3 #define MAX_TRY_WRITE 20
samux 7:4567996414a5 4 #define MAX_TRY_READ 10
samux 3:9589afa4712e 5
defrost 24:6f30d0c4ff7b 6 //#define DEBUG
defrost 26:e13e6b11b780 7 #define INFOMESSAGES
defrost 20:ae675d49fa7f 8 #define WARNMESSAGES
defrost 20:ae675d49fa7f 9 #define ERRMESSAGES
defrost 26:e13e6b11b780 10 #define FUNCNAME "WS"
defrost 26:e13e6b11b780 11 #include "messages.h"
defrost 20:ae675d49fa7f 12
defrost 26:e13e6b11b780 13 Serial* Websocket::SerialCommPort;
samux 3:9589afa4712e 14
defrost 26:e13e6b11b780 15 Websocket::Websocket(char * url, Serial* infoMessages) {
samux 3:9589afa4712e 16 fillFields(url);
samux 3:9589afa4712e 17 socket.set_blocking(false, 400);
defrost 26:e13e6b11b780 18 SerialCommPort = infoMessages;
samux 3:9589afa4712e 19 }
samux 3:9589afa4712e 20
defrost 26:e13e6b11b780 21 Websocket::Websocket(Serial* infoMessages) {
defrost 26:e13e6b11b780 22 SerialCommPort = infoMessages;
defrost 11:85bff70bab45 23 }
defrost 11:85bff70bab45 24
defrost 27:bbe2b90ebd3c 25 Websocket::Websocket(void){
defrost 27:bbe2b90ebd3c 26 return;
defrost 27:bbe2b90ebd3c 27 }
defrost 27:bbe2b90ebd3c 28
defrost 27:bbe2b90ebd3c 29 void Websocket::SetSerialPort(Serial * scp){
defrost 27:bbe2b90ebd3c 30 SerialCommPort = scp;
defrost 27:bbe2b90ebd3c 31 return;
defrost 27:bbe2b90ebd3c 32 }
defrost 27:bbe2b90ebd3c 33
defrost 11:85bff70bab45 34 void Websocket::Initialize(char * url){
defrost 11:85bff70bab45 35 fillFields(url);
defrost 11:85bff70bab45 36 socket.set_blocking(false, 400);
defrost 11:85bff70bab45 37 }
defrost 11:85bff70bab45 38
defrost 15:9df4ffc6ce48 39 void Websocket::setBaud(int baudrate){
defrost 15:9df4ffc6ce48 40 socket.setBaud(baudrate);
defrost 26:e13e6b11b780 41 DBG(SerialCommPort, "Baud Rate set to: %d", baudrate);
defrost 15:9df4ffc6ce48 42 return;
defrost 15:9df4ffc6ce48 43 }
defrost 15:9df4ffc6ce48 44
samux 3:9589afa4712e 45 void Websocket::fillFields(char * url) {
donatien 6:86e89a0369b9 46 int ret = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
donatien 6:86e89a0369b9 47 if(ret)
donatien 6:86e89a0369b9 48 {
defrost 26:e13e6b11b780 49 ERR(SerialCommPort, "URL parsing failed; please use: \"ws://ip-or-domain[:port]/path\"");
donatien 6:86e89a0369b9 50 return;
donatien 6:86e89a0369b9 51 }
samux 3:9589afa4712e 52
donatien 6:86e89a0369b9 53 if(port == 0) //TODO do handle WSS->443
donatien 6:86e89a0369b9 54 {
donatien 6:86e89a0369b9 55 port = 80;
donatien 6:86e89a0369b9 56 }
donatien 6:86e89a0369b9 57
donatien 6:86e89a0369b9 58 if(strcmp(scheme, "ws"))
donatien 6:86e89a0369b9 59 {
defrost 26:e13e6b11b780 60 ERR(SerialCommPort, "Wrong scheme, please use \"ws\" instead");
donatien 6:86e89a0369b9 61 }
donatien 6:86e89a0369b9 62 }
samux 3:9589afa4712e 63
donatien 6:86e89a0369b9 64 int Websocket::parseURL(const char* url, char* scheme, size_t maxSchemeLen, char* host, size_t maxHostLen, uint16_t* port, char* path, size_t maxPathLen) //Parse URL
donatien 6:86e89a0369b9 65 {
donatien 6:86e89a0369b9 66 char* schemePtr = (char*) url;
donatien 6:86e89a0369b9 67 char* hostPtr = (char*) strstr(url, "://");
donatien 6:86e89a0369b9 68 if(hostPtr == NULL)
donatien 6:86e89a0369b9 69 {
defrost 26:e13e6b11b780 70 WARN(SerialCommPort, "Could not find host");
donatien 6:86e89a0369b9 71 return -1; //URL is invalid
donatien 6:86e89a0369b9 72 }
donatien 6:86e89a0369b9 73
donatien 6:86e89a0369b9 74 if( maxSchemeLen < hostPtr - schemePtr + 1 ) //including NULL-terminating char
donatien 6:86e89a0369b9 75 {
defrost 26:e13e6b11b780 76 WARN(SerialCommPort, "Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1);
donatien 6:86e89a0369b9 77 return -1;
donatien 6:86e89a0369b9 78 }
donatien 6:86e89a0369b9 79 memcpy(scheme, schemePtr, hostPtr - schemePtr);
donatien 6:86e89a0369b9 80 scheme[hostPtr - schemePtr] = '\0';
donatien 6:86e89a0369b9 81
donatien 6:86e89a0369b9 82 hostPtr+=3;
donatien 6:86e89a0369b9 83
donatien 6:86e89a0369b9 84 size_t hostLen = 0;
samux 3:9589afa4712e 85
donatien 6:86e89a0369b9 86 char* portPtr = strchr(hostPtr, ':');
donatien 6:86e89a0369b9 87 if( portPtr != NULL )
donatien 6:86e89a0369b9 88 {
donatien 6:86e89a0369b9 89 hostLen = portPtr - hostPtr;
donatien 6:86e89a0369b9 90 portPtr++;
donatien 6:86e89a0369b9 91 if( sscanf(portPtr, "%hu", port) != 1)
donatien 6:86e89a0369b9 92 {
defrost 26:e13e6b11b780 93 WARN(SerialCommPort, "Could not find port");
donatien 6:86e89a0369b9 94 return -1;
donatien 6:86e89a0369b9 95 }
donatien 6:86e89a0369b9 96 }
donatien 6:86e89a0369b9 97 else
donatien 6:86e89a0369b9 98 {
donatien 6:86e89a0369b9 99 *port=0;
donatien 6:86e89a0369b9 100 }
donatien 6:86e89a0369b9 101 char* pathPtr = strchr(hostPtr, '/');
donatien 6:86e89a0369b9 102 if( hostLen == 0 )
donatien 6:86e89a0369b9 103 {
donatien 6:86e89a0369b9 104 hostLen = pathPtr - hostPtr;
donatien 6:86e89a0369b9 105 }
samux 3:9589afa4712e 106
donatien 6:86e89a0369b9 107 if( maxHostLen < hostLen + 1 ) //including NULL-terminating char
donatien 6:86e89a0369b9 108 {
defrost 26:e13e6b11b780 109 WARN(SerialCommPort, "Host str is too small (%d >= %d)", maxHostLen, hostLen + 1);
donatien 6:86e89a0369b9 110 return -1;
donatien 6:86e89a0369b9 111 }
donatien 6:86e89a0369b9 112 memcpy(host, hostPtr, hostLen);
donatien 6:86e89a0369b9 113 host[hostLen] = '\0';
samux 3:9589afa4712e 114
donatien 6:86e89a0369b9 115 size_t pathLen;
donatien 6:86e89a0369b9 116 char* fragmentPtr = strchr(hostPtr, '#');
donatien 6:86e89a0369b9 117 if(fragmentPtr != NULL)
donatien 6:86e89a0369b9 118 {
donatien 6:86e89a0369b9 119 pathLen = fragmentPtr - pathPtr;
donatien 6:86e89a0369b9 120 }
donatien 6:86e89a0369b9 121 else
donatien 6:86e89a0369b9 122 {
donatien 6:86e89a0369b9 123 pathLen = strlen(pathPtr);
donatien 6:86e89a0369b9 124 }
donatien 6:86e89a0369b9 125
donatien 6:86e89a0369b9 126 if( maxPathLen < pathLen + 1 ) //including NULL-terminating char
donatien 6:86e89a0369b9 127 {
defrost 26:e13e6b11b780 128 WARN(SerialCommPort, "Path str is too small (%d >= %d)", maxPathLen, pathLen + 1);
donatien 6:86e89a0369b9 129 return -1;
donatien 6:86e89a0369b9 130 }
donatien 6:86e89a0369b9 131 memcpy(path, pathPtr, pathLen);
donatien 6:86e89a0369b9 132 path[pathLen] = '\0';
donatien 6:86e89a0369b9 133
donatien 6:86e89a0369b9 134 return 0;
samux 3:9589afa4712e 135 }
samux 3:9589afa4712e 136
samux 3:9589afa4712e 137
samux 3:9589afa4712e 138 bool Websocket::connect() {
samux 3:9589afa4712e 139 char cmd[200];
samux 3:9589afa4712e 140
donatien 6:86e89a0369b9 141 while (socket.connect(host, port) < 0) {
defrost 26:e13e6b11b780 142 ERR(SerialCommPort, "Unable to connect to (%s) on port (%d)", host, port);
samux 3:9589afa4712e 143 wait(0.2);
donatien 6:86e89a0369b9 144 return false;
samux 3:9589afa4712e 145 }
defrost 26:e13e6b11b780 146 INFO(SerialCommPort, "TCP/IP Connection established, upgrading protocol...");
samux 3:9589afa4712e 147 // sent http header to upgrade to the ws protocol
donatien 6:86e89a0369b9 148 sprintf(cmd, "GET %s HTTP/1.1\r\n", path);
samux 3:9589afa4712e 149 write(cmd, strlen(cmd));
donatien 6:86e89a0369b9 150
donatien 6:86e89a0369b9 151 sprintf(cmd, "Host: %s:%d\r\n", host, port);
samux 3:9589afa4712e 152 write(cmd, strlen(cmd));
samux 3:9589afa4712e 153
samux 3:9589afa4712e 154 sprintf(cmd, "Upgrade: WebSocket\r\n");
samux 3:9589afa4712e 155 write(cmd, strlen(cmd));
samux 3:9589afa4712e 156
samux 3:9589afa4712e 157 sprintf(cmd, "Connection: Upgrade\r\n");
samux 3:9589afa4712e 158 write(cmd, strlen(cmd));
samux 3:9589afa4712e 159
samux 3:9589afa4712e 160 sprintf(cmd, "Sec-WebSocket-Key: L159VM0TWUzyDxwJEIEzjw==\r\n");
samux 3:9589afa4712e 161 write(cmd, strlen(cmd));
samux 3:9589afa4712e 162
samux 3:9589afa4712e 163 sprintf(cmd, "Sec-WebSocket-Version: 13\r\n\r\n");
samux 3:9589afa4712e 164 int ret = write(cmd, strlen(cmd));
samux 3:9589afa4712e 165 if (ret != strlen(cmd)) {
samux 3:9589afa4712e 166 close();
defrost 26:e13e6b11b780 167 ERR(SerialCommPort, "Could not send request");
samux 3:9589afa4712e 168 return false;
samux 3:9589afa4712e 169 }
samux 3:9589afa4712e 170
samux 3:9589afa4712e 171 ret = read(cmd, 200, 100);
samux 3:9589afa4712e 172 if (ret < 0) {
samux 3:9589afa4712e 173 close();
defrost 26:e13e6b11b780 174 ERR(SerialCommPort, "Could not receive answer\r\n");
samux 3:9589afa4712e 175 return false;
samux 3:9589afa4712e 176 }
samux 3:9589afa4712e 177
samux 3:9589afa4712e 178 cmd[ret] = '\0';
defrost 26:e13e6b11b780 179 DBG(SerialCommPort, "recv: %s\r\n", cmd);
samux 3:9589afa4712e 180
samux 3:9589afa4712e 181 if ( strstr(cmd, "DdLWT/1JcX+nQFHebYP+rqEx5xI=") == NULL ) {
defrost 26:e13e6b11b780 182 ERR(SerialCommPort, "Wrong answer from server, got \"%s\" instead\r\n", cmd);
samux 3:9589afa4712e 183 do {
samux 3:9589afa4712e 184 ret = read(cmd, 200, 100);
samux 3:9589afa4712e 185 if (ret < 0) {
defrost 26:e13e6b11b780 186 ERR(SerialCommPort, "Could not receive answer\r\n");
samux 3:9589afa4712e 187 return false;
samux 3:9589afa4712e 188 }
samux 3:9589afa4712e 189 cmd[ret] = '\0';
defrost 26:e13e6b11b780 190 DBG(SerialCommPort, "%s",cmd);
samux 3:9589afa4712e 191 } while (ret > 0);
samux 3:9589afa4712e 192 close();
samux 3:9589afa4712e 193 return false;
samux 3:9589afa4712e 194 }
samux 3:9589afa4712e 195
defrost 26:e13e6b11b780 196 INFO(SerialCommPort, "\r\n\thost: %s\r\n\tpath: %s\r\n\tport: %d\r\n\r\n", host, path, port);
samux 3:9589afa4712e 197 return true;
samux 3:9589afa4712e 198 }
samux 3:9589afa4712e 199
samux 4:466f90b7849a 200 int Websocket::sendLength(uint32_t len, char * msg) {
samux 3:9589afa4712e 201
samux 3:9589afa4712e 202 if (len < 126) {
samux 4:466f90b7849a 203 msg[0] = len | (1<<7);
samux 3:9589afa4712e 204 return 1;
samux 3:9589afa4712e 205 } else if (len < 65535) {
samux 4:466f90b7849a 206 msg[0] = 126 | (1<<7);
samux 4:466f90b7849a 207 msg[1] = (len >> 8) & 0xff;
samux 4:466f90b7849a 208 msg[2] = len & 0xff;
samux 3:9589afa4712e 209 return 3;
samux 3:9589afa4712e 210 } else {
samux 4:466f90b7849a 211 msg[0] = 127 | (1<<7);
samux 3:9589afa4712e 212 for (int i = 0; i < 8; i++) {
samux 4:466f90b7849a 213 msg[i+1] = (len >> i*8) & 0xff;
samux 3:9589afa4712e 214 }
samux 3:9589afa4712e 215 return 9;
samux 3:9589afa4712e 216 }
samux 3:9589afa4712e 217 }
samux 3:9589afa4712e 218
samux 3:9589afa4712e 219 int Websocket::readChar(char * pC, bool block) {
samux 3:9589afa4712e 220 return read(pC, 1, 1);
samux 3:9589afa4712e 221 }
samux 3:9589afa4712e 222
samux 4:466f90b7849a 223 int Websocket::sendOpcode(uint8_t opcode, char * msg) {
samux 4:466f90b7849a 224 msg[0] = 0x80 | (opcode & 0x0f);
samux 4:466f90b7849a 225 return 1;
samux 3:9589afa4712e 226 }
samux 3:9589afa4712e 227
samux 4:466f90b7849a 228 int Websocket::sendMask(char * msg) {
defrost 28:33ea48ed24ca 229 // The point of the mask is to encode the data slightly. Right now, it does not do anything.
samux 3:9589afa4712e 230 for (int i = 0; i < 4; i++) {
samux 4:466f90b7849a 231 msg[i] = 0;
samux 3:9589afa4712e 232 }
samux 3:9589afa4712e 233 return 4;
samux 3:9589afa4712e 234 }
samux 3:9589afa4712e 235
samux 3:9589afa4712e 236 int Websocket::send(char * str) {
samux 4:466f90b7849a 237 char msg[strlen(str) + 15];
samux 4:466f90b7849a 238 int idx = 0;
defrost 28:33ea48ed24ca 239 idx = sendOpcode(0x01, msg); // Op code 1 is for strings.
samux 4:466f90b7849a 240 idx += sendLength(strlen(str), msg + idx);
samux 4:466f90b7849a 241 idx += sendMask(msg + idx);
samux 4:466f90b7849a 242 memcpy(msg+idx, str, strlen(str));
samux 4:466f90b7849a 243 int res = write(msg, idx + strlen(str));
samux 3:9589afa4712e 244 return res;
samux 3:9589afa4712e 245 }
samux 3:9589afa4712e 246
defrost 28:33ea48ed24ca 247 int Websocket::sendBytes(char * bytes, unsigned int nb){
defrost 28:33ea48ed24ca 248 // Send nb number of bytes.
defrost 28:33ea48ed24ca 249 char msg[nb + 15];
defrost 28:33ea48ed24ca 250 int idx = 0;
defrost 28:33ea48ed24ca 251 idx = sendOpcode(0x02, msg); // Opcode 2 is for sending binary data. See https://tools.ietf.org/html/rfc6455#section-11.8 for all of the opcodes
defrost 28:33ea48ed24ca 252 idx += sendLength(nb, msg + idx);
defrost 28:33ea48ed24ca 253 idx += sendMask(msg + idx);
defrost 28:33ea48ed24ca 254 memcpy(msg+idx, bytes, nb);
defrost 28:33ea48ed24ca 255 int res = write(msg, idx + nb);
defrost 28:33ea48ed24ca 256 return res;
defrost 28:33ea48ed24ca 257 }
defrost 28:33ea48ed24ca 258
defrost 29:33d77a538611 259 int Websocket::readBytes(char * bytes){
defrost 29:33d77a538611 260 // Receive bytes, and return the number of received bytes
defrost 29:33d77a538611 261 // Returns 0 if nothing is read, -1 for an error
defrost 29:33d77a538611 262 int i = 0;
defrost 29:33d77a538611 263 uint32_t len_msg;
defrost 29:33d77a538611 264 char opcode = 0;
defrost 29:33d77a538611 265 char c;
defrost 29:33d77a538611 266 char mask[4] = {0, 0, 0, 0};
defrost 29:33d77a538611 267 bool is_masked = false;
defrost 29:33d77a538611 268 Timer tmr;
defrost 29:33d77a538611 269
defrost 29:33d77a538611 270 // read the opcode
defrost 29:33d77a538611 271 tmr.start();
defrost 29:33d77a538611 272 while (true) {
defrost 29:33d77a538611 273 if (tmr.read() > 3) {
defrost 29:33d77a538611 274 DBG(SerialCommPort, "timeout ws\r\n");
defrost 29:33d77a538611 275 return -1;
defrost 29:33d77a538611 276 }
defrost 29:33d77a538611 277
defrost 29:33d77a538611 278 if(!socket.is_connected())
defrost 29:33d77a538611 279 {
defrost 29:33d77a538611 280 WARN(SerialCommPort, "Connection was closed by server");
defrost 29:33d77a538611 281 return -1;
defrost 29:33d77a538611 282 }
defrost 29:33d77a538611 283
defrost 29:33d77a538611 284 socket.set_blocking(false, 1);
defrost 30:0b5a84149a79 285 if (socket.receive(&opcode, 1) != 1) {
defrost 29:33d77a538611 286 socket.set_blocking(false, 2000);
defrost 30:0b5a84149a79 287 DBG(SerialCommPort, "opcode: %d", opcode);
defrost 29:33d77a538611 288 return 0;
defrost 29:33d77a538611 289 }
defrost 29:33d77a538611 290
defrost 29:33d77a538611 291 socket.set_blocking(false, 2000);
defrost 29:33d77a538611 292
defrost 29:33d77a538611 293 if (opcode == 0x82)
defrost 29:33d77a538611 294 break;
defrost 29:33d77a538611 295 }
defrost 29:33d77a538611 296 DBG(SerialCommPort, "opcode: 0x%X", opcode);
defrost 29:33d77a538611 297
defrost 29:33d77a538611 298 readChar(&c);
defrost 29:33d77a538611 299 len_msg = c & 0x7f;
defrost 29:33d77a538611 300 is_masked = c & 0x80;
defrost 29:33d77a538611 301 if (len_msg == 126) {
defrost 29:33d77a538611 302 readChar(&c);
defrost 29:33d77a538611 303 len_msg = c << 8;
defrost 29:33d77a538611 304 readChar(&c);
defrost 29:33d77a538611 305 len_msg += c;
defrost 29:33d77a538611 306 } else if (len_msg == 127) {
defrost 29:33d77a538611 307 len_msg = 0;
defrost 29:33d77a538611 308 for (int i = 0; i < 8; i++) {
defrost 29:33d77a538611 309 readChar(&c);
defrost 29:33d77a538611 310 len_msg += (c << (7-i)*8);
defrost 29:33d77a538611 311 }
defrost 29:33d77a538611 312 }
defrost 29:33d77a538611 313
defrost 29:33d77a538611 314 if (len_msg == 0) {
defrost 29:33d77a538611 315 return 0;
defrost 29:33d77a538611 316 }
defrost 29:33d77a538611 317 DBG(SerialCommPort, "length: %d", len_msg);
defrost 29:33d77a538611 318
defrost 29:33d77a538611 319 if (is_masked) {
defrost 29:33d77a538611 320 for (i = 0; i < 4; i++)
defrost 29:33d77a538611 321 readChar(&c);
defrost 29:33d77a538611 322 mask[i] = c;
defrost 29:33d77a538611 323 }
defrost 29:33d77a538611 324
defrost 29:33d77a538611 325 DBG(SerialCommPort, "Done readChar.");
defrost 29:33d77a538611 326
defrost 29:33d77a538611 327 int nb = read(bytes, len_msg, len_msg);
defrost 29:33d77a538611 328
defrost 30:0b5a84149a79 329 DBG(SerialCommPort, "Done read(), nb = %d", nb);
defrost 30:0b5a84149a79 330
defrost 29:33d77a538611 331 if (nb != len_msg){
defrost 29:33d77a538611 332 ERR(SerialCommPort, "Unexpected number of bytes read: %d, expected: %d", nb, len_msg);
defrost 29:33d77a538611 333 return 0;
defrost 29:33d77a538611 334 }
defrost 30:0b5a84149a79 335
defrost 30:0b5a84149a79 336 DBG(SerialCommPort, "Masking...");
defrost 30:0b5a84149a79 337
defrost 29:33d77a538611 338 for (i = 0; i < len_msg; i++) {
defrost 29:33d77a538611 339 bytes[i] = bytes[i] ^ mask[i % 4];
defrost 29:33d77a538611 340 }
defrost 29:33d77a538611 341
defrost 30:0b5a84149a79 342 DBG(SerialCommPort, "Returning nb = %d", nb);
defrost 30:0b5a84149a79 343
defrost 29:33d77a538611 344 // Return the number of bytes read:
defrost 29:33d77a538611 345 return nb;
defrost 29:33d77a538611 346 }
defrost 29:33d77a538611 347
samux 3:9589afa4712e 348
defrost 23:0d7b33cd11f9 349 int Websocket::readmsg(char * message) {
samux 3:9589afa4712e 350 int i = 0;
samux 3:9589afa4712e 351 uint32_t len_msg;
samux 3:9589afa4712e 352 char opcode = 0;
samux 3:9589afa4712e 353 char c;
samux 3:9589afa4712e 354 char mask[4] = {0, 0, 0, 0};
samux 3:9589afa4712e 355 bool is_masked = false;
samux 3:9589afa4712e 356 Timer tmr;
samux 3:9589afa4712e 357
samux 3:9589afa4712e 358 // read the opcode
samux 3:9589afa4712e 359 tmr.start();
samux 3:9589afa4712e 360 while (true) {
samux 3:9589afa4712e 361 if (tmr.read() > 3) {
defrost 26:e13e6b11b780 362 DBG(SerialCommPort, "timeout ws\r\n");
defrost 23:0d7b33cd11f9 363 return -1;
samux 3:9589afa4712e 364 }
donatien 5:bb09d7a6c92f 365
donatien 5:bb09d7a6c92f 366 if(!socket.is_connected())
donatien 5:bb09d7a6c92f 367 {
defrost 26:e13e6b11b780 368 WARN(SerialCommPort, "Connection was closed by server");
defrost 23:0d7b33cd11f9 369 return -1;
donatien 5:bb09d7a6c92f 370 }
samux 3:9589afa4712e 371
samux 3:9589afa4712e 372 socket.set_blocking(false, 1);
samux 3:9589afa4712e 373 if (socket.receive(&opcode, 1) != 1) {
samux 3:9589afa4712e 374 socket.set_blocking(false, 2000);
defrost 23:0d7b33cd11f9 375 return 0;
samux 3:9589afa4712e 376 }
samux 3:9589afa4712e 377
samux 3:9589afa4712e 378 socket.set_blocking(false, 2000);
samux 3:9589afa4712e 379
samux 3:9589afa4712e 380 if (opcode == 0x81)
samux 3:9589afa4712e 381 break;
samux 3:9589afa4712e 382 }
defrost 26:e13e6b11b780 383 DBG(SerialCommPort, "opcode: 0x%X", opcode);
samux 3:9589afa4712e 384
samux 3:9589afa4712e 385 readChar(&c);
samux 3:9589afa4712e 386 len_msg = c & 0x7f;
samux 3:9589afa4712e 387 is_masked = c & 0x80;
samux 3:9589afa4712e 388 if (len_msg == 126) {
samux 3:9589afa4712e 389 readChar(&c);
samux 3:9589afa4712e 390 len_msg = c << 8;
samux 3:9589afa4712e 391 readChar(&c);
samux 3:9589afa4712e 392 len_msg += c;
samux 3:9589afa4712e 393 } else if (len_msg == 127) {
samux 3:9589afa4712e 394 len_msg = 0;
samux 3:9589afa4712e 395 for (int i = 0; i < 8; i++) {
samux 3:9589afa4712e 396 readChar(&c);
samux 3:9589afa4712e 397 len_msg += (c << (7-i)*8);
samux 3:9589afa4712e 398 }
samux 3:9589afa4712e 399 }
samux 3:9589afa4712e 400
samux 3:9589afa4712e 401 if (len_msg == 0) {
defrost 23:0d7b33cd11f9 402 return 0;
samux 3:9589afa4712e 403 }
defrost 26:e13e6b11b780 404 DBG(SerialCommPort, "length: %d", len_msg);
samux 3:9589afa4712e 405
samux 3:9589afa4712e 406 if (is_masked) {
samux 3:9589afa4712e 407 for (i = 0; i < 4; i++)
samux 3:9589afa4712e 408 readChar(&c);
samux 3:9589afa4712e 409 mask[i] = c;
samux 3:9589afa4712e 410 }
defrost 12:0979caf96fa6 411
defrost 26:e13e6b11b780 412 DBG(SerialCommPort, "Done readChar.");
samux 3:9589afa4712e 413
samux 3:9589afa4712e 414 int nb = read(message, len_msg, len_msg);
defrost 26:e13e6b11b780 415 DBG(SerialCommPort, "Done nb:%d = read(message:%s, len_msg:%d, len_msg:%d)", nb, message, len_msg, len_msg);
samux 3:9589afa4712e 416 if (nb != len_msg)
defrost 23:0d7b33cd11f9 417 return 0;
samux 3:9589afa4712e 418
samux 3:9589afa4712e 419 for (i = 0; i < len_msg; i++) {
samux 3:9589afa4712e 420 message[i] = message[i] ^ mask[i % 4];
samux 3:9589afa4712e 421 }
samux 3:9589afa4712e 422
samux 3:9589afa4712e 423 message[len_msg] = '\0';
defrost 26:e13e6b11b780 424 DBG(SerialCommPort, "Websocket::read() returning true, message:%s", message);
defrost 23:0d7b33cd11f9 425 return 1;
samux 3:9589afa4712e 426 }
samux 3:9589afa4712e 427
samux 3:9589afa4712e 428 bool Websocket::close() {
samux 3:9589afa4712e 429 if (!is_connected())
samux 3:9589afa4712e 430 return false;
samux 3:9589afa4712e 431
samux 3:9589afa4712e 432 int ret = socket.close();
samux 3:9589afa4712e 433 if (ret < 0) {
defrost 26:e13e6b11b780 434 ERR(SerialCommPort, "Could not disconnect");
samux 3:9589afa4712e 435 return false;
samux 3:9589afa4712e 436 }
samux 3:9589afa4712e 437 return true;
samux 3:9589afa4712e 438 }
samux 3:9589afa4712e 439
samux 3:9589afa4712e 440 bool Websocket::is_connected() {
samux 3:9589afa4712e 441 return socket.is_connected();
samux 3:9589afa4712e 442 }
samux 3:9589afa4712e 443
donatien 6:86e89a0369b9 444 char* Websocket::getPath() {
samux 3:9589afa4712e 445 return path;
samux 3:9589afa4712e 446 }
samux 3:9589afa4712e 447
samux 3:9589afa4712e 448 int Websocket::write(char * str, int len) {
samux 3:9589afa4712e 449 int res = 0, idx = 0;
samux 3:9589afa4712e 450
samux 3:9589afa4712e 451 for (int j = 0; j < MAX_TRY_WRITE; j++) {
donatien 5:bb09d7a6c92f 452
donatien 5:bb09d7a6c92f 453 if(!socket.is_connected())
donatien 5:bb09d7a6c92f 454 {
defrost 26:e13e6b11b780 455 WARN(SerialCommPort, "Connection was closed by server");
donatien 5:bb09d7a6c92f 456 break;
donatien 5:bb09d7a6c92f 457 }
samux 3:9589afa4712e 458
samux 3:9589afa4712e 459 if ((res = socket.send_all(str + idx, len - idx)) == -1)
samux 3:9589afa4712e 460 continue;
samux 3:9589afa4712e 461
samux 3:9589afa4712e 462 idx += res;
samux 3:9589afa4712e 463
samux 3:9589afa4712e 464 if (idx == len)
samux 3:9589afa4712e 465 return len;
samux 3:9589afa4712e 466 }
defrost 26:e13e6b11b780 467 WARN(SerialCommPort, "Websocket::write.idx on exit: %d", idx);
samux 3:9589afa4712e 468 return (idx == 0) ? -1 : idx;
samux 3:9589afa4712e 469 }
samux 3:9589afa4712e 470
samux 3:9589afa4712e 471 int Websocket::read(char * str, int len, int min_len) {
samux 3:9589afa4712e 472 int res = 0, idx = 0;
samux 3:9589afa4712e 473
samux 3:9589afa4712e 474 for (int j = 0; j < MAX_TRY_WRITE; j++) {
samux 3:9589afa4712e 475
samux 3:9589afa4712e 476 if ((res = socket.receive_all(str + idx, len - idx)) == -1)
samux 3:9589afa4712e 477 continue;
samux 3:9589afa4712e 478 idx += res;
defrost 30:0b5a84149a79 479 DBG(SerialCommPort, "In read(* str, len = %d, min_len = %d), res = %d, idx = %d", len, min_len, res, idx);
samux 3:9589afa4712e 480 if (idx == len || (min_len != -1 && idx > min_len))
samux 3:9589afa4712e 481 return idx;
samux 3:9589afa4712e 482 }
samux 3:9589afa4712e 483
samux 3:9589afa4712e 484 return (idx == 0) ? -1 : idx;
samux 3:9589afa4712e 485 }