Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
237ad52bef |
Generated
+1
-1
@@ -436,7 +436,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dosh"
|
name = "dosh"
|
||||||
version = "0.1.16"
|
version = "0.1.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "dosh"
|
name = "dosh"
|
||||||
version = "0.1.16"
|
version = "0.1.17"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
.PHONY: build test fmt clippy release-check install package-release package-release-linux package-release-windows publish-release bench-report bench-local bench-local-json bench-docker-ssh bench-docker-mosh fuzz-smoke fuzz-deep soak-local tui-harness
|
.PHONY: build test fmt clippy release-check 1.0-check reconnect-check hostile-network-check persistence-check package-check install package-release package-release-linux package-release-windows publish-release bench-report bench-local bench-local-json bench-docker-ssh bench-docker-mosh fuzz-smoke fuzz-deep soak-local tui-harness
|
||||||
|
|
||||||
build:
|
build:
|
||||||
cargo build --release
|
cargo build --release
|
||||||
@@ -19,6 +19,24 @@ release-check:
|
|||||||
cargo test
|
cargo test
|
||||||
$(MAKE) tui-harness
|
$(MAKE) tui-harness
|
||||||
|
|
||||||
|
1.0-check: release-check reconnect-check hostile-network-check persistence-check package-check
|
||||||
|
|
||||||
|
reconnect-check:
|
||||||
|
cargo test --test integration_smoke resume_updates_udp_endpoint_for_roaming -- --nocapture
|
||||||
|
DOSH_SOAK_SECONDS=$${DOSH_SOAK_SECONDS:-300} cargo test --test integration_smoke sleep_roaming_soak_30m -- --ignored --nocapture
|
||||||
|
|
||||||
|
hostile-network-check:
|
||||||
|
cargo test --test hostile_network -- --nocapture
|
||||||
|
|
||||||
|
persistence-check:
|
||||||
|
cargo test --test integration_smoke session_survives_server_restart_same_shell_and_screen -- --nocapture
|
||||||
|
cargo test --test integration_smoke multiple_persistent_named_sessions_survive_restart_independently -- --nocapture
|
||||||
|
|
||||||
|
package-check:
|
||||||
|
$(MAKE) package-release-linux
|
||||||
|
$(MAKE) package-release-windows
|
||||||
|
sh scripts/verify-release-artifacts.sh
|
||||||
|
|
||||||
install:
|
install:
|
||||||
sh install.sh --from-current
|
sh install.sh --from-current
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
repo_root="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
|
||||||
|
cd "$repo_root"
|
||||||
|
|
||||||
|
version="$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | sed -n '1p')"
|
||||||
|
out_dir="${DOSH_PACKAGE_DIR:-target/dosh-release}"
|
||||||
|
|
||||||
|
artifact_version() {
|
||||||
|
artifact="$1"
|
||||||
|
case "$artifact" in
|
||||||
|
*.tar.gz)
|
||||||
|
tar -xOf "$artifact" dosh/VERSION 2>/dev/null | tr -d '\r\n'
|
||||||
|
;;
|
||||||
|
*.zip)
|
||||||
|
unzip -p "$artifact" dosh/VERSION 2>/dev/null | tr -d '\r\n'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
failed=0
|
||||||
|
for artifact in \
|
||||||
|
"$out_dir/dosh-linux-x86_64.tar.gz" \
|
||||||
|
"$out_dir/dosh-macos-aarch64.tar.gz" \
|
||||||
|
"$out_dir/dosh-windows-x86_64.zip"; do
|
||||||
|
if [ ! -f "$artifact" ]; then
|
||||||
|
echo "missing release artifact: $artifact" >&2
|
||||||
|
failed=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ ! -f "$artifact.sha256" ]; then
|
||||||
|
echo "missing release checksum: $artifact.sha256" >&2
|
||||||
|
failed=1
|
||||||
|
fi
|
||||||
|
actual="$(artifact_version "$artifact" || true)"
|
||||||
|
if [ "$actual" != "$version" ]; then
|
||||||
|
echo "artifact version mismatch: $artifact has ${actual:-unknown}, expected $version" >&2
|
||||||
|
failed=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit "$failed"
|
||||||
+57
-5
@@ -4610,6 +4610,22 @@ async fn run_terminal(
|
|||||||
}
|
}
|
||||||
PacketKind::Pong => {
|
PacketKind::Pong => {
|
||||||
last_packet_at = Instant::now();
|
last_packet_at = Instant::now();
|
||||||
|
if should_flush_terminal_input_after_contact(
|
||||||
|
forward_only,
|
||||||
|
&cred.mode,
|
||||||
|
pending_user_input.is_empty(),
|
||||||
|
) {
|
||||||
|
flush_pending_user_input(
|
||||||
|
&socket,
|
||||||
|
addr,
|
||||||
|
&cred,
|
||||||
|
&mut send_seq,
|
||||||
|
&mut predictor,
|
||||||
|
&mut pending_user_input,
|
||||||
|
&mut pending_user_input_bytes,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PacketKind::Rekey => {
|
PacketKind::Rekey => {
|
||||||
// Server-initiated transport rekey (spec §11). The Rekey is
|
// Server-initiated transport rekey (spec §11). The Rekey is
|
||||||
@@ -5439,6 +5455,14 @@ fn should_hold_during_startup_gate(
|
|||||||
mode == StartupGateMode::HoldAll || already_queued || should_hold_post_submit_input(bytes)
|
mode == StartupGateMode::HoldAll || already_queued || should_hold_post_submit_input(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn should_flush_terminal_input_after_contact(
|
||||||
|
forward_only: bool,
|
||||||
|
mode: &str,
|
||||||
|
pending_empty: bool,
|
||||||
|
) -> bool {
|
||||||
|
!forward_only && !pending_empty && mode != "view-only" && mode != "forward-only"
|
||||||
|
}
|
||||||
|
|
||||||
async fn flush_pending_user_input(
|
async fn flush_pending_user_input(
|
||||||
socket: &UdpSocket,
|
socket: &UdpSocket,
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
@@ -7095,11 +7119,11 @@ mod tests {
|
|||||||
release_tag_download_url, release_tag_from_effective_url, release_version_from_tag,
|
release_tag_download_url, release_tag_from_effective_url, release_version_from_tag,
|
||||||
render_status_clear, render_status_overlay, requested_env, resolved_startup_command,
|
render_status_clear, render_status_overlay, requested_env, resolved_startup_command,
|
||||||
retransmit_stream_opens, rewrite_forward_command, selected_predict_mode, selected_udp_host,
|
retransmit_stream_opens, rewrite_forward_command, selected_predict_mode, selected_udp_host,
|
||||||
server_version_mismatch, should_hold_during_startup_gate, should_hold_post_submit_input,
|
server_version_mismatch, should_flush_terminal_input_after_contact,
|
||||||
split_after_command_submit, ssh_destination_host, ssh_username, ssh_with_user,
|
should_hold_during_startup_gate, should_hold_post_submit_input, split_after_command_submit,
|
||||||
startup_command, status_ssh_target, strip_stale_mouse_reports, toml_bare_key_or_quoted,
|
ssh_destination_host, ssh_username, ssh_with_user, startup_command, status_ssh_target,
|
||||||
update_check_requested, update_version_status, upsert_managed_block, valid_forward_host,
|
strip_stale_mouse_reports, toml_bare_key_or_quoted, update_check_requested,
|
||||||
vscode_safe_alias,
|
update_version_status, upsert_managed_block, valid_forward_host, vscode_safe_alias,
|
||||||
};
|
};
|
||||||
use dosh::config::{ClientConfig, CommandExtension, HostConfig};
|
use dosh::config::{ClientConfig, CommandExtension, HostConfig};
|
||||||
use dosh::native::EnvVar;
|
use dosh::native::EnvVar;
|
||||||
@@ -7879,6 +7903,34 @@ mod tests {
|
|||||||
assert_eq!(post_submit_hold_duration(b"x"), POST_SUBMIT_ALL_INPUT_HOLD);
|
assert_eq!(post_submit_hold_duration(b"x"), POST_SUBMIT_ALL_INPUT_HOLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn contact_flushes_pending_terminal_input_for_interactive_sessions() {
|
||||||
|
assert!(should_flush_terminal_input_after_contact(
|
||||||
|
false, "normal", false
|
||||||
|
));
|
||||||
|
assert!(should_flush_terminal_input_after_contact(
|
||||||
|
false,
|
||||||
|
"read-write",
|
||||||
|
false
|
||||||
|
));
|
||||||
|
assert!(!should_flush_terminal_input_after_contact(
|
||||||
|
false, "normal", true
|
||||||
|
));
|
||||||
|
assert!(!should_flush_terminal_input_after_contact(
|
||||||
|
true, "normal", false
|
||||||
|
));
|
||||||
|
assert!(!should_flush_terminal_input_after_contact(
|
||||||
|
false,
|
||||||
|
"view-only",
|
||||||
|
false
|
||||||
|
));
|
||||||
|
assert!(!should_flush_terminal_input_after_contact(
|
||||||
|
false,
|
||||||
|
"forward-only",
|
||||||
|
false
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reconnect_refreshes_live_send_address_from_credentials() {
|
fn reconnect_refreshes_live_send_address_from_credentials() {
|
||||||
let mut addr = "127.0.0.1:50000".parse().unwrap();
|
let mut addr = "127.0.0.1:50000".parse().unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user