2015-05-22 14:19:01 +02:00
/**
* @ file WebSocketsServer . cpp
* @ date 20.05 .2015
* @ author Markus Sattler
*
* Copyright ( c ) 2015 Markus Sattler . All rights reserved .
* This file is part of the WebSockets for Arduino .
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
*
*/
# include "WebSockets.h"
# include "WebSocketsServer.h"
2016-01-14 17:28:00 +01:00
WebSocketsServer : : WebSocketsServer ( uint16_t port , String origin , String protocol ) {
2015-05-22 14:19:01 +02:00
_port = port ;
2016-01-14 17:28:00 +01:00
_origin = origin ;
_protocol = protocol ;
2018-05-10 18:55:23 +02:00
_runnning = false ;
2016-01-14 17:28:00 +01:00
2015-12-10 11:16:08 +01:00
_server = new WEBSOCKETS_NETWORK_SERVER_CLASS ( port ) ;
2015-05-22 23:02:47 +02:00
2016-01-23 16:27:02 +01:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
_server - > onClient ( [ ] ( void * s , AsyncClient * c ) {
( ( WebSocketsServer * ) s ) - > newClient ( new AsyncTCPbuffer ( c ) ) ;
} , this ) ;
# endif
2015-05-22 23:02:47 +02:00
_cbEvent = NULL ;
2016-06-08 23:04:18 +01:00
_httpHeaderValidationFunc = NULL ;
_mandatoryHttpHeaders = NULL ;
_mandatoryHttpHeaderCount = 0 ;
2017-10-06 18:30:05 +02:00
memset ( & _clients [ 0 ] , 0x00 , ( sizeof ( WSclient_t ) * WEBSOCKETS_SERVER_CLIENT_MAX ) ) ;
2015-05-22 14:19:01 +02:00
}
2015-05-22 20:35:51 +02:00
2016-01-23 16:27:02 +01:00
2015-05-22 14:19:01 +02:00
WebSocketsServer : : ~ WebSocketsServer ( ) {
2015-12-10 09:36:18 +01:00
// disconnect all clients
2018-05-10 18:55:23 +02:00
close ( ) ;
2016-01-14 17:28:00 +01:00
2016-06-08 23:04:18 +01:00
if ( _mandatoryHttpHeaders )
delete [ ] _mandatoryHttpHeaders ;
_mandatoryHttpHeaderCount = 0 ;
2015-05-22 14:19:01 +02:00
}
2015-05-22 23:02:47 +02:00
/**
2016-06-08 23:04:18 +01:00
* called to initialize the Websocket server
2015-05-22 23:02:47 +02:00
*/
2015-05-22 14:19:01 +02:00
void WebSocketsServer : : begin ( void ) {
2015-05-22 20:35:51 +02:00
WSclient_t * client ;
2015-05-22 14:19:01 +02:00
// init client storage
for ( uint8_t i = 0 ; i < WEBSOCKETS_SERVER_CLIENT_MAX ; i + + ) {
client = & _clients [ i ] ;
2015-05-22 14:40:46 +02:00
client - > num = i ;
2015-12-10 09:36:18 +01:00
client - > status = WSC_NOT_CONNECTED ;
client - > tcp = NULL ;
2017-07-30 00:54:17 +02:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
2015-12-10 09:36:18 +01:00
client - > isSSL = false ;
client - > ssl = NULL ;
# endif
2015-05-22 14:19:01 +02:00
client - > cUrl = " " ;
2015-12-10 09:36:18 +01:00
client - > cCode = 0 ;
2015-05-22 14:19:01 +02:00
client - > cKey = " " ;
client - > cProtocol = " " ;
client - > cVersion = 0 ;
client - > cIsUpgrade = false ;
client - > cIsWebsocket = false ;
2016-01-23 16:27:02 +01:00
2016-02-17 17:56:03 +01:00
client - > base64Authorization = " " ;
2016-01-23 16:27:02 +01:00
client - > cWsRXsize = 0 ;
2016-06-08 23:04:18 +01:00
2016-01-23 16:27:02 +01:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client - > cHttpLine = " " ;
# endif
2015-05-22 14:19:01 +02:00
}
2015-12-10 09:36:18 +01:00
# ifdef ESP8266
randomSeed ( RANDOM_REG32 ) ;
2017-07-30 00:54:17 +02:00
# elif defined(ESP32)
# define DR_REG_RNG_BASE 0x3ff75144
randomSeed ( READ_PERI_REG ( DR_REG_RNG_BASE ) ) ;
2015-12-10 09:36:18 +01:00
# else
// TODO find better seed
2015-05-24 15:40:47 +02:00
randomSeed ( millis ( ) ) ;
2015-12-10 09:36:18 +01:00
# endif
2015-05-24 15:40:47 +02:00
2018-05-10 18:55:23 +02:00
_runnning = true ;
2015-05-22 14:19:01 +02:00
_server - > begin ( ) ;
2015-12-10 09:36:18 +01:00
DEBUG_WEBSOCKETS ( " [WS-Server] Server Started. \n " ) ;
2015-05-22 14:19:01 +02:00
}
2018-05-10 18:55:23 +02:00
void WebSocketsServer : : close ( void ) {
_runnning = false ;
disconnect ( ) ;
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
_server - > close ( ) ;
2018-06-21 09:30:11 +02:00
# elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
2018-05-10 18:55:23 +02:00
_server - > end ( ) ;
# else
// TODO how to close server?
# endif
}
2016-01-23 18:41:45 +01:00
# if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
2015-05-23 09:20:44 +02:00
/**
* called in arduino loop
*/
2015-05-22 14:19:01 +02:00
void WebSocketsServer : : loop ( void ) {
2018-05-10 18:55:23 +02:00
if ( _runnning ) {
handleNewClients ( ) ;
handleClientData ( ) ;
}
2015-05-22 14:19:01 +02:00
}
2016-01-23 18:41:45 +01:00
# endif
2015-05-22 14:19:01 +02:00
2015-05-22 23:02:47 +02:00
/**
* set callback function
* @ param cbEvent WebSocketServerEvent
*/
void WebSocketsServer : : onEvent ( WebSocketServerEvent cbEvent ) {
2015-05-23 23:51:32 +02:00
_cbEvent = cbEvent ;
2015-05-22 23:02:47 +02:00
}
2016-06-08 23:04:18 +01:00
/*
* Sets the custom http header validator function
* @ param httpHeaderValidationFunc WebSocketServerHttpHeaderValFunc ///< pointer to the custom http header validation function
2016-06-09 19:48:38 +01:00
* @ param mandatoryHttpHeaders [ ] const char * ///< the array of named http headers considered to be mandatory / must be present in order for websocket upgrade to succeed
* @ param mandatoryHttpHeaderCount size_t ///< the number of items in the mandatoryHttpHeaders array
2016-06-08 23:04:18 +01:00
*/
void WebSocketsServer : : onValidateHttpHeader (
WebSocketServerHttpHeaderValFunc validationFunc ,
2016-06-09 19:48:38 +01:00
const char * mandatoryHttpHeaders [ ] ,
size_t mandatoryHttpHeaderCount )
2016-06-08 23:04:18 +01:00
{
_httpHeaderValidationFunc = validationFunc ;
if ( _mandatoryHttpHeaders )
delete [ ] _mandatoryHttpHeaders ;
2016-06-09 19:48:38 +01:00
_mandatoryHttpHeaderCount = mandatoryHttpHeaderCount ;
2016-06-08 23:04:18 +01:00
_mandatoryHttpHeaders = new String [ _mandatoryHttpHeaderCount ] ;
for ( size_t i = 0 ; i < _mandatoryHttpHeaderCount ; i + + ) {
_mandatoryHttpHeaders [ i ] = mandatoryHttpHeaders [ i ] ;
}
}
/*
2015-05-22 23:02:47 +02:00
* send text data to client
* @ param num uint8_t client id
* @ param payload uint8_t *
* @ param length size_t
2015-10-11 10:11:32 +02:00
* @ param headerToPayload bool ( see sendFrame for more details )
2016-02-20 12:27:19 +01:00
* @ return true if ok
2015-05-22 23:02:47 +02:00
*/
2016-02-20 12:27:19 +01:00
bool WebSocketsServer : : sendTXT ( uint8_t num , uint8_t * payload , size_t length , bool headerToPayload ) {
2015-05-22 23:02:47 +02:00
if ( num > = WEBSOCKETS_SERVER_CLIENT_MAX ) {
2016-02-20 12:27:19 +01:00
return false ;
2015-05-22 23:02:47 +02:00
}
create overloaded functions for send and broadcast for easy usage
void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, char * payload, size_t length = 0);
void sendTXT(uint8_t num, const char * payload, size_t length = 0);
void sendTXT(uint8_t num, String payload);
void broadcastTXT(uint8_t * payload, size_t length = 0);
void broadcastTXT(const uint8_t * payload, size_t length = 0);
void broadcastTXT(char * payload, size_t length = 0);
void broadcastTXT(const char * payload, size_t length = 0);
void broadcastTXT(String payload);
void sendBIN(uint8_t num, uint8_t * payload, size_t length);
void sendBIN(uint8_t num, const uint8_t * payload, size_t length);
void broadcastBIN(uint8_t * payload, size_t length);
void broadcastBIN(const uint8_t * payload, size_t length);
send URL as payload on WStype_CONNECTED event
move Sec-WebSocket-Accept generation in function
2015-05-23 09:02:59 +02:00
if ( length = = 0 ) {
length = strlen ( ( const char * ) payload ) ;
}
2015-05-22 23:02:47 +02:00
WSclient_t * client = & _clients [ num ] ;
if ( clientIsConnected ( client ) ) {
2018-09-21 23:58:48 +05:30
return sendFrame ( client , WSop_text , payload , length , true , headerToPayload ) ;
2015-05-22 23:02:47 +02:00
}
2016-02-20 12:27:19 +01:00
return false ;
2015-05-22 23:02:47 +02:00
}
2016-02-20 12:27:19 +01:00
bool WebSocketsServer : : sendTXT ( uint8_t num , const uint8_t * payload , size_t length ) {
return sendTXT ( num , ( uint8_t * ) payload , length ) ;
create overloaded functions for send and broadcast for easy usage
void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, char * payload, size_t length = 0);
void sendTXT(uint8_t num, const char * payload, size_t length = 0);
void sendTXT(uint8_t num, String payload);
void broadcastTXT(uint8_t * payload, size_t length = 0);
void broadcastTXT(const uint8_t * payload, size_t length = 0);
void broadcastTXT(char * payload, size_t length = 0);
void broadcastTXT(const char * payload, size_t length = 0);
void broadcastTXT(String payload);
void sendBIN(uint8_t num, uint8_t * payload, size_t length);
void sendBIN(uint8_t num, const uint8_t * payload, size_t length);
void broadcastBIN(uint8_t * payload, size_t length);
void broadcastBIN(const uint8_t * payload, size_t length);
send URL as payload on WStype_CONNECTED event
move Sec-WebSocket-Accept generation in function
2015-05-23 09:02:59 +02:00
}
2016-02-20 12:27:19 +01:00
bool WebSocketsServer : : sendTXT ( uint8_t num , char * payload , size_t length , bool headerToPayload ) {
return sendTXT ( num , ( uint8_t * ) payload , length , headerToPayload ) ;
create overloaded functions for send and broadcast for easy usage
void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, char * payload, size_t length = 0);
void sendTXT(uint8_t num, const char * payload, size_t length = 0);
void sendTXT(uint8_t num, String payload);
void broadcastTXT(uint8_t * payload, size_t length = 0);
void broadcastTXT(const uint8_t * payload, size_t length = 0);
void broadcastTXT(char * payload, size_t length = 0);
void broadcastTXT(const char * payload, size_t length = 0);
void broadcastTXT(String payload);
void sendBIN(uint8_t num, uint8_t * payload, size_t length);
void sendBIN(uint8_t num, const uint8_t * payload, size_t length);
void broadcastBIN(uint8_t * payload, size_t length);
void broadcastBIN(const uint8_t * payload, size_t length);
send URL as payload on WStype_CONNECTED event
move Sec-WebSocket-Accept generation in function
2015-05-23 09:02:59 +02:00
}
2016-02-20 12:27:19 +01:00
bool WebSocketsServer : : sendTXT ( uint8_t num , const char * payload , size_t length ) {
return sendTXT ( num , ( uint8_t * ) payload , length ) ;
create overloaded functions for send and broadcast for easy usage
void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, char * payload, size_t length = 0);
void sendTXT(uint8_t num, const char * payload, size_t length = 0);
void sendTXT(uint8_t num, String payload);
void broadcastTXT(uint8_t * payload, size_t length = 0);
void broadcastTXT(const uint8_t * payload, size_t length = 0);
void broadcastTXT(char * payload, size_t length = 0);
void broadcastTXT(const char * payload, size_t length = 0);
void broadcastTXT(String payload);
void sendBIN(uint8_t num, uint8_t * payload, size_t length);
void sendBIN(uint8_t num, const uint8_t * payload, size_t length);
void broadcastBIN(uint8_t * payload, size_t length);
void broadcastBIN(const uint8_t * payload, size_t length);
send URL as payload on WStype_CONNECTED event
move Sec-WebSocket-Accept generation in function
2015-05-23 09:02:59 +02:00
}
2016-02-20 12:27:19 +01:00
bool WebSocketsServer : : sendTXT ( uint8_t num , String & payload ) {
return sendTXT ( num , ( uint8_t * ) payload . c_str ( ) , payload . length ( ) ) ;
2015-05-22 23:02:47 +02:00
}
/**
* send text data to client all
* @ param payload uint8_t *
* @ param length size_t
2015-10-11 10:11:32 +02:00
* @ param headerToPayload bool ( see sendFrame for more details )
2016-02-20 12:27:19 +01:00
* @ return true if ok
2015-05-22 23:02:47 +02:00
*/
2016-02-20 12:27:19 +01:00
bool WebSocketsServer : : broadcastTXT ( uint8_t * payload , size_t length , bool headerToPayload ) {
2015-05-22 23:02:47 +02:00
WSclient_t * client ;
2016-02-20 12:27:19 +01:00
bool ret = true ;
create overloaded functions for send and broadcast for easy usage
void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, char * payload, size_t length = 0);
void sendTXT(uint8_t num, const char * payload, size_t length = 0);
void sendTXT(uint8_t num, String payload);
void broadcastTXT(uint8_t * payload, size_t length = 0);
void broadcastTXT(const uint8_t * payload, size_t length = 0);
void broadcastTXT(char * payload, size_t length = 0);
void broadcastTXT(const char * payload, size_t length = 0);
void broadcastTXT(String payload);
void sendBIN(uint8_t num, uint8_t * payload, size_t length);
void sendBIN(uint8_t num, const uint8_t * payload, size_t length);
void broadcastBIN(uint8_t * payload, size_t length);
void broadcastBIN(const uint8_t * payload, size_t length);
send URL as payload on WStype_CONNECTED event
move Sec-WebSocket-Accept generation in function
2015-05-23 09:02:59 +02:00
if ( length = = 0 ) {
length = strlen ( ( const char * ) payload ) ;
}
2015-05-23 23:51:32 +02:00
2015-05-22 23:02:47 +02:00
for ( uint8_t i = 0 ; i < WEBSOCKETS_SERVER_CLIENT_MAX ; i + + ) {
client = & _clients [ i ] ;
if ( clientIsConnected ( client ) ) {
2018-09-21 23:58:48 +05:30
if ( ! sendFrame ( client , WSop_text , payload , length , true , headerToPayload ) ) {
2016-02-20 12:27:19 +01:00
ret = false ;
}
2015-05-22 23:02:47 +02:00
}
2016-01-23 16:27:02 +01:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
2015-05-23 23:51:32 +02:00
delay ( 0 ) ;
2015-05-24 15:40:47 +02:00
# endif
2015-05-22 23:02:47 +02:00
}
2016-02-20 12:27:19 +01:00
return ret ;
2015-05-22 23:02:47 +02:00
}
2016-02-20 12:27:19 +01:00
bool WebSocketsServer : : broadcastTXT ( const uint8_t * payload , size_t length ) {
return broadcastTXT ( ( uint8_t * ) payload , length ) ;
create overloaded functions for send and broadcast for easy usage
void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, char * payload, size_t length = 0);
void sendTXT(uint8_t num, const char * payload, size_t length = 0);
void sendTXT(uint8_t num, String payload);
void broadcastTXT(uint8_t * payload, size_t length = 0);
void broadcastTXT(const uint8_t * payload, size_t length = 0);
void broadcastTXT(char * payload, size_t length = 0);
void broadcastTXT(const char * payload, size_t length = 0);
void broadcastTXT(String payload);
void sendBIN(uint8_t num, uint8_t * payload, size_t length);
void sendBIN(uint8_t num, const uint8_t * payload, size_t length);
void broadcastBIN(uint8_t * payload, size_t length);
void broadcastBIN(const uint8_t * payload, size_t length);
send URL as payload on WStype_CONNECTED event
move Sec-WebSocket-Accept generation in function
2015-05-23 09:02:59 +02:00
}
2016-02-20 12:27:19 +01:00
bool WebSocketsServer : : broadcastTXT ( char * payload , size_t length , bool headerToPayload ) {
return broadcastTXT ( ( uint8_t * ) payload , length , headerToPayload ) ;
create overloaded functions for send and broadcast for easy usage
void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, char * payload, size_t length = 0);
void sendTXT(uint8_t num, const char * payload, size_t length = 0);
void sendTXT(uint8_t num, String payload);
void broadcastTXT(uint8_t * payload, size_t length = 0);
void broadcastTXT(const uint8_t * payload, size_t length = 0);
void broadcastTXT(char * payload, size_t length = 0);
void broadcastTXT(const char * payload, size_t length = 0);
void broadcastTXT(String payload);
void sendBIN(uint8_t num, uint8_t * payload, size_t length);
void sendBIN(uint8_t num, const uint8_t * payload, size_t length);
void broadcastBIN(uint8_t * payload, size_t length);
void broadcastBIN(const uint8_t * payload, size_t length);
send URL as payload on WStype_CONNECTED event
move Sec-WebSocket-Accept generation in function
2015-05-23 09:02:59 +02:00
}
2016-02-20 12:27:19 +01:00
bool WebSocketsServer : : broadcastTXT ( const char * payload , size_t length ) {
return broadcastTXT ( ( uint8_t * ) payload , length ) ;
create overloaded functions for send and broadcast for easy usage
void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, char * payload, size_t length = 0);
void sendTXT(uint8_t num, const char * payload, size_t length = 0);
void sendTXT(uint8_t num, String payload);
void broadcastTXT(uint8_t * payload, size_t length = 0);
void broadcastTXT(const uint8_t * payload, size_t length = 0);
void broadcastTXT(char * payload, size_t length = 0);
void broadcastTXT(const char * payload, size_t length = 0);
void broadcastTXT(String payload);
void sendBIN(uint8_t num, uint8_t * payload, size_t length);
void sendBIN(uint8_t num, const uint8_t * payload, size_t length);
void broadcastBIN(uint8_t * payload, size_t length);
void broadcastBIN(const uint8_t * payload, size_t length);
send URL as payload on WStype_CONNECTED event
move Sec-WebSocket-Accept generation in function
2015-05-23 09:02:59 +02:00
}
2016-02-20 12:27:19 +01:00
bool WebSocketsServer : : broadcastTXT ( String & payload ) {
return broadcastTXT ( ( uint8_t * ) payload . c_str ( ) , payload . length ( ) ) ;
2015-05-22 23:02:47 +02:00
}
/**
* send binary data to client
* @ param num uint8_t client id
* @ param payload uint8_t *
* @ param length size_t
2015-10-11 10:11:32 +02:00
* @ param headerToPayload bool ( see sendFrame for more details )
2016-02-20 12:27:19 +01:00
* @ return true if ok
2015-05-22 23:02:47 +02:00
*/
2016-02-20 12:27:19 +01:00
bool WebSocketsServer : : sendBIN ( uint8_t num , uint8_t * payload , size_t length , bool headerToPayload ) {
2015-05-22 23:02:47 +02:00
if ( num > = WEBSOCKETS_SERVER_CLIENT_MAX ) {
2016-02-20 12:27:19 +01:00
return false ;
2015-05-22 23:02:47 +02:00
}
WSclient_t * client = & _clients [ num ] ;
if ( clientIsConnected ( client ) ) {
2018-09-21 23:58:48 +05:30
return sendFrame ( client , WSop_binary , payload , length , true , headerToPayload ) ;
2015-05-22 23:02:47 +02:00
}
2016-02-20 12:27:19 +01:00
return false ;
2015-05-22 23:02:47 +02:00
}
2016-02-20 12:27:19 +01:00
bool WebSocketsServer : : sendBIN ( uint8_t num , const uint8_t * payload , size_t length ) {
return sendBIN ( num , ( uint8_t * ) payload , length ) ;
create overloaded functions for send and broadcast for easy usage
void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, char * payload, size_t length = 0);
void sendTXT(uint8_t num, const char * payload, size_t length = 0);
void sendTXT(uint8_t num, String payload);
void broadcastTXT(uint8_t * payload, size_t length = 0);
void broadcastTXT(const uint8_t * payload, size_t length = 0);
void broadcastTXT(char * payload, size_t length = 0);
void broadcastTXT(const char * payload, size_t length = 0);
void broadcastTXT(String payload);
void sendBIN(uint8_t num, uint8_t * payload, size_t length);
void sendBIN(uint8_t num, const uint8_t * payload, size_t length);
void broadcastBIN(uint8_t * payload, size_t length);
void broadcastBIN(const uint8_t * payload, size_t length);
send URL as payload on WStype_CONNECTED event
move Sec-WebSocket-Accept generation in function
2015-05-23 09:02:59 +02:00
}
2015-05-22 23:02:47 +02:00
/**
* send binary data to client all
* @ param payload uint8_t *
* @ param length size_t
2015-10-11 10:11:32 +02:00
* @ param headerToPayload bool ( see sendFrame for more details )
2016-02-20 12:27:19 +01:00
* @ return true if ok
2015-05-22 23:02:47 +02:00
*/
2016-02-20 12:27:19 +01:00
bool WebSocketsServer : : broadcastBIN ( uint8_t * payload , size_t length , bool headerToPayload ) {
2015-05-22 23:02:47 +02:00
WSclient_t * client ;
2016-02-20 12:27:19 +01:00
bool ret = true ;
2015-05-22 23:02:47 +02:00
for ( uint8_t i = 0 ; i < WEBSOCKETS_SERVER_CLIENT_MAX ; i + + ) {
client = & _clients [ i ] ;
if ( clientIsConnected ( client ) ) {
2018-09-21 23:58:48 +05:30
if ( ! sendFrame ( client , WSop_binary , payload , length , true , headerToPayload ) ) {
2016-02-20 12:27:19 +01:00
ret = false ;
}
2015-05-22 23:02:47 +02:00
}
2016-01-23 16:27:02 +01:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
2015-05-23 23:51:32 +02:00
delay ( 0 ) ;
2015-05-24 15:40:47 +02:00
# endif
2015-05-22 23:02:47 +02:00
}
2016-02-20 12:27:19 +01:00
return ret ;
2015-05-22 23:02:47 +02:00
}
2016-02-20 12:27:19 +01:00
bool WebSocketsServer : : broadcastBIN ( const uint8_t * payload , size_t length ) {
return broadcastBIN ( ( uint8_t * ) payload , length ) ;
create overloaded functions for send and broadcast for easy usage
void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, char * payload, size_t length = 0);
void sendTXT(uint8_t num, const char * payload, size_t length = 0);
void sendTXT(uint8_t num, String payload);
void broadcastTXT(uint8_t * payload, size_t length = 0);
void broadcastTXT(const uint8_t * payload, size_t length = 0);
void broadcastTXT(char * payload, size_t length = 0);
void broadcastTXT(const char * payload, size_t length = 0);
void broadcastTXT(String payload);
void sendBIN(uint8_t num, uint8_t * payload, size_t length);
void sendBIN(uint8_t num, const uint8_t * payload, size_t length);
void broadcastBIN(uint8_t * payload, size_t length);
void broadcastBIN(const uint8_t * payload, size_t length);
send URL as payload on WStype_CONNECTED event
move Sec-WebSocket-Accept generation in function
2015-05-23 09:02:59 +02:00
}
2016-10-22 19:47:44 +02:00
/**
* sends a WS ping to Client
* @ param num uint8_t client id
* @ param payload uint8_t *
* @ param length size_t
* @ return true if ping is send out
*/
bool WebSocketsServer : : sendPing ( uint8_t num , uint8_t * payload , size_t length ) {
if ( num > = WEBSOCKETS_SERVER_CLIENT_MAX ) {
return false ;
}
WSclient_t * client = & _clients [ num ] ;
if ( clientIsConnected ( client ) ) {
return sendFrame ( client , WSop_ping , payload , length ) ;
}
return false ;
}
bool WebSocketsServer : : sendPing ( uint8_t num , String & payload ) {
return sendPing ( num , ( uint8_t * ) payload . c_str ( ) , payload . length ( ) ) ;
}
/**
* sends a WS ping to all Client
* @ param payload uint8_t *
* @ param length size_t
* @ return true if ping is send out
*/
bool WebSocketsServer : : broadcastPing ( uint8_t * payload , size_t length ) {
WSclient_t * client ;
bool ret = true ;
for ( uint8_t i = 0 ; i < WEBSOCKETS_SERVER_CLIENT_MAX ; i + + ) {
client = & _clients [ i ] ;
if ( clientIsConnected ( client ) ) {
if ( ! sendFrame ( client , WSop_ping , payload , length ) ) {
ret = false ;
}
}
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
delay ( 0 ) ;
# endif
}
return ret ;
}
bool WebSocketsServer : : broadcastPing ( String & payload ) {
return broadcastPing ( ( uint8_t * ) payload . c_str ( ) , payload . length ( ) ) ;
}
2015-05-23 09:20:44 +02:00
/**
* disconnect all clients
*/
void WebSocketsServer : : disconnect ( void ) {
WSclient_t * client ;
for ( uint8_t i = 0 ; i < WEBSOCKETS_SERVER_CLIENT_MAX ; i + + ) {
client = & _clients [ i ] ;
if ( clientIsConnected ( client ) ) {
WebSockets : : clientDisconnect ( client , 1000 ) ;
}
}
}
/**
* disconnect one client
2015-05-23 09:47:39 +02:00
* @ param num uint8_t client id
2015-05-23 09:20:44 +02:00
*/
void WebSocketsServer : : disconnect ( uint8_t num ) {
if ( num > = WEBSOCKETS_SERVER_CLIENT_MAX ) {
return ;
}
WSclient_t * client = & _clients [ num ] ;
if ( clientIsConnected ( client ) ) {
WebSockets : : clientDisconnect ( client , 1000 ) ;
}
}
2016-02-17 17:56:03 +01:00
2016-06-08 23:04:18 +01:00
/*
* set the Authorization for the http request
2016-02-17 17:56:03 +01:00
* @ param user const char *
* @ param password const char *
*/
void WebSocketsServer : : setAuthorization ( const char * user , const char * password ) {
if ( user & & password ) {
String auth = user ;
auth + = " : " ;
auth + = password ;
_base64Authorization = base64_encode ( ( uint8_t * ) auth . c_str ( ) , auth . length ( ) ) ;
}
}
/**
* set the Authorizatio for the http request
* @ param auth const char * base64
*/
void WebSocketsServer : : setAuthorization ( const char * auth ) {
if ( auth ) {
_base64Authorization = auth ;
}
}
2018-05-10 20:42:03 +02:00
/**
* count the connected clients ( optional ping them )
* @ param ping bool ping the connected clients
*/
int WebSocketsServer : : connectedClients ( bool ping ) {
WSclient_t * client ;
int count = 0 ;
for ( uint8_t i = 0 ; i < WEBSOCKETS_SERVER_CLIENT_MAX ; i + + ) {
client = & _clients [ i ] ;
if ( client - > status = = WSC_CONNECTED ) {
if ( ping ! = true | | sendPing ( i ) ) {
count + + ;
}
}
}
return count ;
}
2017-07-30 00:54:17 +02:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
2015-05-23 09:47:39 +02:00
/**
* get an IP for a client
* @ param num uint8_t client id
* @ return IPAddress
*/
IPAddress WebSocketsServer : : remoteIP ( uint8_t num ) {
if ( num < WEBSOCKETS_SERVER_CLIENT_MAX ) {
WSclient_t * client = & _clients [ num ] ;
if ( clientIsConnected ( client ) ) {
2015-12-10 09:36:18 +01:00
return client - > tcp - > remoteIP ( ) ;
2015-05-23 09:47:39 +02:00
}
}
return IPAddress ( ) ;
}
2015-12-10 11:16:08 +01:00
# endif
2015-05-23 09:47:39 +02:00
2015-05-22 14:19:01 +02:00
//#################################################################################
//#################################################################################
//#################################################################################
2016-01-23 16:27:02 +01:00
/**
* handle new client connection
* @ param client
*/
bool WebSocketsServer : : newClient ( WEBSOCKETS_NETWORK_CLASS * TCPclient ) {
WSclient_t * client ;
// search free list entry for client
for ( uint8_t i = 0 ; i < WEBSOCKETS_SERVER_CLIENT_MAX ; i + + ) {
client = & _clients [ i ] ;
// state is not connected or tcp connection is lost
if ( ! clientIsConnected ( client ) ) {
2016-01-23 18:34:30 +01:00
2016-01-23 16:27:02 +01:00
client - > tcp = TCPclient ;
2017-07-30 00:54:17 +02:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
2016-01-23 16:27:02 +01:00
client - > isSSL = false ;
client - > tcp - > setNoDelay ( true ) ;
# endif
# if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
// set Timeout for readBytesUntil and readStringUntil
client - > tcp - > setTimeout ( WEBSOCKETS_TCP_TIMEOUT ) ;
# endif
client - > status = WSC_HEADER ;
2017-07-30 00:54:17 +02:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
2016-01-23 16:27:02 +01:00
IPAddress ip = client - > tcp - > remoteIP ( ) ;
DEBUG_WEBSOCKETS ( " [WS-Server][%d] new client from %d.%d.%d.%d \n " , client - > num , ip [ 0 ] , ip [ 1 ] , ip [ 2 ] , ip [ 3 ] ) ;
# else
DEBUG_WEBSOCKETS ( " [WS-Server][%d] new client \n " , client - > num ) ;
# endif
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
2016-01-23 18:34:30 +01:00
client - > tcp - > onDisconnect ( std : : bind ( [ ] ( WebSocketsServer * server , AsyncTCPbuffer * obj , WSclient_t * client ) - > bool {
DEBUG_WEBSOCKETS ( " [WS-Server][%d] Disconnect client \n " , client - > num ) ;
AsyncTCPbuffer * * sl = & server - > _clients [ client - > num ] . tcp ;
if ( * sl = = obj ) {
client - > status = WSC_NOT_CONNECTED ;
* sl = NULL ;
}
return true ;
} , this , std : : placeholders : : _1 , client ) ) ;
2016-01-23 16:27:02 +01:00
client - > tcp - > readStringUntil ( ' \n ' , & ( client - > cHttpLine ) , std : : bind ( & WebSocketsServer : : handleHeader , this , client , & ( client - > cHttpLine ) ) ) ;
# endif
return true ;
break ;
}
}
return false ;
}
2015-05-22 23:02:47 +02:00
/**
*
* @ param client WSclient_t * ptr to the client struct
* @ param opcode WSopcode_t
* @ param payload uint8_t *
2017-03-06 15:07:20 -05:00
* @ param length size_t
2015-05-22 23:02:47 +02:00
*/
2017-03-06 15:07:20 -05:00
void WebSocketsServer : : messageReceived ( WSclient_t * client , WSopcode_t opcode , uint8_t * payload , size_t length , bool fin ) {
2015-05-22 23:02:47 +02:00
WStype_t type = WStype_ERROR ;
switch ( opcode ) {
case WSop_text :
2017-02-22 14:29:26 +01:00
type = fin ? WStype_TEXT : WStype_FRAGMENT_TEXT_START ;
2015-05-22 23:02:47 +02:00
break ;
case WSop_binary :
2017-02-22 14:29:26 +01:00
type = fin ? WStype_BIN : WStype_FRAGMENT_BIN_START ;
break ;
case WSop_continuation :
type = fin ? WStype_FRAGMENT_FIN : WStype_FRAGMENT ;
2015-05-22 23:02:47 +02:00
break ;
2018-05-12 11:39:59 +02:00
case WSop_close :
case WSop_ping :
case WSop_pong :
default :
break ;
2015-05-22 23:02:47 +02:00
}
2017-03-06 15:07:20 -05:00
runCbEvent ( client - > num , type , payload , length ) ;
2015-10-31 11:37:07 +01:00
2015-05-22 23:02:47 +02:00
}
2015-05-22 14:19:01 +02:00
/**
* Disconnect an client
2015-05-22 23:02:47 +02:00
* @ param client WSclient_t * ptr to the client struct
2015-05-22 14:19:01 +02:00
*/
2015-05-22 20:35:51 +02:00
void WebSocketsServer : : clientDisconnect ( WSclient_t * client ) {
2015-05-22 14:19:01 +02:00
2015-12-10 09:36:18 +01:00
2017-07-30 00:54:17 +02:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
2015-12-10 09:36:18 +01:00
if ( client - > isSSL & & client - > ssl ) {
if ( client - > ssl - > connected ( ) ) {
client - > ssl - > flush ( ) ;
client - > ssl - > stop ( ) ;
}
delete client - > ssl ;
client - > ssl = NULL ;
client - > tcp = NULL ;
}
# endif
2015-05-22 14:19:01 +02:00
if ( client - > tcp ) {
2015-12-10 09:36:18 +01:00
if ( client - > tcp - > connected ( ) ) {
2016-01-23 16:27:02 +01:00
# if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
2015-12-10 09:36:18 +01:00
client - > tcp - > flush ( ) ;
2016-01-23 16:27:02 +01:00
# endif
2015-12-10 09:36:18 +01:00
client - > tcp - > stop ( ) ;
}
2016-01-23 18:34:30 +01:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client - > status = WSC_NOT_CONNECTED ;
# else
2015-12-10 09:36:18 +01:00
delete client - > tcp ;
2016-01-23 18:34:30 +01:00
# endif
2015-12-10 09:36:18 +01:00
client - > tcp = NULL ;
2015-05-22 14:19:01 +02:00
}
2015-05-22 14:40:46 +02:00
client - > cUrl = " " ;
client - > cKey = " " ;
client - > cProtocol = " " ;
client - > cVersion = 0 ;
client - > cIsUpgrade = false ;
client - > cIsWebsocket = false ;
2016-01-23 16:27:02 +01:00
client - > cWsRXsize = 0 ;
2016-06-08 23:04:18 +01:00
2016-01-23 16:27:02 +01:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client - > cHttpLine = " " ;
# endif
2015-05-22 14:19:01 +02:00
client - > status = WSC_NOT_CONNECTED ;
2015-05-22 14:40:46 +02:00
DEBUG_WEBSOCKETS ( " [WS-Server][%d] client disconnected. \n " , client - > num ) ;
2015-05-22 14:19:01 +02:00
2015-10-31 11:37:07 +01:00
runCbEvent ( client - > num , WStype_DISCONNECTED , NULL , 0 ) ;
2015-05-22 14:19:01 +02:00
}
/**
* get client state
2015-05-22 23:02:47 +02:00
* @ param client WSclient_t * ptr to the client struct
2016-06-08 23:04:18 +01:00
* @ return true = connected
2015-05-22 14:19:01 +02:00
*/
2015-05-22 20:35:51 +02:00
bool WebSocketsServer : : clientIsConnected ( WSclient_t * client ) {
2015-05-22 14:19:01 +02:00
2015-12-10 09:36:18 +01:00
if ( ! client - > tcp ) {
return false ;
}
if ( client - > tcp - > connected ( ) ) {
2015-12-05 11:43:03 +01:00
if ( client - > status ! = WSC_NOT_CONNECTED ) {
return true ;
}
} else {
// client lost
if ( client - > status ! = WSC_NOT_CONNECTED ) {
DEBUG_WEBSOCKETS ( " [WS-Server][%d] client connection lost. \n " , client - > num ) ;
// do cleanup
clientDisconnect ( client ) ;
}
2015-05-22 14:19:01 +02:00
}
2015-12-10 09:36:18 +01:00
if ( client - > tcp ) {
// do cleanup
2016-01-23 18:34:30 +01:00
DEBUG_WEBSOCKETS ( " [WS-Server][%d] client list cleanup. \n " , client - > num ) ;
2015-12-10 09:36:18 +01:00
clientDisconnect ( client ) ;
}
2015-05-22 14:19:01 +02:00
return false ;
}
2016-01-23 16:27:02 +01:00
# if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
2015-05-22 14:19:01 +02:00
/**
2016-06-08 23:04:18 +01:00
* Handle incoming Connection Request
2015-05-22 14:19:01 +02:00
*/
void WebSocketsServer : : handleNewClients ( void ) {
2016-01-23 16:27:02 +01:00
2017-09-03 09:55:15 +02:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
2015-05-22 14:19:01 +02:00
while ( _server - > hasClient ( ) ) {
2015-12-10 11:16:08 +01:00
# endif
2015-05-22 14:19:01 +02:00
bool ok = false ;
2017-07-30 00:54:17 +02:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
2016-01-23 16:27:02 +01:00
// store new connection
WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS ( _server - > available ( ) ) ;
2015-12-10 11:16:08 +01:00
# else
2016-01-23 16:27:02 +01:00
WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS ( _server - > available ( ) ) ;
2015-12-10 11:16:08 +01:00
# endif
2015-12-10 09:36:18 +01:00
2016-01-23 16:27:02 +01:00
if ( ! tcpClient ) {
DEBUG_WEBSOCKETS ( " [WS-Client] creating Network class failed! " ) ;
return ;
2015-05-22 14:19:01 +02:00
}
2016-01-23 16:27:02 +01:00
ok = newClient ( tcpClient ) ;
2015-05-22 14:19:01 +02:00
if ( ! ok ) {
// no free space to handle client
2017-07-30 00:54:17 +02:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
2016-01-23 16:27:02 +01:00
IPAddress ip = tcpClient - > remoteIP ( ) ;
2015-05-22 14:19:01 +02:00
DEBUG_WEBSOCKETS ( " [WS-Server] no free space new client from %d.%d.%d.%d \n " , ip [ 0 ] , ip [ 1 ] , ip [ 2 ] , ip [ 3 ] ) ;
2015-12-10 11:16:08 +01:00
# else
DEBUG_WEBSOCKETS ( " [WS-Server] no free space new client \n " ) ;
# endif
2016-01-23 16:27:02 +01:00
tcpClient - > stop ( ) ;
2015-05-22 14:19:01 +02:00
}
2017-07-30 00:54:17 +02:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
2016-01-23 16:27:02 +01:00
delay ( 0 ) ;
2015-05-22 14:19:01 +02:00
}
2015-12-10 11:16:08 +01:00
# endif
2016-01-23 16:27:02 +01:00
2015-05-22 14:19:01 +02:00
}
2016-01-23 16:27:02 +01:00
2015-05-22 14:19:01 +02:00
/**
* Handel incomming data from Client
*/
void WebSocketsServer : : handleClientData ( void ) {
2015-05-22 20:35:51 +02:00
WSclient_t * client ;
2015-05-22 14:19:01 +02:00
for ( uint8_t i = 0 ; i < WEBSOCKETS_SERVER_CLIENT_MAX ; i + + ) {
2015-05-22 14:40:46 +02:00
client = & _clients [ i ] ;
if ( clientIsConnected ( client ) ) {
2015-12-10 09:36:18 +01:00
int len = client - > tcp - > available ( ) ;
2015-05-22 14:19:01 +02:00
if ( len > 0 ) {
2016-01-23 16:27:02 +01:00
//DEBUG_WEBSOCKETS("[WS-Server][%d][handleClientData] len: %d\n", client->num, len);
2015-05-22 14:19:01 +02:00
switch ( client - > status ) {
case WSC_HEADER :
2016-01-23 16:27:02 +01:00
{
String headerLine = client - > tcp - > readStringUntil ( ' \n ' ) ;
handleHeader ( client , & headerLine ) ;
}
2015-05-22 14:19:01 +02:00
break ;
case WSC_CONNECTED :
2015-05-22 20:35:51 +02:00
WebSockets : : handleWebsocket ( client ) ;
2015-05-22 14:19:01 +02:00
break ;
default :
create overloaded functions for send and broadcast for easy usage
void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, char * payload, size_t length = 0);
void sendTXT(uint8_t num, const char * payload, size_t length = 0);
void sendTXT(uint8_t num, String payload);
void broadcastTXT(uint8_t * payload, size_t length = 0);
void broadcastTXT(const uint8_t * payload, size_t length = 0);
void broadcastTXT(char * payload, size_t length = 0);
void broadcastTXT(const char * payload, size_t length = 0);
void broadcastTXT(String payload);
void sendBIN(uint8_t num, uint8_t * payload, size_t length);
void sendBIN(uint8_t num, const uint8_t * payload, size_t length);
void broadcastBIN(uint8_t * payload, size_t length);
void broadcastBIN(const uint8_t * payload, size_t length);
send URL as payload on WStype_CONNECTED event
move Sec-WebSocket-Accept generation in function
2015-05-23 09:02:59 +02:00
WebSockets : : clientDisconnect ( client , 1002 ) ;
2015-05-22 14:19:01 +02:00
break ;
}
}
}
2016-01-23 16:27:02 +01:00
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
2015-05-22 14:19:01 +02:00
delay ( 0 ) ;
2015-05-24 15:40:47 +02:00
# endif
2015-05-22 14:19:01 +02:00
}
}
2016-01-23 16:27:02 +01:00
# endif
2016-06-08 23:04:18 +01:00
/*
* returns an indicator whether the given named header exists in the configured _mandatoryHttpHeaders collection
* @ param headerName String ///< the name of the header being checked
*/
bool WebSocketsServer : : hasMandatoryHeader ( String headerName ) {
for ( size_t i = 0 ; i < _mandatoryHttpHeaderCount ; i + + ) {
if ( _mandatoryHttpHeaders [ i ] . equalsIgnoreCase ( headerName ) )
return true ;
}
return false ;
}
2015-05-22 14:19:01 +02:00
2017-02-22 15:30:58 +01:00
2015-05-22 14:19:01 +02:00
/**
2016-06-08 23:04:18 +01:00
* handles http header reading for WebSocket upgrade
* @ param client WSclient_t * ///< pointer to the client struct
* @ param headerLine String ///< the header being read / processed
2015-05-22 14:19:01 +02:00
*/
2016-01-23 16:27:02 +01:00
void WebSocketsServer : : handleHeader ( WSclient_t * client , String * headerLine ) {
2015-05-22 14:19:01 +02:00
2017-02-22 15:30:58 +01:00
static const char * NEW_LINE = " \r \n " ;
2018-05-12 11:27:03 +02:00
headerLine - > trim ( ) ; // remove \r
2015-05-22 14:19:01 +02:00
2018-05-12 11:27:03 +02:00
if ( headerLine - > length ( ) > 0 ) {
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] RX: %s \n " , client - > num , headerLine - > c_str ( ) ) ;
2015-05-22 14:19:01 +02:00
2018-05-12 11:27:03 +02:00
// websocket requests always start with GET see rfc6455
if ( headerLine - > startsWith ( " GET " ) ) {
2016-06-08 23:04:18 +01:00
2018-05-12 11:27:03 +02:00
// cut URL out
client - > cUrl = headerLine - > substring ( 4 , headerLine - > indexOf ( ' ' , 4 ) ) ;
2016-06-08 23:04:18 +01:00
2018-05-12 11:27:03 +02:00
//reset non-websocket http header validation state for this client
2016-06-08 23:04:18 +01:00
client - > cHttpHeadersValid = true ;
client - > cMandatoryHeadersCount = 0 ;
2018-05-12 11:27:03 +02:00
} else if ( headerLine - > indexOf ( ' : ' ) ) {
String headerName = headerLine - > substring ( 0 , headerLine - > indexOf ( ' : ' ) ) ;
String headerValue = headerLine - > substring ( headerLine - > indexOf ( ' : ' ) + 1 ) ;
2018-05-12 11:22:16 +02:00
// remove space in the beginning (RFC2616)
if ( headerValue [ 0 ] = = ' ' ) {
headerValue . remove ( 0 , 1 ) ;
}
2015-07-26 11:08:02 +02:00
2018-05-12 11:27:03 +02:00
if ( headerName . equalsIgnoreCase ( WEBSOCKETS_STRING ( " Connection " ) ) ) {
headerValue . toLowerCase ( ) ;
if ( headerValue . indexOf ( WEBSOCKETS_STRING ( " upgrade " ) ) > = 0 ) {
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-Version " ) ) ) {
client - > cVersion = headerValue . toInt ( ) ;
} else if ( headerName . equalsIgnoreCase ( WEBSOCKETS_STRING ( " Sec-WebSocket-Key " ) ) ) {
client - > cKey = headerValue ;
client - > cKey . 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 ( " Authorization " ) ) ) {
client - > base64Authorization = headerValue ;
} else {
client - > cHttpHeadersValid & = execHttpHeaderValidation ( headerName , headerValue ) ;
if ( _mandatoryHttpHeaderCount > 0 & & hasMandatoryHeader ( headerName ) ) {
client - > cMandatoryHeadersCount + + ;
}
}
2016-06-08 23:04:18 +01:00
2018-05-12 11:27:03 +02:00
} else {
DEBUG_WEBSOCKETS ( " [WS-Client][handleHeader] Header error (%s) \n " , headerLine - > c_str ( ) ) ;
}
2015-05-22 14:19:01 +02:00
2016-01-23 16:27:02 +01:00
( * headerLine ) = " " ;
# if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client - > tcp - > readStringUntil ( ' \n ' , & ( client - > cHttpLine ) , std : : bind ( & WebSocketsServer : : handleHeader , this , client , & ( client - > cHttpLine ) ) ) ;
# endif
2015-05-22 14:19:01 +02:00
} else {
2016-06-08 23:04:18 +01:00
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] Header read fin. \n " , client - > num ) ;
2015-05-23 07:33:26 +02:00
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] - cURL: %s \n " , client - > num , client - > cUrl . c_str ( ) ) ;
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] - cIsUpgrade: %d \n " , client - > num , client - > cIsUpgrade ) ;
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] - cIsWebsocket: %d \n " , client - > num , client - > cIsWebsocket ) ;
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] - cKey: %s \n " , client - > num , client - > cKey . c_str ( ) ) ;
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] - cProtocol: %s \n " , client - > num , client - > cProtocol . c_str ( ) ) ;
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] - cExtensions: %s \n " , client - > num , client - > cExtensions . c_str ( ) ) ;
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] - cVersion: %d \n " , client - > num , client - > cVersion ) ;
2016-03-05 12:13:13 +01:00
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] - base64Authorization: %s \n " , client - > num , client - > base64Authorization . c_str ( ) ) ;
2016-06-08 23:04:18 +01:00
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] - cHttpHeadersValid: %d \n " , client - > num , client - > cHttpHeadersValid ) ;
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] - cMandatoryHeadersCount: %d \n " , client - > num , client - > cMandatoryHeadersCount ) ;
2015-05-22 14:19:01 +02:00
bool ok = ( client - > cIsUpgrade & & client - > cIsWebsocket ) ;
2018-05-12 11:27:03 +02:00
if ( ok ) {
if ( client - > cUrl . length ( ) = = 0 ) {
ok = false ;
}
if ( client - > cKey . length ( ) = = 0 ) {
2015-05-22 14:19:01 +02:00
ok = false ;
}
2015-05-22 14:40:46 +02:00
if ( client - > cVersion ! = 13 ) {
2015-05-22 14:19:01 +02:00
ok = false ;
}
2016-06-08 23:04:18 +01:00
if ( ! client - > cHttpHeadersValid ) {
ok = false ;
}
if ( client - > cMandatoryHeadersCount ! = _mandatoryHttpHeaderCount ) {
ok = false ;
}
2015-05-22 14:19:01 +02:00
}
2016-02-17 17:56:03 +01:00
if ( _base64Authorization . length ( ) > 0 ) {
2017-03-18 10:32:37 +01:00
String auth = WEBSOCKETS_STRING ( " Basic " ) ;
auth + = _base64Authorization ;
if ( auth ! = client - > base64Authorization ) {
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] HTTP Authorization failed! \n " , client - > num ) ;
handleAuthorizationFailed ( client ) ;
return ;
}
2016-02-17 17:56:03 +01:00
}
2015-05-22 14:19:01 +02:00
if ( ok ) {
2016-01-23 16:27:02 +01:00
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] Websocket connection incoming. \n " , client - > num ) ;
2015-05-22 14:19:01 +02:00
2015-05-22 18:44:16 +02:00
// generate Sec-WebSocket-Accept key
2015-05-23 09:34:09 +02:00
String sKey = acceptKey ( client - > cKey ) ;
2015-05-22 18:44:16 +02:00
2015-05-23 09:34:09 +02:00
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] - sKey: %s \n " , client - > num , sKey . c_str ( ) ) ;
2015-05-22 18:44:16 +02:00
client - > status = WSC_CONNECTED ;
2017-02-22 15:30:58 +01:00
String handshake = WEBSOCKETS_STRING ( " HTTP/1.1 101 Switching Protocols \r \n "
2015-05-24 18:00:35 +02:00
" Server: arduino-WebSocketsServer \r \n "
2015-05-22 18:44:16 +02:00
" Upgrade: websocket \r \n "
" Connection: Upgrade \r \n "
" Sec-WebSocket-Version: 13 \r \n "
" Sec-WebSocket-Accept: " ) ;
2017-02-22 15:30:58 +01:00
handshake + = sKey + NEW_LINE ;
2016-01-14 17:28:00 +01:00
if ( _origin . length ( ) > 0 ) {
2017-02-22 15:30:58 +01:00
handshake + = WEBSOCKETS_STRING ( " Access-Control-Allow-Origin: " ) ;
handshake + = _origin + NEW_LINE ;
2016-01-14 17:28:00 +01:00
}
2015-05-22 20:35:51 +02:00
if ( client - > cProtocol . length ( ) > 0 ) {
2017-02-22 15:30:58 +01:00
handshake + = WEBSOCKETS_STRING ( " Sec-WebSocket-Protocol: " ) ;
handshake + = _protocol + NEW_LINE ;
2015-05-22 20:35:51 +02:00
}
// header end
2017-02-22 15:30:58 +01:00
handshake + = NEW_LINE ;
DEBUG_WEBSOCKETS ( " [WS-Server][%d][handleHeader] handshake %s " , client - > num , ( uint8_t * ) handshake . c_str ( ) ) ;
2017-04-09 17:58:23 +02:00
write ( client , ( uint8_t * ) handshake . c_str ( ) , handshake . length ( ) ) ;
2015-05-22 14:19:01 +02:00
2016-01-23 16:27:02 +01:00
headerDone ( client ) ;
create overloaded functions for send and broadcast for easy usage
void sendTXT(uint8_t num, uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
void sendTXT(uint8_t num, char * payload, size_t length = 0);
void sendTXT(uint8_t num, const char * payload, size_t length = 0);
void sendTXT(uint8_t num, String payload);
void broadcastTXT(uint8_t * payload, size_t length = 0);
void broadcastTXT(const uint8_t * payload, size_t length = 0);
void broadcastTXT(char * payload, size_t length = 0);
void broadcastTXT(const char * payload, size_t length = 0);
void broadcastTXT(String payload);
void sendBIN(uint8_t num, uint8_t * payload, size_t length);
void sendBIN(uint8_t num, const uint8_t * payload, size_t length);
void broadcastBIN(uint8_t * payload, size_t length);
void broadcastBIN(const uint8_t * payload, size_t length);
send URL as payload on WStype_CONNECTED event
move Sec-WebSocket-Accept generation in function
2015-05-23 09:02:59 +02:00
// send ping
WebSockets : : sendFrame ( client , WSop_ping ) ;
2015-10-31 11:37:07 +01:00
runCbEvent ( client - > num , WStype_CONNECTED , ( uint8_t * ) client - > cUrl . c_str ( ) , client - > cUrl . length ( ) ) ;
2015-05-22 23:02:47 +02:00
2015-05-22 14:19:01 +02:00
} else {
2015-08-08 19:54:36 +02:00
handleNonWebsocketConnection ( client ) ;
2015-05-22 14:19:01 +02:00
}
}
}
2015-05-22 20:35:51 +02:00
2015-08-08 19:54:36 +02:00