Skip to contentSkip to conversation

pull request

PATCH In review Inaky Perez-Gonzalez 3 participants 20 messages Aug 6, 2010 Kbuild

lore
Share & tools
lore
#0 lore raw

v5 cover pull request

From: Inaky Perez-Gonzalez <[email protected]>

v5 (there have been more than five submissions, but whatever) contains the following changes as requested by Dennis:

- multi fragment message ref and the unique message ID are decoupled now. this allows...

- UUID is generated in tx_queue_entry_new()

- UUID is expanded to 32-bits from 16 bits

Catchas

- UUID is not used in the RX path yet, the old mechanism (sms->next_msg_id) is still in place

- __ofono_sms_txq_submit() still has to be modified. No better alternatives have been proposed.

The following changes since commit f01de438bd4f834a27f9c36e74e6a1067f778a21:
João Paulo Rechi Vita (1):
huawei: Fix SIM state logic

are available in the git repository at:

git://gitorious.org/~inakypg/ofono/ofono-inakypg.git master

Patches follow for reviewing convenience.

Inaky Perez-Gonzalez (17):
sms: replace sequential SMS message ID with hash
sms: _txq_submit() returns pointer to object
sms: document the org.ofono.SmsMessage interface
sms: document handle_sms_status_report()
sms: introduce bare state machine and transitions
sms: introduce the Wait-for-Status-Report state
sms: introduce a state change callback for messages
sms: export outgoing messages over D-Bus
sms: send PropertyChanged signals on state change
sms: introduce sms_msg_cancel and its D-Bus wrapper
sms: Implement D-Bus SMS-MSG::GetProperties
sms: document SMS Message's D-Bus 'To' property
sms: test code for message's D-Bus GetProperties
automake: fix generation of symlinks for headers
sms: document variable usage in sms_msg_send()
sms: add test case for message cancel
sms: add test case for state change signals

 Makefile.am                      |    2 +-
 doc/sms-api.txt                  |   54 ++++-
 src/ofono.h                      |   46 +++-
 src/sms.c                        |  576 ++++++++++++++++++++++++++++++++++----
 src/stk.c                        |   19 ++-
 test/test-sms-msg-cancel         |  173 ++++++++++++
 test/test-sms-msg-get-properties |   26 ++
 test/test-sms-msg-state-change   |   24 ++
 8 files changed, 852 insertions(+), 68 deletions(-)
 create mode 100755 test/test-sms-msg-cancel
 create mode 100755 test/test-sms-msg-get-properties
 create mode 100755 test/test-sms-msg-state-change
#1 lore raw

PATCH v5 1/17 sms: replace sequential SMS message ID with hash

From: Inaky Perez-Gonzalez <[email protected]>

The SMS messages's ID number (used for history, D-Bus naming and storage in external database) is updated to use a hash (based on PDUs and submission time) to further avoid ID collision concerns.

---
 src/sms.c |   50 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 49 insertions(+), 1 deletions(-)
src/sms.c +49 -1
index 01596ef..f5c3162 100644
@@ -29,6 +29,7 @@
 
 #include <glib.h>
 #include <gdbus.h>
+#include <sys/time.h>
 
 #include "ofono.h"
 
@@ -539,6 +540,52 @@ static void set_ref_and_to(GSList *msg_list, guint16 ref, int offset,
 	}
 }
 
+/**
+ * Generate a UUID from an SMS PDU List
+ *
+ * @param pdu Pointer to array of PDUs data to generate the ID from
+ * @param pdus Number of entries in the \e pdu array
+ * @return 0 in error (no memory or serious code inconsistency in the
+ *     input data structures), otherwise the SMS UUID.
+ *
+ * @internal
+ *
+ * Note we use memcpy() instead of dropping the uuid param straight to
+ * g_checksum_get_digest(). This is because g_checksum_get_digest()
+ * seems to randomly not copy the digest data if the buffer is smaller
+ * than what the digest should have.
+ *
+ * The current time is added to avoid the UUID being the same when the
+ * same message is sent to the same destination repeatedly. Note we
+ * need a high resolution time (not just seconds), otherwise resending
+ * in the same second (not that rare) could yield the same UUID.
+ */
+static unsigned int sms_uuid_from_pdus(const struct pending_pdu *pdu,
+					size_t pdus)
+{
+	unsigned int uuid = 0;
+	GChecksum *checksum;
+	gsize uuid_size = g_checksum_type_get_length(G_CHECKSUM_SHA256);
+	guint8 data[uuid_size];
+	unsigned cnt;
+	struct timeval now;
+
+	checksum = g_checksum_new(G_CHECKSUM_SHA256);
+	if (checksum == NULL)
+		goto error_new;
+
+	for (cnt = 0; cnt < pdus; cnt++)
+		g_checksum_update(checksum, pdu[cnt].pdu, pdu[cnt].pdu_len);
+
+	gettimeofday(&now, NULL);
+	g_checksum_update(checksum, (void *) &now, sizeof(now));
+	g_checksum_get_digest(checksum, data, &uuid_size);
+	memcpy(&uuid, data, MIN(sizeof(uuid), sizeof(data)));
+	g_checksum_free(checksum);
+error_new:
+	return uuid;
+}
+
 static struct tx_queue_entry *tx_queue_entry_new(GSList *msg_list)
 {
 	struct tx_queue_entry *entry = g_new0(struct tx_queue_entry, 1);
@@ -558,6 +605,8 @@ static struct tx_queue_entry *tx_queue_entry_new(GSList *msg_list)
 				pdu->pdu_len, pdu->tpdu_len);
 	}
 
+	entry->msg_id = sms_uuid_from_pdus(entry->pdus, entry->num_pdus);
+
 	return entry;
 }
 
@@ -1336,7 +1385,6 @@ unsigned int __ofono_sms_txq_submit(struct ofono_sms *sms, GSList *list,
 				sizeof(entry->receiver));
 	}
 
-	entry->msg_id = sms->next_msg_id++;
 	entry->flags = flags;
 	entry->cb = cb;
 	entry->data = data;
Signature · 1 line
1.6.6.1
#2 lore raw

PATCH v5 2/17 sms: _txq_submit() returns pointer to object

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

This makes __ofono_sms_txq_submit() return a pointer to the newly allocated message object, from where the message ID can be recovered.

This is needed for future commits where the object pointer is needed to use it as the handle for the D-Bus wrapping functionality. This allows for an effective and simple implementation.

---
 src/ofono.h |   10 ++++++----
 src/sms.c   |   19 +++++++++++--------
 2 files changed, 17 insertions(+), 12 deletions(-)
src/ofono.h +6 -4
index aaa01d9..6fba8c3 100644
@@ -185,10 +185,12 @@ enum ofono_sms_submit_flag {
 
 typedef void (*ofono_sms_txq_submit_cb_t)(gboolean ok, void *data);
 
-unsigned int __ofono_sms_txq_submit(struct ofono_sms *sms, GSList *list,
-					unsigned int flags,
-					ofono_sms_txq_submit_cb_t cb,
-					void *data, ofono_destroy_func destroy);
+struct tx_queue_entry *__ofono_sms_txq_submit(struct ofono_sms *sms,
+						GSList *list,
+						unsigned int flags,
+						ofono_sms_txq_submit_cb_t cb,
+						void *data,
+						ofono_destroy_func destroy);
 
 #include <ofono/sim.h>
 #include <ofono/stk.h>
src/sms.c +11 -8
index f5c3162..dce7d36 100644
@@ -654,7 +654,7 @@ static DBusMessage *sms_send_message(DBusConnection *conn, DBusMessage *msg,
 	int ref_offset;
 	struct ofono_modem *modem;
 	unsigned int flags;
-	unsigned int msg_id;
+	struct tx_queue_entry *sms_msg;
 
 	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &to,
 					DBUS_TYPE_STRING, &text,
@@ -685,7 +685,7 @@ static DBusMessage *sms_send_message(DBusConnection *conn, DBusMessage *msg,
 	if (sms->use_delivery_reports)
 		flags |= OFONO_SMS_SUBMIT_FLAG_REQUEST_SR;
 
-	msg_id = __ofono_sms_txq_submit(sms, msg_list, flags, send_message_cb,
+	sms_msg = __ofono_sms_txq_submit(sms, msg_list, flags, send_message_cb,
 						dbus_message_ref(msg),
 						send_message_destroy);
 
@@ -693,7 +693,8 @@ static DBusMessage *sms_send_message(DBusConnection *conn, DBusMessage *msg,
 	g_slist_free(msg_list);
 
 	modem = __ofono_atom_get_modem(sms->atom);
-	__ofono_history_sms_send_pending(modem, msg_id, to, time(NULL), text);
+	__ofono_history_sms_send_pending(modem, sms_msg->msg_id, to,
+						time(NULL), text);
 
 	return NULL;
 }
@@ -1371,10 +1372,12 @@ void *ofono_sms_get_data(struct ofono_sms *sms)
 	return sms->driver_data;
 }
 
-unsigned int __ofono_sms_txq_submit(struct ofono_sms *sms, GSList *list,
-					unsigned int flags,
-					ofono_sms_txq_submit_cb_t cb,
-					void *data, ofono_destroy_func destroy)
+struct tx_queue_entry *__ofono_sms_txq_submit(struct ofono_sms *sms,
+						GSList *list,
+						unsigned int flags,
+						ofono_sms_txq_submit_cb_t cb,
+						void *data,
+						ofono_destroy_func destroy)
 {
 	struct tx_queue_entry *entry = tx_queue_entry_new(list);
 
@@ -1395,5 +1398,5 @@ unsigned int __ofono_sms_txq_submit(struct ofono_sms *sms, GSList *list,
 	if (g_queue_get_length(sms->txq) == 1)
 		sms->tx_source = g_timeout_add(0, tx_next, sms);
 
-	return entry->msg_id;
+	return entry;
 }
Signature · 1 line
1.6.6.1
#3 lore raw

PATCH v5 3/17 sms: document the org.ofono.SmsMessage interface

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

---
 doc/sms-api.txt |   49 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 47 insertions(+), 2 deletions(-)
doc/sms-api.txt +47 -2
index 1fc32ac..2bf588f 100644
@@ -22,9 +22,27 @@ Methods		dict GetProperties()
 			Possible Errors: [service].Error.InvalidArguments
 					 [service].Error.DoesNotExist
 
-		void SendMessage(string to, string text)
+		object SendMessage(string to, string text)
 
-			Send the message in text to the number in to.
+			Submit a message for delivery /
+			processing. oFono owns it from now on until
+			successful delivery, cancellation (by the
+			user) or cancellation (by oFono). User has to
+			keep a copy around as oFono only offers
+			persistence to satisfy its needs.
+
+			Returns the name of the D-Bus object that
+			represents said SMS Message.
+
+			Possible Errors: [service].Error.InvalidArguments
+
+		array{object} Messages()
+
+			Returns a list of SMS Messages that have been
+			submitted for delivery and that are still
+			pending.
+
+			FIXME: currently not implemented
 
 Signals		PropertyChanged(string name, variant value)
 
@@ -64,3 +82,30 @@ Properties	string ServiceCenterAddress
 				"ps-preferred" - Use CS if PS is unavailable
 
 			By default oFono uses "cs-preferred" setting.
+
+
+SMS / Messaging interface
+=========================
+
+Service		org.ofono
+Interface	org.ofono.SmsMessage
+Object path	[variable prefix]/{modem0,modem1...}/{message01,message02...}
+
+Methods		dict GetProperties()
+
+			Returns a dictionary with the current
+			properties of a message.
+
+		void Cancel()
+
+			Cancels a pending message's delivery.
+
+Signals		PropertyChanged(string name, variant value)
+
+			This signal indicates a changed value of the given
+			property.
+
+Properties	string State
+
+			Current transmission state {queued, wsr, done,
+			canceling, cancelled, failed, expired}
Signature · 1 line
1.6.6.1
#4 lore raw

PATCH v5 4/17 sms: document handle_sms_status_report()

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

---
 src/sms.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)
src/sms.c +9 -0
index dce7d36..d0563d0 100644
@@ -930,6 +930,15 @@ static void handle_deliver(struct ofono_sms *sms, const struct sms *incoming)
 	g_slist_free(l);
 }
 
+
+/*
+ * Handle a delivery/status report has been received for an SMS
+ * apparently sent from here.
+ *
+ * We need to find the message in the SMS manager's
+ * waiting-for-acknoledge queue (sms->tx_wfaq) and remove it. As well,
+ * fill out history for it.
+ */
 static void handle_sms_status_report(struct ofono_sms *sms,
 						const struct sms *incoming)
 {
Signature · 1 line
1.6.6.1
#5 lore raw

PATCH v5 5/17 sms: introduce bare state machine and transitions

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

This adds state to outgoing/in-transit SMS messages. This will be used later on for persistence / D-Bus, when the SMS life cycle is expanded.

The state is a variable in the 'struct tx_queue_entry' which gets updated as messages go through the hoops.

---
 src/ofono.h |   33 +++++++++++++++++
 src/sms.c   |  117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 148 insertions(+), 2 deletions(-)
src/ofono.h +33 -0
index 6fba8c3..2f7dfba 100644
@@ -183,6 +183,39 @@ enum ofono_sms_submit_flag {
 	OFONO_SMS_SUBMIT_FLAG_RETRY =		0x4,
 };
 
+/*
+ * SMS TX message's state
+ *
+ * When a message is queued to be delivered, it will transition
+ * through a set of states.
+ *
+ * Allowed transition table (Allowed, Not-allowed) from left to right:
+ *
+ *          UNINITIALIZED         CANCELING  FAILED
+ *               | QUEUED WSR DONE   | CANCELLED  EXPIRED
+ * UNINITIALIZED -    A    N    N    N    N    N    N
+ * QUEUED        N    -    A    A    A    N    A    N
+ * WSR           N    N    -    A    A    N    A    A
+ * DONE          A    N    N    -    N    N    N    N
+ * CANCELING     N    N    N    N    -    A    A    A
+ * CANCELLED     A    N    N    N    N    -    N    N
+ * FAILED        A    N    N    N    N    N    -    N
+ * EXPIRED       A    N    N    N    N    N    N    -
+ */
+enum ofono_sms_tx_state {
+	OFONO_SMS_TX_ST_UNINITIALIZED,
+	OFONO_SMS_TX_ST_QUEUED,
+	OFONO_SMS_TX_ST_WSR,
+	OFONO_SMS_TX_ST_DONE,
+	OFONO_SMS_TX_ST_CANCELING,
+	OFONO_SMS_TX_ST_CANCELLED,
+	OFONO_SMS_TX_ST_FAILED,
+	OFONO_SMS_TX_ST_EXPIRED,
+	__OFONO_SMS_TX_ST_INVALID,
+};
+
+const char *ofono_sms_tx_state_to_string(enum ofono_sms_tx_state);
+
 typedef void (*ofono_sms_txq_submit_cb_t)(gboolean ok, void *data);
 
 struct tx_queue_entry *__ofono_sms_txq_submit(struct ofono_sms *sms,
src/sms.c +115 -2

179 lines not on this page · raw message

Signature · 1 line
1.6.6.1
#6 lore raw

PATCH v5 6/17 sms: introduce the Wait-for-Status-Report state

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

A WSR (Waiting for Status Report) state definition is added to the state transtition machine; as well, a queue (ofono_sms->tx_wfaq) where messages waiting for an status report are queued. When the message's delivery is acknowledged, the message is removed from the queue and the message's status machine is updated, which can trigger things such as D-Bus signals.

---
 src/sms.c |   80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 73 insertions(+), 7 deletions(-)
src/sms.c +73 -7
index 90be5c1..a5e3a85 100644
@@ -67,6 +67,11 @@ const char *ofono_sms_tx_state_to_string(enum ofono_sms_tx_state status)
 	}
 }
 
+/**
+ * @tx_wsrq: Waiting-for-Status-Report queue; messages in this queue
+ *     have been delivered but are waiting to be acknoledged by the
+ *     network.
+ */
 struct ofono_sms {
 	int flags;
 	DBusMessage *pending;
@@ -75,6 +80,7 @@ struct ofono_sms {
 	unsigned int next_msg_id;
 	guint ref;
 	GQueue *txq;
+	GQueue *tx_wsrq;
 	gint tx_source;
 	struct ofono_message_waiting *mw;
 	unsigned int mw_watch;
@@ -475,10 +481,19 @@ static void __ofono_sms_tx_state_set(struct tx_queue_entry *entry,
 	case OFONO_SMS_TX_ST_QUEUED:
 		ofono_sms_tx_state_check(
 			file, line, entry, state_old, state_new,
+			1 << OFONO_SMS_TX_ST_WSR
+			| 1 << OFONO_SMS_TX_ST_DONE
+			| 1 << OFONO_SMS_TX_ST_CANCELING);
+		g_queue_remove(entry->sms_mgr->txq, entry);
+		break;
+	case OFONO_SMS_TX_ST_WSR:
+		ofono_sms_tx_state_check(
+			file, line, entry, state_old, state_new,
 			1 << OFONO_SMS_TX_ST_DONE
 			| 1 << OFONO_SMS_TX_ST_CANCELING
-			| 1 << OFONO_SMS_TX_ST_FAILED);
-		g_queue_remove(entry->sms_mgr->txq, entry);
+			| 1 << OFONO_SMS_TX_ST_FAILED
+			| 1 << OFONO_SMS_TX_ST_EXPIRED);
+		g_queue_remove(entry->sms_mgr->tx_wsrq, entry);
 		break;
 	case OFONO_SMS_TX_ST_CANCELING:
 		ofono_sms_tx_state_check(
@@ -521,6 +536,8 @@ static void tx_queue_entry_destroy(struct tx_queue_entry *entry)
 
 	if (entry->state == OFONO_SMS_TX_ST_QUEUED)
 		g_queue_remove(entry->sms_mgr->txq, entry);
+	else if (entry->state == OFONO_SMS_TX_ST_WSR)
+		g_queue_remove(entry->sms_mgr->tx_wsrq, entry);
 
 	entry->state = __OFONO_SMS_TX_ST_INVALID;
 	g_free(entry);
@@ -593,12 +610,16 @@ next_q:
 		__ofono_history_sms_send_status(modem, entry->msg_id,
 						time(NULL), hs);
 	}
-	if (ok)
+	if (ok && entry->flags & OFONO_SMS_SUBMIT_FLAG_REQUEST_SR) {
+		ofono_sms_tx_state_set(entry, OFONO_SMS_TX_ST_WSR);
+		g_queue_push_tail(sms->tx_wsrq, entry);
+	} else if (ok && !(entry->flags & OFONO_SMS_SUBMIT_FLAG_REQUEST_SR)) {
 		ofono_sms_tx_state_set(entry, OFONO_SMS_TX_ST_DONE);
-	else
+		tx_queue_entry_destroy(entry);
+	} else {
 		ofono_sms_tx_state_set(entry, OFONO_SMS_TX_ST_FAILED);
-
-	tx_queue_entry_destroy(entry);
+		tx_queue_entry_destroy(entry);
+	}
 
 	if (g_queue_peek_head(sms->txq)) {
 		DBG("Scheduling next");
@@ -1041,13 +1062,45 @@ static void handle_deliver(struct ofono_sms *sms, const struct sms *incoming)
 	g_slist_free(l);
 }
 
+/*
+ * Pack information needed to locate a message from a Status Report
+ * and decide if it was succesfully delivered.
+ */
+struct sms_msg_sr_locator {
+	unsigned int msg_id;
+	gboolean delivered;
+};
+
+/*
+ * This function is a g_queue_foreach() functor called by
+ * handle_sms_status_report() to destroy the message that matches the
+ * reported MSG-ID in the SMS manager's list of messages waiting for
+ * acknowledgement.
+ */
+static void  __sms_find_destroy_by_msg_id(gpointer _sms_msg, gpointer _locator)
+{
+	const struct sms_msg_sr_locator *locator = _locator;
+	struct tx_queue_entry *sms_msg = _sms_msg;
+
+	if (sms_msg->msg_id != locator->msg_id)
+		return;
+	ofono_debug("SMS: ACKED %p msg_id match %x", sms_msg, locator->msg_id);
+	g_queue_remove(sms_msg->sms_mgr->tx_wsrq, sms_msg);
+
+	if (locator->delivered)
+		ofono_sms_tx_state_set(sms_msg, OFONO_SMS_TX_ST_DONE);
+	else
+		ofono_sms_tx_state_set(sms_msg, OFONO_SMS_TX_ST_FAILED);
+
+	tx_queue_entry_destroy(sms_msg);
+}
 
 /*
  * Handle a delivery/status report has been received for an SMS
  * apparently sent from here.
  *
  * We need to find the message in the SMS manager's
- * waiting-for-acknoledge queue (sms->tx_wfaq) and remove it. As well,
+ * waiting-for-status report queue (sms->tx_wsrq) and remove it. As well,
  * fill out history for it.
  */
 static void handle_sms_status_report(struct ofono_sms *sms,
@@ -1056,11 +1109,16 @@ static void handle_sms_status_report(struct ofono_sms *sms,
 	struct ofono_modem *modem = __ofono_atom_get_modem(sms->atom);
 	gboolean delivered;
 	unsigned int msg_id;
+	struct sms_msg_sr_locator locator;
 
 	if (status_report_assembly_report(sms->sr_assembly, incoming, &msg_id,
 						&delivered) == FALSE)
 		return;
 
+	locator.msg_id = msg_id;
+	locator.delivered = delivered;
+	g_queue_foreach(sms->tx_wsrq, __sms_find_destroy_by_msg_id, &locator);
+
 	__ofono_history_sms_send_status(modem, msg_id, time(NULL),
 			delivered ? OFONO_HISTORY_SMS_STATUS_DELIVERED :
 			OFONO_HISTORY_SMS_STATUS_DELIVER_FAILED);
@@ -1288,6 +1346,13 @@ static void sms_remove(struct ofono_atom *atom)
 		sms->txq = NULL;
 	}
 
+	if (sms->tx_wsrq) {
+		g_queue_foreach(sms->tx_wsrq,
+				tx_queue_entry_destroy_foreach, NULL);
+		g_queue_free(sms->tx_wsrq);
+		sms->tx_wsrq = NULL;
+	}
+
 	if (sms->settings) {
 		g_key_file_set_integer(sms->settings, SETTINGS_GROUP,
 					"NextMessageId", sms->next_msg_id);
@@ -1344,6 +1409,7 @@ struct ofono_sms *ofono_sms_create(struct ofono_modem *modem,
 	sms->sca.type = 129;
 	sms->ref = 1;
 	sms->txq = g_queue_new();
+	sms->tx_wsrq = g_queue_new();
 	sms->atom = __ofono_modem_add_atom(modem, OFONO_ATOM_TYPE_SMS,
 						sms_remove, sms);
 
Signature · 1 line
1.6.6.1
#7 lore raw

PATCH v5 7/17 sms: introduce a state change callback for messages

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

When the SMS message going through the TX hoops changes states, call the given callback function (if any). This will be used later to hook up the D-Bus propagation of property changed signals.

Note this will do away with the ofono_sms_txq_submit_cb callback, as it can be implemented in terms of a state change callback.

---
 src/ofono.h |    5 +++--
 src/sms.c   |   31 +++++++++++++++++++++++--------
 src/stk.c   |   19 +++++++++++++++++--
 3 files changed, 43 insertions(+), 12 deletions(-)
src/ofono.h +3 -2
index 2f7dfba..38e877f 100644
@@ -216,12 +216,13 @@ enum ofono_sms_tx_state {
 
 const char *ofono_sms_tx_state_to_string(enum ofono_sms_tx_state);
 
-typedef void (*ofono_sms_txq_submit_cb_t)(gboolean ok, void *data);
+typedef void (*ofono_sms_msg_stch_cb_t)(void *data,
+					enum ofono_sms_tx_state new_state);
 
 struct tx_queue_entry *__ofono_sms_txq_submit(struct ofono_sms *sms,
 						GSList *list,
 						unsigned int flags,
-						ofono_sms_txq_submit_cb_t cb,
+						ofono_sms_msg_stch_cb_t stch_cb,
 						void *data,
 						ofono_destroy_func destroy);
 
src/sms.c +23 -8
index a5e3a85..0d786a1 100644
@@ -115,7 +115,7 @@ struct tx_queue_entry {
 	unsigned int msg_id;
 	unsigned int retry;
 	unsigned int flags;
-	ofono_sms_txq_submit_cb_t cb;
+	ofono_sms_msg_stch_cb_t stch_cb;
 	void *data;
 	ofono_destroy_func destroy;
 };
@@ -518,6 +518,8 @@ static void __ofono_sms_tx_state_set(struct tx_queue_entry *entry,
 	ofono_debug("%s:%d: SMS state change: %p %u -> %u\n",
 		    file, line, entry, state_old, state_new);
 	entry->state = state_new;
+	if (entry->stch_cb)
+		entry->stch_cb(entry->data, state_new);
 }
 
 
@@ -596,9 +598,6 @@ static void tx_finished(const struct ofono_error *error, int mr, void *data)
 next_q:
 	entry = g_queue_peek_head(sms->txq);
 
-	if (entry->cb)
-		entry->cb(ok, entry->data);
-
 	if (entry->flags & OFONO_SMS_SUBMIT_FLAG_RECORD_HISTORY) {
 		enum ofono_history_sms_status hs;
 
@@ -742,11 +741,26 @@ static struct tx_queue_entry *tx_queue_entry_new(GSList *msg_list)
 	return entry;
 }
 
-static void send_message_cb(gboolean ok, void *data)
+static void send_message_stch_cb(void *data, enum ofono_sms_tx_state new_state)
 {
 	DBusConnection *conn = ofono_dbus_get_connection();
 	DBusMessage *msg = data;
 	DBusMessage *reply;
+	gboolean ok;
+
+	/*
+	 * We care about only the final states
+	 * (DONE/CANCELLED/FAILED/EXPIRED), the rest are just
+	 * ignored.
+	 */
+	if (new_state == OFONO_SMS_TX_ST_DONE)
+		ok = TRUE;
+	else if (new_state == OFONO_SMS_TX_ST_CANCELLED
+		 || new_state == OFONO_SMS_TX_ST_FAILED
+		 || new_state == OFONO_SMS_TX_ST_EXPIRED)
+		ok = FALSE;
+	else
+		return;
 
 	if (ok)
 		reply = dbus_message_new_method_return(msg);
@@ -817,7 +831,8 @@ static DBusMessage *sms_send_message(DBusConnection *conn, DBusMessage *msg,
 	if (sms->use_delivery_reports)
 		flags |= OFONO_SMS_SUBMIT_FLAG_REQUEST_SR;
 
-	sms_msg = __ofono_sms_txq_submit(sms, msg_list, flags, send_message_cb,
+	sms_msg = __ofono_sms_txq_submit(sms, msg_list, flags,
+						send_message_stch_cb,
 						dbus_message_ref(msg),
 						send_message_destroy);
 
@@ -1561,7 +1576,7 @@ void *ofono_sms_get_data(struct ofono_sms *sms)
 struct tx_queue_entry *__ofono_sms_txq_submit(struct ofono_sms *sms,
 						GSList *list,
 						unsigned int flags,
-						ofono_sms_txq_submit_cb_t cb,
+						ofono_sms_msg_stch_cb_t stch_cb,
 						void *data,
 						ofono_destroy_func destroy)
 {
@@ -1575,7 +1590,7 @@ struct tx_queue_entry *__ofono_sms_txq_submit(struct ofono_sms *sms,
 	}
 
 	entry->flags = flags;
-	entry->cb = cb;
+	entry->stch_cb = stch_cb;
 	entry->data = data;
 	entry->destroy = destroy;
 	entry->sms_mgr = sms;
src/stk.c +17 -2
index 7d98f92..5636eb6 100644
@@ -660,12 +660,27 @@ static void send_sms_cancel(struct ofono_stk *stk)
 	stk_alpha_id_unset(stk);
 }
 
-static void send_sms_submit_cb(gboolean ok, void *data)
+static void send_sms_stch_cb(void *data, enum ofono_sms_tx_state new_state)
 {
 	struct sms_submit_req *req = data;
 	struct ofono_stk *stk = req->stk;
 	struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
 	struct stk_response rsp;
+	gboolean ok;
+
+	/*
+	 * We care about only the final states
+	 * (DONE/CANCELLED/FAILED/EXPIRED), the rest are just
+	 * ignored.
+	 */
+	if (new_state == OFONO_SMS_TX_ST_DONE)
+		ok = TRUE;
+	else if (new_state == OFONO_SMS_TX_ST_CANCELLED
+		 || new_state == OFONO_SMS_TX_ST_FAILED
+		 || new_state == OFONO_SMS_TX_ST_EXPIRED)
+		ok = FALSE;
+	else
+		return;
 
 	ofono_debug("SMS submission %s", ok ? "successful" : "failed");
 
@@ -712,7 +727,7 @@ static gboolean handle_command_send_sms(const struct stk_command *cmd,
 	msg_list.data = (void *) &cmd->send_sms.gsm_sms;
 	msg_list.next = NULL;
 
-	__ofono_sms_txq_submit(sms, &msg_list, 0, send_sms_submit_cb,
+	__ofono_sms_txq_submit(sms, &msg_list, 0, send_sms_stch_cb,
 				stk->sms_submit_req, g_free);
 
 	stk->cancel_cmd = send_sms_cancel;
Signature · 1 line
1.6.6.1
#8 lore raw

PATCH v5 8/17 sms: export outgoing messages over D-Bus

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

Splits sms_send_message() into a D-Bus front end and an internal API:

- sms_msg_send(), a full C interface for SMS sending

- dbus_sms_msg_send(): adapts sms_msg_send() to be a D-Bus call, exporting the object on the bus, returning its name and setting up all the callbacks and D-Bus specific data. The call is synchronous.

This allows internal code to use the same infrastructure as D-Bus clients to send SMS messages.

---
 src/sms.c |  191 ++++++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 139 insertions(+), 52 deletions(-)
src/sms.c +139 -52
index 0d786a1..146027d 100644
@@ -42,6 +42,10 @@
 
 #define SMS_MANAGER_FLAG_CACHED 0x1
 
+/* D-Bus interface name for SMS messages (not for the manager!) */
+static
+const char SMS_MSG_INTERFACE[] = "org.ofono.SmsMessage";
+
 #define SETTINGS_STORE "sms"
 #define SETTINGS_GROUP "Settings"
 
@@ -524,6 +528,24 @@ static void __ofono_sms_tx_state_set(struct tx_queue_entry *entry,
 
 
 /*
+ * D-Bus SMS Message interface
+ *
+ * NOTE: the sms_msg_{methods,signals} tables should be const, but
+ * then g_dbus_register_interface() type warns.
+ */
+
+static
+GDBusMethodTable sms_msg_methods[] = {
+	{ }
+};
+
+static
+GDBusSignalTable sms_msg_signals[] = {
+	{ "PropertyChanged",	"sv"		},
+	{ }
+};
+
+/*
  * Destroy/release the contents of a 'struct tx_queue_entry'
  *
  * This releases resources allocated *inside* @entry and @entry
@@ -543,6 +565,7 @@ static void tx_queue_entry_destroy(struct tx_queue_entry *entry)
 
 	entry->state = __OFONO_SMS_TX_ST_INVALID;
 	g_free(entry);
+	ofono_debug("%s():%d: sms_msg %p freed", __func__, __LINE__, entry);
 }
 
 static void tx_queue_entry_destroy_foreach(gpointer _entry, gpointer unused)
@@ -741,48 +764,36 @@ static struct tx_queue_entry *tx_queue_entry_new(GSList *msg_list)
 	return entry;
 }
 
-static void send_message_stch_cb(void *data, enum ofono_sms_tx_state new_state)
+
+static void sms_msg_dbus_destroy(void *_dbus_path)
 {
-	DBusConnection *conn = ofono_dbus_get_connection();
-	DBusMessage *msg = data;
-	DBusMessage *reply;
-	gboolean ok;
+	char *dbus_path = _dbus_path;
 
-	/*
-	 * We care about only the final states
-	 * (DONE/CANCELLED/FAILED/EXPIRED), the rest are just
-	 * ignored.
-	 */
-	if (new_state == OFONO_SMS_TX_ST_DONE)
-		ok = TRUE;
-	else if (new_state == OFONO_SMS_TX_ST_CANCELLED
-		 || new_state == OFONO_SMS_TX_ST_FAILED
-		 || new_state == OFONO_SMS_TX_ST_EXPIRED)
-		ok = FALSE;
-	else
+	if (dbus_path == NULL)
 		return;
 
-	if (ok)
-		reply = dbus_message_new_method_return(msg);
-	else
-		reply = __ofono_error_failed(msg);
-
-	g_dbus_send_message(conn, reply);
+	g_dbus_unregister_interface(ofono_dbus_get_connection(),
+				    dbus_path, SMS_MSG_INTERFACE);
+	g_free(dbus_path);
 }
 
-static void send_message_destroy(void *data)
-{
-	DBusMessage *msg = data;
-
-	dbus_message_unref(msg);
-}
+/* Flags to sms_msg_send() */
+enum sms_msg_send_flags {
+	/* Record/dont this message to the history database */
+	SMS_MSG_SEND_HISTORY = 0x01,
+};
 
 /*
- * Pre-process a SMS text message and deliver it [D-Bus SendMessage()]
+ * Pre-process a SMS text message and deliver it
  *
  * @conn: D-Bus connection
  * @msg: message data (telephone number and text)
  * @data: SMS object to use for transmision
+ * @send_flags: flags that manipulate how the message is sent.
+ * @send_cb: function called when the message is sent
+ * @destroy_cb: function called when the message structure is
+ *    being released
+ * @priv: pointer to pass to the @data and @send_cb functions
  *
  * An alphabet is chosen for the text and it (might be) segmented in
  * fragments by sms_text_prepare() into @msg_list. A queue list @entry
@@ -790,31 +801,27 @@ static void send_message_destroy(void *data)
  * appends that entry to the SMS transmit queue. Then the tx_next()
  * function is scheduled to run to process the queue.
  */
-static DBusMessage *sms_send_message(DBusConnection *conn, DBusMessage *msg,
-					void *data)
+static
+struct tx_queue_entry *sms_msg_send(
+	struct ofono_sms *sms, const char *to, const char *text,
+	enum sms_msg_send_flags send_flags,
+	ofono_sms_msg_stch_cb_t stch_cb,
+	void (*destroy_cb)(void *), void *priv)
 {
-	struct ofono_sms *sms = data;
-	const char *to;
-	const char *text;
 	GSList *msg_list;
 	int ref_offset;
 	struct ofono_modem *modem;
 	unsigned int flags;
 	struct tx_queue_entry *sms_msg;
 
-	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &to,
-					DBUS_TYPE_STRING, &text,
-					DBUS_TYPE_INVALID))
-		return __ofono_error_invalid_args(msg);
-
 	if (valid_phone_number_format(to) == FALSE)
-		return __ofono_error_invalid_format(msg);
+		return NULL;
 
 	msg_list = sms_text_prepare(text, 0, TRUE, &ref_offset,
 					sms->use_delivery_reports);
 
 	if (!msg_list)
-		return __ofono_error_invalid_format(msg);
+		return NULL;
 
 	set_ref_and_to(msg_list, sms->ref, ref_offset, to);
 	DBG("ref: %d, offset: %d", sms->ref, ref_offset);
@@ -826,24 +833,105 @@ static DBusMessage *sms_send_message(DBusConnection *conn, DBusMessage *msg,
 			sms->ref = sms->ref + 1;
 	}
 
-	flags = OFONO_SMS_SUBMIT_FLAG_RECORD_HISTORY;
+	if (send_flags & SMS_MSG_SEND_HISTORY)
+		flags = OFONO_SMS_SUBMIT_FLAG_RECORD_HISTORY;
 	flags |= OFONO_SMS_SUBMIT_FLAG_RETRY;
 	if (sms->use_delivery_reports)
 		flags |= OFONO_SMS_SUBMIT_FLAG_REQUEST_SR;
 
-	sms_msg = __ofono_sms_txq_submit(sms, msg_list, flags,
-						send_message_stch_cb,
-						dbus_message_ref(msg),
-						send_message_destroy);
+	sms_msg = __ofono_sms_txq_submit(sms, msg_list, flags, stch_cb,
+						priv, destroy_cb);
 
 	g_slist_foreach(msg_list, (GFunc)g_free, NULL);
 	g_slist_free(msg_list);
 
 	modem = __ofono_atom_get_modem(sms->atom);
-	__ofono_history_sms_send_pending(modem, sms_msg->msg_id, to,
-						time(NULL), text);
 
-	return NULL;
+	if (flags & OFONO_SMS_SUBMIT_FLAG_RECORD_HISTORY)
+		__ofono_history_sms_send_pending(modem, sms_msg->msg_id, to,
+							time(NULL), text);
+
+	return sms_msg;
+}
+
+/*
+ * D-Bus: Send a SMS text message
+ *
+ * @conn: D-Bus connection
+ * @msg: message data (telephone number and text)
+ * @data: SMS object to use for transmision
+ *
+ * Unwraps the arguments and sends the request to sms_msg_send()
+ */
+static DBusMessage *dbus_sms_msg_send(DBusConnection *conn, DBusMessage *msg,
+				      void *data)
+{
+	struct ofono_sms *sms = data;
+	const char *to;
+	const char *text;
+	struct tx_queue_entry *sms_msg;
+	DBusMessage *reply;
+	char *dbus_path;
+	const char *sms_path = __ofono_atom_get_path(sms->atom);
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &to,
+					DBUS_TYPE_STRING, &text,
+					DBUS_TYPE_INVALID))
+		return __ofono_error_invalid_args(msg);
+
+	/*
+	 * This is released by @ sms_msg_dbus_destroy() -- first we
+	 * allocate and then once we have the MSG ID, we re-write it.
+	 */
+	dbus_path = g_strdup_printf("%s/%08x", sms_path, 0);
+	sms_msg = sms_msg_send(sms, to, text, SMS_MSG_SEND_HISTORY,
+			       NULL,
+			       sms_msg_dbus_destroy,
+			       dbus_path);
+
+	if (sms_msg == NULL)
+		goto error_sms_msg_send;
+
+	/* Set the MSG ID in the D-Bus path now that we have it. */
+	sprintf(dbus_path, "%s/%08x", sms_path, sms_msg->msg_id & 0xffffffff);
+
+	if (!g_dbus_register_interface(ofono_dbus_get_connection(),
+					dbus_path, SMS_MSG_INTERFACE,
+					sms_msg_methods, sms_msg_signals,
+					NULL, sms_msg, NULL)) {
+		ofono_error("%s():%d: %s: Could not create %s interface",
+			    __func__, __LINE__, dbus_path, SMS_MSG_INTERFACE);
+		goto error_dbus_register_interface;
+	}
+
+	ofono_debug("%s():%d: sms %p @ %s: MSG registered",
+		    __func__, __LINE__, sms_msg, dbus_path);
+
+	reply = dbus_message_new_method_return(msg);
+
+	if (!reply)
+		goto error_dbus_new_method_return;
+
+	dbus_message_append_args(reply, DBUS_TYPE_STRING, &dbus_path,
+					DBUS_TYPE_INVALID);
+	return reply;
+
+
+error_dbus_new_method_return:
+	g_dbus_unregister_interface(ofono_dbus_get_connection(),
+					dbus_path, SMS_MSG_INTERFACE);
+error_dbus_register_interface:
+	/*
+	 * Note we don't want the destructor called, as we do it's
+	 * steps manually here when falling through. Kind of layering
+	 * violation, but it is the cleaner way as things are
+	 * currently laid out.
+	 */
+	sms_msg->destroy = NULL;
+	tx_queue_entry_destroy(sms_msg);
+error_sms_msg_send:
+	g_free(dbus_path);
+	return __ofono_error_invalid_format(msg);
 }
 
 static GDBusMethodTable sms_manager_methods[] = {
@@ -851,8 +939,7 @@ static GDBusMethodTable sms_manager_methods[] = {
 							G_DBUS_METHOD_FLAG_ASYNC },
 	{ "SetProperty",	"sv",	"",		sms_set_property,
 							G_DBUS_METHOD_FLAG_ASYNC },
-	{ "SendMessage",	"ss",	"",		sms_send_message,
-							G_DBUS_METHOD_FLAG_ASYNC },
+	{ "SendMessage",	"ss",	"",		dbus_sms_msg_send, 0 },
 	{ }
 };
 
Signature · 1 line
1.6.6.1
#9 lore raw

PATCH v5 9/17 sms: send PropertyChanged signals on state change

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

This hooks sms_msg_stch_dbus_cb() into the SMS state change callback so that a D-Bus signal will be emitted whenever an SMS Message transitions state. This allows a client to track, if desired, what is going on with the SMS Message it cares about.

---
 src/sms.c |   36 +++++++++++++++++++++++++++++++++++-
 1 files changed, 35 insertions(+), 1 deletions(-)
src/sms.c +35 -1
index 146027d..638492e 100644
@@ -855,6 +855,40 @@ struct tx_queue_entry *sms_msg_send(
 }
 
 /*
+ * Send a PropertyChange signal when the state changes
+ *
+ * In D-Bus we don't care about the initial state transition to
+ * _QUEUED, as the object path hasn't even been published yet in the
+ * bus.
+ */
+static
+void sms_msg_stch_dbus_cb(void *_dbus_path,
+			  enum ofono_sms_tx_state new_state)
+{
+	char *dbus_path = _dbus_path;
+	DBusConnection *dbus_conn = ofono_dbus_get_connection();
+	DBusMessage *dbus_signal;
+	DBusMessageIter iter;
+	const char *property = "State";
+	const char *new_state_str;
+
+	if (new_state == OFONO_SMS_TX_ST_QUEUED)
+		return;
+
+	dbus_signal = dbus_message_new_signal(
+		dbus_path, SMS_MSG_INTERFACE, "PropertyChanged");
+
+	if (!dbus_signal)
+		return;
+
+	dbus_message_iter_init_append(dbus_signal, &iter);
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
+	new_state_str = ofono_sms_tx_state_to_string(new_state);
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &new_state_str);
+	g_dbus_send_message(dbus_conn, dbus_signal);
+}
+
+/*
  * D-Bus: Send a SMS text message
  *
  * @conn: D-Bus connection
@@ -885,7 +919,7 @@ static DBusMessage *dbus_sms_msg_send(DBusConnection *conn, DBusMessage *msg,
 	 */
 	dbus_path = g_strdup_printf("%s/%08x", sms_path, 0);
 	sms_msg = sms_msg_send(sms, to, text, SMS_MSG_SEND_HISTORY,
-			       NULL,
+			       sms_msg_stch_dbus_cb,
 			       sms_msg_dbus_destroy,
 			       dbus_path);
 
Signature · 1 line
1.6.6.1
#10 lore raw

PATCH v5 10/17 sms: introduce sms_msg_cancel and its D-Bus wrapper

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

This introduces the ability to cancel a pending SMS message, accessible via an internal API and over a D-Bus wrapper.

Sending a note to the network to cancel an in-transit message is not yet implemented.

Note the test case code requires follow up commits that propagate the message's state changes over D-Bus.

---
 src/sms.c |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 55 insertions(+), 0 deletions(-)
src/sms.c +55 -0
index 638492e..40b4cf1 100644
@@ -527,6 +527,20 @@ static void __ofono_sms_tx_state_set(struct tx_queue_entry *entry,
 }
 
 
+
+static void sms_msg_cancel(struct tx_queue_entry *);
+/*
+ * Note that the D-Bus specific cleanups are taken care by the
+ * sms_msg_dbus_destroy() callback passed in dbus_sms_msg_send().
+ */
+static DBusMessage *dbus_sms_msg_cancel(
+	DBusConnection * conn, DBusMessage *msg, void *data)
+{
+	struct tx_queue_entry *sms_msg = data;
+	sms_msg_cancel(sms_msg);
+	return dbus_message_new_method_return(msg);
+}
+
 /*
  * D-Bus SMS Message interface
  *
@@ -536,6 +550,8 @@ static void __ofono_sms_tx_state_set(struct tx_queue_entry *entry,
 
 static
 GDBusMethodTable sms_msg_methods[] = {
+	{ "Cancel",		"",	"",
+	  dbus_sms_msg_cancel, 0 },
 	{ }
 };
 
@@ -581,6 +597,11 @@ static void tx_finished(const struct ofono_error *error, int mr, void *data)
 	gboolean ok = error->type == OFONO_ERROR_TYPE_NO_ERROR;
 
 	DBG("tx_finished");
+	/*
+	 * Queue is empty? Messages might have been cancelled.
+	 */
+	if (entry == NULL)
+		return;
 
 	if (ok == FALSE) {
 		if (!(entry->flags & OFONO_SMS_SUBMIT_FLAG_RETRY)) {
@@ -854,6 +875,40 @@ struct tx_queue_entry *sms_msg_send(
 	return sms_msg;
 }
 
+/**
+ * Cancel a pending SMS message
+ *
+ * @sms_msg: message to cancel
+ *
+ * This function cancels a message that is pending or being
+ * actively transmitted. Note that after this function returns, the
+ * @sms_msg handle is no longer valid.
+ *
+ * \internal
+ *
+ * There is no need to cancel the calling of tx_next() by
+ * g_timeout_add() scheduled in sms_msg_send(). The rationale behind
+ * this is that the tx_next() function is scheduled to go over the
+ * list of messages in the @sms object, so it might have been
+ * scheduled for other messages also rather than just for this one
+ * @sms_msg. By the time it gets to run, it might see the list empty
+ * or see other messages, but @sms_msg won't be there.
+ */
+static void sms_msg_cancel(struct tx_queue_entry *sms_msg)
+{
+	struct ofono_sms *sms = sms_msg->sms_mgr;
+	DBG("%s (%p)\n", __func__, sms_msg);
+
+	if (sms_msg->state == OFONO_SMS_TX_ST_QUEUED)
+		g_queue_remove(sms->txq, sms_msg);
+	else if (sms_msg->state == OFONO_SMS_TX_ST_WSR)
+		g_queue_remove(sms->tx_wsrq, sms_msg);
+
+	ofono_sms_tx_state_set(sms_msg, OFONO_SMS_TX_ST_CANCELING);
+	ofono_sms_tx_state_set(sms_msg, OFONO_SMS_TX_ST_CANCELLED);
+	tx_queue_entry_destroy(sms_msg);
+}
+
 /*
  * Send a PropertyChange signal when the state changes
  *
Signature · 1 line
1.6.6.1
#11 lore raw

PATCH v5 11/17 sms: Implement D-Bus SMS-MSG::GetProperties

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

Currently this only returns the state of the SMS message and the destination number. Note we make the @receiver field in 'struct tx_queue_entry' be always filled out in __ofono_sms_txq_submit() as now it is always needed for the properties, not only when a Status Report is requested.

---
 src/sms.c |   39 +++++++++++++++++++++++++++++++++------
 1 files changed, 33 insertions(+), 6 deletions(-)
src/sms.c +33 -6
index 40b4cf1..e648fd0 100644
@@ -526,7 +526,35 @@ static void __ofono_sms_tx_state_set(struct tx_queue_entry *entry,
 		entry->stch_cb(entry->data, state_new);
 }
 
+static DBusMessage *dbus_sms_msg_get_properties(
+	DBusConnection * conn, DBusMessage *dbus_msg, void *_sms_msg)
+{
+	struct tx_queue_entry *sms_msg = _sms_msg;
+	DBusMessage *reply;
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+	const char *str;
+
+	reply = dbus_message_new_method_return(dbus_msg);
+	if (!reply)
+		return NULL;
+
+	dbus_message_iter_init_append(reply, &iter);
 
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+					 OFONO_PROPERTIES_ARRAY_SIGNATURE,
+					 &dict);
+
+	str = ofono_sms_tx_state_to_string(sms_msg->state);
+	ofono_dbus_dict_append(&dict, "State", DBUS_TYPE_STRING, &str);
+
+	str = sms_address_to_string(&sms_msg->receiver);
+	ofono_dbus_dict_append(&dict, "To", DBUS_TYPE_STRING, &str);
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	return reply;
+}
 
 static void sms_msg_cancel(struct tx_queue_entry *);
 /*
@@ -550,6 +578,8 @@ static DBusMessage *dbus_sms_msg_cancel(
 
 static
 GDBusMethodTable sms_msg_methods[] = {
+	{ "GetProperties",	"",	"a{sv}",
+	  dbus_sms_msg_get_properties, 0 },
 	{ "Cancel",		"",	"",
 	  dbus_sms_msg_cancel, 0 },
 	{ }
@@ -1757,13 +1787,10 @@ struct tx_queue_entry *__ofono_sms_txq_submit(struct ofono_sms *sms,
 						ofono_destroy_func destroy)
 {
 	struct tx_queue_entry *entry = tx_queue_entry_new(list);
+	struct sms *head = list->data;
 
-	if (flags & OFONO_SMS_SUBMIT_FLAG_REQUEST_SR) {
-		struct sms *head = list->data;
-
-		memcpy(&entry->receiver, &head->submit.daddr,
-				sizeof(entry->receiver));
-	}
+	memcpy(&entry->receiver, &head->submit.daddr,
+		sizeof(entry->receiver));
 
 	entry->flags = flags;
 	entry->stch_cb = stch_cb;
Signature · 1 line
1.6.6.1
#12 lore raw

PATCH v5 12/17 sms: document SMS Message's D-Bus 'To' property

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

---
 doc/sms-api.txt |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)
doc/sms-api.txt +5 -0
index 2bf588f..70eb492 100644
@@ -109,3 +109,8 @@ Properties	string State
 
 			Current transmission state {queued, wsr, done,
 			canceling, cancelled, failed, expired}
+
+		string To
+
+			Destination number to which the message is
+			being sent.
Signature · 1 line
1.6.6.1
#13 lore raw

PATCH v5 13/17 sms: test code for message's D-Bus GetProperties

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

---
 test/test-sms-msg-get-properties |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)
 create mode 100755 test/test-sms-msg-get-properties
test/test-sms-msg-get-properties new file +26 -0
new file mode 100755
index 0000000..eaac7b8
@@ -0,0 +1,26 @@
+#!/usr/bin/python
+
+import sys
+import dbus
+
+if len(sys.argv) != 2:
+    print "Error: missing argument (SMS message D-Bus object name)"
+    sys.exit(1)
+
+
+bus = dbus.SystemBus()
+
+manager = dbus.Interface(bus.get_object('org.ofono', '/'),
+                         'org.ofono.Manager')
+
+properties = manager.GetProperties()
+
+path = properties["Modems"][0]
+
+manager = dbus.Interface(bus.get_object('org.ofono', path),
+                         'org.ofono.SmsManager')
+
+sms_msg = dbus.Interface(bus.get_object('org.ofono', sys.argv[1]),
+                         'org.ofono.SmsMessage')
+properties = sms_msg.GetProperties()
+print "To: %s\nState: %s\n" % (properties["To"], properties["State"])
Signature · 1 line
1.6.6.1
#14 lore raw

PATCH v5 14/17 automake: fix generation of symlinks for headers

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

When running 'make distcheck' from a vpath build directory (ie: one that is not where the source lives), the target headers in include/ofono are not generated properly due to a typo in the Makefile.am, that is using _srcdir where _buildir should be being used.

---
 Makefile.am |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
Makefile.am +1 -1
index b64ce8e..28d1e77 100644
@@ -446,7 +446,7 @@ include/ofono/version.h: include/version.h
 
 include/ofono/%.h: include/%.h
 	$(AM_V_at)$(MKDIR_P) include/ofono
-	$(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
+	$(AM_V_GEN)$(LN_S) $(abs_top_builddir)/$< $@
 
 clean-local:
 	@$(RM) -rf include/ofono
Signature · 1 line
1.6.6.1
#15 lore raw

Re: [SMS D-Bus v5 14/17] automake: fix generation of symlinks for headers

Hi Inaky,

Quoted 14 lines

When running 'make distcheck' from a vpath build directory (ie: one that is not where the source lives), the target headers in include/ofono are not generated properly due to a typo in the Makefile.am, that is using _srcdir where _buildir should be being used.

---
 Makefile.am |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
Makefile.am +0 -0
index b64ce8e..28d1e77 100644

Makefile.am include/ofono/version.h: include/version.h · line 449

Quoted 5 lines
Makefile.am +1 -1
@@ -446,7 +446,7 @@ include/ofono/version.h: include/version.h
 
 include/ofono/%.h: include/%.h
 	$(AM_V_at)$(MKDIR_P) include/ofono
-	$(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
+	$(AM_V_GEN)$(LN_S) $(abs_top_builddir)/$< $@

are we having the same problem in ConnMan. I am seeing only builddir be used for the version.h generation.

Regards

Marcel

#16 lore raw

Re: [SMS D-Bus v5 14/17] automake: fix generation of symlinks for headers

Quoted 17 lines · Marcel Holtmann

Hi Inaky,

Quoted 15 lines

When running 'make distcheck' from a vpath build directory (ie: one that is not where the source lives), the target headers in include/ofono are not generated properly due to a typo in the Makefile.am, that is using _srcdir where _buildir should be being used.

---
 Makefile.am |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
Makefile.am +0 -0
index b64ce8e..28d1e77 100644
@@ -446,7 +446,7 @@ include/ofono/version.h: include/version.h
 
Quoted 7 lines

Makefile.am include/ofono/version.h: include/version.h · line 449

Quoted 4 lines
Makefile.am +1 -1
 include/ofono/%.h: include/%.h
 	$(AM_V_at)$(MKDIR_P) include/ofono
-	$(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
+	$(AM_V_GEN)$(LN_S) $(abs_top_builddir)/$< $@

are we having the same problem in ConnMan. I am seeing only builddir be used for the version.h generation.

Sorry, not groking what do you mean. So yes, this does exactly the same thing as done for version.h, where it works pretty well.

Haven't tried connman, but it will have the same problem if you use a similar construct.

#17 lore raw

PATCH v5 15/17 sms: document variable usage in sms_msg_send()

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

---
 src/sms.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
src/sms.c +3 -0
index e648fd0..2b21e0c 100644
@@ -851,6 +851,9 @@ enum sms_msg_send_flags {
  * is created by tx_queue_entry_new() and g_queue_push_tail()
  * appends that entry to the SMS transmit queue. Then the tx_next()
  * function is scheduled to run to process the queue.
+ *
+ * @sms is the main SMS driver struct, @entry and @msg_list represent
+ * the current message being processed.
  */
 static
 struct tx_queue_entry *sms_msg_send(
Signature · 1 line
1.6.6.1
#18 lore raw

PATCH v5 16/17 sms: add test case for message cancel

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

---
 test/test-sms-msg-cancel |  173 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 173 insertions(+), 0 deletions(-)
 create mode 100755 test/test-sms-msg-cancel
test/test-sms-msg-cancel new file +173 -0
new file mode 100755
index 0000000..e9bb40f
@@ -0,0 +1,173 @@
+#!/usr/bin/python
+#
+# Sends a message and inmediately cancels it once the state moves to
+# "queued"; fails if the message doesn't move to the CANCELLED state.
+#
+# Arguments are: DEST-PHONE-NUMBER MSG-TEXT BOOLEAN
+#
+# BOOLEAN: request delivery confirmation / no
+#
+# Notes: accessing the globals result and reason using 'globals'
+#
+
+import gobject
+import sys
+import dbus
+import dbus.mainloop.glib
+
+dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+class sms_msg_cancel_test:
+        number = ""
+        text = ""
+        wsr = ""
+        target_state = ""
+
+        result = ""
+        reason = ""
+
+        sms_msg_path = ""
+
+        # FIXME
+        def __init__(self, number, text, wsr):
+                self.number = number
+                self.text = text
+                self.wsr = wsr
+                self.mainloop = gobject.MainLoop()
+
+                self.dbus = dbus.SystemBus()
+                ofono_manager = dbus.Interface(self.dbus.get_object('org.ofono', '/'),
+                                               'org.ofono.Manager')
+                path = ofono_manager.GetProperties()["Modems"][0]
+                self.sms_manager = dbus.Interface(self.dbus.get_object('org.ofono', path),
+                                                  'org.ofono.SmsManager')
+                self.sms_manager.SetProperty("UseDeliveryReports", dbus.Boolean(int(self.wsr)))
+
+                # Connect the signal *before* creating the message, otherwise we miss
+                # the transition - this also means we can't use sms_msg.connect_to_signal()
+                self.dbus.add_signal_receiver(self.property_changed, bus_name="org.ofono",
+                                              signal_name = "PropertyChanged",
+                                              path_keyword="path",
+                                              interface_keyword="interface")
+                self.result = "FAILED"
+                self.reason = "didn't see CANCELING state"
+
+        # Cancel the message and update test state
+        def msg_cancel(self):
+                print "I: %s[%s]: SMS message: canceling because " \
+                    "target state was reached" \
+                    % (self.sms_msg_path, self.target_state)
+                sms_msg = dbus.Interface(self.dbus.get_object('org.ofono', self.sms_msg_path),
+                                         'org.ofono.SmsMessage')
+                try:
+                        sms_msg.Cancel()
+                except dbus.DBusException as dbus_ex:
+                        if dbus_ex.get_dbus_name() != 'org.freedesktop.DBus.Error.UnknownMethod':
+                                pass
+                        # Object has been cancelled already--this is
+                        # why we get the D-Bus exception, so we can
+                        # consider this a win
+                        print "I: %s[%s]: SMS message: ok, D-Bus object already removed" \
+                            % (self.sms_msg_path, self.target_state)
+                        self.result = "SUCCESS"
+                        self.reason = "object dissapeared from the bus, meaning it was cancelled"
+                        self.mainloop.quit()
+                        return
+
+        # Run the actual test FIXME
+        def run(self, target_state):
+                self.target_state = target_state
+
+                self.result = "FAILED"
+                self.reason = "didn't see %s state to allow cancelling" \
+                    % target_state
+
+                print "I: [%s]: starting test" % self.target_state
+                self.sms_msg_path = self.sms_manager.SendMessage(number, text)
+                print "I: %s[%s]: SMS message: D-Bus object created" \
+                    % (self.sms_msg_path, self.target_state)
+
+                # wait for property changed signals, property_changed() will be called
+                # when there is a transition and the thing cancelled.
+                gobject.timeout_add(20000, self.timeout_fail)
+                # If the target state to cancel on is QUEUED, schedule a
+                # cancellation inmediately -- note we need to schedule it in
+                # the mainloop to ensure property_changed() signals are
+                # properly propagated.
+                if target_state == "queued" \
+                            or target_state == "canceling" \
+                            or target_state == "cancelled":
+                        gobject.idle_add(self.msg_cancel)
+                self.mainloop.run()
+                if self.result == "SUCCESS":
+                        letter = "I"
+                        result = 0
+                else:
+                        letter = "E"
+                        result = 1
+                print "%s: %s[%s]: %s: %s" % (letter, self.sms_msg_path,
+                                              self.target_state,
+                                              self.result, self.reason)
+                return result
+
+        def timeout_fail(self):
+                self.result = "FAILED"
+                self.reason = "%s (timedout)" % self.reason
+                self.mainloop.quit()
+                # Don't rearm the timeout ... doesn't really matter as we
+                # quit the mainloop.
+                return 0
+
+
+        # When the message's state (the one we created) switches to QUEUED, cancel
+        def property_changed(self, property_name, property_value,
+                             path, interface):
+                if interface != "org.ofono.SmsMessage":
+                        return
+                if self.sms_msg_path != path:
+                        return
+                if property_name != "State":
+                        return
+                print "I: %s[%s]: SMS message: transitioning to %s state" \
+                    % (self.sms_msg_path, self.target_state, property_value)
+                if property_value == "canceling":
+                        print "I: %s[%s]: SMS message: ok, saw canceling state" \
+                            % (self.sms_msg_path, self.target_state)
+                        self.result = "FAIL"
+                        self.reason = "didn't see the CANCELLED state"
+                if property_value == "cancelled":
+                        print "I: %s[%s]: SMS message: ok, saw cancelled state, quiting" \
+                            % (self.sms_msg_path, self.target_state)
+                        self.result = "SUCCESS"
+                        self.reason = "saw CANCELLED state"
+                        self.mainloop.quit()
+                # If we get to the state that is the target state for
+                # the test, cancel the message -- we need to do this
+                # after evaluating propery_value or we might enter
+                # into conflicts (as self.msg_cancel() will change
+                # self.{result,reason} if it turns out the operation
+                # is complete).
+                if self.target_state == property_value:
+                        # Cancel the message
+                        self.msg_cancel()
+
+
+# Send the message
+if len(sys.argv) == 4:
+        wsr = int(sys.argv[3])
+elif len(sys.argv) == 3:
+        wsr = 0
+else:
+        raise NameError("E: Bad number of arguments (expected NUMBER TEXT [BOOLEAN])")
+
+number = sys.argv[1]
+text = sys.argv[2]
+global test
+
+test = sms_msg_cancel_test(number, text, wsr)
+
+test.run('queued')
+test.run('wsr')
+test.run('canceling')
+test.run('cancelled')
+test.run('done')
Signature · 1 line
1.6.6.1
#19 lore raw

PATCH v5 17/17 sms: add test case for state change signals

In reply to Inaky Perez-Gonzalez

From: Inaky Perez-Gonzalez <[email protected]>

---
 test/test-sms-msg-state-change |   24 ++++++++++++++++++++++++
 1 files changed, 24 insertions(+), 0 deletions(-)
 create mode 100755 test/test-sms-msg-state-change
test/test-sms-msg-state-change new file +24 -0
new file mode 100755
index 0000000..331b722
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+
+import gobject
+
+import dbus
+import dbus.mainloop.glib
+
+def property_changed(name, value, path, interface):
+        if interface == "org.ofono.SmsMessage":
+                print "%s: name %s value %s interface %s" \
+                    % (path, name, value, interface)
+
+if __name__ == '__main__':
+        print "FIXME: this should test the whole state change transition machine"
+	dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+	bus = dbus.SystemBus()
+
+	bus.add_signal_receiver(
+                property_changed, bus_name="org.ofono",
+                signal_name = "PropertyChanged", path_keyword="path",
+                interface_keyword="interface")
+	mainloop = gobject.MainLoop()
+	mainloop.run()
Signature · 1 line
1.6.6.1