smpp_codec/pdus/submission_pdus/
submit_multi_request.rs1use crate::common::{
2 read_c_string, write_c_string, Npi, PduError, Ton, CMD_SUBMIT_MULTI_SM, HEADER_LEN,
3};
4use crate::tlv::Tlv;
5use std::io::Read;
6use std::io::{Cursor, Write};
7
8#[derive(Debug, Clone, PartialEq)]
9pub enum Destination {
11 SmeAddress {
13 ton: Ton,
15 npi: Npi,
17 address: String,
19 },
20 DistributionList(String),
22}
23
24#[derive(Debug, Clone, PartialEq)]
28pub struct SubmitMulti {
29 pub sequence_number: u32,
31 pub service_type: String,
33 pub source_addr_ton: Ton,
35 pub source_addr_npi: Npi,
37 pub source_addr: String,
39 pub destinations: Vec<Destination>,
41 pub esm_class: u8,
43 pub protocol_id: u8,
45 pub priority_flag: u8,
47 pub schedule_delivery_time: String,
49 pub validity_period: String,
51 pub registered_delivery: u8,
53 pub replace_if_present_flag: u8,
55 pub data_coding: u8,
57 pub sm_default_msg_id: u8,
59 pub short_message: Vec<u8>,
61 pub optional_params: Vec<Tlv>,
63}
64
65impl SubmitMulti {
66 pub fn new(
89 sequence_number: u32,
90 source_addr: String,
91 destinations: Vec<Destination>,
92 short_message: Vec<u8>,
93 ) -> Self {
94 Self {
95 sequence_number,
96 service_type: String::new(),
97 source_addr_ton: Ton::Unknown,
98 source_addr_npi: Npi::Unknown,
99 source_addr,
100 destinations,
101 esm_class: 0,
102 protocol_id: 0,
103 priority_flag: 0,
104 schedule_delivery_time: String::new(),
105 validity_period: String::new(),
106 registered_delivery: 0, replace_if_present_flag: 0,
108 data_coding: 0, sm_default_msg_id: 0,
110 short_message,
111 optional_params: Vec::new(),
112 }
113 }
114
115 pub fn encode(&self, writer: &mut impl Write) -> Result<(), PduError> {
121 let mut dest_len = 0;
123 for dest in &self.destinations {
124 match dest {
125 Destination::SmeAddress { address, .. } => {
126 dest_len += 1 + 1 + 1 + address.len() + 1;
128 }
129 Destination::DistributionList(name) => {
130 dest_len += 1 + name.len() + 1;
132 }
133 }
134 }
135
136 let tlvs_len: usize = self
138 .optional_params
139 .iter()
140 .map(|tlv| 4 + tlv.length as usize)
141 .sum();
142
143 let body_len = self.service_type.len() + 1 +
153 1 + 1 + self.source_addr.len() + 1 +
154 1 + dest_len +
155 1 + 1 + 1 + self.schedule_delivery_time.len() + 1 +
157 self.validity_period.len() + 1 +
158 1 + 1 + 1 + 1 + 1 + self.short_message.len() +
160 tlvs_len;
161
162 let command_len = (HEADER_LEN + body_len) as u32;
163
164 writer.write_all(&command_len.to_be_bytes())?;
165 writer.write_all(&CMD_SUBMIT_MULTI_SM.to_be_bytes())?;
166 writer.write_all(&0u32.to_be_bytes())?;
167 writer.write_all(&self.sequence_number.to_be_bytes())?;
168
169 write_c_string(writer, &self.service_type)?;
170 writer.write_all(&[self.source_addr_ton as u8, self.source_addr_npi as u8])?;
171 write_c_string(writer, &self.source_addr)?;
172
173 if self.destinations.len() > 255 {
176 }
179 writer.write_all(&[self.destinations.len() as u8])?;
180 for dest in &self.destinations {
181 match dest {
182 Destination::SmeAddress { ton, npi, address } => {
183 writer.write_all(&[1])?; writer.write_all(&[*ton as u8, *npi as u8])?;
185 write_c_string(writer, address)?;
186 }
187 Destination::DistributionList(name) => {
188 writer.write_all(&[2])?; write_c_string(writer, name)?;
190 }
191 }
192 }
193
194 writer.write_all(&[self.esm_class, self.protocol_id, self.priority_flag])?;
195 write_c_string(writer, &self.schedule_delivery_time)?;
196 write_c_string(writer, &self.validity_period)?;
197 writer.write_all(&[
198 self.registered_delivery,
199 self.replace_if_present_flag,
200 self.data_coding,
201 self.sm_default_msg_id,
202 self.short_message.len() as u8,
203 ])?;
204 writer.write_all(&self.short_message)?;
205
206 for tlv in &self.optional_params {
207 tlv.encode(writer)?;
208 }
209 Ok(())
210 }
211
212 pub fn decode(buffer: &[u8]) -> Result<Self, PduError> {
218 if buffer.len() < HEADER_LEN {
219 return Err(PduError::BufferTooShort);
220 }
221 let mut cursor = Cursor::new(buffer);
222 cursor.set_position(12); let mut bytes = [0u8; 4];
225 cursor.read_exact(&mut bytes)?;
226 let sequence_number = u32::from_be_bytes(bytes);
227
228 let service_type = read_c_string(&mut cursor)?;
229
230 let mut u8_buf = [0u8; 1];
231 cursor.read_exact(&mut u8_buf)?;
232 let source_addr_ton = Ton::from(u8_buf[0]);
233 cursor.read_exact(&mut u8_buf)?;
234 let source_addr_npi = Npi::from(u8_buf[0]);
235 let source_addr = read_c_string(&mut cursor)?;
236
237 cursor.read_exact(&mut u8_buf)?;
239 let dest_count = u8_buf[0];
240 let mut destinations = Vec::with_capacity(dest_count as usize);
241
242 for _ in 0..dest_count {
243 cursor.read_exact(&mut u8_buf)?;
244 let dest_flag = u8_buf[0];
245 if dest_flag == 1 {
246 cursor.read_exact(&mut u8_buf)?;
248 let ton = Ton::from(u8_buf[0]);
249 cursor.read_exact(&mut u8_buf)?;
250 let npi = Npi::from(u8_buf[0]);
251 let address = read_c_string(&mut cursor)?;
252 destinations.push(Destination::SmeAddress { ton, npi, address });
253 } else {
254 let dl_name = read_c_string(&mut cursor)?;
256 destinations.push(Destination::DistributionList(dl_name));
257 }
258 }
259
260 cursor.read_exact(&mut u8_buf)?;
261 let esm_class = u8_buf[0];
262 cursor.read_exact(&mut u8_buf)?;
263 let protocol_id = u8_buf[0];
264 cursor.read_exact(&mut u8_buf)?;
265 let priority_flag = u8_buf[0];
266
267 let schedule_delivery_time = read_c_string(&mut cursor)?;
268 let validity_period = read_c_string(&mut cursor)?;
269
270 cursor.read_exact(&mut u8_buf)?;
271 let registered_delivery = u8_buf[0];
272 cursor.read_exact(&mut u8_buf)?;
273 let replace_if_present_flag = u8_buf[0];
274 cursor.read_exact(&mut u8_buf)?;
275 let data_coding = u8_buf[0];
276 cursor.read_exact(&mut u8_buf)?;
277 let sm_default_msg_id = u8_buf[0];
278
279 cursor.read_exact(&mut u8_buf)?;
280 let sm_length = u8_buf[0] as usize;
281 let mut short_message = vec![0u8; sm_length];
282 cursor.read_exact(&mut short_message)?;
283
284 let mut optional_params = Vec::new();
285 while let Some(tlv) = Tlv::decode(&mut cursor)? {
286 optional_params.push(tlv);
287 }
288
289 Ok(Self {
290 sequence_number,
291 service_type,
292 source_addr_ton,
293 source_addr_npi,
294 source_addr,
295 destinations,
296 esm_class,
297 protocol_id,
298 priority_flag,
299 schedule_delivery_time,
300 validity_period,
301 registered_delivery,
302 replace_if_present_flag,
303 data_coding,
304 sm_default_msg_id,
305 short_message,
306 optional_params,
307 })
308 }
309}