X Tutup
#ifndef SRC_HTTPCONNECTION_HPP_ #define SRC_HTTPCONNECTION_HPP_ #include #include #include #include #include // Required for sockets #include "lwip/netdb.h" #undef read #include "lwip/sockets.h" #include "HTTPSServerConstants.hpp" #include "ConnectionContext.hpp" #include "HTTPHeaders.hpp" #include "HTTPHeader.hpp" #include "ResourceResolver.hpp" #include "ResolvedResource.hpp" #include "ResourceNode.hpp" #include "HTTPRequest.hpp" #include "HTTPResponse.hpp" #include "WebsocketHandler.hpp" #include "WebsocketNode.hpp" namespace httpsserver { /** * \brief Represents a single open connection for the plain HTTPServer, without TLS */ class HTTPConnection : private ConnectionContext { public: HTTPConnection(ResourceResolver * resResolver); virtual ~HTTPConnection(); virtual int initialize(int serverSocketID, HTTPHeaders *defaultHeaders); virtual void closeConnection(); virtual bool isSecure(); void loop(); bool isClosed(); bool isError(); protected: friend class HTTPRequest; friend class HTTPResponse; friend class WebsocketInputStreambuf; virtual size_t writeBuffer(byte* buffer, size_t length); virtual size_t readBytesToBuffer(byte* buffer, size_t length); virtual bool canReadData(); virtual size_t pendingByteCount(); // Timestamp of the last transmission action unsigned long _lastTransmissionTS; // Timestamp of when the shutdown was started unsigned long _shutdownTS; // Internal state machine of the connection: // // O --- > STATE_UNDEFINED -- initialize() --> STATE_INITIAL -- get / http/1.1 --> STATE_REQUEST_FINISHED --. // | | | | // | | | | Host: ...\r\n // STATE_ERROR <- on error-----------------------<---------------------------------------< | Foo: bar\r\n // ^ | | | \r\n // | shutdown .--> STATE_CLOSED | | | \r\n // | fails | | | | // | | close() | | | // STATE_CLOSING <---- STATE_WEBSOCKET <-. | | | // ^ | | | | // `---------- close() ---------- STATE_BODY_FINISHED <-- Body received or GET -- STATE_HEADERS_FINISHED <-ยด // enum { // The order is important, to be able to use state <= STATE_HEADERS_FINISHED etc. // The connection has not been established yet STATE_UNDEFINED, // The connection has just been created STATE_INITIAL, // The request line has been parsed STATE_REQUEST_FINISHED, // The headers have been parsed STATE_HEADERS_FINISHED, // The body has been parsed/the complete request has been processed (GET has body of length 0) STATE_BODY_FINISHED, // The connection is in websocket mode STATE_WEBSOCKET, // The connection is about to close (and waiting for the client to send close notify) STATE_CLOSING, // The connection has been closed STATE_CLOSED, // An error has occured STATE_ERROR } _connectionState; enum { CSTATE_UNDEFINED, CSTATE_ACTIVE, CSTATE_CLOSED } _clientState; private: void raiseError(uint16_t code, std::string reason); void readLine(int lengthLimit); bool isTimeoutExceeded(); void refreshTimeout(); int updateBuffer(); size_t pendingBufferSize(); void signalClientClose(); void signalRequestError(); size_t readBuffer(byte* buffer, size_t length); size_t getCacheSize(); bool checkWebsocket(); // The receive buffer char _receiveBuffer[HTTPS_CONNECTION_DATA_CHUNK_SIZE]; // First index on _receive_buffer that has not been processed yet (anything before may be discarded) int _bufferProcessed; // The index on the receive_buffer that is the first one which is empty at the end. int _bufferUnusedIdx; // Socket address, length etc for the connection struct sockaddr _sockAddr; socklen_t _addrLen; int _socket; // Resource resolver used to resolve resources ResourceResolver * _resResolver; // The parser line. The struct is used to read the next line up to the \r\n in readLine() struct { std::string text = ""; bool parsingFinished = false; } _parserLine; // HTTP properties: Method, Request, Headers std::string _httpMethod; std::string _httpResource; HTTPHeaders * _httpHeaders; // Default headers that are applied to every response HTTPHeaders * _defaultHeaders; // Should we use keep alive bool _isKeepAlive; //Websocket connection WebsocketHandler * _wsHandler; }; void handleWebsocketHandshake(HTTPRequest * req, HTTPResponse * res); std::string websocketKeyResponseHash(std::string const &key); void validationMiddleware(HTTPRequest * req, HTTPResponse * res, std::function next); } /* namespace httpsserver */ #endif /* SRC_HTTPCONNECTION_HPP_ */
X Tutup