aboutsummaryrefslogtreecommitdiff
path: root/src/zenhttp
diff options
context:
space:
mode:
Diffstat (limited to 'src/zenhttp')
-rw-r--r--src/zenhttp/auth/oidc.cpp24
-rw-r--r--src/zenhttp/clients/httpclientcommon.cpp5
-rw-r--r--src/zenhttp/clients/httpwsclient.cpp8
-rw-r--r--src/zenhttp/include/zenhttp/httpclient.h14
-rw-r--r--src/zenhttp/include/zenhttp/httpserver.h2
-rw-r--r--src/zenhttp/include/zenhttp/packageformat.h2
-rw-r--r--src/zenhttp/include/zenhttp/websocket.h2
-rw-r--r--src/zenhttp/servers/httpparser.cpp8
-rw-r--r--src/zenhttp/servers/httpparser.h2
-rw-r--r--src/zenhttp/servers/httpplugin.cpp4
-rw-r--r--src/zenhttp/servers/httptracer.h4
-rw-r--r--src/zenhttp/servers/wsasio.cpp6
-rw-r--r--src/zenhttp/servers/wsasio.h2
-rw-r--r--src/zenhttp/servers/wsframecodec.cpp7
-rw-r--r--src/zenhttp/servers/wshttpsys.cpp6
-rw-r--r--src/zenhttp/servers/wshttpsys.h2
16 files changed, 59 insertions, 39 deletions
diff --git a/src/zenhttp/auth/oidc.cpp b/src/zenhttp/auth/oidc.cpp
index 38e7586ad..23bbc17e8 100644
--- a/src/zenhttp/auth/oidc.cpp
+++ b/src/zenhttp/auth/oidc.cpp
@@ -32,6 +32,25 @@ namespace details {
using namespace std::literals;
+static std::string
+FormUrlEncode(std::string_view Input)
+{
+ std::string Result;
+ Result.reserve(Input.size());
+ for (char C : Input)
+ {
+ if ((C >= 'A' && C <= 'Z') || (C >= 'a' && C <= 'z') || (C >= '0' && C <= '9') || C == '-' || C == '_' || C == '.' || C == '~')
+ {
+ Result.push_back(C);
+ }
+ else
+ {
+ Result.append(fmt::format("%{:02X}", static_cast<uint8_t>(C)));
+ }
+ }
+ return Result;
+}
+
OidcClient::OidcClient(const OidcClient::Options& Options)
{
m_BaseUrl = std::string(Options.BaseUrl);
@@ -67,6 +86,8 @@ OidcClient::Initialize()
.TokenEndpoint = Json["token_endpoint"].string_value(),
.UserInfoEndpoint = Json["userinfo_endpoint"].string_value(),
.RegistrationEndpoint = Json["registration_endpoint"].string_value(),
+ .EndSessionEndpoint = Json["end_session_endpoint"].string_value(),
+ .DeviceAuthorizationEndpoint = Json["device_authorization_endpoint"].string_value(),
.JwksUri = Json["jwks_uri"].string_value(),
.SupportedResponseTypes = details::ToStringArray(Json["response_types_supported"]),
.SupportedResponseModes = details::ToStringArray(Json["response_modes_supported"]),
@@ -81,7 +102,8 @@ OidcClient::Initialize()
OidcClient::RefreshTokenResult
OidcClient::RefreshToken(std::string_view RefreshToken)
{
- const std::string Body = fmt::format("grant_type=refresh_token&refresh_token={}&client_id={}", RefreshToken, m_ClientId);
+ const std::string Body =
+ fmt::format("grant_type=refresh_token&refresh_token={}&client_id={}", FormUrlEncode(RefreshToken), FormUrlEncode(m_ClientId));
HttpClient Http{m_Config.TokenEndpoint};
diff --git a/src/zenhttp/clients/httpclientcommon.cpp b/src/zenhttp/clients/httpclientcommon.cpp
index 9ded23375..6f4c67dd0 100644
--- a/src/zenhttp/clients/httpclientcommon.cpp
+++ b/src/zenhttp/clients/httpclientcommon.cpp
@@ -142,7 +142,10 @@ namespace detail {
DataSize -= CopySize;
if (m_CacheBufferOffset == CacheBufferSize)
{
- AppendData(m_CacheBuffer, CacheBufferSize);
+ if (std::error_code Ec = AppendData(m_CacheBuffer, CacheBufferSize))
+ {
+ return Ec;
+ }
if (DataSize > 0)
{
ZEN_ASSERT(DataSize < CacheBufferSize);
diff --git a/src/zenhttp/clients/httpwsclient.cpp b/src/zenhttp/clients/httpwsclient.cpp
index 36a6f081b..9497dadb8 100644
--- a/src/zenhttp/clients/httpwsclient.cpp
+++ b/src/zenhttp/clients/httpwsclient.cpp
@@ -351,9 +351,8 @@ struct HttpWsClient::Impl
}
// Echo masked close frame if we haven't sent one yet
- if (!m_CloseSent)
+ if (!m_CloseSent.exchange(true))
{
- m_CloseSent = true;
std::vector<uint8_t> CloseFrame = WsFrameCodec::BuildMaskedCloseFrame(Code);
EnqueueWrite(std::move(CloseFrame));
}
@@ -479,9 +478,8 @@ struct HttpWsClient::Impl
return;
}
- if (!m_CloseSent)
+ if (!m_CloseSent.exchange(true))
{
- m_CloseSent = true;
std::vector<uint8_t> CloseFrame = WsFrameCodec::BuildMaskedCloseFrame(Code, Reason);
EnqueueWrite(std::move(CloseFrame));
}
@@ -515,7 +513,7 @@ struct HttpWsClient::Impl
bool m_IsWriting = false;
std::atomic<bool> m_IsOpen{false};
- bool m_CloseSent = false;
+ std::atomic<bool> m_CloseSent{false};
};
//////////////////////////////////////////////////////////////////////////
diff --git a/src/zenhttp/include/zenhttp/httpclient.h b/src/zenhttp/include/zenhttp/httpclient.h
index d87082d10..bec4984db 100644
--- a/src/zenhttp/include/zenhttp/httpclient.h
+++ b/src/zenhttp/include/zenhttp/httpclient.h
@@ -128,7 +128,7 @@ public:
struct ErrorContext
{
- int ErrorCode;
+ int ErrorCode = 0;
std::string ErrorMessage;
/** True when the error is a transport-level connection failure (connect timeout, refused, DNS) */
@@ -179,19 +179,19 @@ public:
KeyValueMap Header;
// The number of bytes sent as part of the request
- int64_t UploadedBytes;
+ int64_t UploadedBytes = 0;
// The number of bytes received as part of the response
- int64_t DownloadedBytes;
+ int64_t DownloadedBytes = 0;
// The elapsed time in seconds for the request to execute
- double ElapsedSeconds;
+ double ElapsedSeconds = 0.0;
struct MultipartBoundary
{
- uint64_t OffsetInPayload;
- uint64_t RangeOffset;
- uint64_t RangeLength;
+ uint64_t OffsetInPayload = 0;
+ uint64_t RangeOffset = 0;
+ uint64_t RangeLength = 0;
HttpContentType ContentType;
};
diff --git a/src/zenhttp/include/zenhttp/httpserver.h b/src/zenhttp/include/zenhttp/httpserver.h
index 02cccc540..c1152dc3e 100644
--- a/src/zenhttp/include/zenhttp/httpserver.h
+++ b/src/zenhttp/include/zenhttp/httpserver.h
@@ -440,7 +440,7 @@ public:
~HttpRpcHandler();
HttpRpcHandler(const HttpRpcHandler&) = delete;
- HttpRpcHandler operator=(const HttpRpcHandler&) = delete;
+ HttpRpcHandler& operator=(const HttpRpcHandler&) = delete;
void AddRpc(std::string_view RpcId, std::function<void(CbObject& RpcArgs)> HandlerFunction);
diff --git a/src/zenhttp/include/zenhttp/packageformat.h b/src/zenhttp/include/zenhttp/packageformat.h
index c90b840da..1a5068580 100644
--- a/src/zenhttp/include/zenhttp/packageformat.h
+++ b/src/zenhttp/include/zenhttp/packageformat.h
@@ -68,7 +68,7 @@ struct CbAttachmentEntry
struct CbAttachmentReferenceHeader
{
uint64_t PayloadByteOffset = 0;
- uint64_t PayloadByteSize = ~0u;
+ uint64_t PayloadByteSize = ~uint64_t(0);
uint16_t AbsolutePathLength = 0;
// This header will be followed by UTF8 encoded absolute path to backing file
diff --git a/src/zenhttp/include/zenhttp/websocket.h b/src/zenhttp/include/zenhttp/websocket.h
index 7a6fb33dd..bc3293282 100644
--- a/src/zenhttp/include/zenhttp/websocket.h
+++ b/src/zenhttp/include/zenhttp/websocket.h
@@ -22,7 +22,7 @@ enum class WebSocketOpcode : uint8_t
struct WebSocketMessage
{
- WebSocketOpcode Opcode;
+ WebSocketOpcode Opcode = WebSocketOpcode::kText;
IoBuffer Payload;
uint16_t CloseCode = 0;
};
diff --git a/src/zenhttp/servers/httpparser.cpp b/src/zenhttp/servers/httpparser.cpp
index 3b1229375..918b55dc6 100644
--- a/src/zenhttp/servers/httpparser.cpp
+++ b/src/zenhttp/servers/httpparser.cpp
@@ -245,13 +245,6 @@ NormalizeUrlPath(std::string_view InUrl, std::string& NormalizedUrl)
NormalizedUrl.reserve(UrlLength);
NormalizedUrl.append(Url, UrlIndex);
}
-
- // NOTE: this check is redundant given the enclosing if,
- // need to verify the intent of this code
- if (!LastCharWasSeparator)
- {
- NormalizedUrl.push_back('/');
- }
}
else if (!NormalizedUrl.empty())
{
@@ -389,6 +382,7 @@ HttpRequestParser::ResetState()
m_UpgradeHeaderIndex = -1;
m_SecWebSocketKeyHeaderIndex = -1;
m_SecWebSocketVersionHeaderIndex = -1;
+ m_RequestVerb = HttpVerb::kGet;
m_Expect100Continue = false;
m_BodyBuffer = {};
m_BodyPosition = 0;
diff --git a/src/zenhttp/servers/httpparser.h b/src/zenhttp/servers/httpparser.h
index d40a5aeb0..23ad9d8fb 100644
--- a/src/zenhttp/servers/httpparser.h
+++ b/src/zenhttp/servers/httpparser.h
@@ -93,7 +93,7 @@ private:
int8_t m_UpgradeHeaderIndex;
int8_t m_SecWebSocketKeyHeaderIndex;
int8_t m_SecWebSocketVersionHeaderIndex;
- HttpVerb m_RequestVerb;
+ HttpVerb m_RequestVerb = HttpVerb::kGet;
std::atomic_bool m_KeepAlive{false};
bool m_Expect100Continue = false;
int m_RequestId = -1;
diff --git a/src/zenhttp/servers/httpplugin.cpp b/src/zenhttp/servers/httpplugin.cpp
index 8564826d6..850dafdca 100644
--- a/src/zenhttp/servers/httpplugin.cpp
+++ b/src/zenhttp/servers/httpplugin.cpp
@@ -123,7 +123,7 @@ struct HttpPluginServerImpl : public HttpPluginServer, TransportServer
bool m_IsRequestLoggingEnabled = false;
LoggerRef m_RequestLog;
std::atomic_uint32_t m_ConnectionIdCounter{0};
- int m_BasePort;
+ int m_BasePort = 0;
HttpServerTracer m_RequestTracer;
@@ -294,7 +294,7 @@ HttpPluginConnectionHandler::Initialize(TransportConnection* Transport, HttpPlug
ConnectionName = "anonymous";
}
- ZEN_LOG_TRACE(m_Server->m_RequestLog, "NEW connection #{} ('')", m_ConnectionId, ConnectionName);
+ ZEN_LOG_TRACE(m_Server->m_RequestLog, "NEW connection #{} ('{}')", m_ConnectionId, ConnectionName);
}
uint32_t
diff --git a/src/zenhttp/servers/httptracer.h b/src/zenhttp/servers/httptracer.h
index da72c79c9..a9a45f162 100644
--- a/src/zenhttp/servers/httptracer.h
+++ b/src/zenhttp/servers/httptracer.h
@@ -1,9 +1,9 @@
// Copyright Epic Games, Inc. All Rights Reserved.
-#include <zenhttp/httpserver.h>
-
#pragma once
+#include <zenhttp/httpserver.h>
+
namespace zen {
/** Helper class for HTTP server implementations
diff --git a/src/zenhttp/servers/wsasio.cpp b/src/zenhttp/servers/wsasio.cpp
index dfc1eac38..3e31b58bc 100644
--- a/src/zenhttp/servers/wsasio.cpp
+++ b/src/zenhttp/servers/wsasio.cpp
@@ -140,9 +140,8 @@ WsAsioConnection::ProcessReceivedData()
}
// Echo close frame back if we haven't sent one yet
- if (!m_CloseSent)
+ if (!m_CloseSent.exchange(true))
{
- m_CloseSent = true;
std::vector<uint8_t> CloseFrame = WsFrameCodec::BuildCloseFrame(Code);
EnqueueWrite(std::move(CloseFrame));
}
@@ -208,9 +207,8 @@ WsAsioConnection::DoClose(uint16_t Code, std::string_view Reason)
return;
}
- if (!m_CloseSent)
+ if (!m_CloseSent.exchange(true))
{
- m_CloseSent = true;
std::vector<uint8_t> CloseFrame = WsFrameCodec::BuildCloseFrame(Code, Reason);
EnqueueWrite(std::move(CloseFrame));
}
diff --git a/src/zenhttp/servers/wsasio.h b/src/zenhttp/servers/wsasio.h
index a638ea836..d8ffdc00a 100644
--- a/src/zenhttp/servers/wsasio.h
+++ b/src/zenhttp/servers/wsasio.h
@@ -65,7 +65,7 @@ private:
bool m_IsWriting = false;
std::atomic<bool> m_IsOpen{true};
- bool m_CloseSent = false;
+ std::atomic<bool> m_CloseSent{false};
};
} // namespace zen::asio_http
diff --git a/src/zenhttp/servers/wsframecodec.cpp b/src/zenhttp/servers/wsframecodec.cpp
index a4c5e0f16..e452141fe 100644
--- a/src/zenhttp/servers/wsframecodec.cpp
+++ b/src/zenhttp/servers/wsframecodec.cpp
@@ -51,6 +51,13 @@ WsFrameCodec::TryParseFrame(const uint8_t* Data, size_t Size)
HeaderSize = 10;
}
+ // Reject frames with unreasonable payload sizes to prevent OOM
+ static constexpr uint64_t kMaxPayloadSize = 256 * 1024 * 1024; // 256 MB
+ if (PayloadLen > kMaxPayloadSize)
+ {
+ return {};
+ }
+
const size_t MaskSize = Masked ? 4 : 0;
const size_t TotalFrame = HeaderSize + MaskSize + PayloadLen;
diff --git a/src/zenhttp/servers/wshttpsys.cpp b/src/zenhttp/servers/wshttpsys.cpp
index 3f0f0b447..3408b64b3 100644
--- a/src/zenhttp/servers/wshttpsys.cpp
+++ b/src/zenhttp/servers/wshttpsys.cpp
@@ -217,9 +217,8 @@ WsHttpSysConnection::ProcessReceivedData()
bool ShouldSendClose = false;
{
RwLock::ExclusiveLockScope _(m_WriteLock);
- if (!m_CloseSent)
+ if (!m_CloseSent.exchange(true))
{
- m_CloseSent = true;
ShouldSendClose = true;
}
}
@@ -412,9 +411,8 @@ WsHttpSysConnection::DoClose(uint16_t Code, std::string_view Reason)
bool ShouldSendClose = false;
{
RwLock::ExclusiveLockScope _(m_WriteLock);
- if (!m_CloseSent)
+ if (!m_CloseSent.exchange(true))
{
- m_CloseSent = true;
ShouldSendClose = true;
}
}
diff --git a/src/zenhttp/servers/wshttpsys.h b/src/zenhttp/servers/wshttpsys.h
index ab0ca381a..d854289e0 100644
--- a/src/zenhttp/servers/wshttpsys.h
+++ b/src/zenhttp/servers/wshttpsys.h
@@ -96,7 +96,7 @@ private:
Ref<WsHttpSysConnection> m_SelfRef;
std::atomic<bool> m_ShutdownRequested{false};
std::atomic<bool> m_IsOpen{true};
- bool m_CloseSent = false;
+ std::atomic<bool> m_CloseSent{false};
};
} // namespace zen