smpp_codec/pdus/session_pdus/
alert_notification.rs1use crate::common::{Npi, PduError, Ton, CMD_ALERT_NOTIFICATION, HEADER_LEN};
2use crate::tlv::Tlv;
3use std::io::{Cursor, Read, Write};
4
5#[derive(Debug, Clone)]
9pub struct AlertNotification {
10 pub sequence_number: u32,
11 pub source_addr_ton: Ton,
12 pub source_addr_npi: Npi,
13 pub source_addr: String, pub esme_addr_ton: Ton,
15 pub esme_addr_npi: Npi,
16 pub esme_addr: String, pub optional_params: Vec<Tlv>,
18}
19
20impl AlertNotification {
21 pub fn new(sequence_number: u32, source_addr: String, esme_addr: String) -> Self {
36 Self {
37 sequence_number,
38 source_addr_ton: Ton::Unknown,
39 source_addr_npi: Npi::Unknown,
40 source_addr,
41 esme_addr_ton: Ton::Unknown,
42 esme_addr_npi: Npi::Unknown,
43 esme_addr,
44 optional_params: Vec::new(),
45 }
46 }
47
48 pub fn with_source_addr(mut self, ton: Ton, npi: Npi, addr: String) -> Self {
50 self.source_addr_ton = ton;
51 self.source_addr_npi = npi;
52 self.source_addr = addr;
53 self
54 }
55
56 pub fn with_esme_addr(mut self, ton: Ton, npi: Npi, addr: String) -> Self {
57 self.esme_addr_ton = ton;
58 self.esme_addr_npi = npi;
59 self.esme_addr = addr;
60 self
61 }
62
63 pub fn add_tlv(&mut self, tlv: Tlv) {
65 self.optional_params.push(tlv);
66 }
67
68 pub fn encode(&self, writer: &mut impl Write) -> Result<(), PduError> {
87 if self.source_addr.len() > 65 {
89 return Err(PduError::StringTooLong("source_addr".into(), 65));
90 }
91 if self.esme_addr.len() > 65 {
92 return Err(PduError::StringTooLong("esme_addr".into(), 65));
93 }
94
95 let mut body = Vec::new();
96
97 body.write_all(&[self.source_addr_ton as u8, self.source_addr_npi as u8])?;
99 write_c_string(&mut body, &self.source_addr)?;
100
101 body.write_all(&[self.esme_addr_ton as u8, self.esme_addr_npi as u8])?;
103 write_c_string(&mut body, &self.esme_addr)?;
104
105 for tlv in &self.optional_params {
108 tlv.encode(&mut body)?;
109 }
110
111 let command_len = (HEADER_LEN + body.len()) as u32;
113 writer.write_all(&command_len.to_be_bytes())?;
114 writer.write_all(&CMD_ALERT_NOTIFICATION.to_be_bytes())?;
115 writer.write_all(&0u32.to_be_bytes())?;
116 writer.write_all(&self.sequence_number.to_be_bytes())?;
117
118 writer.write_all(&body)?;
120
121 Ok(())
122 }
123
124 pub fn decode(buffer: &[u8]) -> Result<Self, PduError> {
144 if buffer.len() < HEADER_LEN {
145 return Err(PduError::BufferTooShort);
146 }
147
148 let mut cursor = Cursor::new(buffer);
149 cursor.set_position(12);
151 let mut bytes = [0u8; 4];
152 cursor.read_exact(&mut bytes)?;
153 let sequence_number = u32::from_be_bytes(bytes);
154
155 let mut u8_buf = [0u8; 1];
157
158 cursor.read_exact(&mut u8_buf)?;
159 let source_addr_ton = Ton::from(u8_buf[0]);
160 cursor.read_exact(&mut u8_buf)?;
161 let source_addr_npi = Npi::from(u8_buf[0]);
162 let source_addr = crate::common::read_c_string(&mut cursor)?;
163
164 cursor.read_exact(&mut u8_buf)?;
165 let esme_addr_ton = Ton::from(u8_buf[0]);
166 cursor.read_exact(&mut u8_buf)?;
167 let esme_addr_npi = Npi::from(u8_buf[0]);
168 let esme_addr = crate::common::read_c_string(&mut cursor)?;
169
170 let mut optional_params = Vec::new();
172 while let Some(tlv) = Tlv::decode(&mut cursor)? {
173 optional_params.push(tlv);
174 }
175
176 Ok(Self {
177 sequence_number,
178 source_addr_ton,
179 source_addr_npi,
180 source_addr,
181 esme_addr_ton,
182 esme_addr_npi,
183 esme_addr,
184 optional_params,
185 })
186 }
187}
188
189fn write_c_string(w: &mut impl Write, s: &str) -> std::io::Result<()> {
191 w.write_all(s.as_bytes())?;
192 w.write_all(&[0])
193}