aboutsummaryrefslogtreecommitdiff
path: root/zenhttp/httpsys.cpp
diff options
context:
space:
mode:
authorPer Larsson <[email protected]>2021-12-09 17:01:57 +0100
committerPer Larsson <[email protected]>2021-12-09 17:01:57 +0100
commit20f3c16b0012cfb8ce7bf9b6dd06a2720b6885c6 (patch)
treefbb0f274840a12c32d93c7e342c0427f2617a651 /zenhttp/httpsys.cpp
parentDisabled cache tracker. (diff)
parentReturn status_code as ErrorCode from jupiter api if not successful (diff)
downloadzen-20f3c16b0012cfb8ce7bf9b6dd06a2720b6885c6.tar.xz
zen-20f3c16b0012cfb8ce7bf9b6dd06a2720b6885c6.zip
Merged main.
Diffstat (limited to 'zenhttp/httpsys.cpp')
-rw-r--r--zenhttp/httpsys.cpp167
1 files changed, 64 insertions, 103 deletions
diff --git a/zenhttp/httpsys.cpp b/zenhttp/httpsys.cpp
index cdf9e0a39..e9472e3b8 100644
--- a/zenhttp/httpsys.cpp
+++ b/zenhttp/httpsys.cpp
@@ -748,15 +748,20 @@ HttpSysServer::~HttpSysServer()
}
void
-HttpSysServer::Initialize(const wchar_t* UrlPath)
+HttpSysServer::InitializeServer(int BasePort)
{
+ using namespace std::literals;
+
+ WideStringBuilder<64> WildcardUrlPath;
+ WildcardUrlPath << u8"http://*:"sv << int64_t(BasePort) << u8"/"sv;
+
m_IsOk = false;
ULONG Result = HttpCreateServerSession(HTTPAPI_VERSION_2, &m_HttpSessionId, 0);
if (Result != NO_ERROR)
{
- ZEN_ERROR("Failed to create server session for '{}': {:#x}", WideToUtf8(UrlPath), Result);
+ ZEN_ERROR("Failed to create server session for '{}': {:#x}", WideToUtf8(WildcardUrlPath), Result);
return;
}
@@ -765,18 +770,44 @@ HttpSysServer::Initialize(const wchar_t* UrlPath)
if (Result != NO_ERROR)
{
- ZEN_ERROR("Failed to create URL group for '{}': {:#x}", WideToUtf8(UrlPath), Result);
+ ZEN_ERROR("Failed to create URL group for '{}': {:#x}", WideToUtf8(WildcardUrlPath), Result);
return;
}
- m_BaseUri = UrlPath;
+ Result = HttpAddUrlToUrlGroup(m_HttpUrlGroupId, WildcardUrlPath.c_str(), HTTP_URL_CONTEXT(0), 0);
- Result = HttpAddUrlToUrlGroup(m_HttpUrlGroupId, UrlPath, HTTP_URL_CONTEXT(0), 0);
+ m_BaseUris.clear();
+ if (Result == NO_ERROR)
+ {
+ m_BaseUris.push_back(WildcardUrlPath.c_str());
+ }
+ else
+ {
+ // If we can't register the wildcard path, we fall back to local paths
+ // This local paths allow requests originating locally to function, but will not allow
+ // remote origin requests to function. This can be remedied by using netsh
+ // during an install process to grant permissions to route public access to the appropriate
+ // port for the current user. eg:
+ // netsh http add urlacl url=http://*:1337/ user=<some_user>
- if (Result != NO_ERROR)
+ const std::u8string_view Hosts[] = { u8"[::1]"sv, u8"localhost"sv, u8"127.0.0.1"sv };
+
+ for (const std::u8string_view Host : Hosts)
+ {
+ WideStringBuilder<64> LocalUrlPath;
+ LocalUrlPath << u8"http://"sv << Host << u8":"sv << int64_t(BasePort) << u8"/"sv;
+
+ if (HttpAddUrlToUrlGroup(m_HttpUrlGroupId, LocalUrlPath.c_str(), HTTP_URL_CONTEXT(0), 0) == NO_ERROR)
+ {
+ m_BaseUris.push_back(LocalUrlPath.c_str());
+ }
+ }
+ }
+
+ if (m_BaseUris.empty())
{
- ZEN_ERROR("Failed to add base URL to URL group for '{}': {:#x}", WideToUtf8(UrlPath), Result);
+ ZEN_ERROR("Failed to add base URL to URL group for '{}': {:#x}", WideToUtf8(WildcardUrlPath), Result);
return;
}
@@ -791,7 +822,7 @@ HttpSysServer::Initialize(const wchar_t* UrlPath)
if (Result != NO_ERROR)
{
- ZEN_ERROR("Failed to create request queue for '{}': {:#x}", WideToUtf8(UrlPath), Result);
+ ZEN_ERROR("Failed to create request queue for '{}': {:#x}", WideToUtf8(m_BaseUris.front()), Result);
return;
}
@@ -803,7 +834,7 @@ HttpSysServer::Initialize(const wchar_t* UrlPath)
if (Result != NO_ERROR)
{
- ZEN_ERROR("Failed to set server binding property for '{}': {:#x}", WideToUtf8(UrlPath), Result);
+ ZEN_ERROR("Failed to set server binding property for '{}': {:#x}", WideToUtf8(m_BaseUris.front()), Result);
return;
}
@@ -815,13 +846,13 @@ HttpSysServer::Initialize(const wchar_t* UrlPath)
if (ErrorCode)
{
- ZEN_ERROR("Failed to create IOCP for '{}': {}", WideToUtf8(UrlPath), ErrorCode.message());
+ ZEN_ERROR("Failed to create IOCP for '{}': {}", WideToUtf8(m_BaseUris.front()), ErrorCode.message());
}
else
{
m_IsOk = true;
- ZEN_INFO("Started http.sys server at '{}'", WideToUtf8(UrlPath));
+ ZEN_INFO("Started http.sys server at '{}'", WideToUtf8(m_BaseUris.front()));
}
}
@@ -952,15 +983,18 @@ HttpSysServer::RegisterService(const char* UrlPath, HttpService& Service)
// Convert to wide string
- std::wstring Url16 = m_BaseUri + PathUtf16;
+ for (const std::wstring& BaseUri : m_BaseUris)
+ {
+ std::wstring Url16 = BaseUri + PathUtf16;
- ULONG Result = HttpAddUrlToUrlGroup(m_HttpUrlGroupId, Url16.c_str(), HTTP_URL_CONTEXT(&Service), 0 /* Reserved */);
+ ULONG Result = HttpAddUrlToUrlGroup(m_HttpUrlGroupId, Url16.c_str(), HTTP_URL_CONTEXT(&Service), 0 /* Reserved */);
- if (Result != NO_ERROR)
- {
- ZEN_ERROR("HttpAddUrlToUrlGroup failed with result: '{}'", GetSystemErrorAsString(Result));
+ if (Result != NO_ERROR)
+ {
+ ZEN_ERROR("HttpAddUrlToUrlGroup failed with result: '{}'", GetSystemErrorAsString(Result));
- return;
+ return;
+ }
}
}
@@ -978,13 +1012,16 @@ HttpSysServer::UnregisterService(const char* UrlPath, HttpService& Service)
// Convert to wide string
- std::wstring Url16 = m_BaseUri + PathUtf16;
+ for (const std::wstring& BaseUri : m_BaseUris)
+ {
+ std::wstring Url16 = BaseUri + PathUtf16;
- ULONG Result = HttpRemoveUrlFromUrlGroup(m_HttpUrlGroupId, Url16.c_str(), 0);
+ ULONG Result = HttpRemoveUrlFromUrlGroup(m_HttpUrlGroupId, Url16.c_str(), 0);
- if (Result != NO_ERROR)
- {
- ZEN_ERROR("HttpRemoveUrlFromUrlGroup failed with result: '{}'", GetSystemErrorAsString(Result));
+ if (Result != NO_ERROR)
+ {
+ ZEN_ERROR("HttpRemoveUrlFromUrlGroup failed with result: '{}'", GetSystemErrorAsString(Result));
+ }
}
}
@@ -1131,83 +1168,12 @@ HttpSysTransaction::InvokeRequestHandler(HttpService& Service, IoBuffer Payload)
{
HttpSysServerRequest& ThisRequest = m_HandlerRequest.emplace(*this, Service, Payload);
- if (ThisRequest.RequestVerb() == HttpVerb::kPost)
- {
- if (ThisRequest.RequestContentType() == HttpContentType::kCbPackageOffer)
- {
- // The client is presenting us with a package attachments offer, we need
- // to filter it down to the list of attachments we need them to send in
- // the follow-up request
-
- m_PackageHandler = Service.HandlePackageRequest(ThisRequest);
-
- if (m_PackageHandler)
- {
- CbObject OfferMessage = LoadCompactBinaryObject(Payload);
-
- std::vector<IoHash> OfferCids;
-
- for (auto& CidEntry : OfferMessage["offer"])
- {
- if (!CidEntry.IsHash())
- {
- // Should yield bad request response?
-
- ZEN_WARN("found invalid entry in offer");
-
- continue;
- }
-
- OfferCids.push_back(CidEntry.AsHash());
- }
-
- ZEN_TRACE("request #{} -> filtering offer of {} entries", ThisRequest.RequestId(), OfferCids.size());
-
- m_PackageHandler->FilterOffer(OfferCids);
-
- ZEN_TRACE("request #{} -> filtered to {} entries", ThisRequest.RequestId(), OfferCids.size());
-
- CbObjectWriter ResponseWriter;
- ResponseWriter.BeginArray("need");
-
- for (const IoHash& Cid : OfferCids)
- {
- ResponseWriter.AddHash(Cid);
- }
-
- ResponseWriter.EndArray();
-
- // Emit filter response
- ThisRequest.WriteResponse(HttpResponseCode::OK, ResponseWriter.Save());
-
- return ThisRequest;
- }
- }
- else if (ThisRequest.RequestContentType() == HttpContentType::kCbPackage)
- {
- // Process chunks in package request
-
- m_PackageHandler = Service.HandlePackageRequest(ThisRequest);
-
- // TODO: this should really be done in a streaming fashion, currently this emulates
- // the intended flow from an API perspective
-
- if (m_PackageHandler)
- {
- m_PackageHandler->OnRequestBegin();
-
- auto CreateBuffer = [&](const IoHash& Cid, uint64_t Size) -> IoBuffer { return m_PackageHandler->CreateTarget(Cid, Size); };
-
- CbPackage Package = ParsePackageMessage(ThisRequest.ReadPayload(), CreateBuffer);
-
- m_PackageHandler->OnRequestComplete();
- }
- }
- }
-
// Default request handling
- Service.HandleRequest(ThisRequest);
+ if (!HandlePackageOffers(Service, ThisRequest, m_PackageHandler))
+ {
+ Service.HandleRequest(ThisRequest);
+ }
return ThisRequest;
}
@@ -1641,12 +1607,7 @@ InitialRequestHandler::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesT
void
HttpSysServer::Initialize(int BasePort)
{
- using namespace std::literals;
-
- WideStringBuilder<64> BaseUri;
- BaseUri << u8"http://*:"sv << int64_t(BasePort) << u8"/"sv;
-
- Initialize(BaseUri.c_str());
+ InitializeServer(BasePort);
StartServer();
}