mirror of
https://github.com/telemt/telemt.git
synced 2026-10-09 19:05:58 +03:00
WEB: websocket-lanes upgrade-fail recovery #925
This commit is contained in:
@@ -391,16 +391,17 @@ function queueLane(value){
|
|||||||
}
|
}
|
||||||
function openLaneSocket(lane){
|
function openLaneSocket(lane){
|
||||||
if(lane.socket||closed)return;lane.socket=new WebSocket(socketURL(),'tproxy-lane-v1.'+sessionToken+'.'+String(lane.id));lane.socket.binaryType='arraybuffer';
|
if(lane.socket||closed)return;lane.socket=new WebSocket(socketURL(),'tproxy-lane-v1.'+sessionToken+'.'+String(lane.id));lane.socket.binaryType='arraybuffer';
|
||||||
const opened=lane.socket,openTimer=setTimeout(()=>{if(!closed&&lanes.get(lane.id)===lane&&lane.socket===opened)finishLane(lane,true)},websocketOpenMs);
|
const opened=lane.socket;let upgraded=false,settled=false,openTimer=null;const finishSocket=reason=>{if(settled)return;settled=true;if(openTimer)clearTimeout(openTimer);openTimer=null;if(closed||lanes.get(lane.id)!==lane||lane.socket!==opened)return;lane.ready=false;if(!upgraded){lane.socket=null;opened.close();recoveryController.recover(reason,null);return}finishLane(lane,true)};
|
||||||
lane.socket.onopen=()=>{if(closed||lanes.get(lane.id)!==lane)return;lane.ready=true;status('connected');runLaneSocketUp(lane)};
|
openTimer=setTimeout(()=>finishSocket('timeout'),websocketOpenMs);
|
||||||
|
lane.socket.onopen=()=>{if(closed||lanes.get(lane.id)!==lane||lane.socket!==opened){opened.close();return}upgraded=true;lane.ready=true;status('connected');runLaneSocketUp(lane)};
|
||||||
lane.socket.onmessage=event=>{
|
lane.socket.onmessage=event=>{
|
||||||
clearTimeout(openTimer);
|
if(openTimer)clearTimeout(openTimer);openTimer=null;
|
||||||
if(closed||lanes.get(lane.id)!==lane||!(event.data instanceof ArrayBuffer)){finishLane(lane,true);return}
|
if(closed||lanes.get(lane.id)!==lane||lane.socket!==opened||!(event.data instanceof ArrayBuffer)){finishLane(lane,true);return}
|
||||||
let values;try{values=splitFrames(event.data);for(const value of values)if(value.id!==lane.id)throw new Error('cross-lane frame')}catch(error){finishLane(lane,true);return}
|
let values;try{values=splitFrames(event.data);for(const value of values)if(value.id!==lane.id)throw new Error('cross-lane frame')}catch(error){finishLane(lane,true);return}
|
||||||
if(values.some(value=>value.type===3))lane.remoteClosed=true;
|
if(values.some(value=>value.type===3))lane.remoteClosed=true;
|
||||||
observeServerFrames(event.data);port.postMessage({t:'traffic',up:0,down:event.data.byteLength});port.postMessage(event.data,[event.data]);status('connected');
|
observeServerFrames(event.data);port.postMessage({t:'traffic',up:0,down:event.data.byteLength});port.postMessage(event.data,[event.data]);status('connected');
|
||||||
};
|
};
|
||||||
lane.socket.onerror=()=>{};lane.socket.onclose=()=>{clearTimeout(openTimer);lane.ready=false;lane.socket=null;if(!closed)finishLane(lane,true)};
|
lane.socket.onerror=()=>{};lane.socket.onclose=()=>finishSocket(upgraded?'network':'upgrade');
|
||||||
}
|
}
|
||||||
async function runLaneSocketUp(lane){
|
async function runLaneSocketUp(lane){
|
||||||
if(lane.running||!lane.ready)return;lane.running=true;let lease=null;
|
if(lane.running||!lane.ready)return;lane.running=true;let lease=null;
|
||||||
|
|||||||
@@ -217,6 +217,39 @@ fn rendered_page_preserves_exact_v1_status_control_envelope() {
|
|||||||
assert!(!page.body.contains("port.postMessage({t:'status',state,"));
|
assert!(!page.body.contains("port.postMessage({t:'status',state,"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn committed_websocket_lane_escalates_only_pre_upgrade_failure() {
|
||||||
|
let page = render_page("LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 4);
|
||||||
|
|
||||||
|
assert!(page.body.contains("let upgraded=false,settled=false"));
|
||||||
|
assert!(page.body.contains(
|
||||||
|
"if(settled)return;settled=true;if(openTimer)clearTimeout(openTimer);openTimer=null"
|
||||||
|
));
|
||||||
|
assert!(page
|
||||||
|
.body
|
||||||
|
.contains("if(closed||lanes.get(lane.id)!==lane||lane.socket!==opened)return"));
|
||||||
|
assert!(page.body.contains(
|
||||||
|
"if(!upgraded){lane.socket=null;opened.close();recoveryController.recover(reason,null);return}"
|
||||||
|
));
|
||||||
|
assert!(page
|
||||||
|
.body
|
||||||
|
.contains("recoveryController.recover(reason,null);return}finishLane(lane,true)"));
|
||||||
|
assert!(page
|
||||||
|
.body
|
||||||
|
.contains("openTimer=setTimeout(()=>finishSocket('timeout'),websocketOpenMs)"));
|
||||||
|
assert!(page.body.contains(
|
||||||
|
"if(closed||lanes.get(lane.id)!==lane||lane.socket!==opened){opened.close();return}"
|
||||||
|
));
|
||||||
|
assert!(page.body.contains("upgraded=true;lane.ready=true"));
|
||||||
|
assert!(page
|
||||||
|
.body
|
||||||
|
.contains("lane.socket.onclose=()=>finishSocket(upgraded?'network':'upgrade')"));
|
||||||
|
assert!(page
|
||||||
|
.body
|
||||||
|
.contains("port.postMessage({t:'status',state})"));
|
||||||
|
assert!(!page.body.contains("port.postMessage({t:'status',state,"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bridge_diagnostic_sideband_is_absent_by_default() {
|
fn bridge_diagnostic_sideband_is_absent_by_default() {
|
||||||
let page = render_page("IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII", 4);
|
let page = render_page("IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII", 4);
|
||||||
|
|||||||
Reference in New Issue
Block a user