smpp_codec/pdus/submission_pdus/
submit_sm_request.rs1use crate::common::{read_c_string, write_c_string, Npi, PduError, Ton, CMD_SUBMIT_SM, HEADER_LEN};
2use crate::encoding::MessageBody;
3use crate::tlv::{tags, Tlv};
4use std::io::{Cursor, Read, Write};
5
6#[derive(Debug, Clone, PartialEq)]
7pub struct SubmitSmRequest {
9 pub sequence_number: u32,
11 pub service_type: String, pub source_addr_ton: Ton,
15 pub source_addr_npi: Npi,
17 pub source_addr: String, pub dest_addr_ton: Ton,
21 pub dest_addr_npi: Npi,
23 pub dest_addr: String, pub esm_class: u8,
27 pub protocol_id: u8,
29 pub priority_flag: u8,
31 pub schedule_delivery_time: String, pub validity_period: String, pub registered_delivery: u8,
37 pub replace_if_present_flag: u8,
39 pub data_coding: u8,
41 pub sm_default_msg_id: u8,
43 pub short_message: Vec<u8>, pub optional_params: Vec<Tlv>,
47}
48
49#[derive(Debug, Clone, PartialEq)]
50pub struct SegmentationInfo {
52 pub ref_num: u16,
54 pub total_segments: u8,
56 pub seq_num: u8,
58}
59
60impl SubmitSmRequest {
61 pub fn new(
77 sequence_number: u32,
78 source_addr: String,
79 dest_addr: String,
80 short_message: Vec<u8>,
81 ) -> Self {
82 Self {
83 sequence_number,
84 service_type: String::new(),
85 source_addr_ton: Ton::Unknown,
86 source_addr_npi: Npi::Unknown,
87 source_addr,
88 dest_addr_ton: Ton::Unknown,
89 dest_addr_npi: Npi::Unknown,
90 dest_addr,
91 esm_class: 0,
92 protocol_id: 0,
93 priority_flag: 0,
94 schedule_delivery_time: String::new(),
95 validity_period: String::new(),
96 registered_delivery: 0, replace_if_present_flag: 0,
98 data_coding: 0, sm_default_msg_id: 0,
100 short_message,
101 optional_params: Vec::new(),
102 }
103 }
104
105 pub fn add_tlv(&mut self, tlv: Tlv) {
107 self.optional_params.push(tlv);
108 }
109
110 pub fn encode(&self, writer: &mut impl Write) -> Result<(), PduError> {
131 if self.service_type.len() > 6 {
133 return Err(PduError::StringTooLong("service_type".into(), 6));
134 }
135 if self.source_addr.len() > 21 {
136 return Err(PduError::StringTooLong("source_addr".into(), 21));
137 }
138 if self.dest_addr.len() > 21 {
139 return Err(PduError::StringTooLong("dest_addr".into(), 21));
140 }
141 if self.schedule_delivery_time.len() > 17 {
142 return Err(PduError::StringTooLong("schedule_delivery_time".into(), 17));
143 }
144 if self.validity_period.len() > 17 {
145 return Err(PduError::StringTooLong("validity_period".into(), 17));
146 }
147 if self.short_message.len() > 254 {
148 return Err(PduError::InvalidLength);
149 } let tlvs_len: usize = self
153 .optional_params
154 .iter()
155 .map(|tlv| 4 + tlv.length as usize)
156 .sum();
157
158 let body_len = self.service_type.len()
161 + 1
162 + (self.source_addr.len() + 1)
163 + (self.dest_addr.len() + 1)
164 + (self.schedule_delivery_time.len() + 1)
165 + (self.validity_period.len() + 1)
166 + self.short_message.len()
167 + 12
168 + tlvs_len;
169
170 let command_len = (HEADER_LEN + body_len) as u32;
172 writer.write_all(&command_len.to_be_bytes())?;
173 writer.write_all(&CMD_SUBMIT_SM.to_be_bytes())?;
174 writer.write_all(&0u32.to_be_bytes())?; writer.write_all(&self.sequence_number.to_be_bytes())?;
176
177 write_c_string(writer, &self.service_type)?;
179
180 writer.write_all(&[self.source_addr_ton as u8, self.source_addr_npi as u8])?;
182 write_c_string(writer, &self.source_addr)?;
183
184 writer.write_all(&[self.dest_addr_ton as u8, self.dest_addr_npi as u8])?;
186 write_c_string(writer, &self.dest_addr)?;
187
188 writer.write_all(&[self.esm_class, self.protocol_id, self.priority_flag])?;
190
191 write_c_string(writer, &self.schedule_delivery_time)?;
192 write_c_string(writer, &self.validity_period)?;
193
194 writer.write_all(&[
195 self.registered_delivery,
196 self.replace_if_present_flag,
197 self.data_coding,
198 self.sm_default_msg_id,
199 ])?;
200
201 writer.write_all(&[self.short_message.len() as u8])?;
203 writer.write_all(&self.short_message)?;
204
205 for tlv in &self.optional_params {
207 tlv.encode(writer)?;
208 }
209
210 Ok(())
211 }
212
213 pub fn decode(buffer: &[u8]) -> Result<Self, PduError> {
231 if buffer.len() < HEADER_LEN {
232 return Err(PduError::BufferTooShort);
233 }
234
235 let mut cursor = Cursor::new(buffer);
236 cursor.set_position(12); let mut bytes = [0u8; 4];
238 cursor.read_exact(&mut bytes)?;
239 let sequence_number = u32::from_be_bytes(bytes);
240
241 let mut u8_buf = [0u8; 1];
243
244 let service_type = read_c_string(&mut cursor)?;
245
246 cursor.read_exact(&mut u8_buf)?;
248 let source_addr_ton = Ton::from(u8_buf[0]);
249 cursor.read_exact(&mut u8_buf)?;
250 let source_addr_npi = Npi::from(u8_buf[0]);
251 let source_addr = read_c_string(&mut cursor)?;
252
253 cursor.read_exact(&mut u8_buf)?;
255 let dest_addr_ton = Ton::from(u8_buf[0]);
256 cursor.read_exact(&mut u8_buf)?;
257 let dest_addr_npi = Npi::from(u8_buf[0]);
258 let dest_addr = read_c_string(&mut cursor)?;
259
260 cursor.read_exact(&mut u8_buf)?;
262 let esm_class = u8_buf[0];
263 cursor.read_exact(&mut u8_buf)?;
264 let protocol_id = u8_buf[0];
265 cursor.read_exact(&mut u8_buf)?;
266 let priority_flag = u8_buf[0];
267
268 let schedule_delivery_time = read_c_string(&mut cursor)?;
269 let validity_period = read_c_string(&mut cursor)?;
270
271 cursor.read_exact(&mut u8_buf)?;
272 let registered_delivery = u8_buf[0];
273 cursor.read_exact(&mut u8_buf)?;
274 let replace_if_present_flag = u8_buf[0];
275 cursor.read_exact(&mut u8_buf)?;
276 let data_coding = u8_buf[0];
277 cursor.read_exact(&mut u8_buf)?;
278 let sm_default_msg_id = u8_buf[0];
279
280 cursor.read_exact(&mut u8_buf)?;
282 let sm_length = u8_buf[0] as usize;
283 let mut short_message = vec![0u8; sm_length];
284 cursor.read_exact(&mut short_message)?;
285
286 let mut optional_params = Vec::new();
288 while let Some(tlv) = Tlv::decode(&mut cursor)? {
289 optional_params.push(tlv);
290 }
291
292 Ok(Self {
293 sequence_number,
294 service_type,
295 source_addr_ton,
296 source_addr_npi,
297 source_addr,
298 dest_addr_ton,
299 dest_addr_npi,
300 dest_addr,
301 esm_class,
302 protocol_id,
303 priority_flag,
304 schedule_delivery_time,
305 validity_period,
306 registered_delivery,
307 replace_if_present_flag,
308 data_coding,
309 sm_default_msg_id,
310 short_message,
311 optional_params,
312 })
313 }
314
315 pub fn get_segmentation_info(&self) -> Option<SegmentationInfo> {
317 let sar_ref = self.get_tlv_u16(tags::SAR_MSG_REF_NUM);
320 let sar_total = self.get_tlv_u16(tags::SAR_TOTAL_SEGMENTS);
321 let sar_seq = self.get_tlv_u16(tags::SAR_SEGMENT_SEQNUM);
322
323 if let (Some(ref_num), Some(total), Some(seq)) = (sar_ref, sar_total, sar_seq) {
324 return Some(SegmentationInfo {
325 ref_num,
326 total_segments: total as u8, seq_num: seq as u8,
328 });
329 }
330
331 if (self.esm_class & 0x40) != 0 && self.short_message.len() > 5 {
334 let udh_len = self.short_message[0] as usize;
335
336 if self.short_message.len() > udh_len {
338 let header_bytes = &self.short_message[1..=udh_len];
339
340 let mut cursor = 0;
342 while cursor < header_bytes.len() {
343 let ie_id = header_bytes[cursor];
344 let ie_len = header_bytes[cursor + 1] as usize;
345 let ie_data = &header_bytes[cursor + 2..cursor + 2 + ie_len];
346
347 if ie_id == 0x00 && ie_len == 3 {
349 return Some(SegmentationInfo {
350 ref_num: ie_data[0] as u16,
351 total_segments: ie_data[1],
352 seq_num: ie_data[2],
353 });
354 }
355 else if ie_id == 0x08 && ie_len == 4 {
357 let ref_num = u16::from_be_bytes([ie_data[0], ie_data[1]]);
358 return Some(SegmentationInfo {
359 ref_num,
360 total_segments: ie_data[2],
361 seq_num: ie_data[3],
362 });
363 }
364
365 cursor += 2 + ie_len;
366 }
367 }
368 }
369
370 None
372 }
373
374 pub fn parse_message(&self) -> MessageBody {
376 let has_udh = (self.esm_class & 0x40) != 0;
377 crate::encoding::process_body(&self.short_message, self.data_coding, has_udh)
378 }
379
380 fn get_tlv_u16(&self, tag: u16) -> Option<u16> {
382 self.optional_params
383 .iter()
384 .find(|t| t.tag == tag)
385 .and_then(|t| {
386 if t.length == 1 {
387 Some(t.value[0] as u16)
388 } else if t.length == 2 {
389 Some(u16::from_be_bytes([t.value[0], t.value[1]]))
390 } else {
391 None
392 }
393 })
394 }
395}