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

Dependents:   IoT_Ex BatteryModelTester BatteryModelTester

Fork of WebSocketClient by Samuel Mokrani

Committer:
defrost
Date:
Wed Aug 31 10:03:43 2016 +0000
Revision:
22:d2c00e47527c
Parent:
21:420b83755885
Child:
25:4a98a3b83b87
- Turned off debug messages

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