smpp_codec/pdus/ancillary_pdus/
query_sm.rs1use crate::common::{get_status_code, Npi, PduError, Ton, CMD_QUERY_SM, HEADER_LEN};
2use std::io::{Cursor, Read, Write};
3
4#[derive(Debug, Clone)]
6pub struct QuerySmRequest {
7 pub sequence_number: u32,
8 pub message_id: String,
9 pub source_addr_ton: Ton,
10 pub source_addr_npi: Npi,
11 pub source_addr: String,
12}
13
14impl QuerySmRequest {
15 pub fn new(sequence_number: u32, message_id: String, source_addr: String) -> Self {
16 Self {
17 sequence_number,
18 message_id,
19 source_addr_ton: Ton::Unknown,
20 source_addr_npi: Npi::Unknown,
21 source_addr,
22 }
23 }
24
25 pub fn encode(&self, writer: &mut impl Write) -> Result<(), PduError> {
26 if self.message_id.len() > 64 {
28 return Err(PduError::StringTooLong("message_id".into(), 64));
29 }
30 if self.source_addr.len() > 21 {
31 return Err(PduError::StringTooLong("source_addr".into(), 21));
32 }
33
34 let mut body = Vec::new();
36 write_c_string(&mut body, &self.message_id)?;
37 body.write_all(&[self.source_addr_ton as u8, self.source_addr_npi as u8])?;
38 write_c_string(&mut body, &self.source_addr)?;
39
40 let command_len = (HEADER_LEN + body.len()) as u32;
42 writer.write_all(&command_len.to_be_bytes())?;
43 writer.write_all(&CMD_QUERY_SM.to_be_bytes())?;
44 writer.write_all(&0u32.to_be_bytes())?;
45 writer.write_all(&self.sequence_number.to_be_bytes())?;
46
47 writer.write_all(&body)?;
49
50 Ok(())
51 }
52
53 pub fn decode(buffer: &[u8]) -> Result<Self, PduError> {
54 if buffer.len() < HEADER_LEN {
55 return Err(PduError::BufferTooShort);
56 }
57
58 let mut cursor = Cursor::new(buffer);
59 cursor.set_position(12);
60
61 let mut bytes = [0u8; 4];
62 cursor.read_exact(&mut bytes)?;
63 let sequence_number = u32::from_be_bytes(bytes);
64
65 let message_id = crate::common::read_c_string(&mut cursor)?;
66
67 let mut u8_buf = [0u8; 1];
68 cursor.read_exact(&mut u8_buf)?;
69 let source_addr_ton = Ton::from(u8_buf[0]);
70 cursor.read_exact(&mut u8_buf)?;
71 let source_addr_npi = Npi::from(u8_buf[0]);
72
73 let source_addr = crate::common::read_c_string(&mut cursor)?;
74
75 Ok(Self {
76 sequence_number,
77 message_id,
78 source_addr_ton,
79 source_addr_npi,
80 source_addr,
81 })
82 }
83}
84
85#[derive(Debug, Clone)]
87pub struct QuerySmResponse {
88 pub sequence_number: u32,
89 pub command_status: u32,
90 pub message_id: String,
91 pub final_date: String,
92 pub message_state: u8,
93 pub error_code: u8,
94 pub status_description: String,
95}
96
97#[derive(Debug, Clone, Copy, PartialEq)]
99#[repr(u8)]
100pub enum MessageState {
101 Enroute = 1,
102 Delivered = 2,
103 Expired = 3,
104 Deleted = 4,
105 Undeliverable = 5,
106 Accepted = 6,
107 Unknown = 7,
108 Rejected = 8,
109}
110
111impl QuerySmResponse {
112 pub fn new(
113 sequence_number: u32,
114 status_name: &str,
115 message_id: String,
116 final_date: String,
117 message_state: u8,
118 error_code: u8,
119 ) -> Self {
120 let command_status = get_status_code(status_name);
121 Self {
122 sequence_number,
123 command_status,
124 message_id,
125 final_date,
126 message_state,
127 error_code,
128 status_description: status_name.to_string(),
129 }
130 }
131
132 pub fn encode(&self, writer: &mut impl Write) -> Result<(), PduError> {
133 let mut body = Vec::new();
134
135 if self.command_status == 0 {
136 write_c_string(&mut body, &self.message_id)?;
137 write_c_string(&mut body, &self.final_date)?;
138 body.write_all(&[self.message_state, self.error_code])?;
139 }
140
141 let command_len = (HEADER_LEN + body.len()) as u32;
142 writer.write_all(&command_len.to_be_bytes())?;
143 writer.write_all(&crate::common::CMD_QUERY_SM_RESP.to_be_bytes())?;
144 writer.write_all(&self.command_status.to_be_bytes())?;
145 writer.write_all(&self.sequence_number.to_be_bytes())?;
146 writer.write_all(&body)?;
147
148 Ok(())
149 }
150
151 pub fn decode(buffer: &[u8]) -> Result<Self, PduError> {
152 if buffer.len() < HEADER_LEN {
153 return Err(PduError::BufferTooShort);
154 }
155 let mut cursor = Cursor::new(buffer);
156 cursor.set_position(8);
157
158 let mut bytes = [0u8; 4];
159 cursor.read_exact(&mut bytes)?;
160 let command_status = u32::from_be_bytes(bytes);
161 cursor.read_exact(&mut bytes)?;
162 let sequence_number = u32::from_be_bytes(bytes);
163
164 let message_id: String;
165 let final_date: String;
166 let message_state: u8;
167 let error_code: u8;
168
169 if command_status == 0 && buffer.len() > HEADER_LEN {
170 message_id = crate::common::read_c_string(&mut cursor)?;
171 final_date = crate::common::read_c_string(&mut cursor)?;
172
173 let mut u8_buf = [0u8; 1];
174 cursor.read_exact(&mut u8_buf)?;
175 message_state = u8_buf[0];
176 cursor.read_exact(&mut u8_buf)?;
177 error_code = u8_buf[0];
178 } else {
179 message_id = String::new();
180 final_date = String::new();
181 message_state = 0;
182 error_code = 0;
183 }
184
185 let status_description = crate::common::get_status_description(command_status);
186
187 Ok(Self {
188 sequence_number,
189 command_status,
190 message_id,
191 final_date,
192 message_state,
193 error_code,
194 status_description,
195 })
196 }
197}
198
199fn write_c_string(w: &mut impl Write, s: &str) -> std::io::Result<()> {
201 w.write_all(s.as_bytes())?;
202 w.write_all(&[0])
203}