Category
Runtime
Operating system
Linux, macOS, and Windows
Package or commit tested
PR #26 final head: cdfeaaf
Steps to reproduce
- Start a valid four-pipe MatterViz session.
- Create a valid v1 or v2 volume frame.
- Change one byte in the volume body without updating its CRC.
- Send the frame and read the acknowledgement.
- Keep the producer pipe open and observe whether the session stops.
Current behavior
Rust detects the invalid frame or CRC, sends a nonzero acknowledgement, and then continues reading the same transport:
|
fn receive_buffered_volume( |
|
reader: &mut platform::PipeReader, |
|
writer: &mut platform::PipeWriter, |
|
store: &VolumeStore, |
|
stop: &AtomicBool, |
|
prelude: [u8; PRELUDE_BYTES], |
|
) -> Result<(), ()> { |
|
let frame_len = declared_volume_frame_len(&prelude).map_err(|_| ())?; |
|
let mut frame = vec![0_u8; frame_len]; |
|
frame[..PRELUDE_BYTES].copy_from_slice(&prelude); |
|
read_exact(reader, &mut frame[PRELUDE_BYTES..], stop)?; |
|
let identity = frame_identity(&frame).ok_or(())?; |
|
let status = if store.insert(frame).is_ok() { 0 } else { 1 }; |
|
let ack = encode_ack(identity.0, identity.1, status).map_err(|_| ())?; |
|
writer.write_all(&ack).map_err(|_| ()) |
|
} |
|
|
|
fn receive_stream_volume( |
|
reader: &mut platform::PipeReader, |
|
writer: &mut platform::PipeWriter, |
|
broker: &VolumeStreamBroker, |
|
stop: &AtomicBool, |
|
prelude: [u8; PRELUDE_BYTES], |
|
) -> Result<(), ()> { |
|
let mut header = [0_u8; VOLUME_HEADER_BYTES]; |
|
header[..PRELUDE_BYTES].copy_from_slice(&prelude); |
|
read_exact(reader, &mut header[PRELUDE_BYTES..], stop)?; |
|
let metadata = decode_stream_volume_header(&header).map_err(|_| ())?; |
|
let request_id = metadata.request_id; |
|
let volume_id = metadata.volume_id; |
|
let expected_crc = metadata.body_crc32c; |
|
let mut sender = broker.sender(request_id); |
|
let mut accepted = sender.as_ref().is_some_and(|channel| { |
|
send_event( |
|
channel, |
|
StreamEvent::Begin(Box::new(metadata.clone()), Box::new(header)), |
|
stop, |
|
) |
|
}); |
|
if !accepted { |
|
sender = None; |
|
} |
|
let mut remaining = metadata.body_bytes; |
|
let mut crc = Crc32c::new(); |
|
while remaining > 0 { |
|
let length = usize::try_from(remaining.min(64 * 1024)).map_err(|_| ())?; |
|
let mut chunk = vec![0_u8; length]; |
|
read_exact(reader, &mut chunk, stop)?; |
|
crc.update(&chunk); |
|
if let Some(channel) = sender.as_ref() { |
|
if !send_event(channel, StreamEvent::Chunk(chunk), stop) { |
|
sender = None; |
|
accepted = false; |
|
} |
|
} |
|
remaining -= length as u64; |
|
} |
|
let valid = crc.finish() == expected_crc; |
|
if let Some(channel) = sender.as_ref() { |
|
let event = if valid { |
|
StreamEvent::End |
|
} else { |
|
StreamEvent::Error("MatterViz volume body CRC mismatch".to_owned()) |
|
}; |
|
if !send_event(channel, event, stop) { |
|
accepted = false; |
|
} |
|
} |
|
broker.finish(request_id); |
|
let status = u32::from(!accepted || !valid); |
|
let ack = encode_stream_ack(request_id, volume_id, status).map_err(|_| ())?; |
|
writer.write_all(&ack).map_err(|_| ()) |
The C adapter converts any otherwise well-formed nonzero acknowledgement to MWFN_ERR_REJECTED:
|
{ |
|
uint8_t ack[MWFN_ACK_BYTES]; |
|
error_code = mwfn_read_exact_posix_deadline((int)ack_read, ack, sizeof(ack), deadline); |
|
if (error_code == ETIMEDOUT) return MWFN_ERR_TIMEOUT; |
|
if (error_code != 0) return error_code; |
|
if (!mwfn_valid_ack(ack, request_id, volume_id)) { |
|
return mwfn_valid_ack_fields(ack, request_id, volume_id, 0) ? MWFN_ERR_REJECTED |
|
: MWFN_ERR_PROTOCOL; |
|
} |
Fortran treats that value as a recoverable memory or admission rejection, keeps the transport open, and may tell the user to reduce the grid size:
|
if (status_out/=0) then |
|
write(*,"(a,i0,a)") " MatterViz binary volume publish failed (",status_out,")" |
|
! A consumer-side memory/admission rejection is request-local. Protocol, |
|
! pipe and timeout failures invalidate the transport for this session. |
|
if (status_out/=-1005) call close_matterviz_transport() |
This hides the real problem, which is corrupted or invalid data.
Expected behavior
A request that is no longer needed may be rejected without closing the whole session. Data that fails format or CRC validation should be reported as a protocol error and should close the formal session.
The user should not be told to reduce the grid size when the received bytes are corrupted.
Input file and reproducer
No scientific input file is required. Start from one of the existing valid protocol fixtures and flip one body byte.
Logs
Current output can report a rejected volume request or suggest reducing the grid instead of identifying a CRC or protocol failure.
Screenshots or comparisons
The regression test should keep the producer open after the bad frame and verify that Rust stops the transport without waiting for the producer to close it.
Before submitting
Category
Runtime
Operating system
Linux, macOS, and Windows
Package or commit tested
PR #26 final head: cdfeaaf
Steps to reproduce
Current behavior
Rust detects the invalid frame or CRC, sends a nonzero acknowledgement, and then continues reading the same transport:
Multiwfn/frontend/matterviz-desktop/src/transport.rs
Lines 94 to 165 in cdfeaaf
The C adapter converts any otherwise well-formed nonzero acknowledgement to MWFN_ERR_REJECTED:
Multiwfn/noGUI/matterviz_spawn.c
Lines 1953 to 1961 in cdfeaaf
Fortran treats that value as a recoverable memory or admission rejection, keeps the transport open, and may tell the user to reduce the grid size:
Multiwfn/noGUI/GUI_matterviz.f90
Lines 1556 to 1560 in cdfeaaf
This hides the real problem, which is corrupted or invalid data.
Expected behavior
A request that is no longer needed may be rejected without closing the whole session. Data that fails format or CRC validation should be reported as a protocol error and should close the formal session.
The user should not be told to reduce the grid size when the received bytes are corrupted.
Input file and reproducer
No scientific input file is required. Start from one of the existing valid protocol fixtures and flip one body byte.
Logs
Current output can report a rejected volume request or suggest reducing the grid instead of identifying a CRC or protocol failure.
Screenshots or comparisons
The regression test should keep the producer open after the bad frame and verify that Rust stops the transport without waiting for the producer to close it.
Before submitting