first pass of merging in warp (doesn't build)

This commit is contained in:
Ryan Ward
2026-07-01 16:08:58 -05:00
parent 2f64909469
commit 4770ac06b5
3662 changed files with 414574 additions and 89772 deletions
+82 -4
View File
@@ -19,18 +19,69 @@ use std::time::Duration;
use super::super::setup;
/// Path to the daemon's Unix domain socket.
/// Path to the daemon's Unix domain socket, versioned on release channels.
pub(super) fn socket_path(identity_key: &str) -> PathBuf {
let dir = setup::remote_server_daemon_dir(identity_key);
let expanded = shellexpand::tilde(&dir).into_owned();
PathBuf::from(expanded).join("server.sock")
PathBuf::from(expanded).join(setup::daemon_socket_name())
}
/// Path to the daemon's PID file (also used as the flock target).
/// Path to the daemon's PID file (also used as the flock target),
/// versioned on release channels.
pub(super) fn pid_path(identity_key: &str) -> PathBuf {
let dir = setup::remote_server_daemon_dir(identity_key);
let expanded = shellexpand::tilde(&dir).into_owned();
PathBuf::from(expanded).join("server.pid")
PathBuf::from(expanded).join(setup::daemon_pid_name())
}
/// Daemon directory for the given identity key (expanded, no tilde).
fn daemon_dir(identity_key: &str) -> PathBuf {
let dir = setup::remote_server_daemon_dir(identity_key);
let expanded = shellexpand::tilde(&dir).into_owned();
PathBuf::from(expanded)
}
/// Scans the identity-key daemon directory and removes socket/PID files
/// from previous daemon versions.
///
/// Old daemons are **not** killed — they may still be serving active
/// connections from an older Warp client. Removing their socket file
/// prevents new proxies from accidentally connecting to them, and the
/// daemon's built-in grace timer (10 min with no connections) will shut
/// it down naturally after the last client disconnects.
///
/// Errors are logged but do not prevent the proxy from proceeding.
fn cleanup_old_versions(identity_key: &str) {
let dir = daemon_dir(identity_key);
let current_socket = setup::daemon_socket_name();
let current_pid = setup::daemon_pid_name();
let entries = match std::fs::read_dir(&dir) {
Ok(entries) => entries,
Err(_) => return,
};
for entry in entries.flatten() {
let name = entry.file_name();
let Some(name_str) = name.to_str() else {
continue;
};
// Remove old PID files: server*.pid that aren't the current version.
if name_str.ends_with(".pid") && name_str.starts_with("server") && name_str != current_pid {
log::info!("Proxy: removing old PID file {name_str}");
let _ = std::fs::remove_file(entry.path());
}
// Remove old socket files: server*.sock that aren't the current version.
if name_str.ends_with(".sock")
&& name_str.starts_with("server")
&& name_str != current_socket
{
log::info!("Proxy: removing old socket file {name_str}");
let _ = std::fs::remove_file(entry.path());
}
}
}
/// Ensures the daemon directory exists with owner-only permissions.
@@ -40,6 +91,13 @@ pub(super) fn ensure_private_daemon_dir(path: &std::path::Path) -> anyhow::Resul
Ok(())
}
/// Maximum usable `sun_path` length for Unix domain sockets.
///
/// macOS has the strictest limit (104 bytes including null terminator,
/// 103 usable). We use 103 on all platforms so a single binary works
/// everywhere without per-target branching.
const SUN_PATH_MAX: usize = 103;
/// Entry point for `remote-server-proxy`.
///
/// Ensures the daemon is running, then bridges stdin/stdout to the daemon's
@@ -48,11 +106,31 @@ pub fn run(identity_key: &str) -> anyhow::Result<()> {
let socket_path = socket_path(identity_key);
let pid_path = pid_path(identity_key);
// Guard against socket paths that exceed the sun_path limit.
// Without this check, UnixListener::bind fails silently in the
// daemon and the proxy times out after 10s with no actionable
// error. With hashed identity + version names the path should
// always fit, so hitting this guard indicates a new path component
// was added without budgeting for sun_path. The error surfaces in
// client telemetry (RemoteServerInitialization) and daemon logs.
let path_len = socket_path.as_os_str().len();
if path_len > SUN_PATH_MAX {
anyhow::bail!(
"daemon socket path is {path_len} bytes, which exceeds the \
sun_path limit of {SUN_PATH_MAX} bytes: {}",
socket_path.display()
);
}
// Ensure the parent directory exists.
if let Some(parent) = socket_path.parent() {
ensure_private_daemon_dir(parent)?;
}
// Clean up socket/PID files from previous daemon versions so stale
// daemons left over after autoupdate don't linger.
cleanup_old_versions(identity_key);
// ---- Acquire exclusive flock on the PID file --------------------------------
//
// This serialises concurrent proxy starts. If two tabs SSH in at the