diff --git a/orbisrpc/cfg.c b/orbisrpc/cfg.c
index 4d4bc60..ee16f37 100644
--- a/orbisrpc/cfg.c
+++ b/orbisrpc/cfg.c
@@ -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);
diff --git a/orbisrpc/cfg.h b/orbisrpc/cfg.h
index e474d91..3b4eb8b 100644
--- a/orbisrpc/cfg.h
+++ b/orbisrpc/cfg.h
@@ -13,6 +13,7 @@ typedef struct {
* large_image becomes .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;
diff --git a/orbisrpc/clock.h b/orbisrpc/clock.h
new file mode 100644
index 0000000..fca3478
--- /dev/null
+++ b/orbisrpc/clock.h
@@ -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
+/* Monotonic seconds (arbitrary epoch, never goes backward). */
+int64_t orbis_mono_s(void);
+#endif
diff --git a/orbisrpc/compat.c b/orbisrpc/compat.c
index e884d32..590e047 100644
--- a/orbisrpc/compat.c
+++ b/orbisrpc/compat.c
@@ -5,6 +5,8 @@
#include
#include
#include
+#include
+#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
+}
diff --git a/orbisrpc/daemon.c b/orbisrpc/daemon.c
index ca0eeb1..acb5bfc 100644
--- a/orbisrpc/daemon.c
+++ b/orbisrpc/daemon.c
@@ -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;
+ }
}
}
diff --git a/orbisrpc/detect.c b/orbisrpc/detect.c
index 4a7c182..8b37cad 100644
--- a/orbisrpc/detect.c
+++ b/orbisrpc/detect.c
@@ -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;
}
\ No newline at end of file
diff --git a/orbisrpc/discord.c b/orbisrpc/discord.c
index cab9baf..6cea33c 100644
--- a/orbisrpc/discord.c
+++ b/orbisrpc/discord.c
@@ -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){
diff --git a/orbisrpc/log.c b/orbisrpc/log.c
index 455da69..a1ed290 100644
--- a/orbisrpc/log.c
+++ b/orbisrpc/log.c
@@ -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();
+}
diff --git a/orbisrpc/log.h b/orbisrpc/log.h
index 4b11b23..b22fc6e 100644
--- a/orbisrpc/log.h
+++ b/orbisrpc/log.h
@@ -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
\ No newline at end of file
diff --git a/orbisrpc/tls.c b/orbisrpc/tls.c
index ba6e373..9daaee6 100644
--- a/orbisrpc/tls.c
+++ b/orbisrpc/tls.c
@@ -13,6 +13,7 @@
*/
#include "tls.h"
#include "log.h"
+#include "clock.h"
#include
#include
#include
@@ -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;
diff --git a/orbisrpc/tmdb.c b/orbisrpc/tmdb.c
index fd4dc75..3205696 100644
--- a/orbisrpc/tmdb.c
+++ b/orbisrpc/tmdb.c
@@ -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
@@ -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;
diff --git a/orbisrpc/updater.c b/orbisrpc/updater.c
index e9aa859..f6eb927 100644
--- a/orbisrpc/updater.c
+++ b/orbisrpc/updater.c
@@ -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;
diff --git a/orbisrpc/ws.c b/orbisrpc/ws.c
index 5399142..e2d2ca8 100644
--- a/orbisrpc/ws.c
+++ b/orbisrpc/ws.c
@@ -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
@@ -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;