rusmpp_core/pdus/owned/
deliver_sm.rs

1use rusmpp_macros::Rusmpp;
2
3use crate::{
4    encode::Length,
5    pdus::owned::Pdu,
6    tlvs::owned::{MessageDeliveryRequestTlvValue, Tlv},
7    types::owned::{COctetString, EmptyOrFullCOctetString, OctetString},
8    values::{owned::*, *},
9};
10
11/// This operation is used by an ESME to submit a short message to the MC for onward
12/// transmission to a specified short message entity (SME).
13#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Rusmpp)]
14#[rusmpp(decode = owned, test = skip)]
15#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
16#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
17#[cfg_attr(feature = "serde-deserialize-unchecked", derive(::serde::Deserialize))]
18pub struct DeliverSm {
19    /// The service_type parameter can be used to
20    /// indicate the SMS Application service
21    /// associated with the message. Specifying the
22    /// service_type allows the ESME to avail of enhanced
23    /// messaging services such as “replace by service_type”
24    /// or to control the teleservice used on the
25    /// air interface.
26    ///
27    /// Set to NULL for default MC settings.
28    pub service_type: ServiceType,
29    /// Type of Number for source address.
30    pub source_addr_ton: Ton,
31    /// Numbering Plan Indicator for source address.
32    pub source_addr_npi: Npi,
33    /// Address of SME which originated this message.
34    pub source_addr: COctetString<1, 21>,
35    /// Type of Number for destination.
36    pub dest_addr_ton: Ton,
37    /// Numbering Plan Indicator for destination.
38    pub dest_addr_npi: Npi,
39    /// Destination address of this
40    /// short message For mobile
41    /// terminated messages, this
42    /// is the directory number of
43    /// the recipient MS
44    pub destination_addr: COctetString<1, 21>,
45    /// Indicates Message Mode
46    /// and Message Type.
47    pub esm_class: EsmClass,
48    /// Protocol Identifier.
49    /// Network specific field.
50    pub protocol_id: u8,
51    /// Designates the priority level of the message.
52    pub priority_flag: PriorityFlag,
53    /// The short message is to be
54    /// scheduled by the MC for delivery.
55    ///
56    /// Set to NULL for immediate message delivery.
57    pub schedule_delivery_time: EmptyOrFullCOctetString<17>,
58    /// The validity period of this message.
59    ///
60    /// Set to NULL to request the MC default validity period.
61    ///
62    /// Note: this is superseded by the qos_time_to_live TLV if
63    /// specified.
64    pub validity_period: EmptyOrFullCOctetString<17>,
65    /// Indicator to signify if a MC delivery receipt, manual
66    /// ACK, delivery ACK or an intermediate notification is required.
67    pub registered_delivery: RegisteredDelivery,
68    /// Flag indicating if the submitted message should replace an existing message.
69    pub replace_if_present_flag: ReplaceIfPresentFlag,
70    /// Defines the encoding scheme of the short message user data.
71    pub data_coding: DataCoding,
72    /// Indicates the short message to send from a list of pre- defined (‘canned’)
73    /// short messages stored on the MC. If not using a MC canned message, set to NULL.
74    pub sm_default_msg_id: u8,
75    /// Length in octets of the short_message user data.
76    sm_length: u8,
77    /// Up to 255 octets of short message user data.
78    ///
79    /// The exact physical limit for short_message size may
80    /// vary according to the underlying network
81    ///
82    /// Note: this field is superceded by the message_payload TLV if
83    /// specified.
84    #[rusmpp(length = sm_length)]
85    short_message: OctetString<0, 255>,
86    /// Message delivery request TLVs ([`MessageDeliveryRequestTlvValue`])
87    #[rusmpp(length = "unchecked")]
88    tlvs: alloc::vec::Vec<Tlv>,
89}
90
91impl DeliverSm {
92    #[allow(clippy::too_many_arguments)]
93    pub fn new(
94        service_type: ServiceType,
95        source_addr_ton: Ton,
96        source_addr_npi: Npi,
97        source_addr: COctetString<1, 21>,
98        dest_addr_ton: Ton,
99        dest_addr_npi: Npi,
100        destination_addr: COctetString<1, 21>,
101        esm_class: EsmClass,
102        protocol_id: u8,
103        priority_flag: PriorityFlag,
104        schedule_delivery_time: EmptyOrFullCOctetString<17>,
105        validity_period: EmptyOrFullCOctetString<17>,
106        registered_delivery: RegisteredDelivery,
107        replace_if_present_flag: ReplaceIfPresentFlag,
108        data_coding: DataCoding,
109        sm_default_msg_id: u8,
110        short_message: OctetString<0, 255>,
111        tlvs: alloc::vec::Vec<MessageDeliveryRequestTlvValue>,
112    ) -> Self {
113        let tlvs = tlvs.into_iter().map(From::from).collect();
114
115        let sm_length = short_message.length() as u8;
116
117        Self {
118            service_type,
119            source_addr_ton,
120            source_addr_npi,
121            source_addr,
122            dest_addr_ton,
123            dest_addr_npi,
124            destination_addr,
125            esm_class,
126            protocol_id,
127            priority_flag,
128            schedule_delivery_time,
129            validity_period,
130            registered_delivery,
131            replace_if_present_flag,
132            data_coding,
133            sm_default_msg_id,
134            sm_length,
135            short_message,
136            tlvs,
137        }
138    }
139
140    pub const fn sm_length(&self) -> u8 {
141        self.sm_length
142    }
143
144    pub fn short_message(&self) -> &OctetString<0, 255> {
145        &self.short_message
146    }
147
148    /// Sets the `short_message` and `sm_length`.
149    ///
150    /// # Note
151    ///
152    /// `short_message` is superceded by [`TlvValue::MessagePayload`](crate::tlvs::owned::TlvValue::MessagePayload) and should only be used if
153    /// [`TlvValue::MessagePayload`](crate::tlvs::owned::TlvValue::MessagePayload) is not present.
154    pub fn set_short_message(&mut self, short_message: OctetString<0, 255>) {
155        self.short_message = short_message;
156        self.sm_length = self.short_message.length() as u8;
157    }
158
159    pub fn tlvs(&self) -> &[Tlv] {
160        &self.tlvs
161    }
162
163    pub fn set_tlvs(&mut self, tlvs: alloc::vec::Vec<MessageDeliveryRequestTlvValue>) {
164        self.tlvs = tlvs.into_iter().map(From::from).collect();
165    }
166
167    pub fn clear_tlvs(&mut self) {
168        self.tlvs.clear();
169    }
170
171    pub fn push_tlv(&mut self, tlv: impl Into<MessageDeliveryRequestTlvValue>) {
172        self.tlvs.push(Tlv::from(tlv.into()));
173    }
174
175    pub fn builder() -> DeliverSmBuilder {
176        DeliverSmBuilder::new()
177    }
178}
179
180impl From<DeliverSm> for Pdu {
181    fn from(value: DeliverSm) -> Self {
182        Self::DeliverSm(value)
183    }
184}
185
186#[derive(Debug, Default)]
187pub struct DeliverSmBuilder {
188    inner: DeliverSm,
189}
190
191impl DeliverSmBuilder {
192    pub fn new() -> Self {
193        Self::default()
194    }
195
196    pub fn service_type(mut self, service_type: ServiceType) -> Self {
197        self.inner.service_type = service_type;
198        self
199    }
200
201    pub fn source_addr_ton(mut self, source_addr_ton: Ton) -> Self {
202        self.inner.source_addr_ton = source_addr_ton;
203        self
204    }
205
206    pub fn source_addr_npi(mut self, source_addr_npi: Npi) -> Self {
207        self.inner.source_addr_npi = source_addr_npi;
208        self
209    }
210
211    pub fn source_addr(mut self, source_addr: COctetString<1, 21>) -> Self {
212        self.inner.source_addr = source_addr;
213        self
214    }
215
216    pub fn dest_addr_ton(mut self, dest_addr_ton: Ton) -> Self {
217        self.inner.dest_addr_ton = dest_addr_ton;
218        self
219    }
220
221    pub fn dest_addr_npi(mut self, dest_addr_npi: Npi) -> Self {
222        self.inner.dest_addr_npi = dest_addr_npi;
223        self
224    }
225
226    pub fn destination_addr(mut self, destination_addr: COctetString<1, 21>) -> Self {
227        self.inner.destination_addr = destination_addr;
228        self
229    }
230
231    pub fn esm_class(mut self, esm_class: EsmClass) -> Self {
232        self.inner.esm_class = esm_class;
233        self
234    }
235
236    pub fn protocol_id(mut self, protocol_id: u8) -> Self {
237        self.inner.protocol_id = protocol_id;
238        self
239    }
240
241    pub fn priority_flag(mut self, priority_flag: PriorityFlag) -> Self {
242        self.inner.priority_flag = priority_flag;
243        self
244    }
245
246    pub fn schedule_delivery_time(
247        mut self,
248        schedule_delivery_time: EmptyOrFullCOctetString<17>,
249    ) -> Self {
250        self.inner.schedule_delivery_time = schedule_delivery_time;
251        self
252    }
253
254    pub fn validity_period(mut self, validity_period: EmptyOrFullCOctetString<17>) -> Self {
255        self.inner.validity_period = validity_period;
256        self
257    }
258
259    pub fn registered_delivery(mut self, registered_delivery: RegisteredDelivery) -> Self {
260        self.inner.registered_delivery = registered_delivery;
261        self
262    }
263
264    pub fn replace_if_present_flag(
265        mut self,
266        replace_if_present_flag: ReplaceIfPresentFlag,
267    ) -> Self {
268        self.inner.replace_if_present_flag = replace_if_present_flag;
269        self
270    }
271
272    pub fn data_coding(mut self, data_coding: DataCoding) -> Self {
273        self.inner.data_coding = data_coding;
274        self
275    }
276
277    pub fn sm_default_msg_id(mut self, sm_default_msg_id: u8) -> Self {
278        self.inner.sm_default_msg_id = sm_default_msg_id;
279        self
280    }
281
282    pub fn short_message(mut self, short_message: OctetString<0, 255>) -> Self {
283        self.inner.set_short_message(short_message);
284        self
285    }
286
287    pub fn tlvs(mut self, tlvs: alloc::vec::Vec<MessageDeliveryRequestTlvValue>) -> Self {
288        self.inner.set_tlvs(tlvs);
289        self
290    }
291
292    pub fn clear_tlvs(mut self) -> Self {
293        self.inner.clear_tlvs();
294        self
295    }
296
297    pub fn push_tlv(mut self, tlv: impl Into<MessageDeliveryRequestTlvValue>) -> Self {
298        self.inner.push_tlv(tlv);
299        self
300    }
301
302    pub fn build(self) -> DeliverSm {
303        self.inner
304    }
305}
306
307#[cfg(test)]
308mod tests {
309    use std::str::FromStr;
310
311    use crate::{tests::TestInstance, types::owned::AnyOctetString};
312
313    use super::*;
314
315    impl TestInstance for DeliverSm {
316        fn instances() -> alloc::vec::Vec<Self> {
317            alloc::vec![
318                Self::default(),
319                Self::builder()
320                    .source_addr_ton(Ton::International)
321                    .source_addr_npi(Npi::Isdn)
322                    .source_addr(COctetString::from_str("Source Address").unwrap())
323                    .dest_addr_ton(Ton::International)
324                    .dest_addr_npi(Npi::Isdn)
325                    .destination_addr(COctetString::from_str("Destination Address").unwrap())
326                    .schedule_delivery_time(EmptyOrFullCOctetString::empty())
327                    .validity_period(EmptyOrFullCOctetString::empty())
328                    .registered_delivery(RegisteredDelivery::default())
329                    .replace_if_present_flag(ReplaceIfPresentFlag::Replace)
330                    .short_message(OctetString::from_static_slice(b"Short Message").unwrap())
331                    .build(),
332                Self::builder()
333                    .source_addr_ton(Ton::International)
334                    .source_addr_npi(Npi::Isdn)
335                    .source_addr(COctetString::from_str("Source Address").unwrap())
336                    .dest_addr_ton(Ton::International)
337                    .dest_addr_npi(Npi::Isdn)
338                    .destination_addr(COctetString::from_str("Destination Address").unwrap())
339                    .protocol_id(0)
340                    .schedule_delivery_time(EmptyOrFullCOctetString::empty())
341                    .validity_period(EmptyOrFullCOctetString::empty())
342                    .registered_delivery(RegisteredDelivery::default())
343                    .replace_if_present_flag(ReplaceIfPresentFlag::Replace)
344                    .data_coding(DataCoding::default())
345                    .sm_default_msg_id(0)
346                    .short_message(OctetString::from_static_slice(b"Short Message").unwrap())
347                    .tlvs(alloc::vec![
348                        MessageDeliveryRequestTlvValue::MessagePayload(MessagePayload::new(
349                            AnyOctetString::from_static_slice(b"Message Payload"),
350                        )),
351                        MessageDeliveryRequestTlvValue::MessagePayload(MessagePayload::new(
352                            AnyOctetString::from_static_slice(b"Message Payload 2"),
353                        )),
354                        MessageDeliveryRequestTlvValue::CallbackNumPresInd(
355                            CallbackNumPresInd::new(
356                                Presentation::NumberNotAvailable,
357                                Screening::VerifiedAndPassed,
358                            ),
359                        ),
360                    ])
361                    .build(),
362            ]
363        }
364    }
365
366    #[test]
367    fn encode_decode() {
368        crate::tests::owned::encode_decode_with_length_test_instances::<DeliverSm>();
369    }
370
371    #[test]
372    fn short_message_length() {
373        let short_message = OctetString::from_static_slice(b"Short Message").unwrap();
374
375        let submit_sm = DeliverSm::builder()
376            .short_message(short_message.clone())
377            .build();
378
379        assert_eq!(submit_sm.short_message(), &short_message);
380        assert_eq!(submit_sm.sm_length(), short_message.length() as u8);
381    }
382}