mirror of
https://github.com/drogonframework/drogon.git
synced 2025-07-23 00:01:23 -04:00
Compare commits
18 Commits
ab73516ae1
...
9d80aaa1e9
Author | SHA1 | Date | |
---|---|---|---|
|
9d80aaa1e9 | ||
|
75f197ecd4 | ||
|
8ce2b853d9 | ||
|
781ef3c194 | ||
|
3eddcafe73 | ||
|
09a8634838 | ||
|
3ea63787e7 | ||
|
7202330f10 | ||
|
e27b800b33 | ||
|
98678dd331 | ||
|
f2a7ac8b2f | ||
|
89786de0fe | ||
|
49cfea3b4a | ||
|
a3a6267577 | ||
|
69f592b726 | ||
|
a0a9f7a337 | ||
|
1a27e8bf1e | ||
|
05a18675fe |
@ -13,7 +13,7 @@ Drogon is a cross-platform framework, It supports Linux, macOS, FreeBSD, OpenBSD
|
||||
|
||||
* Use a non-blocking I/O network lib based on epoll (kqueue under macOS/FreeBSD) to provide high-concurrency, high-performance network IO, please visit the [TFB Tests Results](https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=composite) for more details;
|
||||
* Provide a completely asynchronous programming mode;
|
||||
* Support Http1.0/1.1 (server side and client side);
|
||||
* Support HTTP/2 (and 1.0/1.1) client and HTTP 1.1/1.0 server
|
||||
* Based on template, a simple reflection mechanism is implemented to completely decouple the main program framework, controllers and views.
|
||||
* Support cookies and built-in sessions;
|
||||
* Support back-end rendering, the controller generates the data to the view to generate the Html page. Views are described by CSP template files, C++ codes are embedded into Html pages through CSP tags. And the drogon command-line tool automatically generates the C++ code files for compilation;
|
||||
|
@ -16,7 +16,7 @@ int main()
|
||||
{
|
||||
trantor::Logger::setLogLevel(trantor::Logger::kTrace);
|
||||
{
|
||||
auto client = HttpClient::newHttpClient("https://clehaxze.tw:8844",
|
||||
auto client = HttpClient::newHttpClient("https://clehaxze.tw",
|
||||
nullptr,
|
||||
false,
|
||||
false);
|
||||
@ -48,7 +48,7 @@ int main()
|
||||
req->setParameter("wd", "wx");
|
||||
req->setParameter("oq", "wx");
|
||||
|
||||
for (int i = 0; i < 1; ++i)
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
client->sendRequest(
|
||||
req, [](ReqResult result, const HttpResponsePtr &response) {
|
||||
@ -76,7 +76,6 @@ int main()
|
||||
});
|
||||
LOG_INFO << "send request";
|
||||
}
|
||||
|
||||
app().run();
|
||||
}
|
||||
app().run();
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,11 +5,93 @@
|
||||
// TOOD: Write our own HPACK implementation
|
||||
#include "hpack/HPacker.h"
|
||||
|
||||
#include <variant>
|
||||
|
||||
namespace drogon
|
||||
{
|
||||
|
||||
namespace internal
|
||||
{
|
||||
struct ByteStream;
|
||||
struct OByteStream;
|
||||
|
||||
struct SettingsFrame
|
||||
{
|
||||
bool ack = false;
|
||||
std::vector<std::pair<uint16_t, uint32_t>> settings;
|
||||
|
||||
static std::optional<SettingsFrame> parse(ByteStream &payload,
|
||||
uint8_t flags);
|
||||
bool serialize(OByteStream &stream, uint8_t &flags) const;
|
||||
};
|
||||
|
||||
struct WindowUpdateFrame
|
||||
{
|
||||
uint32_t windowSizeIncrement = 0;
|
||||
|
||||
static std::optional<WindowUpdateFrame> parse(ByteStream &payload,
|
||||
uint8_t flags);
|
||||
bool serialize(OByteStream &stream, uint8_t &flags) const;
|
||||
};
|
||||
|
||||
struct HeadersFrame
|
||||
{
|
||||
uint8_t padLength = 0;
|
||||
bool exclusive = false;
|
||||
uint32_t streamDependency = 0;
|
||||
uint8_t weight = 0;
|
||||
std::vector<uint8_t> headerBlockFragment;
|
||||
bool endHeaders = false;
|
||||
bool endStream = false;
|
||||
|
||||
static std::optional<HeadersFrame> parse(ByteStream &payload,
|
||||
uint8_t flags);
|
||||
bool serialize(OByteStream &stream, uint8_t &flags) const;
|
||||
};
|
||||
|
||||
struct GoAwayFrame
|
||||
{
|
||||
uint32_t lastStreamId = 0;
|
||||
uint32_t errorCode = 0;
|
||||
std::vector<uint8_t> additionalDebugData;
|
||||
|
||||
static std::optional<GoAwayFrame> parse(ByteStream &payload, uint8_t flags);
|
||||
bool serialize(OByteStream &stream, uint8_t &flags) const;
|
||||
};
|
||||
|
||||
struct DataFrame
|
||||
{
|
||||
uint8_t padLength = 0;
|
||||
std::vector<uint8_t> data;
|
||||
bool endStream = false;
|
||||
|
||||
static std::optional<DataFrame> parse(ByteStream &payload, uint8_t flags);
|
||||
bool serialize(OByteStream &stream, uint8_t &flags) const;
|
||||
};
|
||||
|
||||
struct PingFrame
|
||||
{
|
||||
std::array<uint8_t, 8> opaqueData;
|
||||
bool ack = false;
|
||||
|
||||
static std::optional<PingFrame> parse(ByteStream &payload, uint8_t flags);
|
||||
bool serialize(OByteStream &stream, uint8_t &flags) const;
|
||||
};
|
||||
|
||||
using H2Frame = std::variant<SettingsFrame,
|
||||
WindowUpdateFrame,
|
||||
HeadersFrame,
|
||||
GoAwayFrame,
|
||||
DataFrame,
|
||||
PingFrame>;
|
||||
|
||||
enum class StreamState
|
||||
{
|
||||
ExpectingHeaders,
|
||||
ExpectingContinuation,
|
||||
ExpectingData,
|
||||
Finished,
|
||||
};
|
||||
|
||||
// Virtual stream that holds properties for the HTTP/2 stream
|
||||
// Defaults to stream 0 global properties
|
||||
@ -17,11 +99,32 @@ struct H2Stream
|
||||
{
|
||||
HttpReqCallback callback;
|
||||
HttpResponseImplPtr response;
|
||||
HttpRequestPtr request;
|
||||
trantor::MsgBuffer body;
|
||||
std::optional<size_t> contentLength;
|
||||
int32_t streamId = 0;
|
||||
StreamState state = StreamState::ExpectingHeaders;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
enum class StreamCloseErrorCode
|
||||
{
|
||||
NoError = 0x0,
|
||||
ProtocolError = 0x1,
|
||||
InternalError = 0x2,
|
||||
FlowControlError = 0x3,
|
||||
SettingsTimeout = 0x4,
|
||||
StreamClosed = 0x5,
|
||||
FrameSizeError = 0x6,
|
||||
RefusedStream = 0x7,
|
||||
Cancel = 0x8,
|
||||
CompressionError = 0x9,
|
||||
ConnectError = 0xa,
|
||||
EnhanceYourCalm = 0xb,
|
||||
InadequateSecurity = 0xc,
|
||||
Http11Required = 0xd,
|
||||
};
|
||||
|
||||
class Http2Transport : public HttpTransport
|
||||
{
|
||||
private:
|
||||
@ -42,9 +145,21 @@ class Http2Transport : public HttpTransport
|
||||
size_t maxFrameSize = 16384;
|
||||
size_t avaliableWindowSize = 0;
|
||||
|
||||
// Configuration settings
|
||||
const size_t windowIncreaseThreshold = 32768;
|
||||
const size_t windowIncreaseSize = 10 * 1024 * 1024; // 10 MiB
|
||||
|
||||
// Set after server settings are received
|
||||
bool serverSettingsReceived = false;
|
||||
std::vector<std::pair<HttpRequestPtr, HttpReqCallback>> bufferedRequests;
|
||||
std::queue<std::pair<HttpRequestPtr, HttpReqCallback>> bufferedRequests;
|
||||
size_t avaliableWindow = 10 * 1024 * 1024; // 10 MiB
|
||||
|
||||
internal::H2Stream &createStream(int32_t streamId);
|
||||
void streamFinished(internal::H2Stream &stream);
|
||||
void streamFinished(int32_t streamId,
|
||||
ReqResult result,
|
||||
StreamCloseErrorCode errorCode,
|
||||
std::string errorMsg = "");
|
||||
|
||||
int32_t nextStreamId()
|
||||
{
|
||||
@ -78,6 +193,10 @@ class Http2Transport : public HttpTransport
|
||||
}
|
||||
}
|
||||
|
||||
void handleFrameForStream(const internal::H2Frame &frame,
|
||||
int32_t streamId,
|
||||
uint8_t flags);
|
||||
|
||||
public:
|
||||
Http2Transport(trantor::TcpConnectionPtr connPtr,
|
||||
size_t *bytesSent,
|
||||
@ -99,10 +218,7 @@ class Http2Transport : public HttpTransport
|
||||
"HTTP/2 handleConnectionClose not implemented");
|
||||
}
|
||||
|
||||
void onError(ReqResult result) override
|
||||
{
|
||||
throw std::runtime_error("HTTP/2 onError not implemented");
|
||||
}
|
||||
void onError(ReqResult result) override;
|
||||
|
||||
protected:
|
||||
void onServerSettingsReceived(){};
|
||||
|
@ -109,6 +109,9 @@ const char *HttpResponseImpl::versionString() const
|
||||
case Version::kHttp11:
|
||||
result = "HTTP/1.1";
|
||||
break;
|
||||
case Version::kHttp2:
|
||||
result = "HTTP/2";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user