Skip to content

Commit 16d17c1

Browse files
committed
Restore stock attach renderer handshake
1 parent 7066d4f commit 16d17c1

1 file changed

Lines changed: 25 additions & 188 deletions

File tree

crates/renderide-shared/src/ipc/connection.rs

Lines changed: 25 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! Matches the managed host's argument convention (see `RenderingManager.GetConnectionParameters`).
44
5-
use std::env::{self, VarError};
5+
use std::env;
66
use std::mem::size_of;
77
use std::net::UdpSocket;
88
use std::num::TryFromIntError;
@@ -15,14 +15,6 @@ use thiserror::Error;
1515
const ATTACH_RENDERER_PORT: u16 = 42_512;
1616
/// Maximum accepted attach handshake payload size.
1717
const ATTACH_RENDERER_PACKET_MAX_BYTES: usize = 4096;
18-
/// Environment variable carrying the debug-attach v2 nonce.
19-
pub const ATTACH_RENDERER_NONCE_ENV: &str = "RENDERIDE_ATTACH_NONCE";
20-
/// Magic prefix for authenticated debug-attach v2 packets.
21-
const ATTACH_RENDERER_V2_MAGIC: &[u8] = b"RenderideAttachV2\0";
22-
/// Minimum nonce length accepted for debug attach.
23-
const ATTACH_RENDERER_MIN_NONCE_BYTES: usize = 16;
24-
/// Maximum nonce length accepted for debug attach.
25-
const ATTACH_RENDERER_MAX_NONCE_BYTES: usize = 128;
2618
/// Maximum number of bytes in a .NET 7-bit encoded i32.
2719
const MAX_7BIT_ENCODED_I32_BYTES: usize = 5;
2820
/// High bit marking another 7-bit length byte.
@@ -52,24 +44,6 @@ enum AttachConnectionError {
5244
/// The attach listener failed while waiting for the host datagram.
5345
#[error("failed to receive attach renderer parameters: {0}")]
5446
Receive(#[source] std::io::Error),
55-
/// An authenticated v2 attach packet was received without a configured nonce.
56-
#[error("attach renderer v2 packet requires {ATTACH_RENDERER_NONCE_ENV}")]
57-
MissingNonce,
58-
/// Attach nonce was outside the accepted size range.
59-
#[error("attach renderer nonce length {len} is outside the accepted range")]
60-
InvalidNonceLength {
61-
/// Nonce byte length.
62-
len: usize,
63-
},
64-
/// Attach nonce could not be read as a Unicode environment value.
65-
#[error("attach renderer nonce is not valid Unicode")]
66-
InvalidNonceEncoding,
67-
/// The packet was not an authenticated v2 attach packet.
68-
#[error("attach renderer packet is not an authenticated v2 packet")]
69-
MissingV2Magic,
70-
/// The packet nonce does not match the expected launch nonce.
71-
#[error("attach renderer nonce mismatch")]
72-
NonceMismatch,
7347
/// The payload ended before the queue name length prefix completed.
7448
#[error("attach renderer payload ended before the queue name length prefix completed")]
7549
TruncatedStringLength,
@@ -179,19 +153,7 @@ fn arg_has_ascii_suffix(arg: &str, suffix: &str) -> bool {
179153

180154
/// Waits for connection parameters from the debug attach UDP handshake.
181155
fn get_connection_parameters_from_attach_renderer() -> Option<ConnectionParams> {
182-
let nonce = match attach_renderer_nonce_from_env() {
183-
Ok(nonce) => nonce,
184-
Err(error) => {
185-
logger::warn!("Attach renderer handshake failed: {error}");
186-
return None;
187-
}
188-
};
189-
if nonce.is_none() {
190-
logger::warn!(
191-
"Attach renderer nonce not configured; accepting unauthenticated legacy attach payloads"
192-
);
193-
}
194-
match receive_attach_renderer_parameters(nonce.as_deref()) {
156+
match receive_attach_renderer_parameters() {
195157
Ok(params) => Some(params),
196158
Err(error) => {
197159
logger::warn!("Attach renderer handshake failed: {error}");
@@ -200,29 +162,8 @@ fn get_connection_parameters_from_attach_renderer() -> Option<ConnectionParams>
200162
}
201163
}
202164

203-
fn attach_renderer_nonce_from_env() -> Result<Option<Vec<u8>>, AttachConnectionError> {
204-
let nonce = match env::var(ATTACH_RENDERER_NONCE_ENV) {
205-
Ok(nonce) => nonce.into_bytes(),
206-
Err(VarError::NotPresent) => return Ok(None),
207-
Err(VarError::NotUnicode(_nonce)) => {
208-
return Err(AttachConnectionError::InvalidNonceEncoding);
209-
}
210-
};
211-
validate_attach_renderer_nonce(&nonce)?;
212-
Ok(Some(nonce))
213-
}
214-
215-
fn validate_attach_renderer_nonce(nonce: &[u8]) -> Result<(), AttachConnectionError> {
216-
if !(ATTACH_RENDERER_MIN_NONCE_BYTES..=ATTACH_RENDERER_MAX_NONCE_BYTES).contains(&nonce.len()) {
217-
return Err(AttachConnectionError::InvalidNonceLength { len: nonce.len() });
218-
}
219-
Ok(())
220-
}
221-
222165
/// Receives and parses the debug attach UDP datagram.
223-
fn receive_attach_renderer_parameters(
224-
expected_nonce: Option<&[u8]>,
225-
) -> Result<ConnectionParams, AttachConnectionError> {
166+
fn receive_attach_renderer_parameters() -> Result<ConnectionParams, AttachConnectionError> {
226167
let socket = UdpSocket::bind(("127.0.0.1", ATTACH_RENDERER_PORT))
227168
.map_err(AttachConnectionError::Bind)?;
228169
logger::info!(
@@ -233,48 +174,11 @@ fn receive_attach_renderer_parameters(
233174
let (len, _) = socket
234175
.recv_from(&mut buf)
235176
.map_err(AttachConnectionError::Receive)?;
236-
parse_attach_renderer_packet(&buf[..len], expected_nonce)
177+
parse_attach_renderer_packet(&buf[..len])
237178
}
238179

239-
/// Parses the authenticated host attach datagram.
240-
fn parse_attach_renderer_packet(
241-
packet: &[u8],
242-
expected_nonce: Option<&[u8]>,
243-
) -> Result<ConnectionParams, AttachConnectionError> {
244-
let Some(rest) = packet.strip_prefix(ATTACH_RENDERER_V2_MAGIC) else {
245-
if expected_nonce.is_some() {
246-
return Err(AttachConnectionError::MissingV2Magic);
247-
}
248-
logger::warn!("Attach renderer accepted unauthenticated legacy payload");
249-
return parse_attach_renderer_legacy_payload(packet);
250-
};
251-
let Some(expected_nonce) = expected_nonce else {
252-
return Err(AttachConnectionError::MissingNonce);
253-
};
254-
validate_attach_renderer_nonce(expected_nonce)?;
255-
let (nonce_len, nonce_offset) = read_7bit_encoded_usize(rest)?;
256-
let nonce_end = nonce_offset.checked_add(nonce_len).ok_or_else(|| {
257-
AttachConnectionError::TruncatedQueueName {
258-
expected: nonce_len,
259-
remaining: rest.len().saturating_sub(nonce_offset),
260-
}
261-
})?;
262-
if nonce_end > rest.len() {
263-
return Err(AttachConnectionError::TruncatedQueueName {
264-
expected: nonce_len,
265-
remaining: rest.len().saturating_sub(nonce_offset),
266-
});
267-
}
268-
if &rest[nonce_offset..nonce_end] != expected_nonce {
269-
return Err(AttachConnectionError::NonceMismatch);
270-
}
271-
parse_attach_renderer_legacy_payload(&rest[nonce_end..])
272-
}
273-
274-
/// Parses the queue portion of the host attach datagram encoded by `.NET BinaryWriter`.
275-
fn parse_attach_renderer_legacy_payload(
276-
packet: &[u8],
277-
) -> Result<ConnectionParams, AttachConnectionError> {
180+
/// Parses the host attach datagram encoded by `.NET BinaryWriter`.
181+
fn parse_attach_renderer_packet(packet: &[u8]) -> Result<ConnectionParams, AttachConnectionError> {
278182
let (queue_name_len, queue_name_offset) = read_7bit_encoded_usize(packet)?;
279183
let Some(queue_name_end) = queue_name_offset.checked_add(queue_name_len) else {
280184
return Err(AttachConnectionError::TruncatedQueueName {
@@ -424,29 +328,14 @@ pub fn publisher_queue_name(base: &str, channel: &str) -> String {
424328
mod tests {
425329
use super::*;
426330

427-
const TEST_NONCE: &[u8] = b"0123456789abcdef";
428-
429331
fn attach_packet(queue_name: &str, queue_capacity: i64) -> Vec<u8> {
430-
v2_packet(&legacy_attach_packet(queue_name, queue_capacity))
431-
}
432-
433-
fn legacy_attach_packet(queue_name: &str, queue_capacity: i64) -> Vec<u8> {
434332
let mut packet = Vec::new();
435333
write_7bit_encoded_usize(queue_name.len(), &mut packet);
436334
packet.extend_from_slice(queue_name.as_bytes());
437335
packet.extend_from_slice(&queue_capacity.to_le_bytes());
438336
packet
439337
}
440338

441-
fn v2_packet(legacy_payload: &[u8]) -> Vec<u8> {
442-
let mut packet = Vec::new();
443-
packet.extend_from_slice(ATTACH_RENDERER_V2_MAGIC);
444-
write_7bit_encoded_usize(TEST_NONCE.len(), &mut packet);
445-
packet.extend_from_slice(TEST_NONCE);
446-
packet.extend_from_slice(legacy_payload);
447-
packet
448-
}
449-
450339
fn write_7bit_encoded_usize(mut value: usize, packet: &mut Vec<u8>) {
451340
while value >= usize::from(SEVEN_BIT_CONTINUATION) {
452341
packet.push((value as u8 & SEVEN_BIT_VALUE_MASK) | SEVEN_BIT_CONTINUATION);
@@ -470,13 +359,10 @@ mod tests {
470359
}
471360

472361
#[test]
473-
fn parse_attach_renderer_packet_accepts_authenticated_binary_writer_payload() {
362+
fn parse_attach_renderer_packet_accepts_binary_writer_payload() {
474363
assert_eq!(
475-
parse_attach_renderer_packet(
476-
&attach_packet("RenderideQueue", 8_388_608),
477-
Some(TEST_NONCE),
478-
)
479-
.expect("attach packet should parse"),
364+
parse_attach_renderer_packet(&attach_packet("RenderideQueue", 8_388_608))
365+
.expect("attach packet should parse"),
480366
ConnectionParams {
481367
queue_name: "RenderideQueue".into(),
482368
queue_capacity: 8_388_608,
@@ -488,7 +374,7 @@ mod tests {
488374
fn parse_attach_renderer_packet_accepts_multibyte_string_length() {
489375
let queue_name = "q".repeat(130);
490376
assert_eq!(
491-
parse_attach_renderer_packet(&attach_packet(&queue_name, 4096), Some(TEST_NONCE))
377+
parse_attach_renderer_packet(&attach_packet(&queue_name, 4096))
492378
.expect("attach packet should parse"),
493379
ConnectionParams {
494380
queue_name,
@@ -497,53 +383,10 @@ mod tests {
497383
);
498384
}
499385

500-
#[test]
501-
fn parse_attach_renderer_packet_rejects_legacy_payload_when_nonce_is_configured() {
502-
let error = parse_attach_renderer_packet(
503-
&legacy_attach_packet("RenderideQueue", 8_388_608),
504-
Some(TEST_NONCE),
505-
)
506-
.expect_err("legacy attach packet should be rejected");
507-
assert!(matches!(error, AttachConnectionError::MissingV2Magic));
508-
}
509-
510-
#[test]
511-
fn parse_attach_renderer_packet_accepts_legacy_payload_when_nonce_is_absent() {
512-
assert_eq!(
513-
parse_attach_renderer_packet(&legacy_attach_packet("RenderideQueue", 8_388_608), None,)
514-
.expect("legacy attach packet should parse"),
515-
ConnectionParams {
516-
queue_name: "RenderideQueue".into(),
517-
queue_capacity: 8_388_608,
518-
}
519-
);
520-
}
521-
522-
#[test]
523-
fn parse_attach_renderer_packet_rejects_v2_payload_when_nonce_is_absent() {
524-
let error = parse_attach_renderer_packet(&attach_packet("RenderideQueue", 8_388_608), None)
525-
.expect_err("v2 attach packet without expected nonce should be rejected");
526-
assert!(matches!(error, AttachConnectionError::MissingNonce));
527-
}
528-
529-
#[test]
530-
fn parse_attach_renderer_packet_rejects_nonce_mismatch() {
531-
let mut wrong_nonce = TEST_NONCE.to_vec();
532-
wrong_nonce[0] ^= 0xff;
533-
534-
let error = parse_attach_renderer_packet(
535-
&attach_packet("RenderideQueue", 8_388_608),
536-
Some(&wrong_nonce),
537-
)
538-
.expect_err("wrong nonce should be rejected");
539-
assert!(matches!(error, AttachConnectionError::NonceMismatch));
540-
}
541-
542386
#[test]
543387
fn parse_attach_renderer_packet_rejects_truncated_string_length() {
544-
let error =
545-
parse_attach_renderer_packet(&v2_packet(&[SEVEN_BIT_CONTINUATION]), Some(TEST_NONCE))
546-
.expect_err("length prefix should be incomplete");
388+
let error = parse_attach_renderer_packet(&[SEVEN_BIT_CONTINUATION])
389+
.expect_err("length prefix should be incomplete");
547390
assert!(matches!(
548391
error,
549392
AttachConnectionError::TruncatedStringLength
@@ -552,11 +395,8 @@ mod tests {
552395

553396
#[test]
554397
fn parse_attach_renderer_packet_rejects_malformed_string_length() {
555-
let error = parse_attach_renderer_packet(
556-
&v2_packet(&[0xff, 0xff, 0xff, 0xff, 0x08]),
557-
Some(TEST_NONCE),
558-
)
559-
.expect_err("length prefix should be malformed");
398+
let error = parse_attach_renderer_packet(&[0xff, 0xff, 0xff, 0xff, 0x08])
399+
.expect_err("length prefix should be malformed");
560400
assert!(matches!(
561401
error,
562402
AttachConnectionError::MalformedStringLength
@@ -565,8 +405,8 @@ mod tests {
565405

566406
#[test]
567407
fn parse_attach_renderer_packet_rejects_truncated_queue_name() {
568-
let error = parse_attach_renderer_packet(&v2_packet(&[4, b'n']), Some(TEST_NONCE))
569-
.expect_err("queue name should be incomplete");
408+
let error =
409+
parse_attach_renderer_packet(&[4, b'n']).expect_err("queue name should be incomplete");
570410
assert!(matches!(
571411
error,
572412
AttachConnectionError::TruncatedQueueName {
@@ -581,7 +421,7 @@ mod tests {
581421
let mut packet = vec![1, 0xff];
582422
packet.extend_from_slice(&4096_i64.to_le_bytes());
583423

584-
let error = parse_attach_renderer_packet(&v2_packet(&packet), Some(TEST_NONCE))
424+
let error = parse_attach_renderer_packet(&packet)
585425
.expect_err("queue name should reject invalid UTF-8");
586426
assert!(matches!(
587427
error,
@@ -591,11 +431,8 @@ mod tests {
591431

592432
#[test]
593433
fn parse_attach_renderer_packet_rejects_truncated_queue_capacity() {
594-
let error = parse_attach_renderer_packet(
595-
&v2_packet(&[4, b'n', b'a', b'm', b'e']),
596-
Some(TEST_NONCE),
597-
)
598-
.expect_err("queue capacity should be incomplete");
434+
let error = parse_attach_renderer_packet(&[4, b'n', b'a', b'm', b'e'])
435+
.expect_err("queue capacity should be incomplete");
599436
assert!(matches!(
600437
error,
601438
AttachConnectionError::TruncatedQueueCapacity { remaining: 0 }
@@ -604,14 +441,14 @@ mod tests {
604441

605442
#[test]
606443
fn parse_attach_renderer_packet_rejects_non_positive_queue_capacity() {
607-
let zero = parse_attach_renderer_packet(&attach_packet("queue", 0), Some(TEST_NONCE))
444+
let zero = parse_attach_renderer_packet(&attach_packet("queue", 0))
608445
.expect_err("zero capacity should be invalid");
609446
assert!(matches!(
610447
zero,
611448
AttachConnectionError::InvalidQueueCapacity { queue_capacity: 0 }
612449
));
613450

614-
let negative = parse_attach_renderer_packet(&attach_packet("queue", -1), Some(TEST_NONCE))
451+
let negative = parse_attach_renderer_packet(&attach_packet("queue", -1))
615452
.expect_err("negative capacity should be invalid");
616453
assert!(matches!(
617454
negative,
@@ -621,10 +458,10 @@ mod tests {
621458

622459
#[test]
623460
fn parse_attach_renderer_packet_rejects_oversized_queue_capacity() {
624-
let error = parse_attach_renderer_packet(
625-
&attach_packet("queue", interprocess::QueueOptions::MAX_CAPACITY + 8),
626-
Some(TEST_NONCE),
627-
)
461+
let error = parse_attach_renderer_packet(&attach_packet(
462+
"queue",
463+
interprocess::QueueOptions::MAX_CAPACITY + 8,
464+
))
628465
.expect_err("oversized capacity should be invalid");
629466
assert!(matches!(
630467
error,

0 commit comments

Comments
 (0)