smpp_codec/pdus/ancillary_pdus/
query_sm.rs1use crate::common::{
2 get_status_code, read_c_string, write_c_string, Npi, PduError, Ton, CMD_QUERY_SM, HEADER_LEN,
3};
4use std::io::{Cursor, Read, Write};
5
6#[derive(Debug, Clone, PartialEq)]
11pub struct QuerySmRequest {
12 pub sequence_number: u32,
14 pub message_id: String,
16 pub source_addr_ton: Ton,
18 pub source_addr_npi: Npi,
20 pub source_addr: String,
22}
23
24impl QuerySmRequest {
25 pub fn new(sequence_number: u32, message_id: String, source_addr: String) -> Self {
27 Self {
28 sequence_number,
29 message_id,
30 source_addr_ton: Ton::Unknown,
31 source_addr_npi: Npi::Unknown,
32 source_addr,
33 }
34 }
35
36 pub fn encode(&self, writer: &mut impl Write) -> Result<(), PduError> {
42 if self.message_id.len() > 64 {
44 return Err(PduError::StringTooLong("message_id".into(), 64));
45 }
46 if self.source_addr.len() > 21 {
47 return Err(PduError::StringTooLong("source_addr".into(), 21));
48 }
49
50 let body_len = self.message_id.len() + 1 +
52 1 + 1 + self.source_addr.len() + 1;
54
55 let command_len = (HEADER_LEN + body_len) as u32;
57 writer.write_all(&command_len.to_be_bytes())?;
58 writer.write_all(&CMD_QUERY_SM.to_be_bytes())?;
59 writer.write_all(&0u32.to_be_bytes())?;
60 writer.write_all(&self.sequence_number.to_be_bytes())?;
61
62 write_c_string(writer, &self.message_id)?;
64 writer.write_all(&[self.source_addr_ton as u8, self.source_addr_npi as u8])?;
65 write_c_string(writer, &self.source_addr)?;
66
67 Ok(())
68 }
69
70 pub fn decode(buffer: &[u8]) -> Result<Self, PduError> {
76 if buffer.len() < HEADER_LEN {
77 return Err(PduError::BufferTooShort);
78 }
79
80 let mut cursor = Cursor::new(buffer);
81 cursor.set_position(12);
82
83 let mut bytes = [0u8; 4];
84 cursor.read_exact(&mut bytes)?;
85 let sequence_number = u32::from_be_bytes(bytes);
86
87 let message_id = read_c_string(&mut cursor)?;
88
89 let mut u8_buf = [0u8; 1];
90 cursor.read_exact(&mut u8_buf)?;
91 let source_addr_ton = Ton::from(u8_buf[0]);
92 cursor.read_exact(&mut u8_buf)?;
93 let source_addr_npi = Npi::from(u8_buf[0]);
94
95 let source_addr = read_c_string(&mut cursor)?;
96
97 Ok(Self {
98 sequence_number,
99 message_id,
100 source_addr_ton,
101 source_addr_npi,
102 source_addr,
103 })
104 }
105}
106
107#[derive(Debug, Clone, PartialEq)]
109pub struct QuerySmResponse {
110 pub sequence_number: u32,
112 pub command_status: u32,
114 pub message_id: String,
116 pub final_date: String,
118 pub message_state: u8,
120 pub error_code: u8,
122 pub status_description: String,
124}
125
126#[derive(Debug, Clone, Copy, PartialEq)]
128#[repr(u8)]
129pub enum MessageState {
130 Enroute = 1,
132 Delivered = 2,
134 Expired = 3,
136 Deleted = 4,
138 Undeliverable = 5,
140 Accepted = 6,
142 Unknown = 7,
144 Rejected = 8,
146}
147
148impl QuerySmResponse {
149 pub fn new(
151 sequence_number: u32,
152 status_name: &str,
153 message_id: String,
154 final_date: String,
155 message_state: u8,
156 error_code: u8,
157 ) -> Self {
158 let command_status = get_status_code(status_name);
159 Self {
160 sequence_number,
161 command_status,
162 message_id,
163 final_date,
164 message_state,
165 error_code,
166 status_description: status_name.to_string(),
167 }
168 }
169
170 pub fn encode(&self, writer: &mut impl Write) -> Result<(), PduError> {
176 let body_len = if self.command_status == 0 {
177 self.message_id.len() + 1 + self.final_date.len() + 1 + 1 + 1 } else {
179 0
180 };
181
182 let command_len = (HEADER_LEN + body_len) as u32;
183 writer.write_all(&command_len.to_be_bytes())?;
184 writer.write_all(&crate::common::CMD_QUERY_SM_RESP.to_be_bytes())?;
185 writer.write_all(&self.command_status.to_be_bytes())?;
186 writer.write_all(&self.sequence_number.to_be_bytes())?;
187
188 if self.command_status == 0 {
189 write_c_string(writer, &self.message_id)?;
190 write_c_string(writer, &self.final_date)?;
191 writer.write_all(&[self.message_state, self.error_code])?;
192 }
193
194 Ok(())
195 }
196
197 pub fn decode(buffer: &[u8]) -> Result<Self, PduError> {
203 if buffer.len() < HEADER_LEN {
204 return Err(PduError::BufferTooShort);
205 }
206 let mut cursor = Cursor::new(buffer);
207 cursor.set_position(8);
208
209 let mut bytes = [0u8; 4];
210 cursor.read_exact(&mut bytes)?;
211 let command_status = u32::from_be_bytes(bytes);
212 cursor.read_exact(&mut bytes)?;
213 let sequence_number = u32::from_be_bytes(bytes);
214
215 let message_id: String;
216 let final_date: String;
217 let message_state: u8;
218 let error_code: u8;
219
220 if command_status == 0 && buffer.len() > HEADER_LEN {
221 message_id = read_c_string(&mut cursor)?;
222 final_date = read_c_string(&mut cursor)?;
223
224 let mut u8_buf = [0u8; 1];
225 cursor.read_exact(&mut u8_buf)?;
226 message_state = u8_buf[0];
227 cursor.read_exact(&mut u8_buf)?;
228 error_code = u8_buf[0];
229 } else {
230 message_id = String::new();
231 final_date = String::new();
232 message_state = 0;
233 error_code = 0;
234 }
235
236 let status_description = crate::common::get_status_description(command_status);
237
238 Ok(Self {
239 sequence_number,
240 command_status,
241 message_id,
242 final_date,
243 message_state,
244 error_code,
245 status_description,
246 })
247 }
248}