From be80ae372a593ff0ed61bb1867f4048fd934804a Mon Sep 17 00:00:00 2001 From: Ofer Chen Date: Wed, 15 Oct 2025 13:42:48 +0200 Subject: [PATCH] Add helper to format legacy daemon greeting --- crates/protocol/src/lib.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 7cb72022d..e0eed6c9e 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -288,6 +288,22 @@ pub fn parse_legacy_daemon_greeting_bytes( } } +/// Formats the legacy ASCII daemon greeting used by pre-protocol-30 peers. +/// +/// Upstream daemons send a line such as `@RSYNCD: 32.0\n` when speaking to +/// older clients. The Rust implementation mirrors that exact layout so callers +/// can emit byte-identical banners during negotiation and round-trip the value +/// through [`parse_legacy_daemon_greeting`]. +#[must_use] +pub fn format_legacy_daemon_greeting(version: ProtocolVersion) -> String { + let mut banner = String::with_capacity(16); + banner.push_str("@RSYNCD: "); + let digits = version.as_u8().to_string(); + banner.push_str(&digits); + banner.push_str(".0\n"); + banner +} + /// Selects the highest mutual protocol version between the Rust implementation and a peer. /// /// The caller provides the list of protocol versions advertised by the peer in any order. @@ -481,6 +497,20 @@ mod tests { )); } + #[test] + fn formats_legacy_daemon_greeting_for_newest_protocol() { + let rendered = format_legacy_daemon_greeting(ProtocolVersion::NEWEST); + assert_eq!(rendered, "@RSYNCD: 32.0\n"); + } + + #[test] + fn formatted_legacy_greeting_round_trips_through_parser() { + let version = ProtocolVersion::try_from(29).expect("valid version"); + let rendered = format_legacy_daemon_greeting(version); + let parsed = parse_legacy_daemon_greeting(&rendered).expect("parseable banner"); + assert_eq!(parsed, version); + } + #[test] fn converts_protocol_version_to_u8() { let version = ProtocolVersion::try_from(31).expect("valid version");