aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@gnumonks.org>2017-08-07 14:01:30 +0100
committerPablo Neira Ayuso <pablo@gnumonks.org>2017-08-09 13:08:53 +0200
commit98849f7ddcbe8b094af5ee5efc30bd841ac12e04 (patch)
tree8b701fa76c372ea74221ed593994bc6e45d4d299
parent52d519220501c4d4c09dfa924e23badac8589614 (diff)
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. The new SMPP TLV tag TLVID_user_message_reference is added to the SMPP messages inconditionally now since this information is required by delivery-reports to associate the status-report with the original SMS. Change-Id: Ic1a9023074bfa938099377980b6aff9b262fab2a
-rw-r--r--openbsc/include/openbsc/gsm_data.h1
-rw-r--r--openbsc/src/libmsc/gsm_04_11.c54
-rw-r--r--openbsc/src/libmsc/smpp_openbsc.c21
-rw-r--r--openbsc/src/libmsc/smpp_smsc.h1
4 files changed, 76 insertions, 1 deletions
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 37a341c7f..6829d22d9 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -456,6 +456,7 @@ struct gsm_sms {
} smpp;
unsigned long validity_minutes;
+ bool is_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 1aed60e64..0edbe0b6c 100644
--- a/openbsc/src/libmsc/gsm_04_11.c
+++ b/openbsc/src/libmsc/gsm_04_11.c
@@ -593,6 +593,57 @@ static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
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();
+ OSMO_ASSERT(sms_report);
+
+ 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->is_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);
+
+ 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 +665,9 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
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 a8037634c..c0aa89bc5 100644
--- a/openbsc/src/libmsc/smpp_openbsc.c
+++ b/openbsc/src/libmsc/smpp_openbsc.c
@@ -200,6 +200,10 @@ static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net,
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,9 @@ void smpp_cmd_ack(struct osmo_smpp_cmd *cmd)
struct gsm_subscriber_connection *conn;
struct gsm_trans *trans;
+ if (cmd->is_report)
+ goto out;
+
conn = connection_for_subscr(cmd->subscr);
if (!conn) {
LOGP(DSMPP, LOGL_ERROR, "No connection to subscriber anymore\n");
@@ -538,6 +545,9 @@ void smpp_cmd_err(struct osmo_smpp_cmd *cmd, uint32_t status)
struct gsm_trans *trans;
int gsm411_cause;
+ if (cmd->is_report)
+ goto out;
+
conn = connection_for_subscr(cmd->subscr);
if (!conn) {
LOGP(DSMPP, LOGL_ERROR, "No connection to subscriber anymore\n");
@@ -575,6 +585,7 @@ static int smpp_cmd_enqueue(struct osmo_esme *esme,
return -1;
cmd->sequence_nr = sequence_number;
+ cmd->is_report = sms->is_report;
cmd->gsm411_msg_ref = sms->gsm411.msg_ref;
cmd->gsm411_trans_id = sms->gsm411.transaction_id;
cmd->subscr = subscr_get(subscr);
@@ -639,7 +650,12 @@ static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms,
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->is_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 +701,9 @@ static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms,
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 468d3b477..257383f1b 100644
--- a/openbsc/src/libmsc/smpp_smsc.h
+++ b/openbsc/src/libmsc/smpp_smsc.h
@@ -92,6 +92,7 @@ struct osmo_smpp_cmd {
uint32_t sequence_nr;
uint32_t gsm411_msg_ref;
uint8_t gsm411_trans_id;
+ bool is_report;
struct osmo_timer_list response_timer;
};