diff options
Diffstat (limited to 'src/api/server.rs')
| -rw-r--r-- | src/api/server.rs | 64 |
1 files changed, 62 insertions, 2 deletions
diff --git a/src/api/server.rs b/src/api/server.rs index 752893c6..aec7274d 100644 --- a/src/api/server.rs +++ b/src/api/server.rs @@ -22,6 +22,9 @@ use crate::ipc::{ socket_file_identity, LocalStream, LocalStreamRead, SocketFileIdentity, }; +mod pane_graphics_stream; +pub(crate) use pane_graphics_stream::cancel_inactive_streams as cancel_inactive_pane_graphics_streams; + const SOCKET_PERMISSION_MODE: u32 = 0o600; pub(super) const CONNECTION_POLL_INTERVAL: Duration = Duration::from_millis(100); pub(super) const APP_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5); @@ -155,14 +158,14 @@ fn handle_connection( let request = match serde_json::from_str::<Request>(line) { Ok(request) => request, - Err(err) => { + Err(request_error) => { write_json_line_allow_disconnect( &mut stream, &ErrorResponse { id: String::new(), error: ErrorBody { code: "invalid_request".into(), - message: format!("invalid request: {err}"), + message: format!("invalid request: {request_error}"), }, }, )?; @@ -176,6 +179,22 @@ fn handle_connection( crate::logging::api_request_started(&request_id, method, changes_ui); match request.method { + Method::PaneGraphicsStream(params) => { + let result = + pane_graphics_stream::serve(stream, request_id.clone(), params, api_tx, running); + match &result { + Ok(()) => crate::logging::api_request_completed( + &request_id, + method, + "stream_closed", + changes_ui, + ), + Err(err) => { + crate::logging::api_request_failed(&request_id, method, &err.to_string()) + } + } + result + } Method::EventsSubscribe(params) => { let result = stream_subscriptions( stream, @@ -374,6 +393,13 @@ fn api_method_name(method: &Method) -> &'static str { Method::PaneSendKeys(_) => "pane.send_keys", Method::PaneSendInput(_) => "pane.send_input", Method::PaneRead(_) => "pane.read", + Method::PaneGraphicsSet(_) => "pane.graphics.set", + Method::PaneGraphicsClear(_) => "pane.graphics.clear", + Method::PaneGraphicsInfo(_) => "pane.graphics.info", + Method::PaneGraphicsStream(_) => "pane.graphics.stream", + Method::PaneGraphicsStreamSet(_) => "pane.graphics.stream.set", + Method::PaneGraphicsStreamOpen(_) => "pane.graphics.stream.open", + Method::PaneGraphicsStreamClose(_) => "pane.graphics.stream.close", Method::PaneReportAgent(_) => "pane.report_agent", Method::PaneReportAgentSession(_) => "pane.report_agent_session", Method::PaneReportMetadata(_) => "pane.report_metadata", @@ -1223,3 +1249,37 @@ mod tests { server_thread.join().unwrap(); } } + +#[cfg(test)] +mod pane_graphics_request_tests { + use super::*; + use base64::Engine as _; + + #[test] + fn maximum_public_graphics_request_fits_initial_json_line() { + let request = Request { + id: "graphics-max".into(), + method: Method::PaneGraphicsSet(crate::api::schema::PaneGraphicsSetParams { + pane_id: "pane_1".into(), + owner: String::new(), + format: crate::api::schema::PaneGraphicsFormat::Png, + image_width: 1, + image_height: 1, + data_base64: base64::engine::general_purpose::STANDARD + .encode(vec![1_u8; crate::api::schema::PANE_GRAPHICS_SET_MAX_BYTES]), + data: None, + placement: crate::api::schema::PaneGraphicsPlacementParams::default(), + }), + }; + let encoded = serde_json::to_vec(&request).unwrap(); + + assert!(encoded.len() < MAX_INITIAL_REQUEST_BYTES); + } + + #[test] + fn duplicate_method_cannot_be_reinterpreted_as_graphics_stream() { + let encoded = r#"{"id":"duplicate","method":"ping","method":"pane.graphics.stream","params":{"pane_id":"pane_1"}}"#; + + assert!(serde_json::from_str::<Request>(encoded).is_err()); + } +} |
