fix: align native daemon port hash with client on Windows (#734)

The client (connection.rs) and native daemon (native/daemon.rs) used
different get_port_for_session() implementations on Windows:

- Client:  i32, .chars(), djb2  — (hash << 5) - hash + c
- Daemon:  i64, .bytes(), Java hashCode — hash * 31 + b

For session name "default", client computes port 50838 while the
daemon binds on 51174, causing a 5-second timeout and startup failure.

Fix: align native/daemon.rs to use the identical djb2 algorithm from
connection.rs (i32, chars, djb2), so both sides agree on the port.

Unix is unaffected (uses Unix domain sockets, no port hashing).

Tests: add port hash regression tests to all three implementations
(native/daemon.rs, connection.rs, daemon.ts) to prevent future drift.

Fixes #705
This commit is contained in:
mikewong23571
2026-03-12 14:15:35 -05:00
committed by GitHub
parent 2fb2a51c82
commit d4f7fbc718
4 changed files with 55 additions and 6 deletions
+21 -4
View File
@@ -258,9 +258,26 @@ fn get_daemon_socket_dir() -> PathBuf {
#[cfg(windows)]
fn get_port_for_session(session: &str) -> u16 {
let mut hash: i64 = 0;
for b in session.bytes() {
hash = hash.wrapping_mul(31).wrapping_add(b as i64);
let mut hash: i32 = 0;
for c in session.chars() {
hash = ((hash << 5).wrapping_sub(hash)).wrapping_add(c as i32);
}
49152 + ((hash.unsigned_abs() as u32 % 16383) as u16)
}
#[cfg(test)]
#[cfg(windows)]
mod tests {
use super::*;
#[test]
fn test_port_matches_client_algorithm() {
// These values are computed by the identical djb2 implementation in
// connection.rs. Both sides must agree on the port for the daemon to
// start successfully.
assert_eq!(get_port_for_session("default"), 50838);
assert_eq!(get_port_for_session("my-session"), 63105);
assert_eq!(get_port_for_session("work"), 51184);
assert_eq!(get_port_for_session(""), 49152);
}
49152 + (hash.unsigned_abs() % 16383) as u16
}