Skip to main content

smpp34/server/
mod.rs

1use async_trait::async_trait;
2use bytes::BytesMut;
3use log::{error, info, warn};
4use std::{
5    net::{IpAddr, SocketAddr},
6    sync::{
7        atomic::{AtomicBool, AtomicU32, Ordering},
8        Arc,
9    },
10    time::Duration,
11};
12use tokio::{
13    io::{AsyncReadExt, AsyncWriteExt},
14    net::TcpListener,
15    sync::{mpsc::Sender, oneshot},
16    task::{self, JoinHandle},
17    time::timeout,
18};
19use uuid::Uuid;
20
21use crate::common::be_u32_at;
22use crate::common::{frame_first_pdu, Framing};
23use crate::{
24    alert_notification, bind_receiver, bind_receiver_resp, bind_transceiver, bind_transceiver_resp,
25    bind_transmitter, bind_transmitter_resp, cancel_sm, cancel_sm_resp,
26    common::{CommandHeader, CommandId, SmppError},
27    data_sm, data_sm_resp, deliver_sm, deliver_sm_resp, generic_nack, query_sm, query_sm_resp,
28    replace_sm, replace_sm_resp,
29    server::state::OPEN,
30    submit_sm, submit_sm_multi, submit_sm_multi_resp, submit_sm_resp, unbind, unbind_resp,
31    SmppConnectionInformation, Tlv, TlvTag, WriteFrame,
32};
33
34mod state;
35
36pub struct SmppServer {
37    address: IpAddr,
38    port: u16,
39    handle: Option<JoinHandle<()>>,
40    alive: Arc<AtomicBool>,
41    handler: Arc<dyn SmppServerListener + Send + Sync + 'static>,
42    session_init_timer: u64,
43    enquire_link_timer: u64,
44    inactivity_timer: u64,
45    response_timer: u64,
46    buffer_size: usize,
47}
48
49pub struct ESME {
50    pub server_address: SocketAddr,
51    pub client_address: SocketAddr,
52    pub session_id: String,
53    pub system_id: String,
54    pub can_receive: bool,
55    tx_channel: Sender<WriteFrame>,
56    sequence_number: Arc<AtomicU32>,
57    response_timer: u64,
58}
59
60impl ESME {
61    fn next_sequence_number(&self) -> u32 {
62        self.sequence_number.fetch_add(1, Ordering::SeqCst)
63    }
64
65    /// Start building a `deliver_sm` to send on this session โ€” an ergonomic
66    /// alternative to the 17-argument [`send_deliver_sm`](ESME::send_deliver_sm).
67    pub fn deliver_sm(&self) -> DeliverSmBuilder<'_> {
68        DeliverSmBuilder::new(self)
69    }
70
71    pub async fn send_deliver_sm(
72        &self,
73        service_type: String,
74        source_addr_ton: u8,
75        source_addr_npi: u8,
76        source_addr: String,
77        dest_addr_ton: u8,
78        dest_addr_npi: u8,
79        destination_addr: String,
80        esm_class: u8,
81        protocol_id: u8,
82        priority_flag: u8,
83        schedule_delivery_time: String,
84        validity_period: String,
85        registered_delivery: u8,
86        replace_if_present_flag: u8,
87        data_coding: u8,
88        sm_default_msg_id: u8,
89        short_message: Vec<u8>,
90    ) -> Result<deliver_sm_resp, SmppError> {
91        self.send_deliver_sm_pdu(deliver_sm::new(
92            0, // overwritten by send_deliver_sm_pdu, which owns the sequence space
93            service_type,
94            source_addr_ton,
95            source_addr_npi,
96            source_addr,
97            dest_addr_ton,
98            dest_addr_npi,
99            destination_addr,
100            esm_class,
101            protocol_id,
102            priority_flag,
103            schedule_delivery_time,
104            validity_period,
105            registered_delivery,
106            replace_if_present_flag,
107            data_coding,
108            sm_default_msg_id,
109            short_message,
110        ))
111        .await
112    }
113
114    /// Send a pre-built `deliver_sm` and await its response.
115    ///
116    /// This is the path for anything the fixed-argument
117    /// [`send_deliver_sm`](ESME::send_deliver_sm) cannot express โ€” above all
118    /// optional parameters (TLVs), which a delivery receipt needs
119    /// (`receipted_message_id`, `message_state`, `network_error_code`). Attach
120    /// them with [`deliver_sm::with_tlvs`] / [`deliver_sm::push_tlv`], or use the
121    /// fluent [`ESME::deliver_sm`] builder.
122    ///
123    /// The session assigns the sequence number: whatever the PDU carries is
124    /// overwritten, so responses correlate against this session's window.
125    pub async fn send_deliver_sm_pdu(
126        &self,
127        mut deliver_sm: deliver_sm,
128    ) -> Result<deliver_sm_resp, SmppError> {
129        if self.can_receive {
130            let sequence_number = self.next_sequence_number();
131            deliver_sm.set_sequence_number(sequence_number);
132            info!(
133                "[{} on server {}] sending deliver_sm with sequence_number {}",
134                self.client_address, self.server_address, sequence_number
135            );
136
137            let (tx, rx) = oneshot::channel();
138
139            let result = self
140                .tx_channel
141                .send(WriteFrame {
142                    our_sequence_number: Some(sequence_number),
143                    pdu: deliver_sm.encode(),
144                    oneshot: Some(tx),
145                })
146                .await;
147
148            match result {
149                Ok(_) => {
150                    match timeout(Duration::from_millis(self.response_timer), rx).await {
151                        Ok(Ok(response)) => {
152                            // response can be either deliver_sm_resp or generic_nack
153                            if let Some(deliver_sm_resp) =
154                                response.as_any().downcast_ref::<deliver_sm_resp>()
155                            {
156                                info!("[{} on server {}] received deliver_sm_resp with sequence_number {}", self.client_address, self.server_address, sequence_number);
157                                Ok(deliver_sm_resp.clone())
158                            } else if let Some(generic_nack) =
159                                response.as_any().downcast_ref::<generic_nack>()
160                            {
161                                error!("[{} on server {}] received generic_nack in response to deliver_sm with sequence_number {}: {:?}", self.client_address, self.server_address, sequence_number, generic_nack.get_error());
162                                Err(generic_nack.get_error())
163                            } else {
164                                error!("[{} on server {}] received unknown response type in response to deliver_sm with sequence_number {}", self.client_address, self.server_address, sequence_number);
165                                Err(SmppError::ESME_RSYSERR)
166                            }
167                        }
168                        Ok(Err(e)) => {
169                            error!(
170                                "[{} on server {}] unable to receive deliver_sm_resp: {}",
171                                self.client_address, self.server_address, e
172                            );
173                            Err(SmppError::ESME_RSYSERR)
174                        }
175                        Err(_) => {
176                            error!("[{} on server {}] deliver_sm_resp with sequence_number {} timed out", self.client_address, self.server_address, sequence_number);
177                            Err(SmppError::ESME_RSYSERR)
178                        }
179                    }
180                }
181                Err(e) => {
182                    error!("[{} on server {}] unable to send deliver_sm with sequence_number {} to writer thread: {}", self.client_address, self.server_address, sequence_number, e);
183                    Err(SmppError::ESME_RSYSERR)
184                }
185            }
186        } else {
187            panic!("Can not send deliver_sm on non RX/TRX bind");
188        }
189    }
190
191    pub async fn send_unbind(&self) -> Result<unbind_resp, SmppError> {
192        let sequence_number = self.next_sequence_number();
193        let unbind = unbind::with_sequence_number(sequence_number);
194        info!(
195            "[{} on server {}] sending unbind with sequence_number {}",
196            self.client_address, self.server_address, sequence_number
197        );
198
199        let (tx, rx) = oneshot::channel();
200
201        match self
202            .tx_channel
203            .send(WriteFrame {
204                our_sequence_number: Some(sequence_number),
205                pdu: unbind.encode(),
206                oneshot: Some(tx),
207            })
208            .await
209        {
210            Ok(_) => {}
211            Err(e) => {
212                error!("[{} on server {}] unable to send unbind with sequence_number {} to writer thread: {}", self.client_address, self.server_address, sequence_number, e);
213                return Err(SmppError::ESME_RSYSERR);
214            }
215        }
216
217        let response = timeout(Duration::from_millis(self.response_timer), rx).await;
218        match response {
219            Ok(Ok(response)) => {
220                // response can be either unbind_resp or generic_nack
221                if let Some(unbind_resp) = response.as_any().downcast_ref::<unbind_resp>() {
222                    info!(
223                        "[{} on server {}] received unbind_resp with sequence_number {}",
224                        self.client_address, self.server_address, sequence_number
225                    );
226                    Ok(unbind_resp.clone())
227                } else if let Some(generic_nack) = response.as_any().downcast_ref::<generic_nack>()
228                {
229                    error!("[{} on server {}] received generic_nack in response to unbind with sequence_number {}: {:?}", self.client_address, self.server_address, sequence_number, generic_nack.get_error());
230                    Err(generic_nack.get_error())
231                } else {
232                    error!("[{} on server {}] received unknown response type in response to unbind with sequence_number {}", self.client_address, self.server_address, sequence_number);
233                    Err(SmppError::ESME_RSYSERR)
234                }
235            }
236            Ok(Err(e)) => {
237                error!(
238                    "[{} on server {}] unable to receive unbind_resp: {}",
239                    self.client_address, self.server_address, e
240                );
241                Err(SmppError::ESME_RSYSERR)
242            }
243            Err(_) => {
244                error!(
245                    "[{} on server {}] unbind_resp with sequence_number {} timed out",
246                    self.client_address, self.server_address, sequence_number
247                );
248                Err(SmppError::ESME_RSYSERR)
249            }
250        }
251    }
252
253    pub async fn send_data_sm(
254        &self,
255        service_type: String,
256        source_addr_ton: u8,
257        source_addr_npi: u8,
258        source_addr: String,
259        dest_addr_ton: u8,
260        dest_addr_npi: u8,
261        destination_addr: String,
262        esm_class: u8,
263        registered_delivery: u8,
264        data_coding: u8,
265    ) -> Result<data_sm_resp, SmppError> {
266        self.send_data_sm_pdu(data_sm::new(
267            0, // overwritten by send_data_sm_pdu, which owns the sequence space
268            service_type,
269            source_addr_ton,
270            source_addr_npi,
271            source_addr,
272            dest_addr_ton,
273            dest_addr_npi,
274            destination_addr,
275            esm_class,
276            registered_delivery,
277            data_coding,
278        ))
279        .await
280    }
281
282    /// Send a pre-built `data_sm` and await its response.
283    ///
284    /// `data_sm` has no `short_message` field: the message body travels in the
285    /// `message_payload` TLV (ยง4.2.2), so this is the only way to send one that
286    /// actually carries a message. Attach the TLVs with
287    /// [`data_sm::with_tlvs`] / [`data_sm::push_tlv`].
288    ///
289    /// The session assigns the sequence number: whatever the PDU carries is
290    /// overwritten, so responses correlate against this session's window.
291    pub async fn send_data_sm_pdu(&self, mut data_sm: data_sm) -> Result<data_sm_resp, SmppError> {
292        let sequence_number = self.next_sequence_number();
293        data_sm.set_sequence_number(sequence_number);
294        info!(
295            "[{} on server {}] sending data_sm with sequence_number {}",
296            self.client_address, self.server_address, sequence_number
297        );
298
299        let (tx, rx) = oneshot::channel();
300
301        match self
302            .tx_channel
303            .send(WriteFrame {
304                our_sequence_number: Some(sequence_number),
305                pdu: data_sm.encode(),
306                oneshot: Some(tx),
307            })
308            .await
309        {
310            Ok(_) => {
311                match timeout(Duration::from_millis(self.response_timer), rx).await {
312                    Ok(Ok(response)) => {
313                        // response can be either data_sm_resp or generic_nack
314                        if let Some(data_sm_resp) = response.as_any().downcast_ref::<data_sm_resp>()
315                        {
316                            info!(
317                                "[{} on server {}] received data_sm_resp with sequence_number {}",
318                                self.client_address, self.server_address, sequence_number
319                            );
320                            Ok(data_sm_resp.clone())
321                        } else if let Some(generic_nack) =
322                            response.as_any().downcast_ref::<generic_nack>()
323                        {
324                            error!("[{} on server {}] received generic_nack in response to data_sm with sequence_number {}: {:?}", self.client_address, self.server_address, sequence_number, generic_nack.get_error());
325                            Err(generic_nack.get_error())
326                        } else {
327                            error!("[{} on server {}] received unknown response type in response to data_sm with sequence_number {}", self.client_address, self.server_address, sequence_number);
328                            Err(SmppError::ESME_RSYSERR)
329                        }
330                    }
331                    Ok(Err(e)) => {
332                        error!(
333                            "[{} on server {}] unable to receive data_sm_resp: {}",
334                            self.client_address, self.server_address, e
335                        );
336                        Err(SmppError::ESME_RSYSERR)
337                    }
338                    Err(_) => {
339                        error!(
340                            "[{} on server {}] data_sm_resp with sequence_number {} timed out",
341                            self.client_address, self.server_address, sequence_number
342                        );
343                        Err(SmppError::ESME_RSYSERR)
344                    }
345                }
346            }
347            Err(e) => {
348                error!("[{} on server {}] unable to send data_sm with sequence_number {} to writer thread: {}", self.client_address, self.server_address, sequence_number, e);
349                Err(SmppError::ESME_RSYSERR)
350            }
351        }
352    }
353
354    pub async fn send_alert_notification(
355        &self,
356        source_addr_ton: u8,
357        source_addr_npi: u8,
358        source_addr: String,
359        esme_addr_ton: u8,
360        esme_addr_npi: u8,
361        esme_addr: String,
362        ms_availability_status: Option<u8>,
363    ) -> u32 {
364        if self.can_receive {
365            let sequence_number = self.next_sequence_number();
366            let alert_notification = alert_notification::new(
367                sequence_number,
368                source_addr_ton,
369                source_addr_npi,
370                source_addr,
371                esme_addr_ton,
372                esme_addr_npi,
373                esme_addr,
374                ms_availability_status,
375            );
376            info!(
377                "[{} on server {}] sending alert_notification with sequence_number {}",
378                self.client_address, self.server_address, sequence_number
379            );
380
381            // No one-shot as this is a notification and we do not expect a response
382            match self
383                .tx_channel
384                .send(WriteFrame {
385                    our_sequence_number: Some(sequence_number),
386                    pdu: alert_notification.encode(),
387                    oneshot: None,
388                })
389                .await
390            {
391                Ok(_) => {}
392                Err(e) => {
393                    error!("[{} on server {}] unable to send alert_notification with sequence_number {} to writer thread: {}", self.client_address, self.server_address, sequence_number, e);
394                }
395            }
396            sequence_number
397        } else {
398            panic!("Can not send alert_notification on non RX/TRX bind");
399        }
400    }
401}
402
403/// Fluent builder for a `deliver_sm`, returned by [`ESME::deliver_sm`].
404///
405/// Every field defaults to `0` / empty, so set only what you need and then call
406/// [`send`](DeliverSmBuilder::send). String setters take `impl Into<String>` and
407/// `short_message` takes `impl Into<Vec<u8>>`.
408///
409/// ```ignore
410/// esme.deliver_sm()
411///     .source_addr("31600000000")
412///     .destination_addr("12345")
413///     .short_message(b"hello")
414///     .tlv(TlvTag::ReceiptedMessageId, "msg-1\0")
415///     .send()
416///     .await?;
417/// ```
418pub struct DeliverSmBuilder<'a> {
419    esme: &'a ESME,
420    service_type: String,
421    source_addr_ton: u8,
422    source_addr_npi: u8,
423    source_addr: String,
424    dest_addr_ton: u8,
425    dest_addr_npi: u8,
426    destination_addr: String,
427    esm_class: u8,
428    protocol_id: u8,
429    priority_flag: u8,
430    schedule_delivery_time: String,
431    validity_period: String,
432    registered_delivery: u8,
433    replace_if_present_flag: u8,
434    data_coding: u8,
435    sm_default_msg_id: u8,
436    short_message: Vec<u8>,
437    tlvs: Vec<Tlv>,
438}
439
440impl<'a> DeliverSmBuilder<'a> {
441    fn new(esme: &'a ESME) -> Self {
442        DeliverSmBuilder {
443            esme,
444            service_type: String::new(),
445            source_addr_ton: 0,
446            source_addr_npi: 0,
447            source_addr: String::new(),
448            dest_addr_ton: 0,
449            dest_addr_npi: 0,
450            destination_addr: String::new(),
451            esm_class: 0,
452            protocol_id: 0,
453            priority_flag: 0,
454            schedule_delivery_time: String::new(),
455            validity_period: String::new(),
456            registered_delivery: 0,
457            replace_if_present_flag: 0,
458            data_coding: 0,
459            sm_default_msg_id: 0,
460            short_message: Vec::new(),
461            tlvs: Vec::new(),
462        }
463    }
464
465    pub fn service_type(mut self, v: impl Into<String>) -> Self {
466        self.service_type = v.into();
467        self
468    }
469    pub fn source_addr_ton(mut self, v: u8) -> Self {
470        self.source_addr_ton = v;
471        self
472    }
473    pub fn source_addr_npi(mut self, v: u8) -> Self {
474        self.source_addr_npi = v;
475        self
476    }
477    pub fn source_addr(mut self, v: impl Into<String>) -> Self {
478        self.source_addr = v.into();
479        self
480    }
481    pub fn dest_addr_ton(mut self, v: u8) -> Self {
482        self.dest_addr_ton = v;
483        self
484    }
485    pub fn dest_addr_npi(mut self, v: u8) -> Self {
486        self.dest_addr_npi = v;
487        self
488    }
489    pub fn destination_addr(mut self, v: impl Into<String>) -> Self {
490        self.destination_addr = v.into();
491        self
492    }
493    pub fn esm_class(mut self, v: u8) -> Self {
494        self.esm_class = v;
495        self
496    }
497    pub fn protocol_id(mut self, v: u8) -> Self {
498        self.protocol_id = v;
499        self
500    }
501    pub fn priority_flag(mut self, v: u8) -> Self {
502        self.priority_flag = v;
503        self
504    }
505    pub fn schedule_delivery_time(mut self, v: impl Into<String>) -> Self {
506        self.schedule_delivery_time = v.into();
507        self
508    }
509    pub fn validity_period(mut self, v: impl Into<String>) -> Self {
510        self.validity_period = v.into();
511        self
512    }
513    pub fn registered_delivery(mut self, v: u8) -> Self {
514        self.registered_delivery = v;
515        self
516    }
517    pub fn replace_if_present_flag(mut self, v: u8) -> Self {
518        self.replace_if_present_flag = v;
519        self
520    }
521    pub fn data_coding(mut self, v: u8) -> Self {
522        self.data_coding = v;
523        self
524    }
525    pub fn sm_default_msg_id(mut self, v: u8) -> Self {
526        self.sm_default_msg_id = v;
527        self
528    }
529    pub fn short_message(mut self, v: impl Into<Vec<u8>>) -> Self {
530        self.short_message = v.into();
531        self
532    }
533
534    /// Append an optional parameter (TLV) from the SMPP 3.4 table, e.g.
535    /// `.tlv(TlvTag::MessageStateTlv, [2])`. Multi-octet values are network byte
536    /// order โ€” `42u16.to_be_bytes()`, not `42u16.to_le_bytes()`.
537    pub fn tlv(mut self, tag: TlvTag, value: impl Into<Vec<u8>>) -> Self {
538        self.tlvs.push(Tlv::from_tag(tag, value.into()));
539        self
540    }
541
542    /// Append an optional parameter by raw tag โ€” for vendor-specific parameters
543    /// (0x1400-0x3FFF) and anything else outside [`TlvTag`].
544    pub fn tlv_raw(mut self, tag: u16, value: impl Into<Vec<u8>>) -> Self {
545        self.tlvs.push(Tlv::new(tag, value.into()));
546        self
547    }
548
549    /// Append several optional parameters at once.
550    pub fn tlvs(mut self, tlvs: impl IntoIterator<Item = Tlv>) -> Self {
551        self.tlvs.extend(tlvs);
552        self
553    }
554
555    /// Send the assembled `deliver_sm` on the session and await its response.
556    pub async fn send(self) -> Result<deliver_sm_resp, SmppError> {
557        self.esme
558            .send_deliver_sm_pdu(
559                deliver_sm::new(
560                    0, // assigned by the session
561                    self.service_type,
562                    self.source_addr_ton,
563                    self.source_addr_npi,
564                    self.source_addr,
565                    self.dest_addr_ton,
566                    self.dest_addr_npi,
567                    self.destination_addr,
568                    self.esm_class,
569                    self.protocol_id,
570                    self.priority_flag,
571                    self.schedule_delivery_time,
572                    self.validity_period,
573                    self.registered_delivery,
574                    self.replace_if_present_flag,
575                    self.data_coding,
576                    self.sm_default_msg_id,
577                    self.short_message,
578                )
579                .with_tlvs(self.tlvs),
580            )
581            .await
582    }
583}
584
585#[async_trait]
586/// Callbacks for a server (SMSC) session.
587///
588/// Every method has a default implementation, so an implementor only overrides
589/// the ones it needs. Binds default to `reject(ESME_RBINDFAIL)`, `on_submit_sm`
590/// / `on_data_sm` to `reject(ESME_RSYSERR)`, `on_cancel_sm` to
591/// `reject(ESME_RCANCELFAIL)`, `on_unbind` to acking, and the notification hooks
592/// to a no-op. Override `on_bind_transceiver` + `on_submit_sm` for a typical SMSC.
593// `session_id: &String` stays `&String` on these trait methods: switching to
594// `&str` would break every existing impl's signature, so it is deferred to a
595// future major release.
596#[allow(clippy::ptr_arg)]
597pub trait SmppServerListener {
598    async fn on_bind_transmitter(
599        &self,
600        bind_transmitter: bind_transmitter,
601        _connection_information: &SmppConnectionInformation,
602        _session_id: &String,
603    ) -> bind_transmitter_resp {
604        bind_transmitter.reject(SmppError::ESME_RBINDFAIL)
605    }
606    async fn on_bind_receiver(
607        &self,
608        bind_receiver: bind_receiver,
609        _connection_information: &SmppConnectionInformation,
610        _session_id: &String,
611    ) -> bind_receiver_resp {
612        bind_receiver.reject(SmppError::ESME_RBINDFAIL)
613    }
614    async fn on_bind_transceiver(
615        &self,
616        bind_transceiver: bind_transceiver,
617        _connection_information: &SmppConnectionInformation,
618        _session_id: &String,
619    ) -> bind_transceiver_resp {
620        bind_transceiver.reject(SmppError::ESME_RBINDFAIL)
621    }
622    async fn on_unbind(
623        &self,
624        unbind: unbind,
625        _connection_information: &SmppConnectionInformation,
626        _session_id: &String,
627    ) -> unbind_resp {
628        unbind.accept()
629    }
630    async fn on_submit_sm(
631        &self,
632        submit_sm: submit_sm,
633        _connection_information: &SmppConnectionInformation,
634        _session_id: &String,
635    ) -> submit_sm_resp {
636        submit_sm.reject(SmppError::ESME_RSYSERR)
637    }
638    async fn on_submit_sm_multi(
639        &self,
640        submit_sm_multi: submit_sm_multi,
641        _connection_information: &SmppConnectionInformation,
642        _session_id: &String,
643    ) -> submit_sm_multi_resp {
644        submit_sm_multi.reject(SmppError::ESME_RSYSERR)
645    }
646    async fn on_cancel_sm(
647        &self,
648        cancel_sm: cancel_sm,
649        _connection_information: &SmppConnectionInformation,
650        _session_id: &String,
651    ) -> cancel_sm_resp {
652        cancel_sm.reject(SmppError::ESME_RCANCELFAIL)
653    }
654    async fn on_query_sm(
655        &self,
656        query_sm: query_sm,
657        _connection_information: &SmppConnectionInformation,
658        _session_id: &String,
659    ) -> query_sm_resp {
660        query_sm.reject(SmppError::ESME_RQUERYFAIL)
661    }
662    async fn on_replace_sm(
663        &self,
664        replace_sm: replace_sm,
665        _connection_information: &SmppConnectionInformation,
666        _session_id: &String,
667    ) -> replace_sm_resp {
668        replace_sm.reject(SmppError::ESME_RREPLACEFAIL)
669    }
670    async fn on_data_sm(
671        &self,
672        data_sm: data_sm,
673        _connection_information: &SmppConnectionInformation,
674        _session_id: &String,
675    ) -> data_sm_resp {
676        data_sm.reject(SmppError::ESME_RSYSERR)
677    }
678
679    /// Notification sent when an SMPP command timed-out (respone_timer triggered)
680    async fn on_timeout(&self, _sequence_number: u32, _session_id: &String) {}
681
682    /// Notification sent when an ESME is in bound state and is ready for receiving commands.
683    /// The ESME wraps the MPSC channel towards the writer thread of the bind
684    async fn on_esme_bound(&self, _esme: ESME, _session_id: &String) {}
685
686    /// Notification sent when the ESME has become unavailable due to a bind being closed or transport error
687    /// It is up to the user of this listener to drop the ESME received on the on_esme_bound notificiation, any attempt to write to the ESME after will result in a panic as the MSPC channel is closed
688    async fn on_esme_unbound(&self, _session_id: &String) {}
689
690    /// Notification sent when the server never came up, because the listening
691    /// socket could not be bound (a port already in use, an address the host does
692    /// not own, a privileged port). No connection will ever be accepted, so this
693    /// is terminal for the server. `error` names the address that failed.
694    ///
695    /// Defaulted to a no-op so existing implementors are unaffected.
696    async fn on_listen_failed(&self, _error: &str) {}
697}
698
699impl SmppServer {
700    pub fn new(
701        address: IpAddr,
702        port: u16,
703        handler: Arc<dyn SmppServerListener + Send + Sync>,
704    ) -> SmppServer {
705        SmppServer::new_with_default_timers(
706            address, port, handler, 5000, 30000, 300000, 30000, 1500,
707        )
708    }
709
710    pub fn new_with_default_timers(
711        address: IpAddr,
712        port: u16,
713        handler: Arc<dyn SmppServerListener + Send + Sync>,
714        session_init_timer: u64,
715        enquire_link_timer: u64,
716        inactivity_timer: u64,
717        response_timer: u64,
718        buffer_size: usize,
719    ) -> SmppServer {
720        SmppServer {
721            address,
722            port,
723            handle: None,
724            alive: Arc::new(AtomicBool::new(false)),
725            handler,
726            session_init_timer,
727            enquire_link_timer,
728            inactivity_timer,
729            response_timer,
730            buffer_size,
731        }
732    }
733
734    pub fn is_alive(&self) -> bool {
735        self.alive.load(Ordering::SeqCst)
736    }
737
738    pub async fn start(&mut self) {
739        if self.alive.load(Ordering::SeqCst) {
740            panic!("Can not start server twice")
741        }
742
743        info!("Starting smpp server on {}:{}", self.address, self.port);
744
745        let server_socket_address = SocketAddr::new(self.address, self.port); // Will be moved out
746
747        // Bind BEFORE spawning the accept loop, so `start()` returning means the
748        // socket is accepting. Binding inside the task made "started" merely mean
749        // "scheduled": every test in this crate had to sleep 100ms afterwards, and
750        // the Python suite, which did not, raced and failed under free-threaded
751        // CPython. It also left the bind error with nowhere to go but `.unwrap()`,
752        // panicking a tokio worker on something as ordinary as a taken port.
753        let listener = match TcpListener::bind(server_socket_address).await {
754            Ok(listener) => listener,
755            Err(error) => {
756                let error = format!("TCP bind of {server_socket_address} failed: {error}");
757                error!("smpp server could not start: {}", error);
758                self.handler.on_listen_failed(&error).await;
759                return;
760            }
761        };
762
763        self.alive.store(true, Ordering::SeqCst);
764
765        let alive = self.alive.clone();
766        let handler = self.handler.clone();
767        let session_init_timer = self.session_init_timer;
768        let enquire_link_timer = self.enquire_link_timer;
769        let response_timer = self.response_timer;
770        let inactivity_timer = self.inactivity_timer;
771        let buffer_size: usize = self.buffer_size;
772
773        self.handle = Some(tokio::spawn(async move {
774            while alive.load(Ordering::SeqCst) {
775                loop {
776                    // An accept error is not a reason to panic the runtime. Log it
777                    // with the listener's address and stop accepting: once the
778                    // listening socket is broken it will not recover, and silently
779                    // spinning on it would burn a core.
780                    let (mut stream, client_socket_address) = match listener.accept().await {
781                        Ok(accepted) => accepted,
782                        Err(error) => {
783                            error!(
784                                "smpp server stopped accepting on {}: {}",
785                                server_socket_address, error
786                            );
787                            alive.store(false, Ordering::SeqCst);
788                            return;
789                        }
790                    };
791                    if alive.load(Ordering::SeqCst) {
792                        let handler = handler.clone();
793                        let session_init_timer_duration =
794                            tokio::time::Duration::from_millis(session_init_timer);
795                        task::spawn(async move {
796                            let session_id = Uuid::new_v4().to_string();
797                            let session_state = OPEN { session_id };
798                            let connection_information = SmppConnectionInformation {
799                                server_address: server_socket_address,
800                                client_address: client_socket_address,
801                            };
802
803                            info!(
804                                "Got a connection from {} on server {}, waiting {}ms for bind",
805                                connection_information.client_address,
806                                connection_information.server_address,
807                                session_init_timer
808                            );
809                            // Frame the handshake rather than assuming one read is
810                            // one PDU. A high-throughput ESME may pipeline its first
811                            // submit_sm without waiting for bind_transceiver_resp, so
812                            // it can share a TCP segment with the bind request; the
813                            // old code handed the whole read to CommandHeader::decode
814                            // and rejected it as a length mismatch. Anything behind
815                            // the bind PDU stays in the buffer and is handed to the
816                            // session read loop.
817                            const MAX_PDU_LEN: usize = 1024 * 1024;
818                            let mut handshake_buffer =
819                                BytesMut::with_capacity(buffer_size.max(1024));
820                            let first_read = loop {
821                                match frame_first_pdu(&handshake_buffer, MAX_PDU_LEN) {
822                                    Framing::Complete(len) => {
823                                        break Ok(Ok(handshake_buffer.split_to(len)))
824                                    }
825                                    Framing::Invalid(command_length) => {
826                                        error!(
827                                            "Connection from {} on server {}: invalid command_length {} in bind request, closing connection",
828                                            connection_information.client_address,
829                                            connection_information.server_address,
830                                            command_length
831                                        );
832                                        break Ok(Ok(BytesMut::new()));
833                                    }
834                                    Framing::Incomplete => {
835                                        match timeout(
836                                            session_init_timer_duration,
837                                            stream.read_buf(&mut handshake_buffer),
838                                        )
839                                        .await
840                                        {
841                                            // EOF before a whole PDU arrived.
842                                            Ok(Ok(0)) => break Ok(Ok(BytesMut::new())),
843                                            Ok(Ok(_)) => continue,
844                                            Ok(Err(e)) => break Ok(Err(e)),
845                                            Err(e) => break Err(e),
846                                        }
847                                    }
848                                }
849                            };
850
851                            match first_read {
852                                Ok(Ok(pdu)) => {
853                                    let pdu_length = pdu.len();
854
855                                    // Try read sequence_number in case we need a generic_nack.
856                                    // If we have at least 16 bytes we are able to read sequence number, if not set it to 0x00000000 as advised in SMPP 3.4 spec
857                                    let potential_seq_no = if pdu_length >= 16 {
858                                        be_u32_at(&pdu, 12)
859                                    } else {
860                                        0
861                                    };
862                                    let command_header = CommandHeader::decode(&pdu);
863
864                                    match command_header {
865                                        Ok(header) => {
866                                            if header.command_id == CommandId::bind_receiver as u32
867                                            {
868                                                match bind_receiver::decode(header, &pdu) {
869                                                    Ok(bind_receiver) => {
870                                                        let system_id =
871                                                            bind_receiver.system_id.clone();
872                                                        let bind_receiver_resp = handler
873                                                            .on_bind_receiver(
874                                                                bind_receiver.clone(),
875                                                                &connection_information,
876                                                                &session_state.session_id,
877                                                            )
878                                                            .await;
879                                                        let session_state = session_state
880                                                            .bind_receiver(
881                                                                stream,
882                                                                bind_receiver,
883                                                                bind_receiver_resp,
884                                                                &connection_information,
885                                                                handler,
886                                                            )
887                                                            .await;
888                                                        // Note from now on the state handler is handling writes to the stream, so we only need to check whether it succeeded or not to be able to go into session mode
889                                                        if let Ok(state) = session_state {
890                                                            state
891                                                                .read_loop(
892                                                                    system_id,
893                                                                    enquire_link_timer,
894                                                                    inactivity_timer,
895                                                                    response_timer,
896                                                                    buffer_size,
897                                                                    handshake_buffer,
898                                                                )
899                                                                .await; // When this function stops either the TCP connection was interrupted or some unbind event happened. Nothing else todo.
900                                                        }
901                                                    }
902                                                    Err(error) => {
903                                                        error!("Connection from {} on server {}, unable to decode bind_receiver", connection_information.client_address, connection_information.server_address);
904                                                        let error = bind_receiver::generic_reject(
905                                                            potential_seq_no,
906                                                            error,
907                                                        )
908                                                        .encode();
909                                                        if let Err(e) =
910                                                            stream.write_all(&error).await
911                                                        {
912                                                            error!("Connection from {} on server {}: could not send the bind rejection ({}), the peer is gone", connection_information.client_address, connection_information.server_address, e);
913                                                        }
914                                                    }
915                                                }
916                                            } else if header.command_id
917                                                == CommandId::bind_transmitter as u32
918                                            {
919                                                match bind_transmitter::decode(header, &pdu) {
920                                                    Ok(bind_transmitter) => {
921                                                        let system_id =
922                                                            bind_transmitter.system_id.clone();
923                                                        let bind_transmitter_resp = handler
924                                                            .on_bind_transmitter(
925                                                                bind_transmitter.clone(),
926                                                                &connection_information,
927                                                                &session_state.session_id,
928                                                            )
929                                                            .await;
930                                                        let session_state = session_state
931                                                            .bind_transmitter(
932                                                                stream,
933                                                                bind_transmitter,
934                                                                &bind_transmitter_resp,
935                                                                &connection_information,
936                                                                handler,
937                                                            )
938                                                            .await;
939                                                        // Note from now on the state handler is handling writes to the stream, so we only need to check whether it succeeded or not to be able to go into session mode
940                                                        if let Ok(state) = session_state {
941                                                            state
942                                                                .read_loop(
943                                                                    system_id,
944                                                                    enquire_link_timer,
945                                                                    inactivity_timer,
946                                                                    response_timer,
947                                                                    buffer_size,
948                                                                    handshake_buffer,
949                                                                )
950                                                                .await; // When this function stops either the TCP connection was interrupted or some unbind event happened. Nothing else todo.
951                                                        }
952                                                    }
953                                                    Err(error) => {
954                                                        error!("Connection from {} on server {}, unable to decode bind_receiver", connection_information.client_address, connection_information.server_address);
955                                                        let error =
956                                                            bind_transmitter::generic_reject(
957                                                                potential_seq_no,
958                                                                error,
959                                                            )
960                                                            .encode();
961                                                        if let Err(e) =
962                                                            stream.write_all(&error).await
963                                                        {
964                                                            error!("Connection from {} on server {}: could not send the bind rejection ({}), the peer is gone", connection_information.client_address, connection_information.server_address, e);
965                                                        }
966                                                    }
967                                                }
968                                            } else if header.command_id
969                                                == CommandId::bind_transceiver as u32
970                                            {
971                                                match bind_transceiver::decode(header, &pdu) {
972                                                    Ok(bind_transceiver) => {
973                                                        let system_id =
974                                                            bind_transceiver.system_id.clone();
975                                                        let bind_transceiver_resp = handler
976                                                            .on_bind_transceiver(
977                                                                bind_transceiver.clone(),
978                                                                &connection_information,
979                                                                &session_state.session_id,
980                                                            )
981                                                            .await;
982                                                        let session_state = session_state
983                                                            .bind_transceiver(
984                                                                stream,
985                                                                bind_transceiver,
986                                                                &bind_transceiver_resp,
987                                                                &connection_information,
988                                                                handler,
989                                                            )
990                                                            .await;
991                                                        // Note from now on the state handler is handling writes to the stream, so we only need to check whether it succeeded or not to be able to go into session mode
992                                                        if let Ok(state) = session_state {
993                                                            state
994                                                                .read_loop(
995                                                                    system_id,
996                                                                    enquire_link_timer,
997                                                                    inactivity_timer,
998                                                                    response_timer,
999                                                                    buffer_size,
1000                                                                    handshake_buffer,
1001                                                                )
1002                                                                .await; // When this function stops either the TCP connection was interrupted or some unbind event happened. Nothing else todo.
1003                                                        }
1004                                                    }
1005                                                    Err(error) => {
1006                                                        error!("Connection from {} on server {}, unable to decode bind_receiver", connection_information.client_address, connection_information.server_address);
1007                                                        let error =
1008                                                            bind_transceiver::generic_reject(
1009                                                                potential_seq_no,
1010                                                                error,
1011                                                            )
1012                                                            .encode();
1013                                                        if let Err(e) =
1014                                                            stream.write_all(&error).await
1015                                                        {
1016                                                            error!("Connection from {} on server {}: could not send the bind rejection ({}), the peer is gone", connection_information.client_address, connection_information.server_address, e);
1017                                                        }
1018                                                    }
1019                                                }
1020                                            } else {
1021                                                // Only allow bind commands, if not a bind command tell ESME about invalid bind status
1022                                                error!("Did not expect command_id {} as bind not established yet, sending ESME_RINVBNDSTS in generick_nack", header.command_id);
1023
1024                                                let generic_nack = generic_nack::new(
1025                                                    SmppError::ESME_RINVBNDSTS,
1026                                                    potential_seq_no,
1027                                                );
1028                                                if let Err(e) =
1029                                                    stream.write_all(&generic_nack.encode()).await
1030                                                {
1031                                                    error!("Connection from {} on server {}: could not send generic_nack ({}), the peer is gone", connection_information.client_address, connection_information.server_address, e);
1032                                                }
1033                                            }
1034                                        }
1035                                        Err(error) => {
1036                                            error!("Unable to decode command_header for PDU, sending {:?} in generic_nack", error);
1037                                            let generic_nack =
1038                                                generic_nack::new(error, potential_seq_no);
1039                                            if let Err(e) =
1040                                                stream.write_all(&generic_nack.encode()).await
1041                                            {
1042                                                error!("Connection from {} on server {}: could not send generic_nack ({}), the peer is gone", connection_information.client_address, connection_information.server_address, e);
1043                                            }
1044                                        }
1045                                    }
1046                                }
1047                                _ => {
1048                                    error!("Unable to read initial SMPP PDU from {} on server {}, after waiting {}ms for bind, TCP connection will be closed", connection_information.client_address, connection_information.server_address, session_init_timer);
1049                                }
1050                            }
1051                        });
1052                    } else {
1053                        break;
1054                    }
1055                }
1056            }
1057        }));
1058    }
1059
1060    pub async fn stop(&mut self) {
1061        // TODO send unbind!!
1062
1063        info!("Stopping smpp server");
1064        self.alive.store(false, Ordering::SeqCst);
1065        match self.handle.take() {
1066            Some(handle) => handle.abort(),
1067            // Reachable whenever start() returned without spawning, i.e. the
1068            // listening socket could not be bound. Stopping something that never
1069            // ran is a no-op, not a panic.
1070            None => warn!("stop() called on an smpp server that is not running"),
1071        }
1072    }
1073}
1074
1075impl Drop for SmppServer {
1076    fn drop(&mut self) {
1077        if self.alive.load(Ordering::SeqCst) {
1078            futures::executor::block_on(self.stop());
1079        }
1080    }
1081}
1082
1083#[cfg(test)]
1084mod tests {
1085    use super::*;
1086
1087    // Compiles only because every `SmppServerListener` method has a default โ€”
1088    // this empty impl is the proof that the defaults exist.
1089    struct MinimalServer;
1090    #[async_trait]
1091    impl SmppServerListener for MinimalServer {}
1092
1093    #[test]
1094    fn minimal_server_listener_compiles() {
1095        let _listener: &dyn SmppServerListener = &MinimalServer;
1096    }
1097}