src/WSclient.cpp
void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {

    headerLine->trim(); // remove \r

    if(headerLine->length() > 0) {
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader] RX: %s\n", headerLine->c_str());

        if(headerLine->startsWith(WEBSOCKETS_STRING("HTTP/1."))) {
            // "HTTP/1.1 101 Switching Protocols"
            client->cCode = headerLine->substring(9, headerLine->indexOf(' ', 9)).toInt();
        } else if(headerLine->indexOf(':')) {
            String headerName = headerLine->substring(0, headerLine->indexOf(':'));
            String headerValue = headerLine->substring(headerLine->indexOf(':') + 2);

            if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Connection"))) {
                if(headerValue.equalsIgnoreCase(WEBSOCKETS_STRING("upgrade"))) {
                    client->cIsUpgrade = true;
                }
            } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Upgrade"))) {
                if(headerValue.equalsIgnoreCase(WEBSOCKETS_STRING("websocket"))) {
                    client->cIsWebsocket = true;
                }
            } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Accept"))) {
                client->cAccept = headerValue;
                client->cAccept.trim(); // see rfc6455
            } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Protocol"))) {
                client->cProtocol = headerValue;
            } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Extensions"))) {
                client->cExtensions = headerValue;
            } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Version"))) {
                client->cVersion = headerValue.toInt();
            } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Set-Cookie"))) {
                if (headerValue.indexOf(WEBSOCKETS_STRING("HttpOnly")) > -1) {
                    client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1, headerValue.indexOf(";"));
                } else { 
                    client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1); 
                }
            }
        } else {
            DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Header error (%s)\n", headerLine->c_str());
        }

        (*headerLine) = "";
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
        client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsClient::handleHeader, this, client, &(client->cHttpLine)));
#endif

    } else {
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Header read fin.\n");
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Client settings:\n");

        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cURL: %s\n", client->cUrl.c_str());
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cKey: %s\n", client->cKey.c_str());

        DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Server header:\n");
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cCode: %d\n", client->cCode);
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cIsUpgrade: %d\n", client->cIsUpgrade);
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cIsWebsocket: %d\n", client->cIsWebsocket);
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cAccept: %s\n", client->cAccept.c_str());
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cProtocol: %s\n", client->cProtocol.c_str());
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cExtensions: %s\n", client->cExtensions.c_str());
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cVersion: %d\n", client->cVersion);
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cSessionId: %s\n", client->cSessionId.c_str());

        bool ok = (client->cIsUpgrade && client->cIsWebsocket);

        if(ok) {
            switch(client->cCode) {
                case 101:  ///< Switching Protocols

                    break;
                case 200:
                    if(client->isSocketIO) {
                        break;
                    }
                case 403: ///< Forbidden
                    // todo handle login
                default:   ///< Server dont unterstand requrst
                    ok = false;
                    DEBUG_WEBSOCKETS("[WS-Client][handleHeader] serverCode is not 101 (%d)\n", client->cCode);
                    clientDisconnect(client);
                    _lastConnectionFail = millis();
                    break;
            }
        }

        if(ok) {

            if(client->cAccept.length() == 0) {
                ok = false;
            } else {
                // generate Sec-WebSocket-Accept key for check
                String sKey = acceptKey(client->cKey);
                if(sKey != client->cAccept) {
                    DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Sec-WebSocket-Accept is wrong\n");
                    ok = false;
                }
            }
        }

        if(ok) {

            DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Websocket connection init done.\n");
            headerDone(client);

            runCbEvent(WStype_CONNECTED, (uint8_t *) client->cUrl.c_str(), client->cUrl.length());

		} else if(clientIsConnected(client) && client->isSocketIO && client->cSessionId.length() > 0) {
			sendHeader(client);
		} else {
			DEBUG_WEBSOCKETS("[WS-Client][handleHeader] no Websocket connection close.\n");
			_lastConnectionFail = millis();
			if(clientIsConnected(client)) {
				write(client, "This is a webSocket client!");
			}
			clientDisconnect(client);
		}
	}
}
/**
 * handle the WebSocket header reading
 * @param client WSclient_t *  ptr to the client struct
 */
handle the WebSocket header reading
@param client WSclient_t *  ptr to the client struct
handle the WebSocket header reading @param client WSclient_t * ptr to the client struct
void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
    headerLine->trim(); 
    if(headerLine->length() > 0) {
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader] RX: %s\n", headerLine->c_str());
        if(headerLine->startsWith(WEBSOCKETS_STRING("HTTP/1."))) {
            client->cCode = headerLine->substring(9, headerLine->indexOf(' ', 9)).toInt();
        } else if(headerLine->indexOf(':')) {
            String headerName = headerLine->substring(0, headerLine->indexOf(':'));
            String headerValue = headerLine->substring(headerLine->indexOf(':') + 2);
            if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Connection"))) {
                if(headerValue.equalsIgnoreCase(WEBSOCKETS_STRING("upgrade"))) {
                    client->cIsUpgrade = true;
                }
            } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Upgrade"))) {
                if(headerValue.equalsIgnoreCase(WEBSOCKETS_STRING("websocket"))) {
                    client->cIsWebsocket = true;
                }
            } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Accept"))) {
                client->cAccept = headerValue;
                client->cAccept.trim(); 
            } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Protocol"))) {
                client->cProtocol = headerValue;
            } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Extensions"))) {
                client->cExtensions = headerValue;
            } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Version"))) {
                client->cVersion = headerValue.toInt();
            } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Set-Cookie"))) {
                if (headerValue.indexOf(WEBSOCKETS_STRING("HttpOnly")) > -1) {
                    client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1, headerValue.indexOf(";"));
                } else { 
                    client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1); 
                }
            }
        } else {
            DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Header error (%s)\n", headerLine->c_str());
        }
        (*headerLine) = "";
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
        client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsClient::handleHeader, this, client, &(client->cHttpLine)));
#endif
    } else {
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Header read fin.\n");
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Client settings:\n");
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cURL: %s\n", client->cUrl.c_str());
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cKey: %s\n", client->cKey.c_str());
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Server header:\n");
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cCode: %d\n", client->cCode);
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cIsUpgrade: %d\n", client->cIsUpgrade);
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cIsWebsocket: %d\n", client->cIsWebsocket);
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cAccept: %s\n", client->cAccept.c_str());
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cProtocol: %s\n", client->cProtocol.c_str());
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cExtensions: %s\n", client->cExtensions.c_str());
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cVersion: %d\n", client->cVersion);
        DEBUG_WEBSOCKETS("[WS-Client][handleHeader]  - cSessionId: %s\n", client->cSessionId.c_str());
        bool ok = (client->cIsUpgrade && client->cIsWebsocket);
        if(ok) {
            switch(client->cCode) {
                case 101:  
                    break;
                case 200:
                    if(client->isSocketIO) {
                        break;
                    }
                case 403: 
                default:   
                    ok = false;
                    DEBUG_WEBSOCKETS("[WS-Client][handleHeader] serverCode is not 101 (%d)\n", client->cCode);
                    clientDisconnect(client);
                    _lastConnectionFail = millis();
                    break;
            }
        }
        if(ok) {
            if(client->cAccept.length() == 0) {
                ok = false;
            } else {
                String sKey = acceptKey(client->cKey);
                if(sKey != client->cAccept) {
                    DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Sec-WebSocket-Accept is wrong\n");
                    ok = false;
                }
            }
        }
        if(ok) {
            DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Websocket connection init done.\n");
            headerDone(client);
            runCbEvent(WStype_CONNECTED, (uint8_t *) client->cUrl.c_str(), client->cUrl.length());
		} else if(clientIsConnected(client) && client->isSocketIO && client->cSessionId.length() > 0) {
			sendHeader(client);
		} else {
			DEBUG_WEBSOCKETS("[WS-Client][handleHeader] no Websocket connection close.\n");
			_lastConnectionFail = millis();
			if(clientIsConnected(client)) {
				write(client, "This is a webSocket client!");
			}
			clientDisconnect(client);
		}
	}
}
void WebSocketsClient :: handleHeader ( WSclient_t * client , String * headerLine ) { headerLine -> trim ( ) ; if ( headerLine -> length ( ) > 0 ) { DEBUG_WEBSOCKETS ( " \n " , headerLine -> c_str ( ) ) ; if ( headerLine -> startsWith ( WEBSOCKETS_STRING ( " " ) ) ) { client -> cCode = headerLine -> substring ( 9 , headerLine -> indexOf ( ' ' , 9 ) ) . toInt ( ) ; } else if ( headerLine -> indexOf ( ' ' ) ) { String headerName = headerLine -> substring ( 0 , headerLine -> indexOf ( ' ' ) ) ; String headerValue = headerLine -> substring ( headerLine -> indexOf ( ' ' ) + 2 ) ; if ( headerName . equalsIgnoreCase ( WEBSOCKETS_STRING ( " " ) ) ) { if ( headerValue . equalsIgnoreCase ( WEBSOCKETS_STRING ( " " ) ) ) { client -> cIsUpgrade = true ; } } else if ( headerName . equalsIgnoreCase ( WEBSOCKETS_STRING ( " " ) ) ) { if ( headerValue . equalsIgnoreCase ( WEBSOCKETS_STRING ( " " ) ) ) { client -> cIsWebsocket = true ; } } else if ( headerName . equalsIgnoreCase ( WEBSOCKETS_STRING ( " " ) ) ) { client -> cAccept = headerValue ; client -> cAccept . trim ( ) ; } else if ( headerName . equalsIgnoreCase ( WEBSOCKETS_STRING ( " " ) ) ) { client -> cProtocol = headerValue ; } else if ( headerName . equalsIgnoreCase ( WEBSOCKETS_STRING ( " " ) ) ) { client -> cExtensions = headerValue ; } else if ( headerName . equalsIgnoreCase ( WEBSOCKETS_STRING ( " " ) ) ) { client -> cVersion = headerValue . toInt ( ) ; } else if ( headerName . equalsIgnoreCase ( WEBSOCKETS_STRING ( " " ) ) ) { if ( headerValue . indexOf ( WEBSOCKETS_STRING ( " " ) ) > -1 ) { client -> cSessionId = headerValue . substring ( headerValue . indexOf ( ' ' ) + 1 , headerValue . indexOf ( " " ) ) ; } else { client -> cSessionId = headerValue . substring ( headerValue . indexOf ( ' ' ) + 1 ) ; } } } else { DEBUG_WEBSOCKETS ( " \n " , headerLine -> c_str ( ) ) ; } ( * headerLine ) = " " ; #if ( WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC ) client -> tcp -> readStringUntil ( ' \n ' , & ( client -> cHttpLine ) , std :: bind ( & WebSocketsClient :: handleHeader , this , client , & ( client -> cHttpLine ) ) ) ; #endif } else { DEBUG_WEBSOCKETS ( " \n " ) ; DEBUG_WEBSOCKETS ( " \n " ) ; DEBUG_WEBSOCKETS ( " \n " , client -> cUrl . c_str ( ) ) ; DEBUG_WEBSOCKETS ( " \n " , client -> cKey . c_str ( ) ) ; DEBUG_WEBSOCKETS ( " \n " ) ; DEBUG_WEBSOCKETS ( " \n " , client -> cCode ) ; DEBUG_WEBSOCKETS ( " \n " , client -> cIsUpgrade ) ; DEBUG_WEBSOCKETS ( " \n " , client -> cIsWebsocket ) ; DEBUG_WEBSOCKETS ( " \n " , client -> cAccept . c_str ( ) ) ; DEBUG_WEBSOCKETS ( " \n " , client -> cProtocol . c_str ( ) ) ; DEBUG_WEBSOCKETS ( " \n " , client -> cExtensions . c_str ( ) ) ; DEBUG_WEBSOCKETS ( " \n " , client -> cVersion ) ; DEBUG_WEBSOCKETS ( " \n " , client -> cSessionId . c_str ( ) ) ; bool ok = ( client -> cIsUpgrade && client -> cIsWebsocket ) ; if ( ok ) { switch ( client -> cCode ) { case 101 : break ; case 200 : if ( client -> isSocketIO ) { break ; } case 403 : default : ok = false ; DEBUG_WEBSOCKETS ( " \n " , client -> cCode ) ; clientDisconnect ( client ) ; _lastConnectionFail = millis ( ) ; break ; } } if ( ok ) { if ( client -> cAccept . length ( ) == 0 ) { ok = false ; } else { String sKey = acceptKey ( client -> cKey ) ; if ( sKey != client -> cAccept ) { DEBUG_WEBSOCKETS ( " \n " ) ; ok = false ; } } } if ( ok ) { DEBUG_WEBSOCKETS ( " \n " ) ; headerDone ( client ) ; runCbEvent ( WStype_CONNECTED , ( uint8_t * ) client -> cUrl . c_str ( ) , client -> cUrl . length ( ) ) ; } else if ( clientIsConnected ( client ) && client -> isSocketIO && client -> cSessionId . length ( ) > 0 ) { sendHeader ( client ) ; } else { DEBUG_WEBSOCKETS ( " \n " ) ; _lastConnectionFail = millis ( ) ; if ( clientIsConnected ( client ) ) { write ( client , " " ) ; } clientDisconnect ( client ) ; } } }
handle the WebSocket header reading
 @param client WSclient_t *  ptr to the client struct
handle the WebSocket header reading @param client WSclient_t * ptr to the client struct
// remove \r // "HTTP/1.1 101 Switching Protocols" // see rfc6455 ///< Switching Protocols ///< Forbidden // todo handle login ///< Server dont unterstand requrst // generate Sec-WebSocket-Accept key for check