mirror of
https://github.com/mihawk-99/PS5_RetroArch.git
synced 2026-10-22 00:22:29 -05:00
The WebUI's new SMB page signs in to one server (guest or a user and password), lists its shares, checks a share and folder and saves them in config/smb.cfg on the console; the password is never answered back. RetroArch's file browser shows the share as SMB, after INTERNAL and EXTERNAL. smb:// paths go through RetroArch's VFS to src/ps5_smb_vfs.c (patches/series 0136), read-only and only on the saved server: a core that reads through the VFS streams the file, one that opens paths itself gets a copy in /app0/smb-cache, removed when the content closes. libsmb2 is pinned at the master revision itsPLK/ps5-pkg-manager runs on the PS5 (LGPL-2.1-or-later), built by tools/build-libsmb2.sh for the PS5 and the host and listed in tooling/notices/components.json: RetroArch 1.22.2 has no SMB client. In a title, getaddrinfo is bound to the platform layer's, which resolves nothing, so libsmb2's resolver calls go to RetroArch's own (src/platform_wraps.c); readv, writev, getlogin_r and getprotobyname are wrapped, so libsmb2 adds no import. SMB sockets set SO_NOSIGPIPE. Evidence: evidence/smb-load-content (python3 tools/evidence.py compare evidence/): on the Base PS5 the console's WebUI listed the PC's guest share and saved share/smb-test; Load Content > SMB listed it and a homebrew NES ROM on it ran under FCEUmm, read through the VFS (build a2c7800a, retroarch.log read back over FTP). Gates: tools/verify.sh (format, unit 214, build, integration, evidence 140) with PS5_REUSE_STAGED_CORES=ps5sx2: in this worktree the SDK's prospero-lld wrapper adds -pie to ps5sx2's link (clang passes its long object list in a response file the wrapper cannot read), so ps5sx2 is the main checkout's build of the same pinned revision. Host tests run a Samba server of their own (tests/smb_server.py, no root). Co-Authored-By: Claude <noreply@anthropic.com>
62 lines
3.3 KiB
Python
62 lines
3.3 KiB
Python
"""Builds the WebUI's server for the host (the tests' fixtures): the given main, the
|
|
server's sources and its libraries, with defines. One list of sources for every test."""
|
|
from pathlib import Path
|
|
import http.client
|
|
import json
|
|
import socket
|
|
import subprocess
|
|
import time
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
SOURCES = ['src/webui_ps5.cpp', 'src/webui_transfer.cpp', 'src/webui_update.cpp', 'src/scraper.cpp',
|
|
'src/scraper_http.cpp', 'src/ps5_forwarders.cpp']
|
|
C_SOURCES = ['src/ps5_library.c', 'src/ps5_smb.c']
|
|
|
|
|
|
def build(output, main, defines=(), flags=('-O1', '-g')):
|
|
output = Path(output)
|
|
http = subprocess.check_output(['bash', 'tools/build-webui-http.sh', 'host'], cwd=ROOT, text=True).strip()
|
|
update = subprocess.check_output(['bash', 'tools/build-webui-update.sh', 'host'], cwd=ROOT, text=True).strip()
|
|
smb2 = subprocess.check_output(['bash', 'tools/build-libsmb2.sh', 'host'], cwd=ROOT, text=True).strip()
|
|
objects = []
|
|
for source in C_SOURCES:
|
|
obj = output.with_name(output.name + '-' + Path(source).stem + '.o')
|
|
subprocess.run(['cc', '-std=c11', '-D_DEFAULT_SOURCE', *flags, '-I' + smb2 + '/include', '-c', source, '-o', str(obj)], cwd=ROOT, check=True)
|
|
objects.append(str(obj))
|
|
subprocess.run(['c++', '-std=c++17', *flags, '-pthread', '-Isrc', '-I' + smb2 + '/include',
|
|
'-I' + str(ROOT / '.deps/webui/libmicrohttpd-1.0.10/src/include'),
|
|
'-I' + str(ROOT / '.deps/native/zlib/zlib-1.3.2/contrib/minizip'),
|
|
'-I' + str(ROOT / 'vendor/retroarch/deps/mbedtls'),
|
|
'-DPS5_SCRAPER_CURL', # the daemon's HTTP client, the host's libcurl
|
|
*[f'-D{d}' for d in defines], main, *SOURCES, *objects, http, update, smb2 + '/lib/libsmb2.a', '-lz', '-lcurl',
|
|
'-o', str(output)], cwd=ROOT, check=True)
|
|
return output
|
|
|
|
|
|
def start(binary, root, env=None, seconds=8.0):
|
|
"""Starts a server built above (tests/webui_server_main.cpp) for the title folder root on a
|
|
free port, once it answers: its process, port and session token. A port found free can be
|
|
taken before the server binds it (another connection gets it as its own port): the server
|
|
then exits at once, "Address already in use", and starts again on another."""
|
|
for _ in range(5):
|
|
with socket.socket() as probe:
|
|
probe.bind(('127.0.0.1', 0))
|
|
port = probe.getsockname()[1]
|
|
process = subprocess.Popen([str(binary), str(root), str(port)], env=env,
|
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
deadline = time.monotonic() + seconds
|
|
while process.poll() is None and time.monotonic() < deadline:
|
|
try:
|
|
connection = http.client.HTTPConnection('127.0.0.1', port, timeout=5)
|
|
connection.request('GET', '/api/status')
|
|
token = json.loads(connection.getresponse().read())['token']
|
|
connection.close()
|
|
return process, port, token
|
|
except (OSError, http.client.HTTPException):
|
|
time.sleep(0.02)
|
|
if process.poll() is None: # running, and no answer: no port problem
|
|
process.kill()
|
|
process.wait()
|
|
break
|
|
raise RuntimeError('the server did not start')
|