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
26struct HttpAsyncClient;
39 static constexpr size_t MaxParts = 8;
46 StringSpan contentType =
"application/octet-stream");
48 [[nodiscard]]
StringSpan getBoundary()
const {
return boundary; }
49 [[nodiscard]]
size_t getNumParts()
const {
return numParts; }
50 [[nodiscard]]
const Part& getPart(
size_t idx)
const {
return parts[idx]; }
51 [[nodiscard]]
size_t getContentLength()
const;
56 char boundaryStorage[71] = {0};
72 void setHeaderMemory(
Span<char> memory) { headerMemory = memory; }
74 [[nodiscard]]
Span<char> getHeaderMemory()
const {
return headerMemory; }
92 void failBody(
Result result);
98 virtual Result asyncRead()
override;
105 [[nodiscard]]
bool getKeepAlive()
const {
return parsedHeaders.parser.connectionKeepAlive; }
140 [[nodiscard]]
bool hasReceivedHeaders()
const {
return parsedHeaders.headersEndReceived; }
141 [[nodiscard]]
Span<char> getUnusedHeaderMemory()
const {
return parsedHeaders.availableHeader; }
143 Result initBodyStream(AsyncBuffersPool& buffersPool, Function<Result()>&& onReadRequest);
144 Result startBodyStream();
145 bool pushBodyData(AsyncBufferView::ID bufferID,
size_t sizeInBytes);
146 void finishBodyStream();
147 void failBodyStream(Result result);
148 void abortBodyStream();
149 Result prepareBodyStream(AsyncBuffersPool& buffersPool, Function<Result()>&& onReadRequest,
150 bool allowCloseDelimited);
151 Result processBodyData(AsyncReadableStream& sourceStream, AsyncBufferView::ID bufferID, Span<const char> readData,
152 bool allowTrailingData);
154 void setBodyBytesRemaining(uint64_t value) { bodyBytesRemaining = value; }
155 void setBodyFramingKind(HttpBodyFramingKind value) { bodyFramingKind = value; }
156 void setBodyComplete(
bool value) { bodyComplete = value; }
157 void attachReadableStream(AsyncReadableStream& stream) { readableStream = &stream; }
169 bool stopAtHeadersEnd,
bool unshiftPendingBodyToStream =
true);
174 enum class ChunkedState :
uint8_t
187 HttpParsedHeaders parsedHeaders;
191 HttpBodyFramingKind bodyFramingKind = HttpBodyFramingKind::None;
192 bool bodyComplete =
true;
193 bool bodyStreamStarted =
false;
194 BodyStream bodyStream;
195 ChunkedState chunkedState = ChunkedState::Size;
198 bool chunkedSizeHasDigits =
false;
259 bool finalChunkStarted =
false;
260 bool finalChunkWritten =
false;
262 char headerStorage[20] = {0};
294 [[nodiscard]]
bool getKeepAlive()
const {
return forceDisableKeepAlive ? false : keepAlive; }
297 enum class KnownHeader :
uint8_t
307 void setHeaderMemory(Span<char> memory);
308 void setWritableStream(AsyncWritableStream& stream)
310 destinationStream = &stream;
311 writableStream = &stream;
314 [[nodiscard]]
bool hasHeader(KnownHeader header)
const;
315 [[nodiscard]]
bool hasSentHeaders()
const {
return headersSent; }
316 [[nodiscard]]
bool hasEnded()
const {
return endCalled; }
317 [[nodiscard]]
bool isChunkedTransferEncodingEnabled()
const {
return chunkedTransferEncodingEnabled; }
319 HttpFixedBufferWriter responseHeaders;
320 Span<char> headerMemory;
322 bool headersSent =
false;
323 bool endCalled =
false;
325 bool forceDisableKeepAlive =
false;
326 bool keepAlive =
true;
327 bool connectionHeaderAdded =
false;
328 bool hostHeaderAdded =
false;
329 bool userAgentHeaderAdded =
false;
330 bool contentLengthAdded =
false;
331 bool contentTypeAdded =
false;
332 bool transferEncodingAdded =
false;
333 bool chunkedTransferEncodingEnabled =
false;
379 [[nodiscard]]
StringSpan getURL()
const {
return url; }
380 [[nodiscard]] BodyType getBodyType()
const {
return bodyType; }
381 [[nodiscard]]
uint64_t getContentLength()
const {
return contentLength; }
382 [[nodiscard]]
bool usesChunkedTransferEncoding()
const {
return chunkedTransferEncodingEnabled; }
387 void setDefaultHost(
StringSpan value) { defaultHost = value; }
389 [[nodiscard]]
bool hasTransferEncodingHeader()
const {
return hasHeader(KnownHeader::TransferEncoding); }
392 [[nodiscard]]
const HttpMultipartWriter* getMultipartWriter()
const {
return multipartWriter; }
398 BodyType bodyType = BodyType::None;
413 struct SC_HTTP_EXPORT
ID
415 size_t getIndex()
const {
return index; }
442 State state = State::Inactive;
447template <
typename Type>
457 constexpr SpanWithStride(
void* data,
size_t sizeInElements,
size_t strideInBytes)
458 : data(data), sizeElements(sizeInElements), strideInBytes(strideInBytes)
461 template <
typename U>
463 : data(span.data()), sizeElements(span.sizeInElements()), strideInBytes(sizeof(U))
466 [[nodiscard]]
constexpr size_t sizeInElements()
const {
return sizeElements; }
467 [[nodiscard]]
constexpr bool empty()
const {
return sizeElements == 0; }
469 template <
typename U>
470 SpanWithStride<U> castTo()
472 return {
static_cast<U*
>(
reinterpret_cast<Type*
>(data)), sizeElements, strideInBytes};
475 [[nodiscard]] Type& operator[](
size_t idx)
477 return *
reinterpret_cast<Type*
>(
reinterpret_cast<char*
>(data) + idx * strideInBytes);
480 [[nodiscard]]
const Type& operator[](
size_t idx)
const
482 return *
reinterpret_cast<const Type*
>(
reinterpret_cast<const char*
>(data) + idx * strideInBytes);
488 size_t strideInBytes;
496 size_t readQueueSize = 3;
497 size_t writeQueueSize = 3;
498 size_t buffersQueueSize = 6;
499 size_t headerBytesLength = 8 * 1024;
500 size_t streamBytesLength = 512 * 1024;
534 return connections[connectionID.index];
549 size_t numConnections = 0;
552 size_t highestActiveConnection = 0;
556template <
int ReadQueue,
int WriteQueue,
int HeaderBytes,
int StreamBytes,
int ExtraBuffers,
typename BaseClass>
564 char headerStorage[HeaderBytes];
565 char streamStorage[StreamBytes];
569 constexpr const size_t NumSlices = ReadQueue;
570 constexpr const size_t SliceLength = StreamBytes / NumSlices;
573 for (
size_t idx = 0; idx < NumSlices; ++idx)
577 buffers[idx] = slice;
580 this->setHeaderMemory(headerStorage);
582 this->readableSocketStream.setReadQueue(readQueue);
583 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:544
Definition AsyncStreams.h:225
Async source abstraction emitting data events in caller provided byte buffers.
Definition AsyncStreams.h:220
Definition AsyncStreams.h:357
Async destination abstraction where bytes can be written to.
Definition AsyncStreams.h:350
Outgoing HTTP request sent by the client.
Definition HttpConnection.h:356
Incoming HTTP response received by the client.
Definition HttpConnection.h:226
Asynchronous HTTP/1.1 client using caller-provided fixed storage.
Definition HttpAsyncClient.h:46
Async Http Server.
Definition HttpAsyncServer.h:40
Shared async transport storage for HTTP client and server endpoints.
Definition HttpConnection.h:62
Definition HttpConnection.h:414
Http connection abstraction holding both the incoming and outgoing messages in an HTTP transaction.
Definition HttpConnection.h:410
void reset()
Prepare this client for re-use, marking it as Inactive.
ID getConnectionID() const
The ID used to find this client in HttpConnectionsPool.
Definition HttpConnection.h:426
Definition HttpConnection.h:495
Definition HttpConnection.h:504
A pool of HttpConnection that can be active or inactive.
Definition HttpConnection.h:493
size_t getNumActiveConnections() const
Returns only the number of active connections.
Definition HttpConnection.h:523
size_t getHighestActiveConnection() const
Returns only the number of active connections.
Definition HttpConnection.h:529
HttpConnection & getConnectionAt(size_t idx)
Returns a connection in the [0, getNumTotalConnections] range.
Definition HttpConnection.h:538
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:532
size_t getNumTotalConnections() const
Returns the total number of connections (active + inactive)
Definition HttpConnection.h:526
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:86
Incoming message from the perspective of the participants of an HTTP transaction.
Definition HttpConnection.h:84
bool getKeepAlive() const
Gets whether the other party requested the connection to stay alive.
Definition HttpConnection.h:105
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:102
bool getHeader(StringSpan headerName, StringSpan &value) const
Gets the value of a specific header (case-insensitive name matching)
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:114
uint64_t getBodyBytesRemaining() const
Returns how many body bytes are still expected for this message.
Definition HttpConnection.h:111
HttpBodyFramingKind getBodyFramingKind() const
Returns the effective framing mode for the incoming body.
Definition HttpConnection.h:108
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:31
Definition HttpConnection.h:29
Definition HttpConnection.h:239
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:237
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:294
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 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:285
Incremental HTTP request or response parser.
Definition HttpParser.h:16
Token
One possible Token reported by the parser.
Definition HttpParser.h:42
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:59
Incoming HTTP request received by the server.
Definition HttpConnection.h:203
StringSpan getURL() const
Gets the request URL.
Definition HttpConnection.h:205
void reset()
Resets this object for it to be re-usable.
Outgoing HTTP response sent by the server.
Definition HttpConnection.h:342
Result startResponse(int httpCode)
Starts the response with a http standard code (200 OK, 404 NOT FOUND etc.)
Adds compile-time configurable read and write queues to any class subclassing HttpConnectionBase.
Definition HttpConnection.h:558
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:449
constexpr SpanWithStride(void *data, size_t sizeInElements, size_t strideInBytes)
Builds a SpanWithStride from data, size, and stride.
Definition HttpConnection.h:457
constexpr SpanWithStride()
Builds an empty SpanWithStride.
Definition HttpConnection.h:451
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