aboutsummaryrefslogtreecommitdiff
path: root/src/api/server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/server.rs')
-rw-r--r--src/api/server.rs64
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());
+ }
+}