mirror of
https://github.com/SirHumza/orbisRPC.git
synced 2026-10-06 09:00:37 +02:00
WIP: debug gate, monotonic clock, titleId sessions, debounce, resolve cache
This commit is contained in:
1 parent
c8fea26699
commit
96c02b8cb4
13 files changed
+175
-34
No files matched your search
@@ -63,6 +63,7 @@ int cfg_load(const char *path, cfg_t *c) {
|
||||
#undef STR
|
||||
o = jl_obj_get(root, "enabled"); if (o && o->type == JL_BOOL) c->enabled = (int)o->num;
|
||||
o = jl_obj_get(root, "auto_update"); if (o && o->type == JL_BOOL) c->auto_update = (int)o->num;
|
||||
o = jl_obj_get(root, "debug"); if (o && o->type == JL_BOOL) c->debug = (int)o->num;
|
||||
o = jl_obj_get(root, "poll_interval_s"); if (o && o->type == JL_NUMBER) c->poll_interval_s = (int)o->num;
|
||||
jl_free(root);
|
||||
clamp_cfg(c);
|
||||
@@ -78,6 +79,7 @@ void cfg_save(const char *path, const cfg_t *c) {
|
||||
jl_obj_set(r, "art_base_url", jl_new_string(c->art_base_url));
|
||||
jl_obj_set(r, "enabled", jl_new_bool(c->enabled));
|
||||
jl_obj_set(r, "auto_update", jl_new_bool(c->auto_update));
|
||||
jl_obj_set(r, "debug", jl_new_bool(c->debug));
|
||||
jl_obj_set(r, "poll_interval_s", jl_new_number((double)c->poll_interval_s));
|
||||
jl_obj_set(r, "presence_state", jl_new_string(c->presence_state));
|
||||
char *s = jl_stringify(r);
|
||||
|
||||
@@ -13,6 +13,7 @@ typedef struct {
|
||||
* large_image becomes <base><lower titleId>.png */
|
||||
int enabled;
|
||||
int auto_update; /* check GitHub releases once per boot, stage newer */
|
||||
int debug; /* verbose debug logging (per-poll detail, no secrets) */
|
||||
int poll_interval_s; /* game-check cadence */
|
||||
char presence_state[128]; /* activity "state" line, e.g. "On PS4" */
|
||||
} cfg_t;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/* clock.h - monotonic time for measuring durations.
|
||||
*
|
||||
* Rule: wall clock (time(NULL)) is ONLY for values that must be wall
|
||||
* clock (Discord epoch timestamps, log stamps). Every duration/deadline
|
||||
* uses orbis_mono_s() so a clock jump can never break local timing.
|
||||
*
|
||||
* PS4: sceKernelGetProcessTime (microseconds, monotonic).
|
||||
* Host: clock_gettime(CLOCK_MONOTONIC). */
|
||||
#ifndef ORBISRPC_CLOCK_H
|
||||
#define ORBISRPC_CLOCK_H
|
||||
#include <stdint.h>
|
||||
/* Monotonic seconds (arbitrary epoch, never goes backward). */
|
||||
int64_t orbis_mono_s(void);
|
||||
#endif
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
#include "clock.h"
|
||||
|
||||
int *__errno_location(void) __attribute__((weak));
|
||||
int *__errno_location(void){
|
||||
@@ -70,3 +72,21 @@ int mbedtls_platform_entropy_poll(void *data, unsigned char *out,
|
||||
*olen = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t orbis_mono_s(void){
|
||||
#if defined(__PS4__) || (defined(__FreeBSD__) && !defined(__APPLE__))
|
||||
/* PS4 builds (--target=x86_64-pc-freebsd12-elf, -D__PS4__). Declared
|
||||
* here instead of including orbis headers so host builds stay clean. */
|
||||
extern unsigned long long sceKernelGetProcessTime(void);
|
||||
return (int64_t)(sceKernelGetProcessTime() / 1000000ull);
|
||||
#else
|
||||
struct timespec ts;
|
||||
#if defined(CLOCK_MONOTONIC)
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
#else
|
||||
ts.tv_sec = time(NULL);
|
||||
ts.tv_nsec = 0;
|
||||
#endif
|
||||
return (int64_t)ts.tv_sec;
|
||||
#endif
|
||||
}
|
||||
+46
-11
@@ -14,6 +14,7 @@
|
||||
* recover, but suspend behavior is UNVERIFIED on hardware.
|
||||
*/
|
||||
#include "cfg.h"
|
||||
#include "clock.h"
|
||||
#include "log.h"
|
||||
#include "ws.h"
|
||||
#include "discord.h"
|
||||
@@ -85,6 +86,8 @@ int daemon_run(const char *fixed_game_name){
|
||||
log_msg("config load failed; running on defaults until valid config appears");
|
||||
}
|
||||
if(!g_cfg.enabled){ log_msg("disabled in config; exiting"); log_close(); return 0; }
|
||||
log_set_debug(g_cfg.debug);
|
||||
if(g_cfg.debug) log_dbg("debug logging on (config)");
|
||||
if(!have_token(&g_cfg)){
|
||||
log_msg("FATAL: put your Discord user token in %s as \"token\":\"...\"", CFG_PATH);
|
||||
log_close();
|
||||
@@ -111,7 +114,12 @@ int daemon_run(const char *fixed_game_name){
|
||||
* On parse failure keep last-good config instead of stale defaults. */
|
||||
{
|
||||
cfg_t next = g_cfg;
|
||||
if(cfg_load(CFG_PATH, &next) == 0) g_cfg = next;
|
||||
if(cfg_load(CFG_PATH, &next) == 0){
|
||||
if(next.debug != g_cfg.debug)
|
||||
log_msg("debug logging %s", next.debug ? "on" : "off");
|
||||
g_cfg = next;
|
||||
log_set_debug(g_cfg.debug);
|
||||
}
|
||||
else log_msg("config reload failed; keeping last-good config");
|
||||
}
|
||||
if(!have_token(&g_cfg)){
|
||||
@@ -140,12 +148,17 @@ int daemon_run(const char *fixed_game_name){
|
||||
* A reconnect re-posts presence only when needed, timer intact. */
|
||||
static int active = 0;
|
||||
static char last[128] = "";
|
||||
static char sess_tid[16] = "";
|
||||
static int64_t started = 0;
|
||||
/* Transition debounce: shell flickers during launches, so a new
|
||||
* title (or disappearance) needs consecutive polls (2 at ~1s). */
|
||||
static char cand_title[16] = "";
|
||||
static int cand_hits = 0, miss_hits = 0;
|
||||
int64_t last_poll = 0;
|
||||
/* re-post after every (re)connect so Discord never sticks on stale */
|
||||
int need_post = active && last[0];
|
||||
while(!s_stop){ /* inner: live session, serviced every second */
|
||||
int64_t now = time(NULL);
|
||||
int64_t now = orbis_mono_s();
|
||||
if(now != last_poll){
|
||||
last_poll = now;
|
||||
char name[128] = "";
|
||||
@@ -160,24 +173,46 @@ int daemon_run(const char *fixed_game_name){
|
||||
}
|
||||
|
||||
if(name[0]){
|
||||
if(!active || strncmp(name,last,sizeof last)!=0){
|
||||
const char *cur_tid = detect_last_titleid();
|
||||
if(!cur_tid) cur_tid = "";
|
||||
if(!strncmp(cur_tid, cand_title, sizeof cand_title)){
|
||||
cand_hits++;
|
||||
} else {
|
||||
strncpy(cand_title, cur_tid, sizeof cand_title-1);
|
||||
cand_title[sizeof cand_title-1] = 0;
|
||||
cand_hits = 1;
|
||||
}
|
||||
miss_hits = 0;
|
||||
if(fixed_game_name || cand_hits >= 2){
|
||||
if(!active || strncmp(cur_tid,sess_tid,sizeof sess_tid)!=0){
|
||||
active = 1;
|
||||
strncpy(sess_tid, cur_tid, sizeof sess_tid-1);
|
||||
strncpy(last, name, sizeof last-1);
|
||||
last[sizeof last-1] = 0;
|
||||
started = time(NULL);
|
||||
need_post = 1;
|
||||
log_msg("GAME_DETECTED title=%s name=%s", cur_tid[0]?cur_tid:"?", name);
|
||||
} else if(strncmp(name,last,sizeof last)!=0){
|
||||
strncpy(last, name, sizeof last-1);
|
||||
last[sizeof last-1] = 0;
|
||||
need_post = 1;
|
||||
}
|
||||
if(need_post){
|
||||
const char *state = g_cfg.presence_state[0] ? g_cfg.presence_state : NULL;
|
||||
const char *tid = detect_last_titleid();
|
||||
const char *tart = detect_last_art();
|
||||
discord_set_presence_ex(&dc, state, name, tid, g_cfg.application_id, g_cfg.art_base_url, tart, started);
|
||||
log_msg("presence: %s", name);
|
||||
strncpy(last, name, sizeof last-1);
|
||||
last[sizeof last-1] = 0;
|
||||
discord_set_presence_ex(&dc, state, last, sess_tid[0]?sess_tid:NULL, g_cfg.application_id, g_cfg.art_base_url, tart, started);
|
||||
log_msg("presence: %s", last);
|
||||
active = 1; need_post = 0;
|
||||
}
|
||||
}
|
||||
}else if(active){
|
||||
discord_clear_presence(&dc);
|
||||
log_msg("presence cleared");
|
||||
last[0]=0; active=0; started=0;
|
||||
cand_title[0] = 0;
|
||||
cand_hits = 0;
|
||||
if(++miss_hits >= 2){
|
||||
discord_clear_presence(&dc);
|
||||
log_msg("presence cleared");
|
||||
last[0]=0; sess_tid[0]=0; active=0; started=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+42
-5
@@ -93,8 +93,32 @@ static int is_title_prefix(const char *n){
|
||||
* detect_current_game / detect_name_for_title. */
|
||||
static char s_last_titleid[16] = "";
|
||||
static char s_last_art[256] = "";
|
||||
static char s_res_titleid[16] = "";
|
||||
static char s_res_name[128] = "";
|
||||
static char s_res_art[256] = "";
|
||||
static int s_res_valid = 0;
|
||||
const char *detect_last_titleid(void){ return s_last_titleid[0] ? s_last_titleid : NULL; }
|
||||
const char *detect_last_art(void){ return s_last_art[0] ? s_last_art : NULL; }
|
||||
static void remember_resolved(const char *ti, const char *name, const char *art){
|
||||
if(!ti || !name) return;
|
||||
strncpy(s_res_titleid, ti, sizeof s_res_titleid - 1);
|
||||
s_res_titleid[sizeof s_res_titleid - 1] = 0;
|
||||
strncpy(s_res_name, name, sizeof s_res_name - 1);
|
||||
s_res_name[sizeof s_res_name - 1] = 0;
|
||||
if(art){
|
||||
strncpy(s_res_art, art, sizeof s_res_art - 1);
|
||||
s_res_art[sizeof s_res_art - 1] = 0;
|
||||
} else s_res_art[0] = 0;
|
||||
s_res_valid = 1;
|
||||
}
|
||||
static int cached_resolve(const char *ti, char *out_name, size_t cap){
|
||||
if(!s_res_valid || !ti || !ti[0] || strcmp(ti, s_res_titleid) != 0) return 0;
|
||||
strncpy(out_name, s_res_name, cap - 1);
|
||||
out_name[cap - 1] = 0;
|
||||
strncpy(s_last_art, s_res_art, sizeof s_last_art - 1);
|
||||
s_last_art[sizeof s_last_art - 1] = 0;
|
||||
return 1;
|
||||
}
|
||||
static void remember_titleid(const char *ti){
|
||||
if(!ti) return;
|
||||
strncpy(s_last_titleid, ti, sizeof s_last_titleid - 1);
|
||||
@@ -213,9 +237,13 @@ int detect_current_game(char *out_name, size_t cap, char *out_path, size_t p_cap
|
||||
if(scan_recent_titleid(titleId,sizeof titleId)==0){
|
||||
remember_titleid(titleId);
|
||||
s_last_art[0] = 0;
|
||||
if(cached_resolve(titleId, out_name, cap)){
|
||||
log_msg("name: %s via cache", out_name);
|
||||
named = 1;
|
||||
}
|
||||
/* cheap, game-process-safe sources first; Sony TMDB (network)
|
||||
* resolves anything local sources miss, on any console. */
|
||||
if(pronunc_title(titleId, out_name, cap)==0){ named=1; log_msg("name: %s via appmeta", out_name); }
|
||||
if(!named && pronunc_title(titleId, out_name, cap)==0){ named=1; log_msg("name: %s via appmeta", out_name); }
|
||||
if(!named){ if(sfo_file_title(titleId, out_name, cap)==0){ named=1; log_msg("name: %s via sfo", out_name); } }
|
||||
if(!named){ if(appxml_title(titleId, out_name, cap)==0){ named=1; log_msg("name: %s via appxml", out_name); } }
|
||||
if(!named){ if(nametable_lookup(titleId, out_name, cap)==0){ named=1; log_msg("name: %s via table", out_name); } }
|
||||
@@ -227,7 +255,10 @@ int detect_current_game(char *out_name, size_t cap, char *out_path, size_t p_cap
|
||||
} else s_last_art[0] = 0;
|
||||
}
|
||||
if(!named){ strncpy(out_name, titleId, cap-1); out_name[cap-1]=0; }
|
||||
remember_resolved(titleId, out_name, s_last_art);
|
||||
}else{
|
||||
remember_titleid("");
|
||||
s_last_art[0] = 0;
|
||||
strncpy(out_name, "(unknown game)", cap-1); out_name[cap-1]=0;
|
||||
}
|
||||
if(out_path){ snprintf(out_path, p_cap, "/data/orbisRPC/.lastgame/%s", titleId[0]?titleId:"unknown"); }
|
||||
@@ -241,21 +272,27 @@ int detect_name_for_title(const char *titleId, char *out_name, size_t cap){
|
||||
if(!titleId || !titleId[0] || !out_name || cap==0) return -1;
|
||||
remember_titleid(titleId);
|
||||
s_last_art[0] = 0;
|
||||
if(cached_resolve(titleId, out_name, cap)){
|
||||
log_msg("name: %s via cache", out_name);
|
||||
return 0;
|
||||
}
|
||||
/* Game-process-safe only: small reads plus one bounded network
|
||||
* lookup; no multi-megabyte scans anywhere in this codebase. */
|
||||
if(pronunc_title(titleId, out_name, cap)==0){ log_msg("name: %s via appmeta", out_name); return 0; }
|
||||
if(pronunc_title(titleId, out_name, cap)==0){ log_msg("name: %s via appmeta", out_name); remember_resolved(titleId, out_name, ""); return 0; }
|
||||
else log_msg("name: appmeta miss for %s", titleId);
|
||||
if(sfo_file_title(titleId, out_name, cap)==0){ log_msg("name: %s via sfo", out_name); return 0; }
|
||||
if(appxml_title(titleId, out_name, cap)==0){ log_msg("name: %s via appxml", out_name); return 0; }
|
||||
if(nametable_lookup(titleId, out_name, cap)==0){ log_msg("name: %s via table", out_name); return 0; }
|
||||
if(sfo_file_title(titleId, out_name, cap)==0){ log_msg("name: %s via sfo", out_name); remember_resolved(titleId, out_name, ""); return 0; }
|
||||
if(appxml_title(titleId, out_name, cap)==0){ log_msg("name: %s via appxml", out_name); remember_resolved(titleId, out_name, ""); return 0; }
|
||||
if(nametable_lookup(titleId, out_name, cap)==0){ log_msg("name: %s via table", out_name); remember_resolved(titleId, out_name, ""); return 0; }
|
||||
{
|
||||
char art[256] = "";
|
||||
if(tmdb_resolve(titleId, out_name, cap, art, sizeof art)==0){
|
||||
strncpy(s_last_art, art, sizeof s_last_art-1);
|
||||
remember_resolved(titleId, out_name, art);
|
||||
return 0; /* tmdb_resolve already logged */
|
||||
}
|
||||
s_last_art[0] = 0;
|
||||
}
|
||||
strncpy(out_name, titleId, cap-1); out_name[cap-1]=0;
|
||||
remember_resolved(titleId, out_name, "");
|
||||
return 0;
|
||||
}
|
||||
+6
-5
@@ -9,6 +9,7 @@
|
||||
* (close 4004) is reported as fatal instead of looping forever.
|
||||
*/
|
||||
#include "discord.h"
|
||||
#include "clock.h"
|
||||
#include "b64.h"
|
||||
#include "log.h"
|
||||
#include "jsonlite.h"
|
||||
@@ -99,7 +100,7 @@ static int rx_frame(discord_t *d, char *buf, size_t cap, int *op, int *fin, int6
|
||||
int nr=ws_recv_frame(&d->ws,buf,cap,op,fin);
|
||||
if(nr==-3){ log_msg("skipped oversized gateway frame"); continue; }
|
||||
if(nr!=0) return nr;
|
||||
if(time(NULL)>deadline) return -4;
|
||||
if(orbis_mono_s()>deadline) return -4;
|
||||
usleep(50000);
|
||||
}
|
||||
}
|
||||
@@ -141,7 +142,7 @@ int discord_connect(discord_t *d, const char *token){
|
||||
int rc=ws_connect(&d->ws, GW_HOST, GW_PORT, GW_PATH, key);
|
||||
if(rc){ log_msg("ws connect fail %d",rc); return -1; }
|
||||
d->connected=1;
|
||||
int64_t now=time(NULL);
|
||||
int64_t now=orbis_mono_s();
|
||||
d->last_heartbeat=now; d->last_ack=now;
|
||||
/* HELLO (text frame carrying {"op":10,...}) */
|
||||
char buf[2048]; int op=0,fin=0;
|
||||
@@ -175,7 +176,7 @@ int discord_connect(discord_t *d, const char *token){
|
||||
log_msg("discord: identify sent, hb=%llds",(long long)(d->hb_interval_ms/1000));
|
||||
/* READY confirms the token was accepted. `op` is the WebSocket frame
|
||||
* type; the gateway event is JSON inside — parse it, don't switch on it. */
|
||||
int64_t dl=time(NULL)+20;
|
||||
int64_t dl=orbis_mono_s()+20;
|
||||
for(;;){
|
||||
nr=rx_frame(d,buf,sizeof buf,&op,&fin,dl);
|
||||
if(nr==-4){ log_msg("no READY after identify (timeout)"); break; }
|
||||
@@ -191,7 +192,7 @@ int discord_connect(discord_t *d, const char *token){
|
||||
if(op==9){ ws_pong(&d->ws); continue; }
|
||||
if(op!=1) continue;
|
||||
int go = gw_op(buf, (size_t)nr);
|
||||
if(go==11){ d->last_ack=time(NULL); continue; }
|
||||
if(go==11){ d->last_ack=orbis_mono_s(); continue; }
|
||||
if(go==0 && is_ready(buf, (size_t)nr)){
|
||||
gw_seq(d, buf, (size_t)nr);
|
||||
log_msg("discord: gateway ready");
|
||||
@@ -322,7 +323,7 @@ int discord_clear_presence(discord_t *d){
|
||||
|
||||
int discord_tick(discord_t *d){
|
||||
if(!d || !d->connected) return -1;
|
||||
int64_t now=time(NULL);
|
||||
int64_t now=orbis_mono_s();
|
||||
long hb_s=(long)(d->hb_interval_ms/1000); if(hb_s<5)hb_s=5;
|
||||
/* gateway must ack heartbeats; 2 missed intervals means it's gone */
|
||||
if(d->sent_hb && now-d->last_ack > hb_s*2+15){
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
static FILE *g_log = NULL;
|
||||
static int g_klog = -1;
|
||||
static volatile int g_log_lock = 0;
|
||||
static volatile int g_debug = 0;
|
||||
void log_set_debug(int on){ g_debug = on ? 1 : 0; }
|
||||
static void log_lock(void){ while(__sync_lock_test_and_set(&g_log_lock, 1)) usleep(1000); }
|
||||
static void log_unlock(void){ __sync_lock_release(&g_log_lock); }
|
||||
|
||||
@@ -92,3 +94,24 @@ void log_close(void) {
|
||||
g_log = NULL;
|
||||
if (g_klog >= 0) { close(g_klog); g_klog = -1; }
|
||||
}
|
||||
|
||||
void log_dbg(const char *fmt, ...) {
|
||||
if (!g_debug || !fmt) return;
|
||||
log_lock();
|
||||
if (!g_log) { g_log = stderr; }
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
time_t t = time(NULL);
|
||||
struct tm tmv; struct tm *tm = NULL;
|
||||
extern struct tm *gmtime_r(const time_t *, struct tm *);
|
||||
tm = gmtime_r(&t, &tmv);
|
||||
char ts[20];
|
||||
if(tm) strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S", tm);
|
||||
else { strncpy(ts, "1970-01-01 00:00:00", sizeof ts); ts[sizeof ts-1]=0; }
|
||||
fprintf(g_log, "[%s] DBG ", ts);
|
||||
vfprintf(g_log, fmt, ap);
|
||||
fprintf(g_log, "\n");
|
||||
fflush(g_log);
|
||||
va_end(ap);
|
||||
log_unlock();
|
||||
}
|
||||
@@ -5,5 +5,9 @@
|
||||
/* Selects the first writable log path, falling back to stderr if needed. */
|
||||
void log_init(const char *path);
|
||||
void log_msg(const char *fmt, ...);
|
||||
/* Debug logging: compiled in, emitted only when log_set_debug(1) is on.
|
||||
* Zero overhead otherwise. For per-poll detail — never for secrets. */
|
||||
void log_set_debug(int on);
|
||||
void log_dbg(const char *fmt, ...);
|
||||
void log_close(void);
|
||||
#endif
|
||||
+5
-4
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
#include "tls.h"
|
||||
#include "log.h"
|
||||
#include "clock.h"
|
||||
#include <mbedtls/ssl.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
@@ -135,7 +136,7 @@ tls_ctx_t *tls_start(int fd, const char *host){
|
||||
|
||||
log_msg("tls: handshake start");
|
||||
{
|
||||
int64_t dl = time(NULL) + 15;
|
||||
int64_t dl = orbis_mono_s() + 15;
|
||||
extern int daemon_stop_requested(void) __attribute__((weak));
|
||||
for(;;){
|
||||
if(daemon_stop_requested && daemon_stop_requested()){ log_msg("tls: aborted (stop)"); goto fail; }
|
||||
@@ -146,7 +147,7 @@ tls_ctx_t *tls_start(int fd, const char *host){
|
||||
log_msg("tls: handshake fail %d (mbedTLS 0x%08x)", rc, (unsigned)rc);
|
||||
goto fail;
|
||||
}
|
||||
if(time(NULL) > dl){ log_msg("tls: handshake timeout"); goto fail; }
|
||||
if(orbis_mono_s() > dl){ log_msg("tls: handshake timeout"); goto fail; }
|
||||
usleep(20000);
|
||||
}
|
||||
}
|
||||
@@ -176,7 +177,7 @@ int tls_write(tls_ctx_t *t, const void *buf, size_t len){
|
||||
if(!t || (!buf && len)) return -1;
|
||||
const unsigned char *p = (const unsigned char *)buf;
|
||||
size_t done = 0;
|
||||
int64_t dl = time(NULL) + 10;
|
||||
int64_t dl = orbis_mono_s() + 10;
|
||||
while(done < len){
|
||||
int r = mbedtls_ssl_write(&t->ssl, p + done, len - done);
|
||||
if(r > 0){ done += (size_t)r; continue; }
|
||||
@@ -184,7 +185,7 @@ int tls_write(tls_ctx_t *t, const void *buf, size_t len){
|
||||
log_msg("tls: write fail %d", r);
|
||||
return -1;
|
||||
}
|
||||
if(time(NULL) > dl){ log_msg("tls: write timeout"); return -1; }
|
||||
if(orbis_mono_s() > dl){ log_msg("tls: write timeout"); return -1; }
|
||||
usleep(10000);
|
||||
}
|
||||
return (int)done;
|
||||
|
||||
+4
-3
@@ -2,6 +2,7 @@
|
||||
* Transport mirrors ws.c patterns (resolver pool, SNDTIMEO connect cap,
|
||||
* recv deadline). One attempt, no retries: failure falls through. */
|
||||
#include "tmdb.h"
|
||||
#include "clock.h"
|
||||
#include "tmdb_crypto.h"
|
||||
#include "log.h"
|
||||
#include <orbis/Net.h>
|
||||
@@ -78,11 +79,11 @@ static int http_get(const char *host, const char *path,
|
||||
path, host);
|
||||
if(rl <= 0 || rl >= (int)sizeof req){ sceNetSocketClose(fd); return -1; }
|
||||
int sent = 0;
|
||||
int64_t dl = time(NULL) + TMDB_DEADLINE_S;
|
||||
int64_t dl = orbis_mono_s() + TMDB_DEADLINE_S;
|
||||
while(sent < rl){
|
||||
int r = sceNetSend(fd, req+sent, rl-sent, 0);
|
||||
if(r > 0){ sent += r; continue; }
|
||||
if(time(NULL) > dl || r == 0){ sceNetSocketClose(fd); return -1; }
|
||||
if(orbis_mono_s() > dl || r == 0){ sceNetSocketClose(fd); return -1; }
|
||||
}
|
||||
/* read headers then body; cap total */
|
||||
char hb[2048];
|
||||
@@ -113,7 +114,7 @@ static int http_get(const char *host, const char *path,
|
||||
body[bl++] = tmp[off++];
|
||||
}
|
||||
if(bl >= cap - 1) break;
|
||||
if(time(NULL) > dl) break;
|
||||
if(orbis_mono_s() > dl) break;
|
||||
}
|
||||
sceNetSocketClose(fd);
|
||||
body[bl] = 0;
|
||||
|
||||
+4
-3
@@ -10,6 +10,7 @@
|
||||
* injection. Never deletes, never writes unvalidated bytes.
|
||||
*/
|
||||
#include "updater.h"
|
||||
#include "clock.h"
|
||||
#include "version.h"
|
||||
#include "jsonlite.h"
|
||||
#include "log.h"
|
||||
@@ -95,13 +96,13 @@ static char *https_get(const char *host, const char *path,
|
||||
size_t bl = 0, hl = 0;
|
||||
static char hb[2048];
|
||||
int hdr_done = 0, status = 0;
|
||||
int64_t dl = time(NULL) + UPD_DEADLINE_S + 20;
|
||||
int64_t dl = orbis_mono_s() + UPD_DEADLINE_S + 20;
|
||||
for(;;){
|
||||
char tmp[2048];
|
||||
int r = tls_read(t, tmp, sizeof tmp);
|
||||
if(r < 0) break;
|
||||
if(r == 0){
|
||||
if(time(NULL) > dl) break;
|
||||
if(orbis_mono_s() > dl) break;
|
||||
usleep(20000);
|
||||
continue;
|
||||
}
|
||||
@@ -121,7 +122,7 @@ static char *https_get(const char *host, const char *path,
|
||||
} else continue;
|
||||
}
|
||||
while(off < (size_t)r && bl < cap - 1) body[bl++] = tmp[off++];
|
||||
if(bl >= cap - 1 || time(NULL) > dl) break;
|
||||
if(bl >= cap - 1 || orbis_mono_s() > dl) break;
|
||||
}
|
||||
tls_free(t);
|
||||
body[bl] = 0;
|
||||
|
||||
+4
-3
@@ -5,6 +5,7 @@
|
||||
* All client->server frames are masked per RFC 6455 5.3, control frames too.
|
||||
*/
|
||||
#include "ws.h"
|
||||
#include "clock.h"
|
||||
#include "tls.h"
|
||||
#include "log.h"
|
||||
#include <orbis/Net.h>
|
||||
@@ -49,7 +50,7 @@ static int ws_send_all(ws_t *w, const unsigned char *data, size_t n){
|
||||
|
||||
static void next_mask(unsigned char mk[4]){
|
||||
static uint32_t mk_seed;
|
||||
if(!mk_seed) mk_seed = (uint32_t)time(NULL) ^ 0x9e3779b9u ^ (uint32_t)(uintptr_t)&mk_seed;
|
||||
if(!mk_seed) mk_seed = (uint32_t)orbis_mono_s() ^ 0x9e3779b9u ^ (uint32_t)(uintptr_t)&mk_seed;
|
||||
mk_seed = mk_seed*1664525u + 1013904223u;
|
||||
mk[0]=(unsigned char)(mk_seed&0xff); mk[1]=(unsigned char)((mk_seed>>8)&0xff);
|
||||
mk[2]=(unsigned char)((mk_seed>>16)&0xff); mk[3]=(unsigned char)((mk_seed>>24)&0xff);
|
||||
@@ -141,7 +142,7 @@ int ws_connect(ws_t *w, const char *host, int port, const char *resource, const
|
||||
log_msg("hs request sent (%dB)", n);
|
||||
/* Read response headers; bytes past "\r\n\r\n" are the first websocket
|
||||
* frame (usually HELLO arriving early) and MUST be kept, not dropped. */
|
||||
char hdr[2048]; int hlen=0, rd; int64_t t0=time(NULL);
|
||||
char hdr[2048]; int hlen=0, rd; int64_t t0=orbis_mono_s();
|
||||
int header_end = -1;
|
||||
extern int daemon_stop_requested(void) __attribute__((weak));
|
||||
while(hlen<(int)sizeof hdr-1){
|
||||
@@ -159,7 +160,7 @@ int ws_connect(ws_t *w, const char *host, int port, const char *resource, const
|
||||
continue;
|
||||
}
|
||||
if(rd==0){
|
||||
if(time(NULL)-t0 > 10){ log_msg("hs timeout (got %dB)", hlen); goto fail; }
|
||||
if(orbis_mono_s()-t0 > 10){ log_msg("hs timeout (got %dB)", hlen); goto fail; }
|
||||
usleep(20000); continue;
|
||||
}
|
||||
goto fail;
|
||||
|
||||
Reference in new issue
Block a user