Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
    npro  
 Modern all-safe Rust Network Protocol library supporting h1, h2, h3, ws, wt sans-IO and with socket IO + tls
git clone https://npro.rs/repo/npro
Author[]Andy Green <andy@warmcat.com> 2025-08-05 06:32 UTC
Committer[]Andy Green <andy@warmcat.com> 2025-08-05 13:45 UTC
Treee941aae1c5844561a0bf99eb6fa12015c7fba3a0   Raw Patch
 
sai-web: api versioning
sai-web: api versioning
diff --git a/assets/sai.js b/assets/sai.js index 3331b95..9248896 100644 --- a/assets/sai.js +++ b/assets/sai.js @@ -1,3 +1,5 @@ +const SAI_JS_API_VERSION = 2; + (function() { /* @@ -1033,6 +1035,7 @@ function ws_open_sai() sai.send("{\"schema\":" + "\"com.warmcat.sai.taskinfo\"," + + "\"js_api_version\": " + SAI_JS_API_VERSION + "," + "\"logs\": 1," + "\"task_hash\":" + JSON.stringify(tid) + "}"); @@ -1051,7 +1054,8 @@ function ws_open_sai() sai.send("{\"schema\":" + "\"com.warmcat.sai.eventinfo\"," + - "\"event_hash\":" + + "\"js_api_version\": " + SAI_JS_API_VERSION + "," + + "\"event_hash\":" + JSON.stringify(eid) + "}"); return; @@ -1062,7 +1066,7 @@ function ws_open_sai() */ sai.send("{\"schema\":" + - "\"com.warmcat.sai.taskinfo\"}"); + "\"com.warmcat.sai.taskinfo\", \"js_api_version\": " + SAI_JS_API_VERSION + "}"); }; sai.onmessage = function got_packet(msg) { @@ -1113,6 +1117,12 @@ function ws_open_sai() } } + if (jso.api_version && jso.api_version !== SAI_JS_API_VERSION) { + console.warn(`Sai JS API version mismatch. Client: ${SAI_JS_API_VERSION}, Server: ${jso.api_version}. Reloading page.`); + location.reload(true); // Force a hard reload + return; // Stop processing this old message + } + switch (jso.schema) { case "com.warmcat.sai.builders": diff --git a/src/common/include/private.h b/src/common/include/private.h index 5291eed..d6a75f2 100644 --- a/src/common/include/private.h +++ b/src/common/include/private.h @@ -421,6 +421,7 @@ typedef struct sai_browse_rx_evinfo { typedef struct sai_browse_rx_taskinfo { char task_hash[65]; unsigned int log_start; + unsigned int js_api_version; uint8_t logs; } sai_browse_rx_taskinfo_t; diff --git a/src/web/w-private.h b/src/web/w-private.h index 9fbef99..4c88487 100644 --- a/src/web/w-private.h +++ b/src/web/w-private.h @@ -23,6 +23,8 @@ #include <sqlite3.h> #include <sys/stat.h> +#define SAIW_API_VERSION 2 + struct sai_plat; typedef struct sai_platm { @@ -167,6 +169,7 @@ struct pss { int log_cache_size; int authorized; int specificity; + unsigned int js_api_version; unsigned long expiry_unix_time; /* notification hmac information */ @@ -318,7 +321,7 @@ saiw_sched_destroy(struct lws_dll2 *d, void *user); void -saiw_ws_broadcast_raw(struct vhd *vhd, const void *buf, size_t len); +saiw_ws_broadcast_raw(struct vhd *vhd, const void *buf, size_t len, unsigned int min_api_version); void saiw_browser_state_changed(struct pss *pss, int established); diff --git a/src/web/w-websrv.c b/src/web/w-websrv.c index ced0742..9c75049 100644 --- a/src/web/w-websrv.c +++ b/src/web/w-websrv.c @@ -117,7 +117,7 @@ saiw_lp_rx(void *userobj, const uint8_t *buf, size_t len, int flags) m->a.ac = NULL; vhd->builders_owner = &((sai_plat_owner_t *)m->a.dest)->plat_owner; - saiw_ws_broadcast_raw(vhd, buf, len); + saiw_ws_broadcast_raw(vhd, buf, len, 0); break; case SAIS_WS_WEBSRV_RX_OVERVIEW: @@ -150,7 +150,7 @@ saiw_lp_rx(void *userobj, const uint8_t *buf, size_t len, int flags) /* A builder sent a load report, forward to all browsers */ lwsl_notice("%s: ===== Received load report, broadcasting to %d browsers\n", __func__, (int)vhd->browsers.count); - saiw_ws_broadcast_raw(vhd, buf, len); + saiw_ws_broadcast_raw(vhd, buf, len, 2); break; } diff --git a/src/web/w-ws-browser.c b/src/web/w-ws-browser.c index 18995f9..9a44614 100644 --- a/src/web/w-ws-browser.c +++ b/src/web/w-ws-browser.c @@ -35,17 +35,25 @@ * all connected browsers, eg, for load reports. */ void -saiw_ws_broadcast_raw(struct vhd *vhd, const void *buf, size_t len) +saiw_ws_broadcast_raw(struct vhd *vhd, const void *buf, size_t len, unsigned int api_ver_min) { + int eff = 0; // lwsl_err("%s: sai-web broadcasting to browsers\n", __func__); // lwsl_hexdump_err(buf, len); lws_start_foreach_dll(struct lws_dll2 *, p, vhd->browsers.head) { struct pss *pss = lws_container_of(p, struct pss, same); - if (lws_buflist_append_segment(&pss->raw_tx, buf, len) >= 0) - lws_callback_on_writable(pss->wsi); + if (pss->js_api_version >= api_ver_min) { + eff++; + if (lws_buflist_append_segment(&pss->raw_tx, buf, len) >= 0) + lws_callback_on_writable(pss->wsi); + } + } lws_end_foreach_dll(p); + + lwsl_notice("%s: broadcast to %d / %d browsers\n", __func__, + eff, (int)vhd->browsers.count); } extern const lws_struct_map_t lsm_load_report_members[2]; @@ -63,11 +71,11 @@ static lws_struct_map_t lsm_browser_taskreset[] = { }; static lws_struct_map_t lsm_browser_taskinfo[] = { - LSM_CARRAY (sai_browse_rx_taskinfo_t, task_hash, "task_hash"), - LSM_UNSIGNED (sai_browse_rx_taskinfo_t, logs, "logs"), + LSM_CARRAY (sai_browse_rx_taskinfo_t, task_hash, "task_hash"), + LSM_UNSIGNED (sai_browse_rx_taskinfo_t, logs, "logs"), + LSM_UNSIGNED (sai_browse_rx_taskinfo_t, js_api_version, "js_api_version"), }; - /* * Schema list so lws_struct can pick the right object to create based on the * incoming schema name @@ -97,6 +105,7 @@ enum { SAIM_WS_BROWSER_RX_EVENTRESET, SAIM_WS_BROWSER_RX_EVENTDELETE, SAIM_WS_BROWSER_RX_TASKCANCEL, + SAIM_WS_BROWSER_RX_JS_HELLO, }; @@ -425,6 +434,10 @@ saiw_ws_json_rx_browser(struct vhd *vhd, struct pss *pss, uint8_t *buf, int m, ret = -1; memset(&a, 0, sizeof(a)); + /* + * pss->js_api_version defaults to 1 (from ESTABLISHED callback). + * A new client will update it by sending a js-hello message. + */ a.map_st[0] = lsm_schema_json_map_bwsrx; a.map_entries_st[0] = LWS_ARRAY_SIZE(lsm_schema_json_map_bwsrx); a.map_entries_st[1] = LWS_ARRAY_SIZE(lsm_schema_json_map_bwsrx); @@ -460,6 +473,9 @@ saiw_ws_json_rx_browser(struct vhd *vhd, struct pss *pss, uint8_t *buf, */ // lwsl_warn("%s: SAIM_WS_BROWSER_RX_TASKINFO: doing WSS_PREPARE_BUILDER_SUMMARY\n", __func__); + if (ti->js_api_version) + pss->js_api_version = ti->js_api_version; + saiw_alloc_sched(pss, WSS_PREPARE_OVERVIEW); saiw_alloc_sched(pss, WSS_PREPARE_BUILDER_SUMMARY); ret = 0; @@ -790,11 +806,13 @@ again: p += lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), "{\"schema\":\"sai.warmcat.com.overview\"," + " \"api_version\":%u," " \"alang\":\"%s\"," " \"authorized\": %d," " \"auth_secs\": %ld," " \"auth_user\": \"%s\"," "\"overview\":[", + SAIW_API_VERSION, lws_json_purify(esc, pss->alang, sizeof(esc) - 1, &iu), pss->authorized, pss->authorized ? pss->expiry_unix_time - lws_now_secs() : 0, lws_json_purify(esc1, pss->auth_user, sizeof(esc1) - 1, &iu)
Page fetched 0s ago, creation time: 6ms (vhost etag hits: 0%, cache hits: 0%)