iscsi_client_rs/models/reject/
response.rs1use anyhow::{Result, bail};
9use tracing::warn;
10use zerocopy::{
11 BigEndian, FromBytes as ZFromBytes, Immutable, IntoBytes, KnownLayout, U32, U64,
12};
13
14use crate::{
15 client::pdu_connection::FromBytes,
16 models::{
17 common::{BasicHeaderSegment, HEADER_LEN, InitiatorTaskTag, SendingData},
18 data_fromat::ZeroCopyType,
19 opcode::{BhsOpcode, Opcode, RawBhsOpcode},
20 reject::reject_description::RawRejectReason,
21 },
22};
23
24#[repr(C)]
26#[derive(Debug, Default, PartialEq, ZFromBytes, IntoBytes, KnownLayout, Immutable)]
27pub struct RejectPdu {
28 pub opcode: RawBhsOpcode, reserved1: u8, pub reason: RawRejectReason, pub reserved2: u8, pub total_ahs_length: u8, pub data_segment_length: [u8; 3], pub reserved3: U64<BigEndian>, pub initiator_task_tag: InitiatorTaskTag, pub reserved4: U32<BigEndian>, pub stat_sn: U32<BigEndian>, pub exp_cmd_sn: U32<BigEndian>, pub max_cmd_sn: U32<BigEndian>, pub data_sn_or_r2_sn: U32<BigEndian>, pub reserved5: U64<BigEndian>, }
43
44impl RejectPdu {
45 pub fn to_bhs_bytes(&self, buf: &mut [u8]) -> Result<()> {
47 if buf.len() != HEADER_LEN {
48 bail!("buffer length must be {HEADER_LEN}, got {}", buf.len());
49 }
50 buf.copy_from_slice(self.as_bytes());
51 Ok(())
52 }
53
54 pub fn from_bhs_bytes(buf: &mut [u8]) -> Result<&mut Self> {
56 let hdr = <Self as zerocopy::FromBytes>::mut_from_bytes(buf)
57 .map_err(|e| anyhow::anyhow!("failed convert buffer RejectPdu: {e}"))?;
58 if hdr.opcode.opcode_known() != Some(Opcode::Reject) {
59 anyhow::bail!(
60 "RejectPdu: invalid opcode 0x{:02x}",
61 hdr.opcode.opcode_raw()
62 );
63 }
64 Ok(hdr)
65 }
66}
67
68impl SendingData for RejectPdu {
69 fn get_final_bit(&self) -> bool {
70 true
71 }
72
73 fn set_final_bit(&mut self) {
74 warn!("RejectPdu Response cannot be marked as Final");
75 }
76
77 fn get_continue_bit(&self) -> bool {
78 false
79 }
80
81 fn set_continue_bit(&mut self) {
82 warn!("RejectPdu Response cannot be marked as Contine");
83 }
84}
85
86impl FromBytes for RejectPdu {
87 fn from_bhs_bytes(bytes: &mut [u8]) -> Result<&mut Self> {
88 RejectPdu::from_bhs_bytes(bytes)
89 }
90}
91
92impl BasicHeaderSegment for RejectPdu {
93 #[inline]
94 fn to_bhs_bytes(&self, buf: &mut [u8]) -> Result<()> {
95 self.to_bhs_bytes(buf)
96 }
97
98 #[inline]
99 fn get_opcode(&self) -> Result<BhsOpcode> {
100 BhsOpcode::try_from(self.opcode.raw())
101 }
102
103 #[inline]
104 fn get_initiator_task_tag(&self) -> u32 {
105 self.initiator_task_tag.get()
106 }
107
108 #[inline]
109 fn get_ahs_length_bytes(&self) -> usize {
110 (self.total_ahs_length as usize) * 4
111 }
112
113 #[inline]
114 fn set_ahs_length_bytes(&mut self, len: u8) {
115 self.total_ahs_length = len >> 2;
116 }
117
118 #[inline]
119 fn get_data_length_bytes(&self) -> usize {
120 u32::from_be_bytes([
121 0,
122 self.data_segment_length[0],
123 self.data_segment_length[1],
124 self.data_segment_length[2],
125 ]) as usize
126 }
127
128 #[inline]
129 fn set_data_length_bytes(&mut self, len: u32) {
130 let be = len.to_be_bytes();
131 self.data_segment_length = [be[1], be[2], be[3]];
132 }
133}
134
135impl ZeroCopyType for RejectPdu {}