WIP: SDK-port net branches + findings archive

This commit is contained in:
SirHumza committed 2026-09-23 16:56:25 +02:00
1 parent 96c02b8cb4
commit c01fc3fb10
12 files changed
+446 -2

No files matched your search

+14
View File
@@ -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.
+37
View File
@@ -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.
+39
View File
@@ -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.
+23
View File
@@ -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).
+45
View File
@@ -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)`.
+31
View File
@@ -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 */
+20
View File
@@ -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 ---------------------------------------------------- */
+22
View File
@@ -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
View File
@@ -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
View File
@@ -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",
+70
View File
@@ -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;
+30
View File
@@ -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"