FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

#include "HTTPConnection.hpp" namespace httpsserver { HTTPConnection::HTTPConnection(ResourceResolver * resResolver): _resResolver(resResolver) { _socket = -1; _addrLen = 0; _bufferProcessed = 0; _bufferUnusedIdx = 0; _connectionState = STATE_UNDEFINED; _clientState = CSTATE_UNDEFINED; _httpHeaders = NULL; _defaultHeaders = NULL; _isKeepAlive = false; _lastTransmissionTS = millis(); _shutdownTS = 0; _wsHandler = nullptr; } HTTPConnection::~HTTPConnection() { // Close the socket closeConnection(); } /** * Initializes the connection from a server socket. * * The call WILL BLOCK if accept(serverSocketID) blocks. So use select() to check for that in advance. */ int HTTPConnection::initialize(int serverSocketID, HTTPHeaders *defaultHeaders) { if (_connectionState == STATE_UNDEFINED) { _defaultHeaders = defaultHeaders; _socket = accept(serverSocketID, (struct sockaddr * )&_sockAddr, &_addrLen); // Build up SSL Connection context if the socket has been created successfully if (_socket >= 0) { HTTPS_DLOGHEX("[-->] New connection. Socket fid is: ", _socket); _connectionState = STATE_INITIAL; _httpHeaders = new HTTPHeaders(); refreshTimeout(); return _socket; } HTTPS_DLOG("[ERR] Could not accept() new connection"); _connectionState = STATE_ERROR; _clientState = CSTATE_ACTIVE; // This will only be called if the connection could not be established and cleanup // variables etc. closeConnection(); } // Error: The connection has already been established or could not be established return -1; } /** * True if the connection is timed out. * * (Should be checkd in the loop and transition should go to CONNECTION_CLOSE if exceeded) */ bool HTTPConnection::isTimeoutExceeded() { return _lastTransmissionTS + HTTPS_CONNECTION_TIMEOUT < millis(); } /** * Resets the timeout to allow again the full HTTPS_CONNECTION_TIMEOUT milliseconds */ void HTTPConnection::refreshTimeout() { _lastTransmissionTS = millis(); } /** * Returns true, if the connection has been closed. */ bool HTTPConnection::isClosed() { return (_connectionState == STATE_ERROR || _connectionState == STATE_CLOSED); } /** * Returns true, if the connection has been closed due to error */ bool HTTPConnection::isError() { return (_connectionState == STATE_ERROR); } bool HTTPConnection::isSecure() { return false; } void HTTPConnection::closeConnection() { // TODO: Call an event handler here, maybe? if (_connectionState != STATE_ERROR && _connectionState != STATE_CLOSED) { // First call to closeConnection - set the timestamp to calculate the timeout later on if (_connectionState != STATE_CLOSING) { _shutdownTS = millis(); } // Set the connection state to closing. We stay in closing as long as SSL has not been shutdown // correctly _connectionState = STATE_CLOSING; } // Tear down the socket if (_socket >= 0) { HTTPS_DLOGHEX("[] Websocket detected"); return true; } else return false; } /** * Middleware function that handles the validation of parameters */ void validationMiddleware(HTTPRequest * req, HTTPResponse * res, std::function next) { bool valid = true; // Get the matched node HTTPNode * node = req->getResolvedNode(); // Get the parameters ResourceParameters * params = req->getParams(); // Iterate over the validators and run them std::vector * validators = node->getValidators(); for(std::vector::iterator validator = validators->begin(); valid && validator != validators->end(); ++validator) { std::string param = params->getUrlParameter((*validator)->_idx); valid = ((*validator)->_validatorFunction)(param); } if (valid) { next(); } else { res->setStatusCode(400); res->setStatusText("Bad Request"); res->print("400 Bad Request"); } } /** * Handler function for the websocket handshake. Will be used by HTTPConnection if a websocket is detected */ void handleWebsocketHandshake(HTTPRequest * req, HTTPResponse * res) { res->setStatusCode(101); res->setStatusText("Switching Protocols"); res->setHeader("Upgrade", "websocket"); res->setHeader("Connection", "Upgrade"); res->setHeader("Sec-WebSocket-Accept", websocketKeyResponseHash(req->getHeader("Sec-WebSocket-Key"))); res->print(""); } /** * Function used to compute the value of the Sec-WebSocket-Accept during Websocket handshake */ std::string websocketKeyResponseHash(std::string const &key) { std::string newKey = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; uint8_t shaData[HTTPS_SHA1_LENGTH]; esp_sha(SHA1, (uint8_t*)newKey.data(), newKey.length(), shaData); // Get output size required for base64 representation size_t b64BufferSize = 0; mbedtls_base64_encode(nullptr, 0, &b64BufferSize, (const unsigned char*)shaData, HTTPS_SHA1_LENGTH); // Do the real encoding unsigned char bufferOut[b64BufferSize]; size_t bytesEncoded = 0; int res = mbedtls_base64_encode( bufferOut, b64BufferSize, &bytesEncoded, (const unsigned char*)shaData, HTTPS_SHA1_LENGTH ); // Check result and return the encoded string if (res != 0) { return std::string(); } return std::string((char*)bufferOut, bytesEncoded); } // WebsocketKeyResponseHash } /* namespace httpsserver */

Back | FazBrowse Home | New Git URL