Network Services

Dependents:   PwrCond_mbed5

Fork of W5500Interface_K22F by Andrew McCartney

Committer:
dgriffin65
Date:
Thu Jun 15 20:29:03 2017 +0000
Revision:
15:14382459c8b7
Converted to a single library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dgriffin65 15:14382459c8b7 1 #include "Websocket.h"
dgriffin65 15:14382459c8b7 2 #include "DNSClient.h"
dgriffin65 15:14382459c8b7 3
dgriffin65 15:14382459c8b7 4 #define MAX_TRY_WRITE 20
dgriffin65 15:14382459c8b7 5 #define MAX_TRY_READ 10
dgriffin65 15:14382459c8b7 6
dgriffin65 15:14382459c8b7 7 //Debug is disabled by default
dgriffin65 15:14382459c8b7 8 #if 1
dgriffin65 15:14382459c8b7 9 #define DBG(x, ...) std::printf("[WebSocket : DBG]"x"\r\n", ##__VA_ARGS__);
dgriffin65 15:14382459c8b7 10 #define WARN(x, ...) std::printf("[WebSocket : WARN]"x"\r\n", ##__VA_ARGS__);
dgriffin65 15:14382459c8b7 11 #define ERR(x, ...) std::printf("[WebSocket : ERR]"x"\r\n", ##__VA_ARGS__);
dgriffin65 15:14382459c8b7 12 #else
dgriffin65 15:14382459c8b7 13 #define DBG(x, ...)
dgriffin65 15:14382459c8b7 14 #define WARN(x, ...)
dgriffin65 15:14382459c8b7 15 #define ERR(x, ...)
dgriffin65 15:14382459c8b7 16 #endif
dgriffin65 15:14382459c8b7 17
dgriffin65 15:14382459c8b7 18 #define INFO(x, ...) printf("[WebSocket : INFO]"x"\r\n", ##__VA_ARGS__);
dgriffin65 15:14382459c8b7 19
dgriffin65 15:14382459c8b7 20 Websocket::Websocket(NetworkStack *ns, char * url) {
dgriffin65 15:14382459c8b7 21 m_ns = ns;
dgriffin65 15:14382459c8b7 22 fillFields(url);
dgriffin65 15:14382459c8b7 23 socket.open(ns);
dgriffin65 15:14382459c8b7 24 socket.set_blocking(false);
dgriffin65 15:14382459c8b7 25 socket.set_timeout(400);
dgriffin65 15:14382459c8b7 26 }
dgriffin65 15:14382459c8b7 27
dgriffin65 15:14382459c8b7 28 void Websocket::fillFields(char * url) {
dgriffin65 15:14382459c8b7 29 int ret = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
dgriffin65 15:14382459c8b7 30 if(ret)
dgriffin65 15:14382459c8b7 31 {
dgriffin65 15:14382459c8b7 32 ERR("URL parsing failed; please use: \"ws://ip-or-domain[:port]/path\"");
dgriffin65 15:14382459c8b7 33 return;
dgriffin65 15:14382459c8b7 34 }
dgriffin65 15:14382459c8b7 35
dgriffin65 15:14382459c8b7 36 if(port == 0) //TODO do handle WSS->443
dgriffin65 15:14382459c8b7 37 {
dgriffin65 15:14382459c8b7 38 port = 80;
dgriffin65 15:14382459c8b7 39 }
dgriffin65 15:14382459c8b7 40
dgriffin65 15:14382459c8b7 41 if(strcmp(scheme, "ws"))
dgriffin65 15:14382459c8b7 42 {
dgriffin65 15:14382459c8b7 43 ERR("Wrong scheme, please use \"ws\" instead");
dgriffin65 15:14382459c8b7 44 }
dgriffin65 15:14382459c8b7 45 }
dgriffin65 15:14382459c8b7 46
dgriffin65 15:14382459c8b7 47 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
dgriffin65 15:14382459c8b7 48 {
dgriffin65 15:14382459c8b7 49 char* schemePtr = (char*) url;
dgriffin65 15:14382459c8b7 50 char* hostPtr = (char*) strstr(url, "://");
dgriffin65 15:14382459c8b7 51 if(hostPtr == NULL)
dgriffin65 15:14382459c8b7 52 {
dgriffin65 15:14382459c8b7 53 WARN("Could not find host");
dgriffin65 15:14382459c8b7 54 return -1; //URL is invalid
dgriffin65 15:14382459c8b7 55 }
dgriffin65 15:14382459c8b7 56
dgriffin65 15:14382459c8b7 57 if( maxSchemeLen < hostPtr - schemePtr + 1 ) //including NULL-terminating char
dgriffin65 15:14382459c8b7 58 {
dgriffin65 15:14382459c8b7 59 WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1);
dgriffin65 15:14382459c8b7 60 return -1;
dgriffin65 15:14382459c8b7 61 }
dgriffin65 15:14382459c8b7 62 memcpy(scheme, schemePtr, hostPtr - schemePtr);
dgriffin65 15:14382459c8b7 63 scheme[hostPtr - schemePtr] = '\0';
dgriffin65 15:14382459c8b7 64
dgriffin65 15:14382459c8b7 65 hostPtr+=3;
dgriffin65 15:14382459c8b7 66
dgriffin65 15:14382459c8b7 67 size_t hostLen = 0;
dgriffin65 15:14382459c8b7 68
dgriffin65 15:14382459c8b7 69 char* portPtr = strchr(hostPtr, ':');
dgriffin65 15:14382459c8b7 70 if( portPtr != NULL )
dgriffin65 15:14382459c8b7 71 {
dgriffin65 15:14382459c8b7 72 hostLen = portPtr - hostPtr;
dgriffin65 15:14382459c8b7 73 portPtr++;
dgriffin65 15:14382459c8b7 74 if( sscanf(portPtr, "%hu", port) != 1)
dgriffin65 15:14382459c8b7 75 {
dgriffin65 15:14382459c8b7 76 WARN("Could not find port");
dgriffin65 15:14382459c8b7 77 return -1;
dgriffin65 15:14382459c8b7 78 }
dgriffin65 15:14382459c8b7 79 }
dgriffin65 15:14382459c8b7 80 else
dgriffin65 15:14382459c8b7 81 {
dgriffin65 15:14382459c8b7 82 *port=0;
dgriffin65 15:14382459c8b7 83 }
dgriffin65 15:14382459c8b7 84 char* pathPtr = strchr(hostPtr, '/');
dgriffin65 15:14382459c8b7 85 if( hostLen == 0 )
dgriffin65 15:14382459c8b7 86 {
dgriffin65 15:14382459c8b7 87 hostLen = pathPtr - hostPtr;
dgriffin65 15:14382459c8b7 88 }
dgriffin65 15:14382459c8b7 89
dgriffin65 15:14382459c8b7 90 if( maxHostLen < hostLen + 1 ) //including NULL-terminating char
dgriffin65 15:14382459c8b7 91 {
dgriffin65 15:14382459c8b7 92 WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1);
dgriffin65 15:14382459c8b7 93 return -1;
dgriffin65 15:14382459c8b7 94 }
dgriffin65 15:14382459c8b7 95 memcpy(host, hostPtr, hostLen);
dgriffin65 15:14382459c8b7 96 host[hostLen] = '\0';
dgriffin65 15:14382459c8b7 97
dgriffin65 15:14382459c8b7 98 size_t pathLen;
dgriffin65 15:14382459c8b7 99 char* fragmentPtr = strchr(hostPtr, '#');
dgriffin65 15:14382459c8b7 100 if(fragmentPtr != NULL)
dgriffin65 15:14382459c8b7 101 {
dgriffin65 15:14382459c8b7 102 pathLen = fragmentPtr - pathPtr;
dgriffin65 15:14382459c8b7 103 }
dgriffin65 15:14382459c8b7 104 else
dgriffin65 15:14382459c8b7 105 {
dgriffin65 15:14382459c8b7 106 pathLen = strlen(pathPtr);
dgriffin65 15:14382459c8b7 107 }
dgriffin65 15:14382459c8b7 108
dgriffin65 15:14382459c8b7 109 if( maxPathLen < pathLen + 1 ) //including NULL-terminating char
dgriffin65 15:14382459c8b7 110 {
dgriffin65 15:14382459c8b7 111 WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1);
dgriffin65 15:14382459c8b7 112 return -1;
dgriffin65 15:14382459c8b7 113 }
dgriffin65 15:14382459c8b7 114 memcpy(path, pathPtr, pathLen);
dgriffin65 15:14382459c8b7 115 path[pathLen] = '\0';
dgriffin65 15:14382459c8b7 116
dgriffin65 15:14382459c8b7 117 return 0;
dgriffin65 15:14382459c8b7 118 }
dgriffin65 15:14382459c8b7 119
dgriffin65 15:14382459c8b7 120
dgriffin65 15:14382459c8b7 121 bool Websocket::connect() {
dgriffin65 15:14382459c8b7 122 DNSClient dns(m_ns);
dgriffin65 15:14382459c8b7 123 char cmd[200];
dgriffin65 15:14382459c8b7 124
dgriffin65 15:14382459c8b7 125 if (!dns.lookup(host)) {
dgriffin65 15:14382459c8b7 126 ERR("Websocket: Unable to resolve hostname (%s)", host);
dgriffin65 15:14382459c8b7 127 wait(0.2);
dgriffin65 15:14382459c8b7 128 connected = false;
dgriffin65 15:14382459c8b7 129 return false;
dgriffin65 15:14382459c8b7 130 }
dgriffin65 15:14382459c8b7 131
dgriffin65 15:14382459c8b7 132 while (socket.connect(dns.get_ip_address(), port) < 0) {
dgriffin65 15:14382459c8b7 133 ERR("Websocket: Unable to connect to (%s) on port (%d)", host, port);
dgriffin65 15:14382459c8b7 134 wait(0.2);
dgriffin65 15:14382459c8b7 135 connected = false;
dgriffin65 15:14382459c8b7 136 return false;
dgriffin65 15:14382459c8b7 137 }
dgriffin65 15:14382459c8b7 138
dgriffin65 15:14382459c8b7 139 connected = true;
dgriffin65 15:14382459c8b7 140
dgriffin65 15:14382459c8b7 141 // sent http header to upgrade to the ws protocol
dgriffin65 15:14382459c8b7 142 sprintf(cmd, "GET %s HTTP/1.1\r\n", path);
dgriffin65 15:14382459c8b7 143 write(cmd, strlen(cmd));
dgriffin65 15:14382459c8b7 144
dgriffin65 15:14382459c8b7 145 sprintf(cmd, "Host: %s:%d\r\n", host, port);
dgriffin65 15:14382459c8b7 146 write(cmd, strlen(cmd));
dgriffin65 15:14382459c8b7 147
dgriffin65 15:14382459c8b7 148 sprintf(cmd, "Upgrade: WebSocket\r\n");
dgriffin65 15:14382459c8b7 149 write(cmd, strlen(cmd));
dgriffin65 15:14382459c8b7 150
dgriffin65 15:14382459c8b7 151 sprintf(cmd, "Connection: Upgrade\r\n");
dgriffin65 15:14382459c8b7 152 write(cmd, strlen(cmd));
dgriffin65 15:14382459c8b7 153
dgriffin65 15:14382459c8b7 154 sprintf(cmd, "Sec-WebSocket-Key: L159VM0TWUzyDxwJEIEzjw==\r\n");
dgriffin65 15:14382459c8b7 155 write(cmd, strlen(cmd));
dgriffin65 15:14382459c8b7 156
dgriffin65 15:14382459c8b7 157 sprintf(cmd, "Sec-WebSocket-Version: 13\r\n\r\n");
dgriffin65 15:14382459c8b7 158 int ret = write(cmd, strlen(cmd));
dgriffin65 15:14382459c8b7 159 if (ret != strlen(cmd)) {
dgriffin65 15:14382459c8b7 160 close();
dgriffin65 15:14382459c8b7 161 ERR("Could not send request");
dgriffin65 15:14382459c8b7 162 return false;
dgriffin65 15:14382459c8b7 163 }
dgriffin65 15:14382459c8b7 164
dgriffin65 15:14382459c8b7 165 ret = read(cmd, 200, 100);
dgriffin65 15:14382459c8b7 166 if (ret < 0) {
dgriffin65 15:14382459c8b7 167 close();
dgriffin65 15:14382459c8b7 168 ERR("Could not receive answer\r\n");
dgriffin65 15:14382459c8b7 169 return false;
dgriffin65 15:14382459c8b7 170 }
dgriffin65 15:14382459c8b7 171
dgriffin65 15:14382459c8b7 172 cmd[ret] = '\0';
dgriffin65 15:14382459c8b7 173 DBG("recv: %s\r\n", cmd);
dgriffin65 15:14382459c8b7 174
dgriffin65 15:14382459c8b7 175 if ( strstr(cmd, "DdLWT/1JcX+nQFHebYP+rqEx5xI=") == NULL ) {
dgriffin65 15:14382459c8b7 176 ERR("Wrong answer from server, got \"%s\" instead\r\n", cmd);
dgriffin65 15:14382459c8b7 177 do {
dgriffin65 15:14382459c8b7 178 ret = read(cmd, 200, 100);
dgriffin65 15:14382459c8b7 179 if (ret < 0) {
dgriffin65 15:14382459c8b7 180 ERR("Could not receive answer\r\n");
dgriffin65 15:14382459c8b7 181 return false;
dgriffin65 15:14382459c8b7 182 }
dgriffin65 15:14382459c8b7 183 cmd[ret] = '\0';
dgriffin65 15:14382459c8b7 184 printf("%s",cmd);
dgriffin65 15:14382459c8b7 185 } while (ret > 0);
dgriffin65 15:14382459c8b7 186 close();
dgriffin65 15:14382459c8b7 187 return false;
dgriffin65 15:14382459c8b7 188 }
dgriffin65 15:14382459c8b7 189
dgriffin65 15:14382459c8b7 190 INFO("\r\nhost: %s\r\npath: %s\r\nport: %d\r\n\r\n", host, path, port);
dgriffin65 15:14382459c8b7 191 return true;
dgriffin65 15:14382459c8b7 192 }
dgriffin65 15:14382459c8b7 193
dgriffin65 15:14382459c8b7 194 int Websocket::sendLength(uint32_t len, char * msg) {
dgriffin65 15:14382459c8b7 195
dgriffin65 15:14382459c8b7 196 if (len < 126) {
dgriffin65 15:14382459c8b7 197 msg[0] = len | (1<<7);
dgriffin65 15:14382459c8b7 198 return 1;
dgriffin65 15:14382459c8b7 199 } else if (len < 65535) {
dgriffin65 15:14382459c8b7 200 msg[0] = 126 | (1<<7);
dgriffin65 15:14382459c8b7 201 msg[1] = (len >> 8) & 0xff;
dgriffin65 15:14382459c8b7 202 msg[2] = len & 0xff;
dgriffin65 15:14382459c8b7 203 return 3;
dgriffin65 15:14382459c8b7 204 } else {
dgriffin65 15:14382459c8b7 205 msg[0] = 127 | (1<<7);
dgriffin65 15:14382459c8b7 206 for (int i = 0; i < 8; i++) {
dgriffin65 15:14382459c8b7 207 msg[i+1] = (len >> i*8) & 0xff;
dgriffin65 15:14382459c8b7 208 }
dgriffin65 15:14382459c8b7 209 return 9;
dgriffin65 15:14382459c8b7 210 }
dgriffin65 15:14382459c8b7 211 }
dgriffin65 15:14382459c8b7 212
dgriffin65 15:14382459c8b7 213 int Websocket::readChar(char * pC, bool block) {
dgriffin65 15:14382459c8b7 214 return read(pC, 1, 1);
dgriffin65 15:14382459c8b7 215 }
dgriffin65 15:14382459c8b7 216
dgriffin65 15:14382459c8b7 217 int Websocket::sendOpcode(uint8_t opcode, char * msg) {
dgriffin65 15:14382459c8b7 218 msg[0] = 0x80 | (opcode & 0x0f);
dgriffin65 15:14382459c8b7 219 return 1;
dgriffin65 15:14382459c8b7 220 }
dgriffin65 15:14382459c8b7 221
dgriffin65 15:14382459c8b7 222 int Websocket::sendMask(char * msg) {
dgriffin65 15:14382459c8b7 223 for (int i = 0; i < 4; i++) {
dgriffin65 15:14382459c8b7 224 msg[i] = 0;
dgriffin65 15:14382459c8b7 225 }
dgriffin65 15:14382459c8b7 226 return 4;
dgriffin65 15:14382459c8b7 227 }
dgriffin65 15:14382459c8b7 228
dgriffin65 15:14382459c8b7 229 int Websocket::send(char * str) {
dgriffin65 15:14382459c8b7 230 char msg[strlen(str) + 15];
dgriffin65 15:14382459c8b7 231 int idx = 0;
dgriffin65 15:14382459c8b7 232 idx = sendOpcode(0x01, msg);
dgriffin65 15:14382459c8b7 233 idx += sendLength(strlen(str), msg + idx);
dgriffin65 15:14382459c8b7 234 idx += sendMask(msg + idx);
dgriffin65 15:14382459c8b7 235 memcpy(msg+idx, str, strlen(str));
dgriffin65 15:14382459c8b7 236 int res = write(msg, idx + strlen(str));
dgriffin65 15:14382459c8b7 237 return res;
dgriffin65 15:14382459c8b7 238 }
dgriffin65 15:14382459c8b7 239
dgriffin65 15:14382459c8b7 240
dgriffin65 15:14382459c8b7 241 bool Websocket::read(char * message) {
dgriffin65 15:14382459c8b7 242 int i = 0;
dgriffin65 15:14382459c8b7 243 uint32_t len_msg;
dgriffin65 15:14382459c8b7 244 char opcode = 0;
dgriffin65 15:14382459c8b7 245 char c;
dgriffin65 15:14382459c8b7 246 char mask[4] = {0, 0, 0, 0};
dgriffin65 15:14382459c8b7 247 bool is_masked = false;
dgriffin65 15:14382459c8b7 248 Timer tmr;
dgriffin65 15:14382459c8b7 249
dgriffin65 15:14382459c8b7 250 // read the opcode
dgriffin65 15:14382459c8b7 251 tmr.start();
dgriffin65 15:14382459c8b7 252 while (true) {
dgriffin65 15:14382459c8b7 253 if (tmr.read() > 3) {
dgriffin65 15:14382459c8b7 254 DBG("timeout ws\r\n");
dgriffin65 15:14382459c8b7 255 return false;
dgriffin65 15:14382459c8b7 256 }
dgriffin65 15:14382459c8b7 257
dgriffin65 15:14382459c8b7 258 if(!connected)
dgriffin65 15:14382459c8b7 259 {
dgriffin65 15:14382459c8b7 260 WARN("Connection was closed by server");
dgriffin65 15:14382459c8b7 261 return false;
dgriffin65 15:14382459c8b7 262 }
dgriffin65 15:14382459c8b7 263
dgriffin65 15:14382459c8b7 264 socket.set_blocking(false);
dgriffin65 15:14382459c8b7 265 socket.set_timeout(1);
dgriffin65 15:14382459c8b7 266 if (socket.recv(&opcode, 1) != 1) {
dgriffin65 15:14382459c8b7 267 socket.set_blocking(false);
dgriffin65 15:14382459c8b7 268 socket.set_timeout(2000);
dgriffin65 15:14382459c8b7 269 return false;
dgriffin65 15:14382459c8b7 270 }
dgriffin65 15:14382459c8b7 271
dgriffin65 15:14382459c8b7 272 socket.set_blocking(false);
dgriffin65 15:14382459c8b7 273 socket.set_timeout(2000);
dgriffin65 15:14382459c8b7 274
dgriffin65 15:14382459c8b7 275 if (opcode == 0x81)
dgriffin65 15:14382459c8b7 276 break;
dgriffin65 15:14382459c8b7 277 }
dgriffin65 15:14382459c8b7 278 DBG("opcode: 0x%X\r\n", opcode);
dgriffin65 15:14382459c8b7 279
dgriffin65 15:14382459c8b7 280 readChar(&c);
dgriffin65 15:14382459c8b7 281 len_msg = c & 0x7f;
dgriffin65 15:14382459c8b7 282 is_masked = c & 0x80;
dgriffin65 15:14382459c8b7 283 if (len_msg == 126) {
dgriffin65 15:14382459c8b7 284 readChar(&c);
dgriffin65 15:14382459c8b7 285 len_msg = c << 8;
dgriffin65 15:14382459c8b7 286 readChar(&c);
dgriffin65 15:14382459c8b7 287 len_msg += c;
dgriffin65 15:14382459c8b7 288 } else if (len_msg == 127) {
dgriffin65 15:14382459c8b7 289 len_msg = 0;
dgriffin65 15:14382459c8b7 290 for (int i = 0; i < 8; i++) {
dgriffin65 15:14382459c8b7 291 readChar(&c);
dgriffin65 15:14382459c8b7 292 len_msg += (c << (7-i)*8);
dgriffin65 15:14382459c8b7 293 }
dgriffin65 15:14382459c8b7 294 }
dgriffin65 15:14382459c8b7 295
dgriffin65 15:14382459c8b7 296 if (len_msg == 0) {
dgriffin65 15:14382459c8b7 297 return false;
dgriffin65 15:14382459c8b7 298 }
dgriffin65 15:14382459c8b7 299 DBG("length: %d\r\n", len_msg);
dgriffin65 15:14382459c8b7 300
dgriffin65 15:14382459c8b7 301 if (is_masked) {
dgriffin65 15:14382459c8b7 302 for (i = 0; i < 4; i++)
dgriffin65 15:14382459c8b7 303 readChar(&c);
dgriffin65 15:14382459c8b7 304 mask[i] = c;
dgriffin65 15:14382459c8b7 305 }
dgriffin65 15:14382459c8b7 306
dgriffin65 15:14382459c8b7 307 int nb = read(message, len_msg, len_msg);
dgriffin65 15:14382459c8b7 308 if (nb != len_msg)
dgriffin65 15:14382459c8b7 309 return false;
dgriffin65 15:14382459c8b7 310
dgriffin65 15:14382459c8b7 311 for (i = 0; i < len_msg; i++) {
dgriffin65 15:14382459c8b7 312 message[i] = message[i] ^ mask[i % 4];
dgriffin65 15:14382459c8b7 313 }
dgriffin65 15:14382459c8b7 314
dgriffin65 15:14382459c8b7 315 message[len_msg] = '\0';
dgriffin65 15:14382459c8b7 316
dgriffin65 15:14382459c8b7 317 return true;
dgriffin65 15:14382459c8b7 318 }
dgriffin65 15:14382459c8b7 319
dgriffin65 15:14382459c8b7 320 bool Websocket::close() {
dgriffin65 15:14382459c8b7 321 if (!is_connected())
dgriffin65 15:14382459c8b7 322 return false;
dgriffin65 15:14382459c8b7 323
dgriffin65 15:14382459c8b7 324 int ret = socket.close();
dgriffin65 15:14382459c8b7 325 if (ret < 0) {
dgriffin65 15:14382459c8b7 326 ERR("Could not disconnect");
dgriffin65 15:14382459c8b7 327 return false;
dgriffin65 15:14382459c8b7 328 }
dgriffin65 15:14382459c8b7 329 return true;
dgriffin65 15:14382459c8b7 330 }
dgriffin65 15:14382459c8b7 331
dgriffin65 15:14382459c8b7 332 bool Websocket::is_connected() {
dgriffin65 15:14382459c8b7 333 return connected;
dgriffin65 15:14382459c8b7 334 }
dgriffin65 15:14382459c8b7 335
dgriffin65 15:14382459c8b7 336 char* Websocket::getPath() {
dgriffin65 15:14382459c8b7 337 return path;
dgriffin65 15:14382459c8b7 338 }
dgriffin65 15:14382459c8b7 339
dgriffin65 15:14382459c8b7 340 int Websocket::write(char * str, int len) {
dgriffin65 15:14382459c8b7 341 int res = 0, idx = 0;
dgriffin65 15:14382459c8b7 342
dgriffin65 15:14382459c8b7 343 for (int j = 0; j < MAX_TRY_WRITE; j++) {
dgriffin65 15:14382459c8b7 344
dgriffin65 15:14382459c8b7 345 if(!connected)
dgriffin65 15:14382459c8b7 346 {
dgriffin65 15:14382459c8b7 347 WARN("Connection was closed by server");
dgriffin65 15:14382459c8b7 348 break;
dgriffin65 15:14382459c8b7 349 }
dgriffin65 15:14382459c8b7 350
dgriffin65 15:14382459c8b7 351 if ((res = socket.send(str + idx, len - idx)) == -1)
dgriffin65 15:14382459c8b7 352 continue;
dgriffin65 15:14382459c8b7 353
dgriffin65 15:14382459c8b7 354 idx += res;
dgriffin65 15:14382459c8b7 355
dgriffin65 15:14382459c8b7 356 if (idx == len)
dgriffin65 15:14382459c8b7 357 return len;
dgriffin65 15:14382459c8b7 358 }
dgriffin65 15:14382459c8b7 359
dgriffin65 15:14382459c8b7 360 return (idx == 0) ? -1 : idx;
dgriffin65 15:14382459c8b7 361 }
dgriffin65 15:14382459c8b7 362
dgriffin65 15:14382459c8b7 363 int Websocket::read(char * str, int len, int min_len) {
dgriffin65 15:14382459c8b7 364 int res = 0, idx = 0;
dgriffin65 15:14382459c8b7 365
dgriffin65 15:14382459c8b7 366 for (int j = 0; j < MAX_TRY_WRITE; j++) {
dgriffin65 15:14382459c8b7 367
dgriffin65 15:14382459c8b7 368 if ((res = socket.recv(str + idx, len - idx)) == -1)
dgriffin65 15:14382459c8b7 369 continue;
dgriffin65 15:14382459c8b7 370
dgriffin65 15:14382459c8b7 371 idx += res;
dgriffin65 15:14382459c8b7 372
dgriffin65 15:14382459c8b7 373 if (idx == len || (min_len != -1 && idx > min_len))
dgriffin65 15:14382459c8b7 374 return idx;
dgriffin65 15:14382459c8b7 375 }
dgriffin65 15:14382459c8b7 376
dgriffin65 15:14382459c8b7 377 return (idx == 0) ? -1 : idx;
dgriffin65 15:14382459c8b7 378 }