Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
HttpConnection.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "HttpParser.h"
5
6#include "../AsyncStreams/AsyncStreams.h"
7#include "../Foundation/StringSpan.h"
8
9namespace SC
10{
13
15struct SC_COMPILER_EXPORT HttpRequest
16{
18 const HttpParser& getParser() const { return parser; }
19
21 StringSpan getURL() const { return url; }
22
24 [[nodiscard]] bool isMultipart() const;
25
27 [[nodiscard]] StringSpan getBoundary() const;
28
33 [[nodiscard]] bool getHeader(StringSpan headerName, StringSpan& value) const;
34
36 void reset();
37
38 private:
39 friend struct HttpConnectionsPool;
40 friend struct HttpResponse;
41 friend struct HttpAsyncServer;
42
47 [[nodiscard]] bool findParserToken(HttpParser::Token token, StringSpan& res) const;
48
51 Result writeHeaders(const uint32_t maxHeaderSize, Span<const char> readData, AsyncReadableStream& stream,
52 AsyncBufferView::ID bufferID);
53
55 [[nodiscard]] size_t getHeadersLength() const;
56
57 struct SC_COMPILER_EXPORT HttpHeaderOffset
58 {
59 HttpParser::Token token = HttpParser::Token::Method;
60
61 uint32_t start = 0;
62 uint32_t length = 0;
63 };
64 Span<char> readHeaders;
65 Span<char> availableHeader;
66
67 bool headersEndReceived = false;
68 bool parsedSuccessfully = true;
69
70 HttpParser parser;
71 StringSpan url;
72
73 static constexpr size_t MaxNumHeaders = 64;
74
75 HttpHeaderOffset headerOffsets[MaxNumHeaders];
76 size_t numHeaders = 0;
77};
78
80struct SC_COMPILER_EXPORT HttpResponse
81{
83 Result startResponse(int httpCode);
84
88 Result addHeader(StringSpan headerName, StringSpan headerValue);
89
92
94 void reset();
95
98
100 AsyncWritableStream& getWritableStream() { return *writableStream; }
101
105 void setKeepAlive(bool keepAlive);
106
109 [[nodiscard]] bool getKeepAlive() const { return forceDisableKeepAlive ? false : keepAlive; }
110
111 private:
112 friend struct HttpConnectionsPool;
113 friend struct HttpAsyncServer;
114
116 void grabUnusedHeaderMemory(HttpRequest& request);
117
118 Span<char> responseHeaders;
119 size_t responseHeadersCapacity = 0;
120
121 bool headersSent = false;
122
123 bool forceDisableKeepAlive = false;
124 bool keepAlive = true;
125 bool connectionHeaderAdded = false;
126
127 AsyncWritableStream* writableStream = nullptr;
128};
129
131struct SC_COMPILER_EXPORT HttpConnection
132{
134
135 struct SC_COMPILER_EXPORT ID
136 {
137 size_t getIndex() const { return index; }
138
139 private:
140 friend struct HttpConnectionsPool;
141 size_t index = 0;
142 };
143
145 void reset();
146
148 void setHeaderMemory(Span<char> memory) { headerMemory = memory; }
149
151 ID getConnectionID() const { return connectionID; }
152
153 HttpRequest request;
154 HttpResponse response;
155
156 AsyncBuffersPool buffersPool;
157 AsyncPipeline pipeline;
158
159 protected:
160 enum class State
161 {
162 Inactive,
163 Active
164 };
165 friend struct HttpConnectionsPool;
166 friend struct HttpAsyncServer;
167
168 State state = State::Inactive;
169 ID connectionID;
170
171 Span<char> headerMemory;
172};
173
175template <typename Type>
176struct SC_COMPILER_EXPORT SpanWithStride
177{
179 constexpr SpanWithStride() : data(nullptr), sizeElements(0), strideInBytes(0) {}
180
185 constexpr SpanWithStride(void* data, size_t sizeInElements, size_t strideInBytes)
186 : data(data), sizeElements(sizeInElements), strideInBytes(strideInBytes)
187 {}
188
189 template <typename U>
190 constexpr SpanWithStride(Span<U> span)
191 : data(span.data()), sizeElements(span.sizeInElements()), strideInBytes(sizeof(U))
192 {}
193
194 [[nodiscard]] constexpr size_t sizeInElements() const { return sizeElements; }
195 [[nodiscard]] constexpr bool empty() const { return sizeElements == 0; }
196
197 template <typename U>
198 SpanWithStride<U> castTo()
199 {
200 return {static_cast<U*>(reinterpret_cast<Type*>(data)), sizeElements, strideInBytes};
201 }
202
203 [[nodiscard]] Type& operator[](size_t idx)
204 {
205 return *reinterpret_cast<Type*>(reinterpret_cast<char*>(data) + idx * strideInBytes);
206 }
207
208 [[nodiscard]] const Type& operator[](size_t idx) const
209 {
210 return *reinterpret_cast<const Type*>(reinterpret_cast<const char*>(data) + idx * strideInBytes);
211 }
212
213 private:
214 void* data;
215 size_t sizeElements;
216 size_t strideInBytes;
217};
218
220struct SC_COMPILER_EXPORT HttpConnectionsPool
221{
224
227
229 [[nodiscard]] size_t getNumActiveConnections() const { return numConnections; }
230
232 [[nodiscard]] size_t getNumTotalConnections() const { return connections.sizeInElements(); }
233
235 [[nodiscard]] size_t getHighestActiveConnection() const { return highestActiveConnection; }
236
239 {
240 return connections[connectionID.index];
241 }
242
244 [[nodiscard]] HttpConnection& getConnectionAt(size_t idx) { return connections[idx]; }
245
247 [[nodiscard]] bool activateNew(HttpConnection::ID& connectionID);
248
250 [[nodiscard]] bool deactivate(HttpConnection::ID connectionID);
251
252 private:
254
255 size_t numConnections = 0;
256 size_t highestActiveConnection = 0;
257};
259
260} // namespace SC
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition PrimitiveTypes.h:38
Definition AsyncStreams.h:52
Holds a Span of AsyncBufferView (allocated by user) holding available memory for the streams.
Definition AsyncStreams.h:163
Pipes read data from SC::AsyncReadableStream, forwarding them to SC::AsyncWritableStream.
Definition AsyncStreams.h:510
Async source abstraction emitting data events in caller provided byte buffers.
Definition AsyncStreams.h:214
Async destination abstraction where bytes can be written to.
Definition AsyncStreams.h:337
Async Http Server.
Definition HttpAsyncServer.h:93
Definition HttpConnection.h:136
Http connection abstraction holding both the incoming and outgoing messages in an HTTP transaction.
Definition HttpConnection.h:132
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:151
void setHeaderMemory(Span< char > memory)
Sets memory for the header.
Definition HttpConnection.h:148
A pool of HttpConnection that can be active or inactive.
Definition HttpConnection.h:221
size_t getNumActiveConnections() const
Returns only the number of active connections.
Definition HttpConnection.h:229
size_t getHighestActiveConnection() const
Returns only the number of active connections.
Definition HttpConnection.h:235
HttpConnection & getConnectionAt(size_t idx)
Returns a connection in the [0, getNumTotalConnections] range.
Definition HttpConnection.h:244
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:238
size_t getNumTotalConnections() const
Returns the total number of connections (active + inactive)
Definition HttpConnection.h:232
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.
Incremental HTTP request or response parser.
Definition HttpParser.h:15
Token
One possible Token reported by the parser.
Definition HttpParser.h:41
Incoming message from the perspective of the participants of an HTTP transaction.
Definition HttpConnection.h:16
const HttpParser & getParser() const
Gets the associated HttpParser.
Definition HttpConnection.h:18
StringSpan getURL() const
Gets the request URL.
Definition HttpConnection.h:21
void reset()
Resets this object for it to be re-usable.
StringSpan getBoundary() const
Gets the multipart boundary string (if isMultipart() returns true)
bool getHeader(StringSpan headerName, StringSpan &value) const
Gets the value of a specific header (case-insensitive name matching)
bool isMultipart() const
Checks if the request is a multipart/form-data request.
Outgoing message from the perspective of the participants of an HTTP transaction.
Definition HttpConnection.h:81
Result startResponse(int httpCode)
Starts the response with a http standard code (200 OK, 404 NOT FOUND etc.)
Result sendHeaders()
Start sending response headers, before sending any data.
void setKeepAlive(bool keepAlive)
Sets whether to keep the connection alive after this response.
Result addHeader(StringSpan headerName, StringSpan headerValue)
Writes an http header to this response.
Result end()
Finalizes the writable stream after sending all in progress writes.
void reset()
Resets this object for it to be re-usable.
AsyncWritableStream & getWritableStream()
Obtain writable stream for sending content back to connected client.
Definition HttpConnection.h:100
bool getKeepAlive() const
Gets whether the connection should be kept alive after this response.
Definition HttpConnection.h:109
An ascii string used as boolean result. SC_TRY macro forwards errors to caller.
Definition Result.h:13
View over a contiguous sequence of items with a custom stride between elements.
Definition HttpConnection.h:177
constexpr SpanWithStride(void *data, size_t sizeInElements, size_t strideInBytes)
Builds a SpanWithStride from data, size, and stride.
Definition HttpConnection.h:185
constexpr SpanWithStride()
Builds an empty SpanWithStride.
Definition HttpConnection.h:179
View over a contiguous sequence of items (pointer + size in elements).
Definition Span.h:29
An read-only view over a string (to avoid including Strings library when parsing is not needed).
Definition StringSpan.h:37