Avoid the HTTP request on sceNetAdhoc init by reading from cache

This commit is contained in:
Henrik Rydgård committed 2026-03-09 10:50:24 +01:00
1 parent 8c8dd0f0d0
commit ae08b31573
3 files changed
+50 -22

No files matched your search

+38 -18
View File
@@ -115,12 +115,13 @@ static const char *AdhocDataModeToString(AdhocDataMode mode) {
return "unknown";
}
// TODO download the list from somewhere and probably cache it on disk
// should also make the url configurable and support file:/ local list besides https:// online lists
// We download the list and cache it on disk.
// The URL can also be a local file path, in which case the download doesn't happen. This is only
// for power users / debugging.
std::mutex g_proAdhocServerListMutex;
std::vector<AdhocServerListEntry> g_proAdhocServerList;
bool ParseServerListEntriesJSON(std::string_view json) {
static bool ParseServerListEntriesJSON(std::string_view json) {
using namespace json;
// Use our JSONReader to parse json into a list of AdhocServerListEntry.
@@ -148,6 +149,7 @@ bool ParseServerListEntriesJSON(std::string_view json) {
entry.location = server.getStringOr("location", "");
entry.description = server.getStringOr("description", "");
entry.mode = equals(server.getStringOr("data_mode", ""), "AemuPostoffice") ? AdhocDataMode::AemuPostoffice : AdhocDataMode::P2P;
entry.statusUrl = server.getStringOr("status_url", "");
if (entry.host.empty()) {
// Skipping invalid entry.
@@ -178,7 +180,7 @@ static void LoadFallbackServerList() {
g_serverListLoaded = true;
}
void AdhocLoadServerList(bool sync) {
void AdhocLoadServerList(AdhocLoadListMode loadMode) {
{
std::lock_guard<std::mutex> guard(g_proAdhocServerListMutex);
if (!g_proAdhocServerList.empty()) {
@@ -190,6 +192,19 @@ void AdhocLoadServerList(bool sync) {
// There's currently no file:// support, as far as I remember.
if (startsWith(g_Config.sAdhocServerListUrl, "http")) {
if (loadMode == AdhocLoadListMode::CacheOnlySync) {
std::string json;
if (g_DownloadManager.ReadFileFromCache(g_Config.sAdhocServerListUrl, &json)) {
if (ParseServerListEntriesJSON(std::string_view(json.data(), json.size()))) {
g_serverListLoaded = true;
return;
}
}
ERROR_LOG(Log::sceNet, "Failed to load cached adhoc server list %s from cache, falling back.", g_Config.sAdhocServerListUrl.c_str());
LoadFallbackServerList();
return;
}
// Download the list.
auto dl = g_DownloadManager.StartDownload(g_Config.sAdhocServerListUrl, Path(), http::RequestFlags::Cached24H, nullptr, "adhoc-servers", [url = g_Config.sAdhocServerListUrl](http::Request &request) {
if (request.Failed()) {
@@ -207,15 +222,6 @@ void AdhocLoadServerList(bool sync) {
return;
}
});
if (sync) {
// Unfortunate.
do {
sleep_ms(10, "waiting-for-adhoc-server-list");
g_DownloadManager.Update();
} while (!dl->HasRunCallback());
dl.reset();
}
g_serverListLoaded = true;
} else if (!g_Config.sAdhocServerListUrl.empty()) {
// Try to read local file.
@@ -234,11 +240,11 @@ void AdhocLoadServerList(bool sync) {
}
}
std::vector<AdhocServerListEntry> AdhocGetServerList(bool sync) {
std::vector<AdhocServerListEntry> AdhocGetServerList(AdhocLoadListMode loadMode) {
if (!g_serverListLoaded) {
// In-game - unfortunately we have to do a synchronous load here.
// If cached it will be fast though.
AdhocLoadServerList(sync);
// We're probably in-game - so we don't want to do a download and risk blocking.
// Instead we read out of cache, it should be good enough.
AdhocLoadServerList(loadMode);
}
std::lock_guard<std::mutex> guard(g_proAdhocServerListMutex);
@@ -246,7 +252,7 @@ std::vector<AdhocServerListEntry> AdhocGetServerList(bool sync) {
}
static AdhocDataMode AdhocGetServerDataMode(std::string_view server) {
std::vector<AdhocServerListEntry> list = AdhocGetServerList(true);
std::vector<AdhocServerListEntry> list = AdhocGetServerList(AdhocLoadListMode::CacheOnlySync);
for (const auto &item : list) {
if (equals(server, item.host)) {
INFO_LOG(Log::sceNet, "server %.*s is in known list, using data mode %s", STR_VIEW(server), AdhocDataModeToString(item.mode));
@@ -254,6 +260,20 @@ static AdhocDataMode AdhocGetServerDataMode(std::string_view server) {
}
}
for (const auto &item : g_Config.vCustomAdhocServerList) {
if (equals(server, item)) {
INFO_LOG(Log::sceNet, "server %.*s is in custom list without relay, using data mode %s", STR_VIEW(server), AdhocDataModeToString(AdhocDataMode::P2P));
return AdhocDataMode::P2P;
}
}
for (const auto &item : g_Config.vCustomAdhocServerListWithRelay) {
if (equals(server, item)) {
INFO_LOG(Log::sceNet, "server %.*s is in custom list with relay, using data mode %s", STR_VIEW(server), AdhocDataModeToString(AdhocDataMode::AemuPostoffice));
return AdhocDataMode::AemuPostoffice;
}
}
INFO_LOG(Log::sceNet, "server %.*s is not in known list, using data mode %s", STR_VIEW(server), AdhocDataModeToString(AdhocDataMode::P2P));
return AdhocDataMode::P2P;
}
+8 -2
View File
@@ -111,11 +111,17 @@ struct AdhocServerListEntry {
std::string discord;
std::string location;
std::string description;
std::string statusUrl; // Usually empty or /data.json.
AdhocDataMode mode = AdhocDataMode::P2P;
};
void AdhocLoadServerList(bool sync = false);
std::vector<AdhocServerListEntry> AdhocGetServerList(bool sync = false);
enum class AdhocLoadListMode {
CacheOnlySync,
AllSourcesAsync,
};
void AdhocLoadServerList(AdhocLoadListMode loadMode);
std::vector<AdhocServerListEntry> AdhocGetServerList(AdhocLoadListMode loadMode);
class PointerWrap;
+4 -2
View File
@@ -164,7 +164,7 @@ AdhocServerScreen::AdhocServerScreen(std::string *value, std::string_view title)
thiz->ResolverThread();
}, this);
editValue_ = *value;
AdhocLoadServerList();
AdhocLoadServerList(AdhocLoadListMode::AllSourcesAsync);
}
AdhocServerScreen::~AdhocServerScreen() {
@@ -188,7 +188,9 @@ void AdhocServerScreen::CreatePopupContents(UI::ViewGroup *parent) {
auto di = GetI18NCategory(I18NCat::DIALOG);
auto n = GetI18NCategory(I18NCat::NETWORKING);
auto listItems = AdhocGetServerList();
// We already kicked off loading the server list in the constructor, so by now it should be either loaded or in the process of loading.
// We can get the cached list immediately, and then update it when the async load finishes.
auto listItems = AdhocGetServerList(AdhocLoadListMode::CacheOnlySync);
PopupTextInputChoice *textInputChoice = parent->Add(new PopupTextInputChoice(GetRequesterToken(), &editValue_, n->T("Hostname"), "", 450, screenManager()));
parent->Add(new Spacer(5.0f));