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