7#include "../Async/Async.h"
8#include "../AsyncStreams/AsyncRequestStreams.h"
9#include "../Foundation/StringSpan.h"
10#include "Internal/HttpFixedBufferWriter.h"
11#include "Internal/HttpParsedHeaders.h"
18enum class HttpBodyFramingKind :
uint8_t
26enum class HttpContentEncoding :
uint8_t
33SC_HTTP_EXPORT StringSpan httpContentEncodingName(HttpContentEncoding encoding);
34SC_HTTP_EXPORT Result httpContentEncodingFromHeader(StringSpan headerValue, HttpContentEncoding& encoding);
36struct HttpAsyncClient;
37struct SyncZLibTransformStream;
50 static constexpr size_t MaxParts = 8;
57 StringSpan contentType =
"application/octet-stream");
59 [[nodiscard]]
StringSpan getBoundary()
const {
return boundary; }
60 [[nodiscard]]
size_t getNumParts()
const {
return numParts; }
61 [[nodiscard]]
const Part& getPart(
size_t idx)
const {
return parts[idx]; }
62 [[nodiscard]]
size_t getContentLength()
const;
67 char boundaryStorage[71] = {0};
83 void setHeaderMemory(
Span<char> memory) { headerMemory = memory; }
85 [[nodiscard]]
Span<char> getHeaderMemory()
const {
return headerMemory; }
103 void failBody(
Result result);
109 virtual Result asyncRead()
override;
110 virtual Result asyncResumeReading()
override;
120 [[nodiscard]]
bool getKeepAlive()
const {
return parsedHeaders.parser.connectionKeepAlive; }
158 [[nodiscard]]
Span<char> getUnusedHeaderMemory()
const {
return parsedHeaders.availableHeader; }
163 void finishBodyStream();
164 void failBodyStream(
Result result);
165 void abortBodyStream();
167 bool allowCloseDelimited);
169 bool allowTrailingData);
171 void setBodyBytesRemaining(
uint64_t value) { bodyBytesRemaining = value; }
172 void setBodyFramingKind(HttpBodyFramingKind value) { bodyFramingKind = value; }
173 void setBodyComplete(
bool value) { bodyComplete = value; }
174 void attachReadableStream(AsyncReadableStream& stream) { readableStream = &stream; }
186 bool stopAtHeadersEnd,
bool unshiftPendingBodyToStream =
true);
191 enum class ChunkedState :
uint8_t
204 HttpParsedHeaders parsedHeaders;
208 HttpBodyFramingKind bodyFramingKind = HttpBodyFramingKind::None;
209 bool bodyComplete =
true;
210 bool bodyStreamStarted =
false;
211 BodyStream bodyStream;
212 ChunkedState chunkedState = ChunkedState::Size;
215 bool chunkedSizeHasDigits =
false;
253 BodyStream& rawBodyStream() {
return bodyStream; }
280 bool finalChunkStarted =
false;
281 bool finalChunkWritten =
false;
283 char headerStorage[20] = {0};
318 [[nodiscard]]
bool getKeepAlive()
const {
return forceDisableKeepAlive ? false : keepAlive; }
321 enum class KnownHeader :
uint8_t
333 void setHeaderMemory(Span<char> memory);
334 void setWritableStream(AsyncWritableStream& stream)
336 destinationStream = &stream;
337 writableStream = &stream;
340 [[nodiscard]]
bool hasHeader(KnownHeader header)
const;
341 [[nodiscard]]
bool hasSentHeaders()
const {
return headersSent; }
342 [[nodiscard]]
bool hasEnded()
const {
return endCalled; }
343 [[nodiscard]]
bool isChunkedTransferEncodingEnabled()
const {
return chunkedTransferEncodingEnabled; }
345 HttpFixedBufferWriter responseHeaders;
346 Span<char> headerMemory;
348 bool headersSent =
false;
349 bool endCalled =
false;
351 bool forceDisableKeepAlive =
false;
352 bool keepAlive =
true;
353 bool connectionHeaderAdded =
false;
354 bool hostHeaderAdded =
false;
355 bool userAgentHeaderAdded =
false;
356 bool contentLengthAdded =
false;
357 bool contentTypeAdded =
false;
358 bool transferEncodingAdded =
false;
359 bool contentEncodingAdded =
false;
360 bool acceptEncodingAdded =
false;
361 bool chunkedTransferEncodingEnabled =
false;
424 HttpContentEncoding encoding);
430 [[nodiscard]]
StringSpan getRequestTarget()
const {
return url; }
431 [[nodiscard]]
StringSpan getURL()
const {
return url; }
432 [[nodiscard]] BodyType getBodyType()
const {
return bodyType; }
433 [[nodiscard]]
uint64_t getContentLength()
const {
return contentLength; }
434 [[nodiscard]]
bool usesChunkedTransferEncoding()
const {
return chunkedTransferEncodingEnabled; }
435 [[nodiscard]] HttpContentEncoding getContentEncoding()
const {
return contentEncoding; }
440 void setDefaultHost(
StringSpan value) { defaultHost = value; }
442 [[nodiscard]]
bool hasTransferEncodingHeader()
const {
return hasHeader(KnownHeader::TransferEncoding); }
443 [[nodiscard]]
bool hasAcceptEncodingHeader()
const {
return hasHeader(KnownHeader::AcceptEncoding); }
447 [[nodiscard]]
const HttpMultipartWriter* getMultipartWriter()
const {
return multipartWriter; }
454 BodyType bodyType = BodyType::None;
457 HttpContentEncoding contentEncoding = HttpContentEncoding::Identity;
470 struct SC_HTTP_EXPORT
ID
472 size_t getIndex()
const {
return index; }
505 State state = State::Inactive;
507 bool webSocketUpgraded =
false;
511template <
typename Type>
521 constexpr SpanWithStride(
void* data,
size_t sizeInElements,
size_t strideInBytes)
522 : data(data), sizeElements(sizeInElements), strideInBytes(strideInBytes)
525 template <
typename U>
527 : data(span.data()), sizeElements(span.sizeInElements()), strideInBytes(sizeof(U))
530 [[nodiscard]]
constexpr size_t sizeInElements()
const {
return sizeElements; }
531 [[nodiscard]]
constexpr bool empty()
const {
return sizeElements == 0; }
533 template <
typename U>
534 SpanWithStride<U> castTo()
536 return {
static_cast<U*
>(
reinterpret_cast<Type*
>(data)), sizeElements, strideInBytes};
539 [[nodiscard]] Type& operator[](
size_t idx)
541 return *
reinterpret_cast<Type*
>(
reinterpret_cast<char*
>(data) + idx * strideInBytes);
544 [[nodiscard]]
const Type& operator[](
size_t idx)
const
546 return *
reinterpret_cast<const Type*
>(
reinterpret_cast<const char*
>(data) + idx * strideInBytes);
552 size_t strideInBytes;
560 size_t readQueueSize = 3;
561 size_t writeQueueSize = 3;
562 size_t buffersQueueSize = 6;
563 size_t headerBytesLength = 8 * 1024;
564 size_t streamBytesLength = 512 * 1024;
598 return connections[connectionID.index];
613 size_t numConnections = 0;
616 size_t highestActiveConnection = 0;
620template <
int ReadQueue,
int WriteQueue,
int HeaderBytes,
int StreamBytes,
int ExtraBuffers,
typename BaseClass>
628 char headerStorage[HeaderBytes];
629 char streamStorage[StreamBytes];
633 constexpr const size_t NumSlices = ReadQueue;
634 constexpr const size_t SliceLength = StreamBytes / NumSlices;
637 for (
size_t idx = 0; idx < NumSlices; ++idx)
641 buffers[idx] = slice;
644 this->setHeaderMemory(headerStorage);
646 this->readableSocketStream.setReadQueue(readQueue);
647 this->writableSocketStream.setWriteQueue(writeQueue);
struct SC_FOUNDATION_EXPORT Function
Wraps function pointers, member functions and lambdas without ever allocating.
Definition Function.h:19
unsigned char uint8_t
Platform independent (1) byte unsigned int.
Definition PrimitiveTypes.h:27
unsigned long long uint64_t
Platform independent (8) bytes unsigned int.
Definition PrimitiveTypes.h:33
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition PrimitiveTypes.h:29
Definition AsyncStreams.h:58
A Span of bytes memory to be read or written by async streams.
Definition AsyncStreams.h:56
void setReusable(bool reusable)
Tags this AsyncBufferView as reusable after its refCount goes to zero.
Definition AsyncStreams.h:97
Holds a Span of AsyncBufferView (allocated by user) holding available memory for the streams.
Definition AsyncStreams.h:169
void setBuffers(Span< AsyncBufferView > newBuffers)
Sets memory for the new buffers.
Definition AsyncStreams.h:199
Pipes read data from SC::AsyncReadableStream, forwarding them to SC::AsyncWritableStream.
Definition AsyncStreams.h:550
Definition AsyncStreams.h:225
Async source abstraction emitting data events in caller provided byte buffers.
Definition AsyncStreams.h:220
Definition AsyncStreams.h:363
Async destination abstraction where bytes can be written to.
Definition AsyncStreams.h:356
Outgoing HTTP request sent by the client.
Definition HttpConnection.h:405
Incoming HTTP response received by the client.
Definition HttpConnection.h:246
Asynchronous HTTP/1.1 client using caller-provided fixed storage.
Definition HttpAsyncClient.h:49
Async Http Server.
Definition HttpAsyncServer.h:40
Shared async transport storage for HTTP client and server endpoints.
Definition HttpConnection.h:73
Definition HttpConnection.h:471
Http connection abstraction holding both the incoming and outgoing messages in an HTTP transaction.
Definition HttpConnection.h:467
bool isWebSocketUpgraded() const
Returns true after the HTTP layer handed this connection to WebSocket code.
Definition HttpConnection.h:489
void reset()
Prepare this client for re-use, marking it as Inactive.
void markWebSocketUpgraded()
Marks this HTTP connection as handed off to a WebSocket owner after a successful upgrade.
Definition HttpConnection.h:486
ID getConnectionID() const
The ID used to find this client in HttpConnectionsPool.
Definition HttpConnection.h:483
Definition HttpConnection.h:559
Definition HttpConnection.h:568
A pool of HttpConnection that can be active or inactive.
Definition HttpConnection.h:557
size_t getNumActiveConnections() const
Returns only the number of active connections.
Definition HttpConnection.h:587
size_t getHighestActiveConnection() const
Returns only the number of active connections.
Definition HttpConnection.h:593
HttpConnection & getConnectionAt(size_t idx)
Returns a connection in the [0, getNumTotalConnections] range.
Definition HttpConnection.h:602
Result init(SpanWithStride< HttpConnection > connectionsStorage)
Initializes the server with memory buffers for connections and headers.
bool activateNew(HttpConnection::ID &connectionID)
Finds an available connection (if any), activates it and returns its ID to use with getConnection(id)
HttpConnection & getConnection(HttpConnection::ID connectionID)
Returns a connection by ID.
Definition HttpConnection.h:596
size_t getNumTotalConnections() const
Returns the total number of connections (active + inactive)
Definition HttpConnection.h:590
Result close()
Closes the server, removing references to the memory buffers passed during init.
bool deactivate(HttpConnection::ID connectionID)
De-activates a connection previously returned by activateNew.
Definition HttpConnection.h:97
Incoming message from the perspective of the participants of an HTTP transaction.
Definition HttpConnection.h:95
bool getKeepAlive() const
Gets whether the other party requested the connection to stay alive.
Definition HttpConnection.h:120
const AsyncReadableStream & getReadableStream() const
Obtains the readable stream for the message body.
AsyncReadableStream & getReadableStream()
Obtains the readable stream for the message body.
bool isMultipart() const
Checks if the request is a multipart/form-data request.
const HttpParser & getParser() const
Gets the associated HttpParser.
Definition HttpConnection.h:114
bool getHeader(StringSpan headerName, StringSpan &value) const
Gets the value of a specific header (case-insensitive name matching)
StringSpan getVersion() const
Gets the parsed HTTP protocol version token, for example HTTP/1.1
size_t getHeadersLength() const
Gets the length of the headers in bytes.
StringSpan getBoundary() const
Gets the multipart boundary string (if isMultipart() returns true)
bool findParserToken(HttpParser::Token token, StringSpan &res) const
Finds a specific HttpParser::Result in the list of parsed header.
Result consumeBodyBytes(size_t bytes)
Decrements the remaining body bytes after consuming data.
bool isBodyComplete() const
Returns true once the full body has been received according to its framing.
Definition HttpConnection.h:132
uint64_t getBodyBytesRemaining() const
Returns how many body bytes are still expected for this message.
Definition HttpConnection.h:129
bool hasReceivedHeaders() const
Returns true once the incoming message headers have been parsed.
Definition HttpConnection.h:117
HttpBodyFramingKind getBodyFramingKind() const
Returns the effective framing mode for the incoming body.
Definition HttpConnection.h:126
Result writeHeaders(const uint32_t maxHeaderSize, Span< const char > readData, AsyncReadableStream &stream, AsyncBufferView::ID bufferID, const char *outOfSpaceError, const char *sizeExceededError, bool stopAtHeadersEnd, bool unshiftPendingBodyToStream=true)
Parses an incoming slice of data eventually copying it to the availableHeader.
Definition HttpConnection.h:42
Definition HttpConnection.h:40
Definition HttpConnection.h:260
virtual Result asyncWrite(AsyncBufferView::ID bufferID, Function< void(AsyncBufferView::ID)> cb) override
Function that every stream must define to implement its custom write operation.
virtual bool canEndWritable() override
Allows keeping a writable in ENDING state until it has finished flushing all pending data.
Outgoing message from the perspective of the participants of an HTTP transaction.
Definition HttpConnection.h:258
Result setChunkedTransferEncoding()
Enables chunked transfer-encoding for subsequent body writes.
bool getKeepAlive() const
Gets whether the connection should be kept alive after this response.
Definition HttpConnection.h:318
Result end()
Finalizes the writable stream after sending all in progress writes.
void reset()
Resets this object for it to be re-usable.
Result sendHeaders(Function< void(AsyncBufferView::ID)> callback={})
Start sending response headers, before sending any data.
Result addContentLength(uint64_t value)
Adds a formatted Content-Length header without caller-side temporary formatting.
Result addHeader(StringSpan headerName, StringSpan headerValue)
Writes an http header to this response.
void setKeepAlive(bool keepAlive)
Sets whether to keep the connection alive after this response.
AsyncWritableStream & getWritableStream()
Obtain writable stream for sending content back to connected client.
Definition HttpConnection.h:309
Incremental HTTP request or response parser.
Definition HttpParser.h:16
Token
One possible Token reported by the parser.
Definition HttpParser.h:46
Method
Method of the current request / response.
Definition HttpParser.h:19
Type
Type of the stream to be parsed (Request or Response)
Definition HttpParser.h:63
Incoming HTTP request received by the server.
Definition HttpConnection.h:220
StringSpan getURL() const
Gets the request URL.
Definition HttpConnection.h:225
void reset()
Resets this object for it to be re-usable.
StringSpan getRequestTarget() const
Gets the raw request target from the request line.
Definition HttpConnection.h:222
Outgoing HTTP response sent by the server.
Definition HttpConnection.h:370
Result startResponse(int httpCode)
Starts the response with a http standard code (200 OK, 404 NOT FOUND etc.)
Result startResponse(int httpCode, StringSpan reasonPhrase)
Starts the response with an explicit status code and reason phrase.
Result sendBody(int httpCode, StringSpan body, StringSpan contentType={})
Sends a caller-owned fixed-size body response.
Result sendText(int httpCode, StringSpan body)
Sends a caller-owned text/plain; charset=utf-8 response body.
Result sendBytes(int httpCode, Span< const char > body, StringSpan contentType={})
Sends a caller-owned fixed-size byte response.
Result sendEmpty(int httpCode)
Sends an empty response with Content-Length: 0.
Result startBody(int httpCode, uint64_t contentLength, StringSpan contentType={})
Starts a fixed-size body response and adds Content-Length plus optional Content-Type.
Adds compile-time configurable read and write queues to any class subclassing HttpConnectionBase.
Definition HttpConnection.h:622
An ascii string used as boolean result. SC_TRY macro forwards errors to caller.
Definition Result.h:13
Low-level OS socket handle.
Definition Socket.h:159
View over a contiguous sequence of items with a custom stride between elements.
Definition HttpConnection.h:513
constexpr SpanWithStride(void *data, size_t sizeInElements, size_t strideInBytes)
Builds a SpanWithStride from data, size, and stride.
Definition HttpConnection.h:521
constexpr SpanWithStride()
Builds an empty SpanWithStride.
Definition HttpConnection.h:515
View over a contiguous sequence of items (pointer + size in elements).
Definition Span.h:29
constexpr bool sliceStartLength(SizeType offsetInElements, SizeType lengthInElements, Span &destination) const
Creates another Span, starting at an offset in elements from current Span of specified length.
Definition Span.h:121
An read-only view over a string (to avoid including Strings library when parsing is not needed).
Definition StringSpan.h:37
Span< const char > toCharSpan() const
Obtain a const char Span from this StringView.
Definition StringSpan.h:82