Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/libs/prx/libSceHttp/src/Curl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class CurlTransport final : public ITransport {
headers.append(line);
std::string name(line.substr(0, line.find(':')));
std::transform(name.begin(), name.end(), name.begin(), [](unsigned char c) { return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c; });
if (name == "location") redirectLocation = true;
if (name == "location" && line.substr(line.find(':') + 1).find_first_not_of(" \t\r\n") != std::string_view::npos) redirectLocation = true;
if (name == "content-length") {
auto text = line.substr(line.find(':') + 1);
while (!text.empty() && (text.front() == ' ' || text.front() == '\t')) text.remove_prefix(1);
Expand Down
8 changes: 8 additions & 0 deletions core/libs/tests/GuestHttpNetwork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,14 @@ int main(int argc, char** argv) {
const auto redirect = Get(connection, "/redirect");
Require(sceHttpGetStatusCode(redirect, &status) == 0 && status == 200 && ReadBody(redirect) == "final", "redirect following");
Require(sceHttpDeleteRequest(redirect) == 0, "redirect cleanup");
#ifdef __linux__
for (const auto* path : {"/emptyredirect", "/blankredirect"}) {
const auto emptyRedirect = Get(connection, path);
Require(sceHttpGetStatusCode(emptyRedirect, &status) == 0 && status == 302, "empty redirect changed status");
Require(ReadBody(emptyRedirect) == "no destination", "empty redirect discarded response body");
Require(sceHttpDeleteRequest(emptyRedirect) == 0, "empty redirect cleanup");
}
#endif
const auto noRedirect = sceHttpCreateRequest(connection, 0, "/redirect", 0);
Require(sceHttpSetAutoRedirect(noRedirect, 0) == 0 && sceHttpSendRequest(noRedirect, nullptr, 0) == 0, "redirect-disabled send");
Require(sceHttpGetStatusCode(noRedirect, &status) == 0 && status == 302 && ReadBody(noRedirect).empty(), "redirect-disabled response");
Expand Down
2 changes: 2 additions & 0 deletions core/libs/tests/http/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ def do_GET(self):
self.close_connection = True
elif self.path == "/redirect":
self.response(302, b"", [("Location", "/final")])
elif self.path in ("/emptyredirect", "/blankredirect"):
self.response(302, b"no destination", [("Location", "" if self.path == "/emptyredirect" else " \t ")])
elif self.path == "/headers":
body = "|".join([self.headers.get("X-Inherited", ""), ",".join(self.headers.get_all("X-Value", [])), self.headers.get("User-Agent", "")])
self.response(200, body.encode())
Expand Down
2 changes: 1 addition & 1 deletion docs/dev/debt/libSceHttp.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@

- [sceHttpAbortWaitRequest, sceHttpWaitRequest](../../../core/libs/prx/libSceHttp/Export.cpp) (libSceHttp) - the abort takes only the epoll handle, as in [Orbital](https://github.com/AlexAltea/orbital/blob/master/tools/ida/db_types.json) and [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/main/src/SharpProspero/Interop/Net/Http.cs); behaviour and error codes follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/main/src/core/libraries/network/http.cpp) (PS4), not confirmed on a PS5 title or hardware. An abort stays set: every later wait on the handle, a poll included, returns `SCE_HTTP_ERROR_ABORTED` (0x80431080) until the handle is destroyed. A wait woken by `sceHttpDestroyEpoll`, or by the `sceHttpTerm` that ends the last context, returns 0 events. The epoll calls return `BEFORE_INIT` (0x80431001) while no `sceHttpInit` context is alive and `INVALID_ID` (0x80431100) for an unknown context or handle, and `sceHttpTerm` returns the same errors instead of succeeding for any id. Handles are pointers, so a stale handle whose address a newer epoll reuses is taken as that epoll

- [Linux HTTP transport](../../../core/libs/prx/libSceHttp/src/Curl.cpp) - the response body is streamed through a 64 KiB host buffer. DNS, connect, upload and receive deadlines use host timing with 25 ms polling, not console measurements. DNS cancellation depends on the host resolver returning. The host CA bundle and curl/mbedTLS diagnostics replace the console trust store and errno details. Certificate callbacks apply the inherited TLS flag assumptions; certificate-loading APIs, nonblocking requests and guest callback dispatch remain unsupported. No title progression is established by loopback tests.
- [Linux HTTP transport](../../../core/libs/prx/libSceHttp/src/Curl.cpp) - the response body is streamed through a 64 KiB host buffer. Empty or whitespace-only Location headers do not suppress the response body, matching curl's header handling; console redirect behaviour is unmeasured. DNS, connect, upload and receive deadlines use host timing with 25 ms polling, not console measurements. DNS cancellation depends on the host resolver returning. The host CA bundle and curl/mbedTLS diagnostics replace the console trust store and errno details. Certificate callbacks apply the inherited TLS flag assumptions; certificate-loading APIs, nonblocking requests and guest callback dispatch remain unsupported. No title progression is established by loopback tests.
Loading