mirror of
https://github.com/MyLuxy/overdrive.git
synced 2026-10-24 14:01:31 +02:00
108 lines
4.5 KiB
C++
108 lines
4.5 KiB
C++
// Copyright (C) 2026 half144 and PS5 React contributors
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
// Additional attribution term: see LICENSE-ATTRIBUTION.
|
|
#include "network.hpp"
|
|
#include "image_loader.hpp"
|
|
#include "app_config.hpp"
|
|
#include "filesystem_access.hpp"
|
|
#include "platform/ps5/system.hpp"
|
|
#include <cstdio>
|
|
#include <string>
|
|
#include <unistd.h>
|
|
#if PS5_REACT_NETWORKING
|
|
extern "C" {
|
|
int sceNetInit(void);
|
|
int sceNetTerm(void);
|
|
int sceNetPoolCreate(const char*, int, int);
|
|
int sceNetPoolDestroy(int);
|
|
}
|
|
namespace network {
|
|
namespace {
|
|
int pool = -1; bool initialized = false;
|
|
constexpr const char* kSystemStore = "/system/common/cert/CA_LIST.cer";
|
|
constexpr const char* kCertificate = "-----BEGIN CERTIFICATE-----";
|
|
char store[256] = "/system/common/cert/CA_LIST.cer";
|
|
|
|
bool read_file(const char* path, std::string& out) {
|
|
FILE* file = std::fopen(path, "rb");
|
|
if (!file) return false;
|
|
out.clear();
|
|
char buffer[16384];
|
|
std::size_t n;
|
|
while ((n = std::fread(buffer, 1, sizeof buffer, file)) > 0) out.append(buffer, n);
|
|
const bool ok = !std::ferror(file);
|
|
std::fclose(file);
|
|
return ok;
|
|
}
|
|
|
|
// Old firmwares' store lacks roots that sites moved to since (4.03 fails GitHub and the cover servers).
|
|
// The app ships Mozilla's (certs/cacert.pem); both go into one file in the cache, passed to curl by path
|
|
// so each transfer pool loads one store and reuses it. Anything missing keeps the system store alone.
|
|
void merge_certificates() {
|
|
char bundle[256], merged[256];
|
|
std::string system, extra, current;
|
|
if (!resolve_filesystem_path("/app0/certs/cacert.pem", bundle, sizeof bundle) ||
|
|
!resolve_filesystem_path("/cache0/ca-bundle.pem", merged, sizeof merged)) {
|
|
hui::sys::log("[PS5-REACT] certificates: no path for the bundle; system store only"); return;
|
|
}
|
|
if (!read_file(bundle, extra) || extra.find(kCertificate) == std::string::npos) {
|
|
hui::sys::log("[PS5-REACT] certificates: %s unreadable; system store only", bundle); return;
|
|
}
|
|
if (!read_file(kSystemStore, system) || system.find(kCertificate) == std::string::npos) {
|
|
hui::sys::log("[PS5-REACT] certificates: the system store is not PEM; system store only"); return;
|
|
}
|
|
if (system.back() != '\n') system += '\n';
|
|
system += extra;
|
|
extra = std::string();
|
|
if (!read_file(merged, current) || current != system) {
|
|
const std::string temporary = std::string(merged) + ".tmp";
|
|
bool written = false;
|
|
if (FILE* file = std::fopen(temporary.c_str(), "wb")) {
|
|
written = std::fwrite(system.data(), 1, system.size(), file) == system.size();
|
|
written = std::fclose(file) == 0 && written;
|
|
}
|
|
if (!written || std::rename(temporary.c_str(), merged) != 0) {
|
|
std::remove(temporary.c_str());
|
|
hui::sys::log("[PS5-REACT] certificates: cannot write %s; system store only", merged); return;
|
|
}
|
|
}
|
|
std::snprintf(store, sizeof store, "%s", merged);
|
|
hui::sys::log("[PS5-REACT] certificates: system store + bundle, %zu bytes", system.size());
|
|
}
|
|
}
|
|
bool platform_start(std::string& error) {
|
|
if (!console_filesystem_accessible()) {
|
|
error = "native networking requires successful console filesystem elevation"; return false;
|
|
}
|
|
if (access(kSystemStore, R_OK) != 0) {
|
|
error = "native networking cannot read the system certificate store"; return false;
|
|
}
|
|
merge_certificates();
|
|
initialized = sceNetInit() == 0;
|
|
pool = sceNetPoolCreate("ps5-react-http", 1024*1024, 0);
|
|
if (pool < 0) {
|
|
if (initialized) sceNetTerm(); initialized = false;
|
|
error = "native networking could not create its libSceNet pool"; return false;
|
|
}
|
|
return true;
|
|
}
|
|
void platform_stop() {
|
|
if (pool >= 0) sceNetPoolDestroy(pool);
|
|
if (initialized) sceNetTerm();
|
|
pool = -1; initialized = false;
|
|
}
|
|
const char* ca_path() { return store; }
|
|
// The title's heap (platform app_heap.c), so download telemetry shows how close it runs.
|
|
extern "C" void hui_heap_stats(std::size_t* live_bytes, std::size_t* peak_bytes, std::size_t* blocks, std::size_t* failures);
|
|
extern "C" void hui_heap_capacity(std::size_t* size, std::size_t* flexible_before, std::size_t* flexible_after);
|
|
void platform_log(const char* line) {
|
|
std::size_t live = 0, peak = 0, blocks = 0, failures = 0, size = 0;
|
|
hui_heap_stats(&live, &peak, &blocks, &failures);
|
|
hui_heap_capacity(&size, nullptr, nullptr);
|
|
const images::Memory image = images::memory();
|
|
hui::sys::log("[PS5-REACT] %s heap=%zu/%zuMiB peak=%zuMiB failed=%zu img=%zu+%zuMiB", line, live >> 20, size >> 20,
|
|
peak >> 20, failures, image.encoded >> 20, image.decoded >> 20);
|
|
}
|
|
}
|
|
#endif
|