aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/openbsc/gsm_data.h1
-rw-r--r--src/libmsc/gsm_04_11.c54
-rw-r--r--src/libmsc/smpp_openbsc.c21
-rw-r--r--src/libmsc/smpp_smsc.h1
4 files changed, 76 insertions, 1 deletions
diff --git a/include/openbsc/gsm_data.h b/include/openbsc/gsm_data.h
index 02823c96..51cf6dcd 100644
--- a/include/openbsc/gsm_data.h
+++ b/include/openbsc/gsm_data.h
@@ -511,6 +511,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/src/libmsc/gsm_04_11.c b/src/libmsc/gsm_04_11.c
index cd238834..b4fa3dff 100644
--- a/src/libmsc/gsm_04_11.c
+++ b/src/libmsc/gsm_04_11.c
@@ -594,6 +594,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)
@@ -615,6 +666,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/src/libmsc/smpp_openbsc.c b/src/libmsc/smpp_openbsc.c
index 5de13687..03482be3 100644
--- a/src/libmsc/smpp_openbsc.c
+++ b/src/libmsc/smpp_openbsc.c
@@ -201,6 +201,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;
}
@@ -518,6 +522,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->vsub);
if (!conn) {
LOGP(DSMPP, LOGL_ERROR, "No connection to subscriber anymore\n");
@@ -542,6 +549,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->vsub);
if (!conn) {
LOGP(DSMPP, LOGL_ERROR, "No connection to subscriber anymore\n");
@@ -579,6 +589,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->vsub = vlr_subscr_get(vsub);
@@ -643,7 +654,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)
@@ -692,6 +708,9 @@ static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms,
append_osmo_tlvs(&deliver.tlv, conn->lchan);
#endif
+ 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/src/libmsc/smpp_smsc.h b/src/libmsc/smpp_smsc.h
index 0f1d35cc..755e6857 100644
--- a/src/libmsc/smpp_smsc.h
+++ b/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;
};