forked from Links2004/arduinoWebSockets
custom http header validation implementation
This commit is contained in:
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* WebSocketServer.ino
|
||||||
|
*
|
||||||
|
* Created on: 22.05.2015
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266WiFiMulti.h>
|
||||||
|
#include <WebSocketsServer.h>
|
||||||
|
#include <Hash.h>
|
||||||
|
|
||||||
|
ESP8266WiFiMulti WiFiMulti;
|
||||||
|
|
||||||
|
WebSocketsServer webSocket = WebSocketsServer(81);
|
||||||
|
|
||||||
|
#define USE_SERIAL Serial1
|
||||||
|
|
||||||
|
const unsigned long int validSessionId = 12345; //some arbitrary value to act as a valid sessionId
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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=<someSessionIdNumberValue>|"
|
||||||
|
*/
|
||||||
|
bool isCookieValid(String rawCookieHeaderValue) {
|
||||||
|
|
||||||
|
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 == validSessionId;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 setup() {
|
||||||
|
// USE_SERIAL.begin(921600);
|
||||||
|
USE_SERIAL.begin(115200);
|
||||||
|
|
||||||
|
//Serial.setDebugOutput(true);
|
||||||
|
USE_SERIAL.setDebugOutput(true);
|
||||||
|
|
||||||
|
USE_SERIAL.println();
|
||||||
|
USE_SERIAL.println();
|
||||||
|
USE_SERIAL.println();
|
||||||
|
|
||||||
|
for(uint8_t t = 4; t > 0; t--) {
|
||||||
|
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
|
||||||
|
USE_SERIAL.flush();
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
WiFiMulti.addAP("SSID", "passpasspass");
|
||||||
|
|
||||||
|
while(WiFiMulti.run() != WL_CONNECTED) {
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
//connecting clients must supply a valid session cookie at websocket upgrade handshake negotiation time
|
||||||
|
const char * headerkeys[] = { "Cookie" };
|
||||||
|
webSocket.onValidateHttpHeader(validateHttpHeader, headerkeys);
|
||||||
|
webSocket.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
webSocket.loop();
|
||||||
|
}
|
||||||
|
|
@ -426,7 +426,7 @@ void WebSockets::handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t
|
|||||||
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] text: %s\n", client->num, payload);
|
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] text: %s\n", client->num, payload);
|
||||||
// no break here!
|
// no break here!
|
||||||
case WSop_binary:
|
case WSop_binary:
|
||||||
messageRecived(client, header->opCode, payload, header->payloadLen);
|
messageReceived(client, header->opCode, payload, header->payloadLen);
|
||||||
break;
|
break;
|
||||||
case WSop_ping:
|
case WSop_ping:
|
||||||
// send pong back
|
// send pong back
|
||||||
|
@ -183,6 +183,9 @@ typedef struct {
|
|||||||
String base64Authorization; ///< Base64 encoded Auth request
|
String base64Authorization; ///< Base64 encoded Auth request
|
||||||
String plainAuthorization; ///< Base64 encoded Auth request
|
String plainAuthorization; ///< Base64 encoded Auth request
|
||||||
|
|
||||||
|
bool cHttpHeadersValid; ///< non-websocket http header validity indicator
|
||||||
|
size_t cMandatoryHeadersCount; ///< non-websocket mandatory http headers present count
|
||||||
|
|
||||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||||
String cHttpLine; ///< HTTP header lines
|
String cHttpLine; ///< HTTP header lines
|
||||||
#endif
|
#endif
|
||||||
@ -202,7 +205,7 @@ class WebSockets {
|
|||||||
virtual void clientDisconnect(WSclient_t * client);
|
virtual void clientDisconnect(WSclient_t * client);
|
||||||
virtual bool clientIsConnected(WSclient_t * client);
|
virtual bool clientIsConnected(WSclient_t * client);
|
||||||
|
|
||||||
virtual void messageRecived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length);
|
virtual void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length);
|
||||||
|
|
||||||
void clientDisconnect(WSclient_t * client, uint16_t code, char * reason = NULL, size_t reasonLen = 0);
|
void clientDisconnect(WSclient_t * client, uint16_t code, char * reason = NULL, size_t reasonLen = 0);
|
||||||
bool sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload = NULL, size_t length = 0, bool mask = false, bool fin = true, bool headerToPayload = false);
|
bool sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload = NULL, size_t length = 0, bool mask = false, bool fin = true, bool headerToPayload = false);
|
||||||
|
@ -40,6 +40,9 @@ WebSocketsServer::WebSocketsServer(uint16_t port, String origin, String protocol
|
|||||||
|
|
||||||
_cbEvent = NULL;
|
_cbEvent = NULL;
|
||||||
|
|
||||||
|
_httpHeaderValidationFunc = NULL;
|
||||||
|
_mandatoryHttpHeaders = NULL;
|
||||||
|
_mandatoryHttpHeaderCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -53,10 +56,14 @@ WebSocketsServer::~WebSocketsServer() {
|
|||||||
// TODO how to close server?
|
// TODO how to close server?
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (_mandatoryHttpHeaders)
|
||||||
|
delete[] _mandatoryHttpHeaders;
|
||||||
|
|
||||||
|
_mandatoryHttpHeaderCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* calles to init the Websockets server
|
* called to initialize the Websocket server
|
||||||
*/
|
*/
|
||||||
void WebSocketsServer::begin(void) {
|
void WebSocketsServer::begin(void) {
|
||||||
WSclient_t * client;
|
WSclient_t * client;
|
||||||
@ -83,6 +90,7 @@ void WebSocketsServer::begin(void) {
|
|||||||
client->base64Authorization = "";
|
client->base64Authorization = "";
|
||||||
|
|
||||||
client->cWsRXsize = 0;
|
client->cWsRXsize = 0;
|
||||||
|
|
||||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||||
client->cHttpLine = "";
|
client->cHttpLine = "";
|
||||||
#endif
|
#endif
|
||||||
@ -118,7 +126,30 @@ void WebSocketsServer::onEvent(WebSocketServerEvent cbEvent) {
|
|||||||
_cbEvent = cbEvent;
|
_cbEvent = cbEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
|
* Sets the custom http header validator function
|
||||||
|
* If this functionality is being used, call this function prior to calling WebSocketsServer::begin
|
||||||
|
* @param httpHeaderValidationFunc WebSocketServerHttpHeaderValFunc ///< pointer to the custom http header validation function
|
||||||
|
* @param mandatoryHttpHeaders const char* ///< the array of named http headers considered to be mandatory / must be present in order for websocket upgrade to succeed
|
||||||
|
*/
|
||||||
|
void WebSocketsServer::onValidateHttpHeader(
|
||||||
|
WebSocketServerHttpHeaderValFunc validationFunc,
|
||||||
|
const char* mandatoryHttpHeaders[])
|
||||||
|
{
|
||||||
|
_httpHeaderValidationFunc = validationFunc;
|
||||||
|
|
||||||
|
if (_mandatoryHttpHeaders)
|
||||||
|
delete[] _mandatoryHttpHeaders;
|
||||||
|
|
||||||
|
_mandatoryHttpHeaderCount = (sizeof(mandatoryHttpHeaders) / sizeof(char*));
|
||||||
|
_mandatoryHttpHeaders = new String[_mandatoryHttpHeaderCount];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < _mandatoryHttpHeaderCount; i++) {
|
||||||
|
_mandatoryHttpHeaders[i] = mandatoryHttpHeaders[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
* send text data to client
|
* send text data to client
|
||||||
* @param num uint8_t client id
|
* @param num uint8_t client id
|
||||||
* @param payload uint8_t *
|
* @param payload uint8_t *
|
||||||
@ -279,9 +310,8 @@ void WebSocketsServer::disconnect(uint8_t num) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
/**
|
* set the Authorization for the http request
|
||||||
* set the Authorizatio for the http request
|
|
||||||
* @param user const char *
|
* @param user const char *
|
||||||
* @param password const char *
|
* @param password const char *
|
||||||
*/
|
*/
|
||||||
@ -388,7 +418,7 @@ bool WebSocketsServer::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) {
|
|||||||
* @param payload uint8_t *
|
* @param payload uint8_t *
|
||||||
* @param lenght size_t
|
* @param lenght size_t
|
||||||
*/
|
*/
|
||||||
void WebSocketsServer::messageRecived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t lenght) {
|
void WebSocketsServer::messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t lenght) {
|
||||||
WStype_t type = WStype_ERROR;
|
WStype_t type = WStype_ERROR;
|
||||||
|
|
||||||
switch(opcode) {
|
switch(opcode) {
|
||||||
@ -446,6 +476,7 @@ void WebSocketsServer::clientDisconnect(WSclient_t * client) {
|
|||||||
client->cIsWebsocket = false;
|
client->cIsWebsocket = false;
|
||||||
|
|
||||||
client->cWsRXsize = 0;
|
client->cWsRXsize = 0;
|
||||||
|
|
||||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||||
client->cHttpLine = "";
|
client->cHttpLine = "";
|
||||||
#endif
|
#endif
|
||||||
@ -461,7 +492,7 @@ void WebSocketsServer::clientDisconnect(WSclient_t * client) {
|
|||||||
/**
|
/**
|
||||||
* get client state
|
* get client state
|
||||||
* @param client WSclient_t * ptr to the client struct
|
* @param client WSclient_t * ptr to the client struct
|
||||||
* @return true = conneted
|
* @return true = connected
|
||||||
*/
|
*/
|
||||||
bool WebSocketsServer::clientIsConnected(WSclient_t * client) {
|
bool WebSocketsServer::clientIsConnected(WSclient_t * client) {
|
||||||
|
|
||||||
@ -492,7 +523,7 @@ bool WebSocketsServer::clientIsConnected(WSclient_t * client) {
|
|||||||
}
|
}
|
||||||
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||||
/**
|
/**
|
||||||
* Handle incomming Connection Request
|
* Handle incoming Connection Request
|
||||||
*/
|
*/
|
||||||
void WebSocketsServer::handleNewClients(void) {
|
void WebSocketsServer::handleNewClients(void) {
|
||||||
|
|
||||||
@ -569,10 +600,22 @@ void WebSocketsServer::handleClientData(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* handle the WebSocket header reading
|
* handles http header reading for WebSocket upgrade
|
||||||
* @param client WSclient_t * ptr to the client struct
|
* @param client WSclient_t * ///< pointer to the client struct
|
||||||
|
* @param headerLine String ///< the header being read / processed
|
||||||
*/
|
*/
|
||||||
void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
||||||
|
|
||||||
@ -581,10 +624,16 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
|||||||
if(headerLine->length() > 0) {
|
if(headerLine->length() > 0) {
|
||||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] RX: %s\n", client->num, headerLine->c_str());
|
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] RX: %s\n", client->num, headerLine->c_str());
|
||||||
|
|
||||||
// websocket request starts allways with GET see rfc6455
|
// websocket requests always start with GET see rfc6455
|
||||||
if(headerLine->startsWith("GET ")) {
|
if(headerLine->startsWith("GET ")) {
|
||||||
|
|
||||||
// cut URL out
|
// cut URL out
|
||||||
client->cUrl = headerLine->substring(4, headerLine->indexOf(' ', 4));
|
client->cUrl = headerLine->substring(4, headerLine->indexOf(' ', 4));
|
||||||
|
|
||||||
|
//reset non-websocket http header validation state for this client
|
||||||
|
client->cHttpHeadersValid = true;
|
||||||
|
client->cMandatoryHeadersCount = 0;
|
||||||
|
|
||||||
} else if(headerLine->indexOf(':')) {
|
} else if(headerLine->indexOf(':')) {
|
||||||
String headerName = headerLine->substring(0, headerLine->indexOf(':'));
|
String headerName = headerLine->substring(0, headerLine->indexOf(':'));
|
||||||
String headerValue = headerLine->substring(headerLine->indexOf(':') + 2);
|
String headerValue = headerLine->substring(headerLine->indexOf(':') + 2);
|
||||||
@ -609,7 +658,13 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
|||||||
client->cExtensions = headerValue;
|
client->cExtensions = headerValue;
|
||||||
} else if(headerName.equalsIgnoreCase("Authorization")) {
|
} else if(headerName.equalsIgnoreCase("Authorization")) {
|
||||||
client->base64Authorization = headerValue;
|
client->base64Authorization = headerValue;
|
||||||
|
} else {
|
||||||
|
client->cHttpHeadersValid &= execHttpHeaderValidation(headerName, headerValue);
|
||||||
|
if (_mandatoryHttpHeaderCount > 0 && hasMandatoryHeader(headerName)) {
|
||||||
|
client->cMandatoryHeadersCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Header error (%s)\n", headerLine->c_str());
|
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Header error (%s)\n", headerLine->c_str());
|
||||||
}
|
}
|
||||||
@ -619,8 +674,8 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
|||||||
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServer::handleHeader, this, client, &(client->cHttpLine)));
|
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServer::handleHeader, this, client, &(client->cHttpLine)));
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] Header read fin.\n", client->num);
|
|
||||||
|
|
||||||
|
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] Header read fin.\n", client->num);
|
||||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cURL: %s\n", client->num, client->cUrl.c_str());
|
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] - 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] - cIsWebsocket: %d\n", client->num, client->cIsWebsocket);
|
||||||
@ -629,6 +684,8 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
|||||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cExtensions: %s\n", client->num, client->cExtensions.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);
|
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cVersion: %d\n", client->num, client->cVersion);
|
||||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - base64Authorization: %s\n", client->num, client->base64Authorization.c_str());
|
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - base64Authorization: %s\n", client->num, client->base64Authorization.c_str());
|
||||||
|
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);
|
||||||
|
|
||||||
bool ok = (client->cIsUpgrade && client->cIsWebsocket);
|
bool ok = (client->cIsUpgrade && client->cIsWebsocket);
|
||||||
|
|
||||||
@ -642,6 +699,12 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
|||||||
if(client->cVersion != 13) {
|
if(client->cVersion != 13) {
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
|
if(!client->cHttpHeadersValid) {
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
if (client->cMandatoryHeadersCount != _mandatoryHttpHeaderCount) {
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_base64Authorization.length() > 0) {
|
if(_base64Authorization.length() > 0) {
|
||||||
|
@ -38,8 +38,10 @@ public:
|
|||||||
|
|
||||||
#ifdef __AVR__
|
#ifdef __AVR__
|
||||||
typedef void (*WebSocketServerEvent)(uint8_t num, WStype_t type, uint8_t * payload, size_t length);
|
typedef void (*WebSocketServerEvent)(uint8_t num, WStype_t type, uint8_t * payload, size_t length);
|
||||||
|
typedef bool (*WebSocketServerHttpHeaderValFunc)(String headerName, String headerValue);
|
||||||
#else
|
#else
|
||||||
typedef std::function<void (uint8_t num, WStype_t type, uint8_t * payload, size_t length)> WebSocketServerEvent;
|
typedef std::function<void (uint8_t num, WStype_t type, uint8_t * payload, size_t length)> WebSocketServerEvent;
|
||||||
|
typedef std::function<bool (String headerName, String headerValue)> WebSocketServerHttpHeaderValFunc;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
WebSocketsServer(uint16_t port, String origin = "", String protocol = "arduino");
|
WebSocketsServer(uint16_t port, String origin = "", String protocol = "arduino");
|
||||||
@ -55,6 +57,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void onEvent(WebSocketServerEvent cbEvent);
|
void onEvent(WebSocketServerEvent cbEvent);
|
||||||
|
void onValidateHttpHeader(WebSocketServerHttpHeaderValFunc validationFunc, const char* mandatoryHttpHeaders[]);
|
||||||
|
|
||||||
|
|
||||||
bool sendTXT(uint8_t num, uint8_t * payload, size_t length = 0, bool headerToPayload = false);
|
bool sendTXT(uint8_t num, uint8_t * payload, size_t length = 0, bool headerToPayload = false);
|
||||||
@ -90,16 +93,19 @@ protected:
|
|||||||
String _origin;
|
String _origin;
|
||||||
String _protocol;
|
String _protocol;
|
||||||
String _base64Authorization; ///< Base64 encoded Auth request
|
String _base64Authorization; ///< Base64 encoded Auth request
|
||||||
|
String * _mandatoryHttpHeaders;
|
||||||
|
size_t _mandatoryHttpHeaderCount;
|
||||||
|
|
||||||
WEBSOCKETS_NETWORK_SERVER_CLASS * _server;
|
WEBSOCKETS_NETWORK_SERVER_CLASS * _server;
|
||||||
|
|
||||||
WSclient_t _clients[WEBSOCKETS_SERVER_CLIENT_MAX];
|
WSclient_t _clients[WEBSOCKETS_SERVER_CLIENT_MAX];
|
||||||
|
|
||||||
WebSocketServerEvent _cbEvent;
|
WebSocketServerEvent _cbEvent;
|
||||||
|
WebSocketServerHttpHeaderValFunc _httpHeaderValidationFunc;
|
||||||
|
|
||||||
bool newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient);
|
bool newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient);
|
||||||
|
|
||||||
void messageRecived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length);
|
void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length);
|
||||||
|
|
||||||
void clientDisconnect(WSclient_t * client);
|
void clientDisconnect(WSclient_t * client);
|
||||||
bool clientIsConnected(WSclient_t * client);
|
bool clientIsConnected(WSclient_t * client);
|
||||||
@ -111,7 +117,6 @@ protected:
|
|||||||
|
|
||||||
void handleHeader(WSclient_t * client, String * headerLine);
|
void handleHeader(WSclient_t * client, String * headerLine);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called if a non Websocket connection is coming in.
|
* called if a non Websocket connection is coming in.
|
||||||
* Note: can be override
|
* Note: can be override
|
||||||
@ -162,6 +167,30 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called at client socket connect handshake negotiation time for each http header that is not
|
||||||
|
* a websocket specific http header (not Connection, Upgrade, Sec-WebSocket-*)
|
||||||
|
* If the custom httpHeaderValidationFunc returns false for any headerName / headerValue passed, the
|
||||||
|
* socket negotiation is considered invalid and the upgrade to websockets request is denied / rejected
|
||||||
|
* This mechanism can be used to enable custom authentication schemes e.g. test the value
|
||||||
|
* of a session cookie to determine if a user is logged on / authenticated
|
||||||
|
*/
|
||||||
|
virtual bool execHttpHeaderValidation(String headerName, String headerValue) {
|
||||||
|
if(_httpHeaderValidationFunc) {
|
||||||
|
//return the value of the custom http header validation function
|
||||||
|
return _httpHeaderValidationFunc(headerName, headerValue);
|
||||||
|
}
|
||||||
|
//no custom http header validation so just assume all is good
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*
|
||||||
|
* 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 hasMandatoryHeader(String headerName);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user