[RFC PATCH 5/6] Support for concatenated SMS status report.

Pasi Miettinen pasi.miettinen at ixonos.com
Fri Jun 4 04:17:36 PDT 2010


---
 include/history.h |    2 +
 src/sms.c         |   67 ++++++++++++++++++++----
 src/smsutil.c     |  152 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/smsutil.h     |   32 +++++++++++
 4 files changed, 243 insertions(+), 10 deletions(-)

diff --git a/include/history.h b/include/history.h
index 300a4fb..17445f0 100644
--- a/include/history.h
+++ b/include/history.h
@@ -33,6 +33,8 @@ enum ofono_history_sms_status {
 	OFONO_HISTORY_SMS_STATUS_PENDING,
 	OFONO_HISTORY_SMS_STATUS_SUBMITTED,
 	OFONO_HISTORY_SMS_STATUS_SUBMIT_FAILED,
+	OFONO_HISTORY_SMS_STATUS_DELIVERED,
+	OFONO_HISTORY_SMS_STATUS_DELIVER_FAILED,
 };
 
 struct ofono_history_context {
diff --git a/src/sms.c b/src/sms.c
index 16a4d41..76b0985 100644
--- a/src/sms.c
+++ b/src/sms.c
@@ -68,6 +68,7 @@ struct ofono_sms {
 	void *driver_data;
 	struct ofono_atom *atom;
 	gboolean use_delivery_reports;
+	GSList *pending_status_reports;
 };
 
 struct pending_pdu {
@@ -83,6 +84,8 @@ struct tx_queue_entry {
 	unsigned int msg_id;
 	unsigned int retry;
 	DBusMessage *msg;
+	gboolean status_report;
+	struct sms_address receiver;
 };
 
 static void set_sca(struct ofono_sms *sms,
@@ -331,6 +334,10 @@ static void tx_finished(const struct ofono_error *error, int mr, void *data)
 	entry->cur_pdu += 1;
 	entry->retry = 0;
 
+	if (entry->status_report)
+		add_pending_status_report(&sms->pending_status_reports, mr,
+					entry->msg_id, &entry->receiver);
+
 	if (entry->cur_pdu < entry->num_pdus) {
 		sms->tx_source = g_timeout_add(0, tx_next, sms);
 		return;
@@ -462,6 +469,8 @@ static DBusMessage *sms_send_message(DBusConnection *conn, DBusMessage *msg,
 	set_ref_and_to(msg_list, sms->ref, ref_offset, to);
 	entry = create_tx_queue_entry(msg_list);
 
+	sms_address_from_string(&entry->receiver, to);
+
 	g_slist_foreach(msg_list, (GFunc)g_free, NULL);
 	g_slist_free(msg_list);
 
@@ -474,6 +483,7 @@ static DBusMessage *sms_send_message(DBusConnection *conn, DBusMessage *msg,
 
 	entry->msg = dbus_message_ref(msg);
 	entry->msg_id = sms->next_msg_id++;
+	entry->status_report = sms->use_delivery_reports;
 
 	g_queue_push_tail(sms->txq, entry);
 
@@ -583,10 +593,12 @@ static void dispatch_sms_delivery_report(struct ofono_sms *sms,
 					const enum sms_st *st,
 					const struct sms_address *raddr,
 					const struct sms_scts *scts,
-					const struct sms_scts *dt)
+					const struct sms_scts *dt,
+					const guint8 mr)
 {
 	DBusConnection *conn = ofono_dbus_get_connection();
 	const char *path = __ofono_atom_get_path(sms->atom);
+	struct ofono_modem *modem = __ofono_atom_get_modem(sms->atom);
 	DBusMessage *signal;
 	DBusMessageIter iter;
 	DBusMessageIter dict;
@@ -595,6 +607,7 @@ static void dispatch_sms_delivery_report(struct ofono_sms *sms,
 	struct tm remote;
 	struct tm local;
 	const char *str = buf;
+	unsigned int relating_msg_id;
 
 	if (!st) {
 		DBG("status unavailable");
@@ -631,21 +644,45 @@ static void dispatch_sms_delivery_report(struct ofono_sms *sms,
 	ofono_dbus_dict_append(&dict, "LocalDeliverTime",
 					DBUS_TYPE_STRING, &str);
 
+	str = sms_address_to_string(raddr);
+
 	/*Status*/
 	if (*st == 0x00) {
-		str = sms_address_to_string(raddr);
-		ofono_dbus_dict_append(&dict, "delivered",
-					DBUS_TYPE_STRING, &str);
+		enum ofono_history_sms_status status;
+
+		status = update_pending_status_report_mr_number(
+					&sms->pending_status_reports, mr, raddr,
+					SMS_STATUS_REPORT_MESSAGE_DELIVERED,
+					&relating_msg_id);
+
+		if (status == OFONO_HISTORY_SMS_STATUS_DELIVERED) {
+			ofono_dbus_dict_append(&dict, "delivered",
+						DBUS_TYPE_STRING, &str);
+			/*dbus-message assembled*/
+			dbus_message_iter_close_container(&iter, &dict);
+			g_dbus_send_message(conn, signal);
+
+			__ofono_history_sms_send_status(modem, relating_msg_id,
+					time(NULL),
+					OFONO_HISTORY_SMS_STATUS_DELIVERED);
+		}
 	} else {
-		str = sms_address_to_string(raddr);
 		ofono_dbus_dict_append(&dict, "undeliverable",
 					DBUS_TYPE_STRING, &str);
-	}
 
-	/*dbus-message assembled*/
-	dbus_message_iter_close_container(&iter, &dict);
+		/*dbus-message assembled*/
+		dbus_message_iter_close_container(&iter, &dict);
+		g_dbus_send_message(conn, signal);
 
-	g_dbus_send_message(conn, signal);
+		update_pending_status_report_mr_number(
+					&sms->pending_status_reports, mr, raddr,
+					SMS_STATUS_REPORT_MESSAGE_NOT_DELIVERED,
+					&relating_msg_id);
+
+		__ofono_history_sms_send_status(modem, relating_msg_id,
+				time(NULL),
+				OFONO_HISTORY_SMS_STATUS_DELIVER_FAILED);
+	}
 }
 
 static void sms_dispatch(struct ofono_sms *sms, GSList *sms_list)
@@ -763,7 +800,8 @@ static void sms_status_report_dispatch(struct ofono_sms *sms, GSList *sms_list)
 	dispatch_sms_delivery_report(sms, &s->status_report.st,
 					&s->status_report.raddr,
 					&s->status_report.scts,
-					&s->status_report.dt);
+					&s->status_report.dt,
+					s->status_report.mr);
 }
 
 static void handle_deliver(struct ofono_sms *sms, const struct sms *incoming)
@@ -1041,6 +1079,15 @@ static void sms_remove(struct ofono_atom *atom)
 		sms->settings = NULL;
 	}
 
+	if (sms->pending_status_reports) {
+
+		g_slist_foreach(sms->pending_status_reports,
+				(GFunc) free_pending_status_report,
+				&sms->pending_status_reports);
+
+		sms->pending_status_reports = NULL;
+	}
+
 	g_free(sms);
 }
 
diff --git a/src/smsutil.c b/src/smsutil.c
index a92089b..6e3caa3 100644
--- a/src/smsutil.c
+++ b/src/smsutil.c
@@ -2635,6 +2635,158 @@ static inline GSList *sms_list_append(GSList *l, const struct sms *in)
 	return l;
 }
 
+static gboolean compare_sms_addresses(const struct sms_address *first,
+					const struct sms_address *second)
+{
+	const char *str1 = first->address;
+	const char *str2 = second->address;
+
+	if (first->number_type != second->number_type)
+		return FALSE;
+
+	if (first->numbering_plan != second->numbering_plan)
+		return FALSE;
+
+	if (g_strcmp0(str1, str2) != 0)
+		return FALSE;
+
+	return TRUE;
+}
+
+void add_pending_status_report(GSList **pending_status_reports, const int mr,
+					const unsigned int msg_id,
+					const struct sms_address *receiver)
+{
+	struct pending_status_report *status_report;
+	GSList *l;
+	struct mr_number *new_mr;
+
+	for (l = *pending_status_reports; l; l = l->next) {
+		status_report = l->data;
+
+		if (status_report->ofono_msg_id == msg_id) {
+
+			/*Relate new MR-number to existing ofono_msg_id*/
+			new_mr = g_new0(struct mr_number, 1);
+			new_mr->mr = mr;
+			new_mr->delivery_status =
+					SMS_STATUS_REPORT_STATUS_PENDING;
+			status_report->related_mr_numbers =
+				g_slist_append(status_report-> \
+						related_mr_numbers, new_mr);
+			return;
+		}
+	}
+
+	/*Create new ofono_msg_id and relate MR-number to it*/
+	status_report = g_new0(struct pending_status_report, 1);
+
+	status_report->ofono_msg_id = msg_id;
+	status_report->receiver = *receiver;
+
+	new_mr = g_new0(struct mr_number, 1);
+	new_mr->mr = mr;
+	new_mr->delivery_status = SMS_STATUS_REPORT_STATUS_PENDING;
+	status_report->related_mr_numbers =
+		g_slist_append(status_report->related_mr_numbers, new_mr);
+
+	*pending_status_reports =
+		g_slist_append(*pending_status_reports, status_report);
+}
+
+void free_pending_status_report(struct pending_status_report *status_report,
+				GSList **pending_status_reports)
+{
+
+	/*Free msg_id and relating MR-numbers*/
+	g_slist_foreach(status_report->related_mr_numbers, (GFunc)g_free, NULL);
+	g_slist_free(status_report->related_mr_numbers);
+
+	*pending_status_reports = g_slist_remove(*pending_status_reports,
+								status_report);
+
+	status_report = NULL;
+}
+
+enum ofono_history_sms_status update_pending_status_report_mr_number(
+		GSList **pending_status_reports, const guint8 mr,
+		const struct sms_address *receiver,
+		const enum sms_status_report_result status_report_result,
+		unsigned int *relating_msg_id)
+{
+	struct pending_status_report *status_report;
+	GSList *l;
+	GSList *i;
+	struct mr_number *current_mr;
+	gboolean delivery_successful;
+	gboolean mr_number_found = FALSE;
+
+	/*Each ofono_msg_id can relate to 1-n mr_numbers*/
+	for (l = *pending_status_reports; l; l = l->next) {
+		delivery_successful = TRUE;
+		status_report = l->data;
+
+		/* MR-number does not relate to this msg_id because of
+		 * different addresses
+		 */
+		if (!compare_sms_addresses(&status_report->receiver, receiver))
+			continue;
+
+		for (i = status_report->related_mr_numbers; i; i = i->next) {
+			current_mr = i->data;
+
+			/*Message with current MR-number was delivered*/
+			if (current_mr->mr == mr &&
+				status_report_result ==
+				SMS_STATUS_REPORT_MESSAGE_DELIVERED) {
+				current_mr->delivery_status =
+					SMS_STATUS_REPORT_MESSAGE_DELIVERED;
+
+				mr_number_found = TRUE;
+
+				continue;
+			}
+
+			/* If one part of the fragmented message is undelivered,
+			 * whole message is declared undelivered
+			 */
+			if (current_mr->mr == mr &&
+				status_report_result ==
+				SMS_STATUS_REPORT_MESSAGE_NOT_DELIVERED) {
+				free_pending_status_report(status_report,
+						pending_status_reports);
+
+				/*Received MR is handled*/
+				return OFONO_HISTORY_SMS_STATUS_DELIVER_FAILED;
+			}
+
+			if (current_mr->delivery_status ==
+				SMS_STATUS_REPORT_STATUS_PENDING)
+				/*msg_id still relates to pending statusreport*/
+				delivery_successful = FALSE;
+		}
+
+		/*all parts of the message succesfully delivered*/
+		if (delivery_successful) {
+			*relating_msg_id = status_report->ofono_msg_id;
+			free_pending_status_report(status_report,
+							pending_status_reports);
+
+			/*Received MR is handled*/
+			return OFONO_HISTORY_SMS_STATUS_DELIVERED;
+		}
+	}
+
+	if (!mr_number_found) {
+		/* MR-number is not found in pending_status_reports. Can this
+		 * kind of error occur? Maybe reboot just before MR-number is
+		 * saved to disk? What to do?
+		 */
+	}
+
+	return OFONO_HISTORY_SMS_STATUS_PENDING;
+}
+
 /* Prepares the text for transmission.  Breaks up into fragments if
  * necessary using ref as the concatenated message reference number.
  * Returns a list of sms messages in order.  If ref_offset is given,
diff --git a/src/smsutil.h b/src/smsutil.h
index cfb2765..a809453 100644
--- a/src/smsutil.h
+++ b/src/smsutil.h
@@ -21,6 +21,8 @@
 
 #define CBS_MAX_GSM_CHARS 93
 
+#include "history.h"
+
 enum sms_type {
 	SMS_TYPE_DELIVER = 0,
 	SMS_TYPE_DELIVER_REPORT_ACK,
@@ -178,6 +180,12 @@ enum sms_pid_type {
 	SMS_PID_TYPE_USIM_DOWNLOAD = 0x7f,
 };
 
+enum sms_status_report_result {
+	SMS_STATUS_REPORT_STATUS_PENDING = 0,
+	SMS_STATUS_REPORT_MESSAGE_NOT_DELIVERED = 1,
+	SMS_STATUS_REPORT_MESSAGE_DELIVERED = 2,
+};
+
 enum cbs_language {
 	CBS_LANGUAGE_GERMAN = 0x0,
 	CBS_LANGUAGE_ENGLISH = 0x1,
@@ -364,6 +372,17 @@ struct sms_assembly {
 	GSList *assembly_list;
 };
 
+struct mr_number {
+	guint8 mr;
+	enum sms_status_report_result delivery_status;
+};
+
+struct pending_status_report {
+	unsigned int ofono_msg_id;
+	struct sms_address receiver;
+	GSList *related_mr_numbers;
+};
+
 struct cbs {
 	enum cbs_geo_scope gs;			/* 2 bits */
 	guint16 message_code;			/* 10 bits */
@@ -481,6 +500,19 @@ GSList *sms_assembly_add_fragment(struct sms_assembly *assembly,
 					guint16 ref, guint8 max, guint8 seq);
 void sms_assembly_expire(struct sms_assembly *assembly, time_t before);
 
+void add_pending_status_report(GSList **pending_status_reports, const int mr,
+					const unsigned int msg_id,
+					const struct sms_address *receiver);
+
+void free_pending_status_report(struct pending_status_report *status_report,
+				GSList **pending_status_reports);
+
+enum ofono_history_sms_status update_pending_status_report_mr_number(
+		GSList **pending_status_reports, const guint8 mr,
+		const struct sms_address *receiver,
+		const enum sms_status_report_result status_report_result,
+		unsigned int *relating_msg_id);
+
 GSList *sms_text_prepare(const char *utf8, guint16 ref,
 				gboolean use_16bit, int *ref_offset,
 				const gboolean use_delivery_reports);
-- 
1.6.0.4




More information about the ofono mailing list