mirror of
https://github.com/SirHumza/orbisRPC.git
synced 2026-10-06 08:00:34 +02:00
WIP: SDK-port net branches + findings archive
This commit is contained in:
1 parent
96c02b8cb4
commit
c01fc3fb10
12 files changed
+446
-2
No files matched your search
@@ -0,0 +1,14 @@
|
||||
# Findings archive
|
||||
|
||||
Hardware-grounded research from bringing OrbisRPC up on a real PS4
|
||||
(9.00, GoldHEN 2.4). Written for humans and for AI assistants joining
|
||||
later: every claim below was observed on-console unless marked THEORY.
|
||||
|
||||
- [loader.md](loader.md) — GoldHEN payloader vs BinLoader server vs
|
||||
elfldr: behaviors, crashes, one-shot rule, ports.
|
||||
- [elf-linkage.md](elf-linkage.md) — why OpenOrbis-linked binaries die
|
||||
instantly in spawned processes; NEEDED/UND analysis; SDK port status.
|
||||
- [tls-ime.md](tls-ime.md) — mbedTLS 3.x PSA failure on-console (fixed),
|
||||
IME dialog init failures (open), exact error codes seen.
|
||||
- [capture.md](capture.md) — how to observe: klog, FTP paths, ports,
|
||||
screenshot locations, what each log proves.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Observing the console (for assistants)
|
||||
|
||||
## Channels
|
||||
|
||||
| Channel | Address | Use |
|
||||
|---|---|---|
|
||||
| FTP | `192.168.1.136:2121` (anonymous) | files up/down |
|
||||
| Kernel log | `192.168.1.136:3232` (TCP stream) | loader events, faults, crashes |
|
||||
| BinLoader server | `192.168.1.136:9020` (one-shot per arm) | inject; NEVER probe first — an empty connect burns the arm, then fire blind |
|
||||
| elfldr (if running) | `192.168.1.136:9021` | third-party ELF test harness |
|
||||
|
||||
## Key paths (FTP)
|
||||
|
||||
- `/data/orbisRPC/log.txt` — daemon log. Absent = payload never ran.
|
||||
- `/data/orbisRPC/app.log` — setup-app + transport logs.
|
||||
- `/data/orbisRPC/screen.log` — every dialog as text + answers.
|
||||
- `/data/orbisRPC/diag.txt` — sanitized report (token structurally excluded).
|
||||
- `/data/GoldHEN/payloads/` — autoloaded at jailbreak.
|
||||
- `/data/payloads/` — Payload Guest scan dir.
|
||||
- `/data/pkg/` — PKG staging.
|
||||
- `/user/av_contents/photo/NPXS20001/<TITLE>/*/*/*.jpg` — screenshots.
|
||||
- `/user/data/sce_coredumps/` — crash dumps.
|
||||
|
||||
## Proof markers
|
||||
|
||||
- Daemon alive: `log.txt` exists with `daemon start` line.
|
||||
- Network proven: `tls: established (TLSv1.2)` in app.log.
|
||||
- September success marker: `gateway ready` + `presence:` lines.
|
||||
- Loader segfault signature: `signal 11 (SIGSEGV), thread GoldHENLoader`,
|
||||
fault address 0, right after `payload launched successfully`.
|
||||
|
||||
## Rules learned the hard way
|
||||
|
||||
1. Never port-check 9020/9090 before sending — fire blind on tap.
|
||||
2. Klog is a live firehose: capture across the send window, not after.
|
||||
3. `log.txt` absent always means "never executed", never "crashed later".
|
||||
4. Rebuild artifacts go stale fast — verify hashes match before concluding.
|
||||
@@ -0,0 +1,39 @@
|
||||
# ELF linkage: why OpenOrbis binaries die in spawned processes
|
||||
|
||||
## Observed
|
||||
|
||||
- elfldr.elf (ps4-payload-sdk build): runs, serves, no faults.
|
||||
- SDK hello_world + SDK getaddrinfo/file probe: run, notification shown,
|
||||
`dns: PASS`.
|
||||
- Every OpenOrbis-linked binary (hello 90KB, v0.4.0, 1.0 daemon): instant
|
||||
silent death, no first log line, under both GoldHEN payloader and elfldr.
|
||||
|
||||
## Structural comparison (llvm-readelf, verified locally)
|
||||
|
||||
| | working (elfldr/sdk) | dying (ours) |
|
||||
|---|---|---|
|
||||
| NEEDED | libkernel_web.sprx, libSceLibcInternal.sprx, libSceNet.sprx | libkernel.so + app-world `.so` set |
|
||||
| Segments | merged RWE LOADs, no RELRO | split R-X/RW, GNU_RELRO, GNU_STACK |
|
||||
| Hash | GNU_HASH + SYSV HASH (both have both) | same |
|
||||
| Relocations | GLOB_DAT / JUMP_SLOT / RELATIVE only | same families |
|
||||
|
||||
elfldr spawns via `rfork_thread(RFPROC|RFCFDG|RFMEM)` then resolves each
|
||||
import and SIGKILLs on the first unresolvable one — silent by design.
|
||||
Our 89 undefined imports (vs ~26 working) include `libkernel.so` symbols
|
||||
with no provider in a bare spawned process, so death occurs before `main`.
|
||||
|
||||
## Consequence
|
||||
|
||||
The daemon must be rebuilt against daemon-world linkage
|
||||
(ps4-payload-sdk: `libkernel_web` + internal libc + `libSceNet`, BSD
|
||||
sockets instead of Sony `orbis/Net.h`). Status: toolchain assembled on
|
||||
macOS (llvm-shim + SDK bindist), SDK hello proven running, daemon port
|
||||
in progress on the `WIP` branch (`ORBISRPC_SDK_PAYLOAD` build flavor;
|
||||
`scripts/build_sdk.sh`). First SDK-linked daemon binary exhibits the same
|
||||
quiet death — import-set bisect ongoing (getaddrinfo/DNS/file proven
|
||||
working; remaining suspects: stdio-heavy and SceNet-derived imports).
|
||||
|
||||
## Ruled out
|
||||
|
||||
- PIE vs EXEC (both crash), SELF vs ELF (page wants ELF), size (90KB dies),
|
||||
hash style, relocation families, segment permissions.
|
||||
@@ -0,0 +1,23 @@
|
||||
# Loader behavior (observed on PS4 9.00, GoldHEN 2.4)
|
||||
|
||||
## The three loaders
|
||||
|
||||
| Loader | Port | Behavior observed |
|
||||
|---|---|---|
|
||||
| GoldHEN settings-page payloader | 9090 (transient) | Accepts bytes, prints "payload launched successfully", then its own `GoldHENLoader` thread SIGSEGVs (null read). Payload never executes. Reproduced with 90KB hello-world, v0.4.0, 1.0 daemon. |
|
||||
| GoldHEN BinLoader server | 9020 (one-shot per arm) | The September success path (`gateway ready` + live presence). Any port *check* (empty connect) burns the arm — fire blind, first connection carries the payload. |
|
||||
| elfldr (ps4-payload-dev v0.7) | 9021 (serves until reboot) | Third-party ELF runs cleanly (bootstraps, serves, no faults). Our OpenOrbis-linked binaries die silently inside it. |
|
||||
|
||||
## Proven facts
|
||||
|
||||
- The 9090 segfault is in GoldHEN's loader thread, not the payload:
|
||||
`signal 11 (SIGSEGV), thread GoldHENLoader, fault address 0`.
|
||||
- ELF support in the settings-page loader needs GoldHEN ≥ v2.4b18.5;
|
||||
older builds cannot load ELFs at all.
|
||||
- 9020 takes bytes with zero kernel reaction when unarmed; refused when down.
|
||||
- FTP (2121) and klog (3232) are the observation channels; see capture.md.
|
||||
|
||||
## Open
|
||||
|
||||
- Whether a newer GoldHEN (v2.4b18+) fixes the 9090 segfault.
|
||||
- The exact GoldHEN build on the test console (About screen).
|
||||
@@ -0,0 +1,45 @@
|
||||
# TLS + IME console findings
|
||||
|
||||
## TLS: mbedTLS 3.x PSA failure (FIXED, verified on hardware)
|
||||
|
||||
Symptom: every handshake died instantly with return `-1` (not a real
|
||||
mbedTLS code), after DNS + TCP succeeded.
|
||||
|
||||
Root cause (from mbedTLS debug trace on-console):
|
||||
|
||||
```text
|
||||
psa_crypto_init() returned -148 (-0x0094, INSUFFICIENT_ENTROPY)
|
||||
```
|
||||
|
||||
mbedTLS 3.x routes TLS 1.3 through the PSA crypto subsystem, whose init
|
||||
fails on PS4 even though `/dev/urandom` reads work fine (ClientHello
|
||||
random bytes prove it).
|
||||
|
||||
Fix (in tree, verified: full handshake, `TLS-ECDHE-ECDSA-WITH-CHACHA20-
|
||||
POLY1305-SHA256`, cert chain verifies, connection test PASSES):
|
||||
|
||||
```c
|
||||
mbedtls_ssl_conf_max_tls_version(&t->conf, MBEDTLS_SSL_VERSION_TLS1_2);
|
||||
```
|
||||
|
||||
Lesson: wire mbedTLS's debug layer (`mbedtls_debug_set_threshold` +
|
||||
`mbedtls_ssl_conf_dbg`) into the log before guessing at handshake bugs.
|
||||
|
||||
## IME keyboard: init refuses (OPEN)
|
||||
|
||||
`sceImeDialogInit` fails on-console; codes seen:
|
||||
|
||||
- `-2135162872` (`0x80BC0008`) with `userId=0`
|
||||
- `-2135162864` (`0x80BC0010`) with real foreground user ID
|
||||
|
||||
Tried, none fixed it: real user ID via UserService, centered position
|
||||
(960,540), default type/label, per-dialog init/terminate lifecycle,
|
||||
stale-session teardown. Reference: Apollo PS4 dialog.c pattern mirrored.
|
||||
Workaround in place: token pre-seeded via config; IME still unresolved.
|
||||
|
||||
## App lifecycle (fixed, verified)
|
||||
|
||||
- Missing `sceMsgDialogInitialize` → every open failed into a black loop.
|
||||
Fixed per Apollo pattern (init + terminate per dialog).
|
||||
- 30s dialog watchdog blanked idle screens — removed, blocking waits now.
|
||||
- Exit path terminates dialogs, unloads modules, `exit(0)`.
|
||||
@@ -8,6 +8,35 @@
|
||||
#include <stdint.h>
|
||||
#include "clock.h"
|
||||
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
/* Payload-SDK builds: the SDK libc already provides errno, gmtime_r,
|
||||
* clock_gettime and friends. Only the entropy poll + monotonic clock
|
||||
* live here, written against plain POSIX. */
|
||||
int mbedtls_platform_entropy_poll(void *data, unsigned char *out,
|
||||
size_t len, size_t *olen){
|
||||
(void)data;
|
||||
if(!out || len == 0) return -1;
|
||||
int fd = open("/dev/urandom", O_RDONLY);
|
||||
if(fd < 0) return -1;
|
||||
size_t got = 0;
|
||||
while(got < len){
|
||||
long r = read(fd, (char *)out + got, len - got);
|
||||
if(r <= 0){ close(fd); return -1; }
|
||||
got += (size_t)r;
|
||||
}
|
||||
close(fd);
|
||||
*olen = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t orbis_mono_s(void){
|
||||
struct timespec ts;
|
||||
if(clock_gettime(CLOCK_MONOTONIC, &ts) != 0) return (int64_t)time(NULL);
|
||||
return (int64_t)ts.tv_sec;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int *__errno_location(void) __attribute__((weak));
|
||||
int *__errno_location(void){
|
||||
static int errno_slot;
|
||||
@@ -90,3 +119,5 @@ int64_t orbis_mono_s(void){
|
||||
return (int64_t)ts.tv_sec;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* ORBISRPC_SDK_PAYLOAD */
|
||||
@@ -23,9 +23,16 @@
|
||||
#include "sfo.h"
|
||||
#include "tmdb.h"
|
||||
#include "nametable.h"
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
/* Payload-SDK build: dlopen/dlsym come from the SDK libc (dlfcn);
|
||||
* there is no UserService here — user_init() below degrades. */
|
||||
#include <dlfcn.h>
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#include <orbis/UserService.h>
|
||||
#include <orbis/libkernel.h>
|
||||
#include <orbis/Sysmodule.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -40,6 +47,12 @@ static int s_user_ok = 0;
|
||||
static int user_init(void){
|
||||
if(s_user_inited) return s_user_ok ? 0 : -1;
|
||||
s_user_inited = 1;
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
/* No UserService in payload-SDK builds: ShellCoreUtil (dlopen) is the
|
||||
* only foreground signal; without it we report inactive (fail closed). */
|
||||
log_msg("UserService unavailable in SDK build; ShellCoreUtil only");
|
||||
return -1;
|
||||
#else
|
||||
/* UserService is an external module -> load via internal id */
|
||||
uint32_t r = sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_USER_SERVICE);
|
||||
if(r != 0){ int32_t ir=(int32_t)r; log_msg("load UserService fail %d", ir); return -1; }
|
||||
@@ -47,6 +60,7 @@ static int user_init(void){
|
||||
if(rc != 0){ log_msg("UserService init fail %d", rc); return -1; }
|
||||
s_user_ok = 1;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* --- ShellCoreUtil runtime resolution ------------------------------- */
|
||||
@@ -76,10 +90,16 @@ int detect_foreground_active(void){
|
||||
/* fallback: foreground user exists. If UserService itself failed,
|
||||
* report inactive instead of guessing "playing". */
|
||||
if(user_init() != 0) return 0;
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
/* No UserService API in SDK builds (user_init always fails there,
|
||||
* so this is unreachable); fail closed regardless. */
|
||||
return 0;
|
||||
#else
|
||||
int32_t fg = -1;
|
||||
int32_t rc = sceUserServiceGetForegroundUser(&fg);
|
||||
if(rc != 0){ log_msg("GetForegroundUser err %d", rc); return 0; }
|
||||
return (fg >= 0) ? 1 : 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* --- title naming ---------------------------------------------------- */
|
||||
|
||||
@@ -18,7 +18,13 @@
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/debug.h>
|
||||
#include <mbedtls/net_sockets.h> /* error codes only; transport is ours */
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#else
|
||||
#include <orbis/Net.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
@@ -72,17 +78,33 @@ static int orbis_poll(void *data, unsigned char *out, size_t len, size_t *olen){
|
||||
static int net_send(void *ctx, const unsigned char *b, size_t n){
|
||||
tls_ctx_t *t = (tls_ctx_t *)ctx;
|
||||
size_t cap = n > 32768 ? 32768 : n;
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
int r = (int)send(t->fd, b, cap, 0);
|
||||
if(r < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
|
||||
return MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
if(r < 0) return MBEDTLS_ERR_NET_SEND_FAILED;
|
||||
return r;
|
||||
#else
|
||||
int r = (int)sceNetSend(t->fd, b, (int)cap, 0);
|
||||
if(r < 0) return MBEDTLS_ERR_SSL_WANT_WRITE; /* NBIO: retry till deadline */
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int net_recv(void *ctx, unsigned char *b, size_t n){
|
||||
tls_ctx_t *t = (tls_ctx_t *)ctx;
|
||||
size_t cap = n > 16384 ? 16384 : n;
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
int r = (int)recv(t->fd, b, cap, 0);
|
||||
if(r < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
|
||||
return MBEDTLS_ERR_SSL_WANT_READ;
|
||||
if(r < 0) return MBEDTLS_ERR_NET_RECV_FAILED;
|
||||
return r;
|
||||
#else
|
||||
int r = (int)sceNetRecv(t->fd, b, (int)cap, 0);
|
||||
if(r < 0) return MBEDTLS_ERR_SSL_WANT_READ; /* NBIO: retry till deadline */
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
|
||||
tls_ctx_t *tls_start(int fd, const char *host){
|
||||
|
||||
+66
-1
@@ -5,11 +5,21 @@
|
||||
#include "clock.h"
|
||||
#include "tmdb_crypto.h"
|
||||
#include "log.h"
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <orbis/Net.h>
|
||||
#include <orbis/Sysmodule.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -28,6 +38,11 @@ static int s_ready = 0;
|
||||
* init inside game processes. */
|
||||
static int net_up(void){
|
||||
if(s_ready) return 0;
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
/* BSD sockets need no init. */
|
||||
s_ready = 1;
|
||||
return 0;
|
||||
#else
|
||||
uint32_t ur = sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_NET);
|
||||
if((int)ur < 0){ log_msg("tmdb: load NET fail %d", (int)ur); return -1; }
|
||||
if(sceNetInit() < 0){ log_msg("tmdb: sceNetInit fail"); return -1; }
|
||||
@@ -35,6 +50,7 @@ static int net_up(void){
|
||||
if(s_pool < 0){ log_msg("tmdb: net pool fail %d", (int)s_pool); return -1; }
|
||||
s_ready = 1;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Minimal blocking HTTP GET with deadline. Returns body bytes, or -1. */
|
||||
@@ -42,6 +58,29 @@ static int http_get(const char *host, const char *path,
|
||||
char *body, size_t cap, int *out_status){
|
||||
if(out_status) *out_status = 0;
|
||||
if(net_up() < 0) return -1;
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
struct addrinfo hints, *res = NULL;
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
{
|
||||
char portbuf[16];
|
||||
snprintf(portbuf, sizeof portbuf, "%d", TMDB_PORT);
|
||||
if(getaddrinfo(host, portbuf, &hints, &res) != 0 || !res){
|
||||
log_msg("tmdb: dns fail");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(fd < 0){ log_msg("tmdb: socket fail"); freeaddrinfo(res); return -1; }
|
||||
struct timeval tv = { .tv_sec = TMDB_DEADLINE_S, .tv_usec = 0 };
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv);
|
||||
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
|
||||
if(connect(fd, res->ai_addr, res->ai_addrlen) < 0){
|
||||
log_msg("tmdb: connect fail"); freeaddrinfo(res); close(fd); return -1;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
#else
|
||||
OrbisNetInAddr in;
|
||||
memset(&in, 0, sizeof in);
|
||||
int ok = 0;
|
||||
@@ -73,17 +112,31 @@ static int http_get(const char *host, const char *path,
|
||||
if(sceNetConnect(fd, &sa, sizeof sa) < 0){
|
||||
log_msg("tmdb: connect fail"); sceNetSocketClose(fd); return -1;
|
||||
}
|
||||
#endif
|
||||
char req[512];
|
||||
int rl = snprintf(req, sizeof req,
|
||||
"GET %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Mozilla/5.0\r\nConnection: close\r\n\r\n",
|
||||
path, host);
|
||||
if(rl <= 0 || rl >= (int)sizeof req){ sceNetSocketClose(fd); return -1; }
|
||||
if(rl <= 0 || rl >= (int)sizeof req){
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
close(fd);
|
||||
#else
|
||||
sceNetSocketClose(fd);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
int sent = 0;
|
||||
int64_t dl = orbis_mono_s() + TMDB_DEADLINE_S;
|
||||
while(sent < rl){
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
int r = (int)send(fd, req+sent, (size_t)(rl-sent), 0);
|
||||
if(r > 0){ sent += r; continue; }
|
||||
if(orbis_mono_s() > dl || r == 0){ close(fd); return -1; }
|
||||
#else
|
||||
int r = sceNetSend(fd, req+sent, rl-sent, 0);
|
||||
if(r > 0){ sent += r; continue; }
|
||||
if(orbis_mono_s() > dl || r == 0){ sceNetSocketClose(fd); return -1; }
|
||||
#endif
|
||||
}
|
||||
/* read headers then body; cap total */
|
||||
char hb[2048];
|
||||
@@ -92,7 +145,11 @@ static int http_get(const char *host, const char *path,
|
||||
size_t bl = 0;
|
||||
for(;;){
|
||||
char tmp[1024];
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
int r = (int)recv(fd, tmp, sizeof tmp, 0);
|
||||
#else
|
||||
int r = sceNetRecv(fd, tmp, sizeof tmp, 0);
|
||||
#endif
|
||||
if(r <= 0) break;
|
||||
size_t off = 0;
|
||||
if(!hdr_done){
|
||||
@@ -107,7 +164,11 @@ static int http_get(const char *host, const char *path,
|
||||
/* off = body bytes already in this chunk */
|
||||
if(off > (size_t)r) off = (size_t)r;
|
||||
} else if(hl >= sizeof hb - 1){
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
close(fd); return -1; /* headers too big */
|
||||
#else
|
||||
sceNetSocketClose(fd); return -1; /* headers too big */
|
||||
#endif
|
||||
} else continue;
|
||||
}
|
||||
while(off < (size_t)r && bl < cap - 1){
|
||||
@@ -116,7 +177,11 @@ static int http_get(const char *host, const char *path,
|
||||
if(bl >= cap - 1) break;
|
||||
if(orbis_mono_s() > dl) break;
|
||||
}
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
close(fd);
|
||||
#else
|
||||
sceNetSocketClose(fd);
|
||||
#endif
|
||||
body[bl] = 0;
|
||||
if(out_status) *out_status = status;
|
||||
if(status != 200 || bl == 0) return -1;
|
||||
|
||||
+49
-1
@@ -20,11 +20,19 @@
|
||||
|
||||
/* ---- PS4 HTTPS transport (mirrors ws.c/tmdb.c bring-up) ---- */
|
||||
#include "tls.h"
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include <orbis/Net.h>
|
||||
#include <orbis/Sysmodule.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
@@ -41,6 +49,10 @@ static int32_t s_upool = -1;
|
||||
static int upd_net(void){
|
||||
static int ready = 0;
|
||||
if(ready) return 0;
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
ready = 1;
|
||||
return 0;
|
||||
#else
|
||||
uint32_t ur = sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_NET);
|
||||
if((int)ur < 0) return -1;
|
||||
if(sceNetInit() < 0) return -1;
|
||||
@@ -48,10 +60,38 @@ static int upd_net(void){
|
||||
if(s_upool < 0) return -1;
|
||||
ready = 1;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int upd_connect(const char *host, int port){
|
||||
if(upd_net() < 0) return -1;
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
struct addrinfo hints, *res = NULL;
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
{
|
||||
char portbuf[16];
|
||||
snprintf(portbuf, sizeof portbuf, "%d", port);
|
||||
if(getaddrinfo(host, portbuf, &hints, &res) != 0 || !res){
|
||||
log_msg("updater: dns fail");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(fd < 0){ freeaddrinfo(res); return -1; }
|
||||
struct timeval tv = { .tv_sec = UPD_DEADLINE_S, .tv_usec = 0 };
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv);
|
||||
if(connect(fd, res->ai_addr, res->ai_addrlen) < 0){
|
||||
close(fd); freeaddrinfo(res); return -1;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
{
|
||||
int fl = fcntl(fd, F_GETFL, 0);
|
||||
if(fl >= 0) fcntl(fd, F_SETFL, fl | O_NONBLOCK);
|
||||
}
|
||||
return fd;
|
||||
#else
|
||||
OrbisNetInAddr in;
|
||||
memset(&in, 0, sizeof in);
|
||||
int32_t rid = sceNetResolverCreate("updR", (uint32_t)s_upool, 0);
|
||||
@@ -74,6 +114,7 @@ static int upd_connect(const char *host, int port){
|
||||
int nb = 1;
|
||||
sceNetSetsockopt(fd, SOL_SOCKET, SO_NBIO, &nb, sizeof nb);
|
||||
return fd;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* HTTPS GET, returns heap body (caller frees) with out_len/out_status. */
|
||||
@@ -84,7 +125,14 @@ static char *https_get(const char *host, const char *path,
|
||||
int fd = upd_connect(host, 443);
|
||||
if(fd < 0) return NULL;
|
||||
tls_ctx_t *t = tls_start(fd, host);
|
||||
if(!t){ sceNetSocketClose(fd); return NULL; }
|
||||
if(!t){
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
close(fd);
|
||||
#else
|
||||
sceNetSocketClose(fd);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
char req[512];
|
||||
int rl = snprintf(req, sizeof req,
|
||||
"GET %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: orbisRPC/%s\r\nConnection: close\r\n\r\n",
|
||||
|
||||
@@ -8,11 +8,23 @@
|
||||
#include "clock.h"
|
||||
#include "tls.h"
|
||||
#include "log.h"
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
/* Payload-SDK build: plain BSD sockets, no Sony modules. getaddrinfo
|
||||
* replaces the kernel resolver; nothing needs initializing. */
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#else
|
||||
#include <orbis/Net.h>
|
||||
#include <orbis/Sysmodule.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -31,6 +43,11 @@ static int s_net_mem = 0;
|
||||
|
||||
static int net_ensure(void){
|
||||
if(s_net_ready) return 0;
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
/* BSD sockets need no init. */
|
||||
s_net_ready = 1;
|
||||
return 0;
|
||||
#else
|
||||
uint32_t ur = sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_NET);
|
||||
if((int)ur < 0){ log_msg("load NET fail %d", (int)ur); return -1; }
|
||||
if(sceNetInit() < 0){ log_msg("sceNetInit fail"); return -2; }
|
||||
@@ -41,6 +58,7 @@ static int net_ensure(void){
|
||||
* a crash recipe. The kernel resolver works fine with just the pool. */
|
||||
s_net_ready = 1;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Write exactly n bytes of plaintext through the TLS engine. */
|
||||
@@ -62,6 +80,49 @@ int ws_connect(ws_t *w, const char *host, int port, const char *resource, const
|
||||
w->rbuf = (unsigned char*)malloc(w->rcap);
|
||||
if(!w->rbuf){ log_msg("ws: rbuf alloc fail"); return -1; }
|
||||
if(net_ensure()<0) goto fail;
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
/* Resolve via libc (works wherever BSD sockets do). */
|
||||
struct addrinfo hints, *res = NULL;
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
{
|
||||
char portbuf[16];
|
||||
snprintf(portbuf, sizeof portbuf, "%d", port);
|
||||
if(getaddrinfo(host, portbuf, &hints, &res) != 0 || !res){
|
||||
log_msg("resolve fail: %s", host);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
{
|
||||
struct sockaddr_in *a = (struct sockaddr_in *)res->ai_addr;
|
||||
unsigned char *q = (unsigned char *)&a->sin_addr.s_addr;
|
||||
log_msg("dial %s -> %u.%u.%u.%u:%d", host, q[0], q[1], q[2], q[3], port);
|
||||
}
|
||||
int fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(fd < 0){ log_msg("socket fail"); freeaddrinfo(res); goto fail; }
|
||||
w->fd = fd; w->sock = fd;
|
||||
{
|
||||
struct timeval tv = { .tv_sec = 10, .tv_usec = 0 };
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv);
|
||||
}
|
||||
if(connect(fd, res->ai_addr, res->ai_addrlen) < 0){
|
||||
log_msg("connect fail (syscall) to %s:%d", host, port);
|
||||
freeaddrinfo(res);
|
||||
goto fail;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
{
|
||||
struct timeval tv0 = { .tv_sec = 0, .tv_usec = 0 };
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv0, sizeof tv0);
|
||||
}
|
||||
{
|
||||
int fl = fcntl(fd, F_GETFL, 0);
|
||||
if(fl >= 0) fcntl(fd, F_SETFL, fl | O_NONBLOCK);
|
||||
}
|
||||
w->nb = 1;
|
||||
log_msg("tcp established");
|
||||
#else
|
||||
/* memid = our net pool: passing 0 here fails with EBADF (0x80410109).
|
||||
* If pool creation failed, skip DNS and only allow IP literals. */
|
||||
int32_t rid = -1;
|
||||
@@ -123,6 +184,7 @@ int ws_connect(ws_t *w, const char *host, int port, const char *resource, const
|
||||
sceNetSetsockopt(fd, SOL_SOCKET, SO_NBIO, &on, sizeof on);
|
||||
w->nb = 1;
|
||||
log_msg("tcp established");
|
||||
#endif
|
||||
/* TLS handshake over the established connection (mbedTLS, no external
|
||||
* module needed). Socket is NBIO; tls_start pumps it with a deadline. */
|
||||
w->tls = tls_start(fd, host);
|
||||
@@ -177,7 +239,11 @@ int ws_connect(ws_t *w, const char *host, int port, const char *resource, const
|
||||
return 0;
|
||||
fail:
|
||||
tls_free((tls_ctx_t*)w->tls); w->tls=NULL;
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
if(w->fd > 0) close(w->fd);
|
||||
#else
|
||||
if(w->fd > 0) sceNetSocketClose(w->fd);
|
||||
#endif
|
||||
free(w->rbuf); w->rbuf=NULL; w->rcap=0;
|
||||
w->connected=0; w->tls=NULL; w->fd=0; w->sock=0;
|
||||
return -9;
|
||||
@@ -331,7 +397,11 @@ int ws_close(ws_t *w){
|
||||
}
|
||||
ws_send_control(w, 0x8); /* best-effort masked CLOSE */
|
||||
tls_free((tls_ctx_t*)w->tls);
|
||||
#ifdef ORBISRPC_SDK_PAYLOAD
|
||||
close(w->fd);
|
||||
#else
|
||||
sceNetSocketClose(w->fd);
|
||||
#endif
|
||||
free(w->rbuf); w->rbuf=NULL; w->rcap=0;
|
||||
w->connected=0; w->sock=0; w->tls=NULL; w->fd=0; w->rlen=0; w->rpos=0;
|
||||
w->skip_left=0;
|
||||
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
# build_sdk.sh - OrbisRPC daemon payload via ps4-payload-sdk (daemon-world
|
||||
# linkage: no libkernel.so, BSD sockets, SDK libc). Test vehicle: elfldr.
|
||||
# Usage: PS4_PAYLOAD_SDK=/path ./scripts/build_sdk.sh
|
||||
set -e
|
||||
SDK="${PS4_PAYLOAD_SDK:-$HOME/ps4-payload-sdk/ps4-payload-sdk}"
|
||||
[ -x "$SDK/toolchain/../../ps4-payload-sdk/bin/orbis-clang" ] || {
|
||||
# resolve relative to SDK root regardless of layout
|
||||
true
|
||||
}
|
||||
CC="$SDK/bin/orbis-clang"
|
||||
export PS4_PAYLOAD_SDK="$SDK"
|
||||
export PATH="$HOME/llvmshim:$PATH"
|
||||
OUT="build-sdk"
|
||||
mkdir -p "$OUT"
|
||||
CFLAGS="-O2 -Wall -DORBISRPC_SDK_PAYLOAD -Iorbisrpc -Ithird_party/mbedtls/include"
|
||||
echo "=== daemon sources (SDK) ==="
|
||||
for f in log cfg jsonlite b64 sfo tmdb_crypto tmdb updater updater_util tls ws detect discord daemon compat clock main; do
|
||||
# clock has no .c (header-only helper lives in compat.c); skip if missing
|
||||
[ -f "orbisrpc/$f.c" ] || continue
|
||||
"$CC" $CFLAGS -c -o "$OUT/$f.o" "orbisrpc/$f.c" || { echo "FAIL: $f"; exit 1; }
|
||||
done
|
||||
echo "=== mbedtls (SDK, skip net_sockets/timing/entropy_poll) ==="
|
||||
for f in $(find third_party/mbedtls/library -name '*.c' ! -name 'net_sockets.c' ! -name 'timing.c' ! -name 'entropy_poll.c' | sort); do
|
||||
o="$OUT/mbed_$(echo "$f" | sed 's|third_party/mbedtls/library/||; s|\.c$||').o"
|
||||
"$CC" $CFLAGS -Wno-unused-parameter -c -o "$o" "$f" || { echo "FAIL: mbedtls $f"; exit 1; }
|
||||
done
|
||||
echo "=== link ==="
|
||||
"$CC" -o "$OUT/orbisrpc_sdk.elf" "$OUT"/*.o || { echo "FAIL: link"; exit 1; }
|
||||
ls -la "$OUT/orbisrpc_sdk.elf"
|
||||
Reference in new issue
Block a user