Review at  https://gerrit.osmocom.org/3434

libmsc: add support for SMPP delivery receipts

If the mobile phone requests a status report via SMS, send a DELIVER_SM
with esm_class = Delivery Receipt to ESME to indicate that the SMS has
been already delivered to its destination.

    MS        GSM 03.40           SMSC       SMPP 3.4               ESME
     |                             |                                |
     |       SMS-DELIVER           |                                |
     |<----------------------------|                                |
     |     GSM 04.11 RP-ACK        |                                |
     |---------------------------->|                                |
     |                             |           DELIVER-SM           |
     |                             |  esm_class = Delivery Receipt  |
     |                             |------------------------------->|
     |                             |         DELIVER-SM-RESP        |
     |                             |<-------------------------------|
     |                             |                                |

This patch implements "Appendix B. Delivery Receipt Format" as specified
in the SMPP 3.4 specs. This string is conveyed in the SMS message as
data, and it is only meaningful to the ESME, for logging purposes. The
"submit date" and "done date" are not yet set, and other fields are just
sent with dummy values, so they are left to be finished as future work.

Change-Id: Ic1a9023074bfa938099377980b6aff9b262fab2a
---
M openbsc/include/openbsc/gsm_data.h
M openbsc/src/libmsc/gsm_04_11.c
M openbsc/src/libmsc/smpp_openbsc.c
M openbsc/src/libmsc/smpp_smsc.h
4 files changed, 83 insertions(+), 1 deletion(-)


  git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/34/3434/1

diff --git a/openbsc/include/openbsc/gsm_data.h 
b/openbsc/include/openbsc/gsm_data.h
index 37a341c..5e9a3a1 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -456,6 +456,7 @@
        } smpp;
 
        unsigned long validity_minutes;
+       bool report;
        uint8_t reply_path_req;
        uint8_t status_rep_req;
        uint8_t ud_hdr_ind;
diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c
index 1aed60e..ea80860 100644
--- a/openbsc/src/libmsc/gsm_04_11.c
+++ b/openbsc/src/libmsc/gsm_04_11.c
@@ -593,6 +593,60 @@
                                rpud_len, rp_ud);
 }
 
+static struct gsm_sms *sms_report_alloc(struct gsm_sms *sms)
+{
+       struct gsm_sms *sms_report;
+       int len;
+
+       sms_report = sms_alloc();
+       if (!sms_report)
+               return NULL;
+
+       sms_report->msg_ref = sms->msg_ref;
+       sms_report->protocol_id = sms->protocol_id;
+       sms_report->data_coding_scheme = GSM338_DCS_1111_8BIT_DATA;
+
+       /* Invert address to send status report back to origin. */
+       sms_report->src = sms->dst;
+       sms_report->dst = sms->src;
+
+       /* As specified by Appendix B. Delivery Receipt Format.
+        * TODO: Many fields in this string are just set with dummy values,
+        *       revisit this.
+        */
+       len = snprintf((char *)sms_report->user_data,
+                      sizeof(sms_report->user_data),
+                      "id:%.08llu sub:000 dlvrd:000 submit date:YYMMDDhhmm 
done date:YYMMDDhhmm stat:DELIVRD err:000 text:%.20s",
+                      sms->id, sms->user_data);
+       sms_report->user_data_len = len;
+       LOGP(DLSMS, LOGL_NOTICE, "%s\n", sms_report->user_data);
+
+       /* This represents a sms report. */
+       sms_report->report = true;
+
+       return sms_report;
+}
+
+static void sms_status_report(struct gsm_sms *gsms,
+                             struct gsm_subscriber_connection *conn)
+{
+       struct gsm_sms *sms_report;
+       int rc;
+
+       sms_report = sms_report_alloc(gsms);
+       if (!sms_report)
+               return;
+
+       rc = sms_route_mt_sms(conn, sms_report);
+       if (rc < 0) {
+               LOGP(DLSMS, LOGL_ERROR,
+                    "Failed to send status report! err=%d\n", rc);
+       }
+       LOGP(DLSMS, LOGL_NOTICE, "Status report has been sent\n");
+
+       sms_free(sms_report);
+}
+
 /* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
 static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
                            struct gsm411_rp_hdr *rph)
@@ -614,6 +668,9 @@
 
        send_signal(S_SMS_DELIVERED, trans, sms, 0);
 
+       if (sms->status_rep_req)
+               sms_status_report(sms, trans->conn);
+
        sms_free(sms);
        trans->sms.sms = NULL;
 
diff --git a/openbsc/src/libmsc/smpp_openbsc.c 
b/openbsc/src/libmsc/smpp_openbsc.c
index a803763..42357e2 100644
--- a/openbsc/src/libmsc/smpp_openbsc.c
+++ b/openbsc/src/libmsc/smpp_openbsc.c
@@ -200,6 +200,10 @@
                sms->user_data_len = sms_msg_len;
        }
 
+       t = find_tlv(submit->tlv, TLVID_user_message_reference);
+       if (t)
+               sms->msg_ref = ntohs(t->value.val16);
+
        *psms = sms;
        return ESME_ROK;
 }
@@ -514,6 +518,13 @@
        struct gsm_subscriber_connection *conn;
        struct gsm_trans *trans;
 
+       /* We got a DELIVER_SM response for this is status report, this was
+        * initiated by the SMSC, so no need to send any RP-ACK to the mobile
+        * station.
+        */
+       if (cmd->report)
+               goto out;
+
        conn = connection_for_subscr(cmd->subscr);
        if (!conn) {
                LOGP(DSMPP, LOGL_ERROR, "No connection to subscriber 
anymore\n");
@@ -537,6 +548,9 @@
        struct gsm_subscriber_connection *conn;
        struct gsm_trans *trans;
        int gsm411_cause;
+
+       if (cmd->report)
+               goto out;
 
        conn = connection_for_subscr(cmd->subscr);
        if (!conn) {
@@ -575,6 +589,7 @@
                return -1;
 
        cmd->sequence_nr        = sequence_number;
+       cmd->report             = sms->report;
        cmd->gsm411_msg_ref     = sms->gsm411.msg_ref;
        cmd->gsm411_trans_id    = sms->gsm411.transaction_id;
        cmd->subscr             = subscr_get(subscr);
@@ -639,7 +654,12 @@
        memcpy(deliver.destination_addr, sms->dst.addr,
                sizeof(deliver.destination_addr));
 
-       deliver.esm_class       = 1;    /* datagram mode */
+       /* Short message contains a delivery receipt? Sect. 5.2.12. */
+       if (sms->report)
+               deliver.esm_class = 0x04;
+       else
+               deliver.esm_class = 1;  /* datagram mode */
+
        if (sms->ud_hdr_ind)
                deliver.esm_class |= 0x40;
        if (sms->reply_path_req)
@@ -685,6 +705,9 @@
        if (esme->acl && esme->acl->osmocom_ext && conn->lchan)
                append_osmo_tlvs(&deliver.tlv, conn->lchan);
 
+       append_tlv_u16(&deliver.tlv, TLVID_user_message_reference,
+                      sms->msg_ref);
+
        ret = smpp_tx_deliver(esme, &deliver);
        if (ret < 0)
                return ret;
diff --git a/openbsc/src/libmsc/smpp_smsc.h b/openbsc/src/libmsc/smpp_smsc.h
index 468d3b4..854d048 100644
--- a/openbsc/src/libmsc/smpp_smsc.h
+++ b/openbsc/src/libmsc/smpp_smsc.h
@@ -92,6 +92,7 @@
        uint32_t                sequence_nr;
        uint32_t                gsm411_msg_ref;
        uint8_t                 gsm411_trans_id;
+       bool                    report;
        struct osmo_timer_list  response_timer;
 };
 

-- 
To view, visit https://gerrit.osmocom.org/3434
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic1a9023074bfa938099377980b6aff9b262fab2a
Gerrit-PatchSet: 1
Gerrit-Project: openbsc
Gerrit-Branch: master
Gerrit-Owner: Pablo Neira Ayuso <pa...@gnumonks.org>

Reply via email to