#ifdef ENABLE_FEATURE_WEB_CONSOLE_WEBSOCKETS /* * Returns a bool value as an indicator to describe whether a user is allowed to initiate a websocket upgrade * based on the value of a cookie. This function expects the rawCookieHeaderValue to look like this "sessionId=|" */ bool isCookieValid(String rawCookieHeaderValue) { if(wsValidSessionId != 0) { if (rawCookieHeaderValue.indexOf("sessionId") != -1) { String sessionIdStr = rawCookieHeaderValue.substring(rawCookieHeaderValue.indexOf("sessionId=") + 10, rawCookieHeaderValue.indexOf("|")); unsigned long int sessionId = strtoul(sessionIdStr.c_str(), NULL, 10); return sessionId == wsValidSessionId; } } return false; } void clearValidSessionId() { // wsValidSessionId = millis() -> clear after timeout to somehow improve "security" if( wsValidSessionId > 0 && (millis() - wsValidSessionId) > 2000 ) wsValidSessionId = 0; } /* * The WebSocketServerHttpHeaderValFunc delegate passed to webSocket.onValidateHttpHeader */ bool validateHttpHeader(String headerName, String headerValue) { //assume a true response for any headers not handled by this validator bool valid = true; if(headerName.equalsIgnoreCase("Cookie")) { //if the header passed is the Cookie header, validate it according to the rules in 'isCookieValid' function valid = isCookieValid(headerValue); } return valid; } void startWebSocketServer() { // Start a WebSocket server //if(strlen(confWeb.http_user) > 0 && strlen(confWeb.http_pass) > 0) webSocket.setAuthorization(confWeb.http_user, confWeb.http_pass); const char * headerkeys[] = { "Cookie" }; size_t headerKeyCount = sizeof(headerkeys) / sizeof(char*); webSocket.onValidateHttpHeader(validateHttpHeader, headerkeys, headerKeyCount); webSocket.begin(); // start the websocket server webSocket.onEvent(webSocketEvent); // if there's an incomming websocket message, go to function 'webSocketEvent' //Serial.println("WebSocket server started."); sendLog("WS: WebSocket server started on Port 81", LOGLEVEL_INFO); } void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { if(length > 0) { // filter message with length=0, otherwise ESP8266 crashes char logBuf[60]; switch(type) { case WStype_DISCONNECTED: Serial.printf("[%u] Disconnected!\n", num); break; case WStype_CONNECTED: { IPAddress ip = webSocket.remoteIP(num); //Serial.printf("WS: Connected Client-[%u], %d.%d.%d.%d, URL: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); sprintf(logBuf, "WS: Client[%u] connected, %d.%d.%d.%d, URL: %s", num, ip[0], ip[1], ip[2], ip[3], payload); sendLog(logBuf, LOGLEVEL_INFO); // send message to client webSocket.sendTXT(num, "Connected\r\n"); } break; case WStype_TEXT: //Serial.printf("WS: received from Client-[%u]: %s\n", num, payload); sprintf(logBuf, "WS: received from Client[%u]: %s", num, payload); sendLog(logBuf, LOGLEVEL_INFO); char buf[31]; sprintf(buf, "%s", payload); // send received text to command handler if(strlen(buf) > 0) strlcpy(cmdPayload, buf, sizeof(cmdPayload)); cmdInQueue = true; // will be checked in next loop() run // send message to client // webSocket.sendTXT(num, "message here"); // send data to all connected clients // webSocket.broadcastTXT("message here"); break; case WStype_ERROR: break; case WStype_BIN: Serial.printf("[%u] get binary length: %u\n", num, length); hexdump(payload, length); break; default: break; // // // send message to client // // webSocket.sendBIN(num, payload, length); // break; } } } #endif