[RFC PATCH 6/6] Save pending SMS Status Reports to disk.

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


---
 src/sms.c     |   11 ++-
 src/smsutil.c |  263 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/smsutil.h |    9 ++-
 3 files changed, 273 insertions(+), 10 deletions(-)

diff --git a/src/sms.c b/src/sms.c
index 76b0985..bf54f0b 100644
--- a/src/sms.c
+++ b/src/sms.c
@@ -336,7 +336,8 @@ static void tx_finished(const struct ofono_error *error, int mr, void *data)
 
 	if (entry->status_report)
 		add_pending_status_report(&sms->pending_status_reports, mr,
-					entry->msg_id, &entry->receiver);
+					entry->msg_id, &entry->receiver,
+					sms->assembly->imsi);
 
 	if (entry->cur_pdu < entry->num_pdus) {
 		sms->tx_source = g_timeout_add(0, tx_next, sms);
@@ -653,11 +654,12 @@ static void dispatch_sms_delivery_report(struct ofono_sms *sms,
 		status = update_pending_status_report_mr_number(
 					&sms->pending_status_reports, mr, raddr,
 					SMS_STATUS_REPORT_MESSAGE_DELIVERED,
-					&relating_msg_id);
+					&relating_msg_id, sms->assembly->imsi);
 
 		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);
@@ -677,7 +679,7 @@ static void dispatch_sms_delivery_report(struct ofono_sms *sms,
 		update_pending_status_report_mr_number(
 					&sms->pending_status_reports, mr, raddr,
 					SMS_STATUS_REPORT_MESSAGE_NOT_DELIVERED,
-					&relating_msg_id);
+					&relating_msg_id, sms->assembly->imsi);
 
 		__ofono_history_sms_send_status(modem, relating_msg_id,
 				time(NULL),
@@ -1226,6 +1228,9 @@ void ofono_sms_register(struct ofono_sms *sms)
 		imsi = ofono_sim_get_imsi(sms->sim);
 		sms->assembly = sms_assembly_new(imsi);
 
+		sms->pending_status_reports =
+			pending_status_reports_load_backup(imsi);
+
 		sms_load_settings(sms, imsi);
 	} else {
 		sms->assembly = sms_assembly_new(NULL);
diff --git a/src/smsutil.c b/src/smsutil.c
index 6e3caa3..1083b76 100644
--- a/src/smsutil.c
+++ b/src/smsutil.c
@@ -45,6 +45,10 @@
 #define SMS_BACKUP_PATH_DIR SMS_BACKUP_PATH "/%s-%i-%i"
 #define SMS_BACKUP_PATH_FILE SMS_BACKUP_PATH_DIR "/%03i"
 
+#define SMS_SR_BACKUP_PATH STORAGEDIR "/%s/sms_sr"
+#define SMS_SR_BACKUP_PATH_DIR SMS_SR_BACKUP_PATH "/%s-%i-%i"
+#define SMS_SR_BACKUP_PATH_FILE SMS_SR_BACKUP_PATH_DIR "/%i/%i"
+
 #define SMS_ADDR_FMT "%24[0-9A-F]"
 
 static GSList *sms_assembly_add_fragment_backup(struct sms_assembly *assembly,
@@ -2635,6 +2639,239 @@ static inline GSList *sms_list_append(GSList *l, const struct sms *in)
 	return l;
 }
 
+static gboolean pending_status_report_backup_mr(
+			const struct pending_status_report *status_report,
+			const struct sms_address *receiver, const char *imsi,
+			const struct mr_number *mr)
+{
+	int len = sizeof(enum sms_status_report_result);
+	unsigned char buf[3];
+
+	if (!imsi)
+		return FALSE;
+
+	/* storagedir/%s/sms_assembly/%s-%i-%i/%i/%i */
+	if (write_file(buf, len, SMS_BACKUP_MODE, SMS_SR_BACKUP_PATH_FILE, imsi,
+			receiver->address, receiver->number_type,
+			receiver->numbering_plan, status_report->ofono_msg_id,
+			mr->mr) != len)
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean pending_status_report_backup_free_mr(
+			const struct pending_status_report *status_report,
+			const struct sms_address *receiver, const char *imsi,
+			const struct mr_number *mr)
+{
+	char *path;
+
+	if (!imsi)
+		return FALSE;
+
+	path = g_strdup_printf(SMS_SR_BACKUP_PATH_FILE, imsi, receiver->address,
+				receiver->number_type,
+				receiver->numbering_plan,
+				status_report->ofono_msg_id, mr->mr);
+
+	unlink(path);
+	g_free(path);
+
+	path = g_strdup_printf(SMS_SR_BACKUP_PATH_DIR "/%i", imsi,
+				receiver->address, receiver->number_type,
+				receiver->numbering_plan,
+				status_report->ofono_msg_id);
+
+	/* If the msg_id does not have relating MR-numbers anymore, remove it */
+	rmdir(path);
+	g_free(path);
+
+	return TRUE;
+}
+
+static gboolean pending_status_report_backup_update_mr(
+			const struct pending_status_report *status_report,
+			const struct sms_address *receiver,
+			const char *imsi, const struct mr_number *mr)
+{
+	if (!pending_status_report_backup_free_mr(status_report, receiver,
+								imsi, mr))
+		return FALSE;
+
+	if (!pending_status_report_backup_mr(status_report, receiver, imsi, mr))
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean pending_status_report_backup_free_id(
+			const struct pending_status_report *status_report,
+			const struct sms_address *receiver, const char *imsi)
+{
+	char *path;
+	GSList *l;
+	struct mr_number *current_mr;
+
+	if (!imsi)
+		return FALSE;
+
+	for (l = status_report->related_mr_numbers; l; l = l->next) {
+		current_mr = l->data;
+
+		pending_status_report_backup_free_mr(status_report, receiver,
+							imsi, current_mr);
+	}
+
+	path = g_strdup_printf(SMS_SR_BACKUP_PATH_DIR "/%i", imsi,
+				receiver->address, receiver->number_type,
+				receiver->numbering_plan,
+				status_report->ofono_msg_id);
+
+	rmdir(path);
+	g_free(path);
+
+	path = g_strdup_printf(SMS_SR_BACKUP_PATH_DIR, imsi,
+				receiver->address, receiver->number_type,
+				receiver->numbering_plan);
+
+	/* If the address does not have pending msg_ids anymore, remove it */
+	rmdir(path);
+	g_free(path);
+
+	return TRUE;
+}
+
+static void pending_status_reports_load_mrs(
+				struct pending_status_report *status_report,
+				const struct dirent *id_dir,
+				const struct dirent *addr_dir, const char *imsi)
+{
+	char *path;
+	struct dirent **mrs;
+	int len;
+	struct mr_number *mr_nmbr;
+	unsigned char buf[3];
+	int r;
+
+	if (id_dir->d_type != DT_DIR)
+		return;
+
+	if (sscanf(id_dir->d_name, "%i", &status_report->ofono_msg_id) < 1)
+		return;
+
+	/* Go through different MR-numbers. MR-number contains the status of
+	 * the related message.
+	 */
+	path = g_strdup_printf(SMS_SR_BACKUP_PATH "/%s/%s",
+		imsi, addr_dir->d_name, id_dir->d_name);
+	len = scandir(path, &mrs, NULL, versionsort);
+
+	g_free(path);
+
+	if (len < 0)
+		return;
+
+	while (len--) {
+		mr_nmbr = g_new0(struct mr_number, 1);
+		r = read_file(buf, sizeof(buf), SMS_SR_BACKUP_PATH "/%s/%s/%s",
+				imsi, addr_dir->d_name,
+				id_dir->d_name, mrs[len]->d_name);
+
+		if (r < 0)
+			return;
+
+		mr_nmbr->mr = atoi(mrs[len]->d_name);
+		mr_nmbr->delivery_status = atoi((char *)buf);
+		status_report->related_mr_numbers =
+			g_slist_append(status_report->related_mr_numbers,
+								mr_nmbr);
+
+		free(mrs[len]);
+	}
+
+	free(mrs);
+}
+
+static void pending_status_reports_load_ids(GSList **pending_status_reports,
+						const struct dirent *addr_dir,
+						const char *imsi)
+{
+	char *path;
+	struct dirent **ids;
+	struct sms_address *addr;
+	struct pending_status_report *status_report;
+	int len;
+	if (addr_dir->d_type != DT_DIR)
+		return;
+
+	addr = g_new0(struct sms_address, 1);
+
+	if (sscanf(addr_dir->d_name, "%[0-9]-%i-%i",
+			addr->address, (int *) &addr->number_type,
+			(int *) &addr->numbering_plan) < 3)
+		return;
+
+	/* Go through different msg_ids. Each msg_id can relate to
+	 * 1-n MR-numbers.
+	 */
+	path = g_strdup_printf(SMS_SR_BACKUP_PATH "/%s", imsi,
+							addr_dir->d_name);
+	len = scandir(path, &ids, NULL, versionsort);
+
+	g_free(path);
+
+	if (len < 0)
+		return;
+
+	/* Do not try to load . and .. directories */
+	while (2 < len--) {
+		status_report = g_new0(struct pending_status_report, 1);
+		status_report->receiver = g_new0(struct sms_address, 1);
+		pending_status_reports_load_mrs(status_report, ids[len],
+								addr_dir, imsi);
+		status_report->ofono_msg_id = atoi(ids[len]->d_name);
+		*status_report->receiver = *addr;
+
+		*pending_status_reports =
+			g_slist_append(*pending_status_reports, status_report);
+		free(ids[len]);
+	}
+
+	free(ids);
+}
+
+GSList *pending_status_reports_load_backup(const char *imsi)
+{
+	GSList *ret = NULL;
+	char *path;
+	struct dirent **addresses;
+	int len;
+
+	if (imsi) {
+		/* Restore state from backup */
+		path = g_strdup_printf(SMS_SR_BACKUP_PATH, imsi);
+		len = scandir(path, &addresses, NULL, alphasort);
+
+		g_free(path);
+
+		if (len < 0)
+			return ret;
+		/* Go through different addresses. Each address can relate to
+		 * 1-n msg_ids. Do not try to load . and .. directories.
+		 */
+		while (2 < len--) {
+			pending_status_reports_load_ids(&ret, addresses[len],
+									imsi);
+			free(addresses[len]);
+		}
+
+		free(addresses);
+	}
+
+	return ret;
+}
+
 static gboolean compare_sms_addresses(const struct sms_address *first,
 					const struct sms_address *second)
 {
@@ -2655,7 +2892,8 @@ static gboolean compare_sms_addresses(const struct sms_address *first,
 
 void add_pending_status_report(GSList **pending_status_reports, const int mr,
 					const unsigned int msg_id,
-					const struct sms_address *receiver)
+					struct sms_address *receiver,
+					const char *imsi)
 {
 	struct pending_status_report *status_report;
 	GSList *l;
@@ -2674,15 +2912,18 @@ void add_pending_status_report(GSList **pending_status_reports, const int mr,
 			status_report->related_mr_numbers =
 				g_slist_append(status_report-> \
 						related_mr_numbers, new_mr);
+			pending_status_report_backup_mr(status_report, receiver,
+							imsi, 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->receiver = g_new0(struct sms_address, 1);
 
 	status_report->ofono_msg_id = msg_id;
-	status_report->receiver = *receiver;
+	*status_report->receiver = *receiver;
 
 	new_mr = g_new0(struct mr_number, 1);
 	new_mr->mr = mr;
@@ -2690,6 +2931,8 @@ void add_pending_status_report(GSList **pending_status_reports, const int mr,
 	status_report->related_mr_numbers =
 		g_slist_append(status_report->related_mr_numbers, new_mr);
 
+	pending_status_report_backup_mr(status_report, receiver, imsi, new_mr);
+
 	*pending_status_reports =
 		g_slist_append(*pending_status_reports, status_report);
 }
@@ -2702,6 +2945,8 @@ void free_pending_status_report(struct pending_status_report *status_report,
 	g_slist_foreach(status_report->related_mr_numbers, (GFunc)g_free, NULL);
 	g_slist_free(status_report->related_mr_numbers);
 
+	g_free(status_report->receiver);
+
 	*pending_status_reports = g_slist_remove(*pending_status_reports,
 								status_report);
 
@@ -2712,7 +2957,7 @@ 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)
+		unsigned int *relating_msg_id, const char *imsi)
 {
 	struct pending_status_report *status_report;
 	GSList *l;
@@ -2729,7 +2974,7 @@ enum ofono_history_sms_status update_pending_status_report_mr_number(
 		/* MR-number does not relate to this msg_id because of
 		 * different addresses
 		 */
-		if (!compare_sms_addresses(&status_report->receiver, receiver))
+		if (!compare_sms_addresses(status_report->receiver, receiver))
 			continue;
 
 		for (i = status_report->related_mr_numbers; i; i = i->next) {
@@ -2742,6 +2987,10 @@ enum ofono_history_sms_status update_pending_status_report_mr_number(
 				current_mr->delivery_status =
 					SMS_STATUS_REPORT_MESSAGE_DELIVERED;
 
+				pending_status_report_backup_update_mr(
+						status_report, receiver, imsi,
+								current_mr);
+
 				mr_number_found = TRUE;
 
 				continue;
@@ -2756,6 +3005,9 @@ enum ofono_history_sms_status update_pending_status_report_mr_number(
 				free_pending_status_report(status_report,
 						pending_status_reports);
 
+				pending_status_report_backup_free_id(
+						status_report, receiver, imsi);
+
 				/*Received MR is handled*/
 				return OFONO_HISTORY_SMS_STATUS_DELIVER_FAILED;
 			}
@@ -2769,6 +3021,9 @@ enum ofono_history_sms_status update_pending_status_report_mr_number(
 		/*all parts of the message succesfully delivered*/
 		if (delivery_successful) {
 			*relating_msg_id = status_report->ofono_msg_id;
+
+			pending_status_report_backup_free_id(status_report,
+								receiver, imsi);
 			free_pending_status_report(status_report,
 							pending_status_reports);
 
diff --git a/src/smsutil.h b/src/smsutil.h
index a809453..11481db 100644
--- a/src/smsutil.h
+++ b/src/smsutil.h
@@ -379,7 +379,7 @@ struct mr_number {
 
 struct pending_status_report {
 	unsigned int ofono_msg_id;
-	struct sms_address receiver;
+	struct sms_address *receiver;
 	GSList *related_mr_numbers;
 };
 
@@ -500,9 +500,12 @@ 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);
 
+GSList *pending_status_reports_load_backup(const char *imsi);
+
 void add_pending_status_report(GSList **pending_status_reports, const int mr,
 					const unsigned int msg_id,
-					const struct sms_address *receiver);
+					struct sms_address *receiver,
+					const char *imsi);
 
 void free_pending_status_report(struct pending_status_report *status_report,
 				GSList **pending_status_reports);
@@ -511,7 +514,7 @@ 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);
+		unsigned int *relating_msg_id, const char *imsi);
 
 GSList *sms_text_prepare(const char *utf8, guint16 ref,
 				gboolean use_16bit, int *ref_offset,
-- 
1.6.0.4




More information about the ofono mailing list