diff --git a/include/openbsc/gsm_data.h b/include/openbsc/gsm_data.h index 02823c969..51cf6dcd4 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 cd2388343..b4fa3dff6 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 5de13687a..03482be33 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 0f1d35cc1..755e68577 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; };