All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2 0/6] Add message agent interface
@ 2010-09-09  9:52 Aki Niemi
  2010-09-09  9:52 ` [PATCHv2 1/6] Add message agent interface documentation Aki Niemi
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Aki Niemi @ 2010-09-09  9:52 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 544 bytes --]

Hi All,

Here the same set with a whitespace fix and fix for a discrepancy in
the method name in documentation and in code.

Here is the diffstat:

 Makefile.am         |    3 +-
 doc/message-api.txt |   63 ++++++++
 include/dbus.h      |    1 +
 src/sms.c           |  207 +++++++++++++++++++++++---
 src/smsagent.c      |  416 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/smsagent.h      |   66 ++++++++
 test/sms-agent      |   84 +++++++++++
 7 files changed, 819 insertions(+), 21 deletions(-)

Cheers,
Aki


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCHv2 1/6] Add message agent interface documentation
  2010-09-09  9:52 [PATCHv2 0/6] Add message agent interface Aki Niemi
@ 2010-09-09  9:52 ` Aki Niemi
  2010-09-09  9:52 ` [PATCHv2 2/6] Add message agent interface definition Aki Niemi
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Aki Niemi @ 2010-09-09  9:52 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 2785 bytes --]

---
 doc/message-api.txt |   63 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 63 insertions(+), 0 deletions(-)

diff --git a/doc/message-api.txt b/doc/message-api.txt
index 693a111..e1baf7a 100644
--- a/doc/message-api.txt
+++ b/doc/message-api.txt
@@ -26,6 +26,35 @@ Methods		dict GetProperties()
 
 			Send the message in text to the number in to.
 
+		void RegisterAgent(object path, string type)
+
+			Registers an agent to handle received messages.
+
+			The object path defines the path of the agent that
+			will be called when a message is ready to be
+			dispatched.  The type parameters accepts a MIME
+			type in RFC 2045 format of the messages this agent
+			is willing to accept.  Currently supported types are:
+
+				"text/plain" - Regular text messages
+				"text/x-vcard" - vCard objects
+				"text/calendar" - vCalendar objects
+				"application/vnd.oma.push" - WAP push
+
+			Possible Errors: [service].Error.InvalidArguments
+					 [service].Error.InvalidFormat
+					 [service].Error.InUse
+
+		void UnregisterAgent(object path)
+
+			Unregisters an agent.  If no agents exist that
+			can handle an incoming message, it will be
+			silently dropped.
+
+			Possible Errors: [service].Error.InvalidArguments
+					 [service].Error.InvalidFormat
+					 [service].NotFound
+
 Signals		PropertyChanged(string name, variant value)
 
 			This signal indicates a changed value of the given
@@ -64,3 +93,37 @@ Properties	string ServiceCenterAddress
 				"ps-preferred" - Use CS if PS is unavailable
 
 			By default oFono uses "cs-preferred" setting.
+
+
+MessageAgent Hierarchy
+===============
+
+Service		unique name
+Interface	org.ofono.MessageAgent
+Object path	freely definable
+
+Methods		void HandleMessage(string message, dict info)
+
+			New incoming text SMS received.  Info has Sender
+			LocalSentTime, and SentTime information.  Sender
+			address is given in string format.  LocalSentTime
+			and SentTime are given in string form using
+			ISO8601 format.
+
+		void HandleDatagram(array{byte} message, dict info)
+
+			New incoming datagram SMS received.  Info has
+			Sender, LocalSentTime, SentTime, ContentType if known
+			or DestinationPort, and SourcePort information.  Sender
+			address is given in string format.  LocalSentTime
+			and SentTime are given in string using ISO8601 format.
+
+			ContentType is given as a MIME media type in string
+			format as defined in RFC 2045, and SourcePort and
+			DestinationPort are given as a 16bit unsigned integer.
+
+		void Release()
+
+			Agent is being released, possibly because of oFono
+			terminating, the MessageManager interface being
+			torn down or modem powering down.
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCHv2 2/6] Add message agent interface definition
  2010-09-09  9:52 [PATCHv2 0/6] Add message agent interface Aki Niemi
  2010-09-09  9:52 ` [PATCHv2 1/6] Add message agent interface documentation Aki Niemi
@ 2010-09-09  9:52 ` Aki Niemi
  2010-09-09  9:52 ` [PATCHv2 3/6] Add message agent implementation Aki Niemi
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Aki Niemi @ 2010-09-09  9:52 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 756 bytes --]

---
 include/dbus.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/dbus.h b/include/dbus.h
index 8cd214d..fb8109f 100644
--- a/include/dbus.h
+++ b/include/dbus.h
@@ -41,6 +41,7 @@ extern "C" {
 #define OFONO_CONNECTION_CONTEXT_INTERFACE "org.ofono.ConnectionContext"
 #define OFONO_CONNECTION_MANAGER_INTERFACE "org.ofono.ConnectionManager"
 #define OFONO_MESSAGE_MANAGER_INTERFACE "org.ofono.MessageManager"
+#define OFONO_MESSAGE_AGENT_INTERFACE "org.ofono.MessageAgent"
 #define OFONO_MESSAGE_WAITING_INTERFACE "org.ofono.MessageWaiting"
 #define OFONO_NETWORK_REGISTRATION_INTERFACE "org.ofono.NetworkRegistration"
 #define OFONO_NETWORK_OPERATOR_INTERFACE "org.ofono.NetworkOperator"
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCHv2 3/6] Add message agent implementation
  2010-09-09  9:52 [PATCHv2 0/6] Add message agent interface Aki Niemi
  2010-09-09  9:52 ` [PATCHv2 1/6] Add message agent interface documentation Aki Niemi
  2010-09-09  9:52 ` [PATCHv2 2/6] Add message agent interface definition Aki Niemi
@ 2010-09-09  9:52 ` Aki Niemi
  2010-09-09  9:52 ` [PATCHv2 4/6] Add message agent implementation to build Aki Niemi
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Aki Niemi @ 2010-09-09  9:52 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 13877 bytes --]

---
 src/smsagent.c |  416 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/smsagent.h |   66 +++++++++
 2 files changed, 482 insertions(+), 0 deletions(-)
 create mode 100644 src/smsagent.c
 create mode 100644 src/smsagent.h

diff --git a/src/smsagent.c b/src/smsagent.c
new file mode 100644
index 0000000..bd99fa0
--- /dev/null
+++ b/src/smsagent.c
@@ -0,0 +1,416 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <gdbus.h>
+
+#include "ofono.h"
+
+#include "common.h"
+#include "smsagent.h"
+
+enum sms_agent_port {
+	SMS_AGENT_PORT_WAP_PUSH = 2948,
+	SMS_AGENT_PORT_WAP_PUSH_S = 2949,	/* Secure push?? */
+	SMS_AGENT_PORT_VCARD = 9204,
+	SMS_AGENT_PORT_VCAL = 9205,
+	SMS_AGENT_PORT_VCARD_S = 9206,		/* vCard secure?? */
+	SMS_AGENT_PORT_VCAL_S = 9207,		/* vCal secure?? */
+};
+
+struct sms_agent {
+	char *path;
+	char *name;
+	enum sms_agent_type type;
+	guint disconnect_watch;
+	sms_agent_remove_cb remove_cb;
+	void *remove_data;
+	GSList *reqs;
+};
+
+struct sms_agent_request {
+	struct sms_agent *agent;
+	DBusMessage *msg;
+	DBusPendingCall *call;
+	sms_agent_dispatch_cb dispatch_cb;
+	void *dispatch_data;
+	ofono_destroy_func destroy;
+};
+
+static inline const char *sms_agent_string_from_port(int port)
+{
+	switch (port) {
+	case SMS_AGENT_PORT_WAP_PUSH:
+	case SMS_AGENT_PORT_WAP_PUSH_S:
+		return "application/vnd.oma.push";
+
+	case SMS_AGENT_PORT_VCARD:
+	case SMS_AGENT_PORT_VCARD_S:
+		return "text/x-vcard";
+
+	case SMS_AGENT_PORT_VCAL:
+	case SMS_AGENT_PORT_VCAL_S:
+		return "text/calendar";
+	}
+	return NULL;
+}
+
+static inline ofono_bool_t sms_agent_type_matches_port(enum sms_agent_type type,
+							int port)
+{
+	switch (type) {
+	case SMS_AGENT_TYPE_TEXT:
+		return FALSE;
+
+	case SMS_AGENT_TYPE_VCARD:
+		return port == SMS_AGENT_PORT_VCARD
+			|| port == SMS_AGENT_PORT_VCARD_S;
+
+	case SMS_AGENT_TYPE_VCAL:
+		return port == SMS_AGENT_PORT_VCAL
+			|| port == SMS_AGENT_PORT_VCAL_S;
+
+	case SMS_AGENT_TYPE_WAP_PUSH:
+		return port == SMS_AGENT_PORT_WAP_PUSH
+			|| port == SMS_AGENT_PORT_WAP_PUSH_S;
+	}
+	return FALSE;
+}
+
+
+static struct sms_agent_request *sms_agent_request_create(struct sms_agent *agent,
+						sms_agent_dispatch_cb cb,
+						void *user_data,
+						ofono_destroy_func destroy)
+{
+	struct sms_agent_request *req;
+
+	req = g_try_new0(struct sms_agent_request, 1);
+	if (!req)
+		return NULL;
+
+	req->agent = agent;
+	req->dispatch_cb = cb;
+	req->dispatch_data = user_data;
+	req->destroy = destroy;
+
+	return req;
+}
+
+static void sms_agent_request_destroy(struct sms_agent_request *req)
+{
+	if (req->msg) {
+		dbus_message_unref(req->msg);
+		req->msg = NULL;
+	}
+
+	if (req->call) {
+		dbus_pending_call_unref(req->call);
+		req->call = NULL;
+	}
+
+	if (req->destroy)
+		req->destroy(req->dispatch_data);
+
+	g_free(req);
+}
+
+static void sms_agent_request_cancel(struct sms_agent_request *req)
+{
+	if (!req->call)
+		return;
+
+	dbus_pending_call_cancel(req->call);
+
+	sms_agent_request_destroy(req);
+}
+
+static void sms_agent_send_noreply(struct sms_agent *agent, const char *method)
+{
+	DBusConnection *conn = ofono_dbus_get_connection();
+	DBusMessage *message;
+
+	message = dbus_message_new_method_call(agent->name, agent->path,
+						OFONO_MESSAGE_AGENT_INTERFACE,
+							method);
+
+	if (!message)
+		return;
+
+	dbus_message_set_no_reply(message, TRUE);
+
+	DBG("Sending: '%s' to '%s' at '%s'", method, agent->name, agent->path);
+	g_dbus_send_message(conn, message);
+}
+
+static inline void sms_agent_send_release(struct sms_agent *agent)
+{
+	sms_agent_send_noreply(agent, "Release");
+}
+
+static void sms_agent_disconnect_cb(DBusConnection *conn, void *data)
+{
+	struct sms_agent *agent = data;
+
+	ofono_debug("Agent exited without calling Unregister");
+
+	agent->disconnect_watch = 0;
+
+	if (agent->remove_cb)
+		agent->remove_cb(agent, agent->remove_data);
+}
+
+struct sms_agent *sms_agent_create(const char *path, const char *name,
+					enum sms_agent_type type,
+					sms_agent_remove_cb cb,
+					void *user_data)
+{
+	struct sms_agent *agent = g_try_new0(struct sms_agent, 1);
+	DBusConnection *conn = ofono_dbus_get_connection();
+
+	if (!agent)
+		return NULL;
+
+	agent->path = g_strdup(path);
+	agent->name = g_strdup(name);
+	agent->remove_cb = cb;
+	agent->remove_data = user_data;
+	agent->type = type;
+
+	agent->disconnect_watch = g_dbus_add_disconnect_watch(conn, name,
+							sms_agent_disconnect_cb,
+							agent, NULL);
+	return agent;
+}
+
+void sms_agent_destroy(struct sms_agent *agent)
+{
+	DBusConnection *conn = ofono_dbus_get_connection();
+
+	if (!agent)
+		return;
+
+	if (agent->disconnect_watch) {
+		sms_agent_send_release(agent);
+
+		g_dbus_remove_watch(conn, agent->disconnect_watch);
+		agent->disconnect_watch = 0;
+	}
+
+	g_slist_foreach(agent->reqs, (GFunc)sms_agent_request_cancel, NULL);
+	g_slist_free(agent->reqs);
+
+	g_free(agent->path);
+	g_free(agent->name);
+	g_free(agent);
+}
+
+ofono_bool_t sms_agent_matches(struct sms_agent *agent, const char *path,
+				const char *name)
+{
+	return (path && strcmp(agent->path, path) == 0)
+		&& (name && strcmp(agent->name, name) == 0);
+}
+
+static enum sms_agent_result sms_agent_check_error(struct sms_agent *agent,
+							DBusMessage *reply)
+{
+	enum sms_agent_result result = SMS_AGENT_RESULT_FAILED;
+	DBusError err;
+
+	dbus_error_init(&err);
+
+	if (!dbus_set_error_from_message(&err, reply))
+		return SMS_AGENT_RESULT_OK;
+
+	if (g_str_equal(err.name, DBUS_ERROR_NO_REPLY))
+		result = SMS_AGENT_RESULT_TIMEOUT;
+
+	ofono_debug("MessageAgent %s replied with error %s, %s",
+			agent->name, err.name, err.message);
+
+	dbus_error_free(&err);
+	return result;
+}
+
+static void sms_agent_dispatch_reply_cb(DBusPendingCall *call, void *data)
+{
+	struct sms_agent_request *req = data;
+	struct sms_agent *agent = req->agent;
+	sms_agent_dispatch_cb cb = req->dispatch_cb;
+	void *dispatch_data = req->dispatch_data;
+	DBusMessage *reply = dbus_pending_call_steal_reply(req->call);
+	enum sms_agent_result result;
+
+	result = sms_agent_check_error(agent, reply);
+
+	agent->reqs = g_slist_remove(agent->reqs, req);
+	sms_agent_request_destroy(req);
+
+	if (cb)
+		cb(agent, result, dispatch_data);
+
+	dbus_message_unref(reply);
+}
+
+int sms_agent_dispatch_text(struct sms_agent *agent, const char *from,
+				const char *sent_time,
+				const char *local_sent_time,
+				const char *message,
+				sms_agent_dispatch_cb cb, void *user_data,
+				ofono_destroy_func destroy)
+{
+	struct sms_agent_request *req;
+	DBusConnection *conn = ofono_dbus_get_connection();
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+
+	if (agent->type != SMS_AGENT_TYPE_TEXT)
+		return -EOPNOTSUPP;
+
+	req = sms_agent_request_create(agent, cb, user_data, destroy);
+	if (!req)
+		return -ENOMEM;
+
+	req->msg = dbus_message_new_method_call(agent->name, agent->path,
+						OFONO_MESSAGE_AGENT_INTERFACE,
+						"HandleMessage");
+	if (!req->msg) {
+		sms_agent_request_destroy(req);
+		return -ENOMEM;
+	}
+
+	dbus_message_iter_init_append(req->msg, &iter);
+
+	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &message);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+					OFONO_PROPERTIES_ARRAY_SIGNATURE,
+					&dict);
+
+	ofono_dbus_dict_append(&dict, "LocalSentTime", DBUS_TYPE_STRING,
+				&local_sent_time);
+	ofono_dbus_dict_append(&dict, "SentTime", DBUS_TYPE_STRING,
+				&sent_time);
+	ofono_dbus_dict_append(&dict, "Sender", DBUS_TYPE_STRING, &from);
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	if (!dbus_connection_send_with_reply(conn, req->msg, &req->call, -1)) {
+		ofono_error("Sending D-Bus method failed");
+		sms_agent_request_destroy(req);
+		return -EIO;
+	}
+
+	agent->reqs = g_slist_append(agent->reqs, req);
+
+	dbus_pending_call_set_notify(req->call, sms_agent_dispatch_reply_cb,
+					req, NULL);
+
+	return 0;
+}
+
+int sms_agent_dispatch_data(struct sms_agent *agent, const char *from,
+				const char *sent_time,
+				const char *local_sent_time,
+				int src_port, int dst_port,
+				const unsigned char *message,
+				unsigned int len,
+				sms_agent_dispatch_cb cb, void *user_data,
+				ofono_destroy_func destroy)
+{
+	struct sms_agent_request *req;
+	DBusConnection *conn = ofono_dbus_get_connection();
+	DBusMessageIter iter;
+	DBusMessageIter array;
+	DBusMessageIter dict;
+	const char *type;
+	dbus_uint16_t src16;
+	dbus_uint16_t dst16;
+
+	if (!sms_agent_type_matches_port(agent->type, dst_port))
+		return -EOPNOTSUPP;
+
+	req = sms_agent_request_create(agent, cb, user_data, destroy);
+	if (!req)
+		return -ENOMEM;
+
+	req->msg = dbus_message_new_method_call(agent->name, agent->path,
+						OFONO_MESSAGE_AGENT_INTERFACE,
+						"HandleDatagram");
+	if (!req->msg) {
+		sms_agent_request_destroy(req);
+		return -ENOMEM;
+	}
+
+	dbus_message_iter_init_append(req->msg, &iter);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "y", &array);
+	dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE, &message, len);
+	dbus_message_iter_close_container(&iter, &array);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+					OFONO_PROPERTIES_ARRAY_SIGNATURE,
+					&dict);
+
+	ofono_dbus_dict_append(&dict, "LocalSentTime", DBUS_TYPE_STRING,
+				&local_sent_time);
+	ofono_dbus_dict_append(&dict, "SentTime", DBUS_TYPE_STRING,
+				&sent_time);
+	ofono_dbus_dict_append(&dict, "Sender", DBUS_TYPE_STRING, &from);
+
+	src16 = src_port;
+	dst16 = dst_port;
+
+	type = sms_agent_string_from_port(dst_port);
+	if (type)
+		ofono_dbus_dict_append(&dict, "ContentType", DBUS_TYPE_STRING,
+					&type);
+	else
+		ofono_dbus_dict_append(&dict, "DestinationPort", DBUS_TYPE_UINT16,
+					&dst16);
+
+	ofono_dbus_dict_append(&dict, "SourcePort", DBUS_TYPE_UINT16, &src16);
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	if (!dbus_connection_send_with_reply(conn, req->msg, &req->call, -1)) {
+		ofono_error("Sending D-Bus method failed");
+		sms_agent_request_destroy(req);
+		return -EIO;
+	}
+
+	agent->reqs = g_slist_append(agent->reqs, req);
+
+	dbus_pending_call_set_notify(req->call, sms_agent_dispatch_reply_cb,
+					req, NULL);
+
+	return 0;
+}
diff --git a/src/smsagent.h b/src/smsagent.h
new file mode 100644
index 0000000..e9f95bc
--- /dev/null
+++ b/src/smsagent.h
@@ -0,0 +1,66 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+struct sms_agent;
+
+enum sms_agent_type {
+	SMS_AGENT_TYPE_TEXT = 0,
+	SMS_AGENT_TYPE_VCARD,
+	SMS_AGENT_TYPE_VCAL,
+	SMS_AGENT_TYPE_WAP_PUSH,
+};
+
+enum sms_agent_result {
+	SMS_AGENT_RESULT_OK = 0,
+	SMS_AGENT_RESULT_FAILED,
+	SMS_AGENT_RESULT_TIMEOUT,
+};
+
+typedef void (*sms_agent_remove_cb) (struct sms_agent *agent, void *data);
+
+typedef void (*sms_agent_dispatch_cb) (struct sms_agent *agent,
+					enum sms_agent_result result,
+					void *data);
+
+struct sms_agent *sms_agent_create(const char *path, const char *name,
+					enum sms_agent_type type,
+					sms_agent_remove_cb cb, void *data);
+
+void sms_agent_destroy(struct sms_agent *agent);
+
+ofono_bool_t sms_agent_matches(struct sms_agent *agent, const char *name,
+				const char *path);
+
+int sms_agent_dispatch_text(struct sms_agent *agent, const char *from,
+				const char *sent_time,
+				const char *local_sent_time,
+				const char *message,
+				sms_agent_dispatch_cb cb, void *user_data,
+				ofono_destroy_func destroy);
+
+int sms_agent_dispatch_data(struct sms_agent *agent, const char *from,
+				const char *sent_time,
+				const char *local_sent_time,
+				int src_port, int dst_port,
+				const unsigned char *message,
+				unsigned int len,
+				sms_agent_dispatch_cb cb, void *user_data,
+				ofono_destroy_func destroy);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCHv2 4/6] Add message agent implementation to build
  2010-09-09  9:52 [PATCHv2 0/6] Add message agent interface Aki Niemi
                   ` (2 preceding siblings ...)
  2010-09-09  9:52 ` [PATCHv2 3/6] Add message agent implementation Aki Niemi
@ 2010-09-09  9:52 ` Aki Niemi
  2010-09-09  9:52 ` [PATCHv2 5/6] Add message agent support to sms atom Aki Niemi
  2010-09-09  9:52 ` [PATCHv2 6/6] Add test message agent Aki Niemi
  5 siblings, 0 replies; 7+ messages in thread
From: Aki Niemi @ 2010-09-09  9:52 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 669 bytes --]

---
 Makefile.am |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index f31180e..fddcaad 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -282,7 +282,8 @@ src_ofonod_SOURCES = $(gdbus_sources) $(builtin_sources) \
 			src/storage.c src/cbs.c src/watch.c src/call-volume.c \
 			src/gprs.c src/idmap.h src/idmap.c \
 			src/radio-settings.c src/stkutil.h src/stkutil.c \
-			src/nettime.c src/stkagent.c src/stkagent.h
+			src/nettime.c src/stkagent.c src/stkagent.h \
+			src/smsagent.c src/smsagent.h
 
 src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ @CAPNG_LIBS@ -ldl
 
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCHv2 5/6] Add message agent support to sms atom
  2010-09-09  9:52 [PATCHv2 0/6] Add message agent interface Aki Niemi
                   ` (3 preceding siblings ...)
  2010-09-09  9:52 ` [PATCHv2 4/6] Add message agent implementation to build Aki Niemi
@ 2010-09-09  9:52 ` Aki Niemi
  2010-09-09  9:52 ` [PATCHv2 6/6] Add test message agent Aki Niemi
  5 siblings, 0 replies; 7+ messages in thread
From: Aki Niemi @ 2010-09-09  9:52 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 8467 bytes --]

---
 src/sms.c |  207 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 187 insertions(+), 20 deletions(-)

diff --git a/src/sms.c b/src/sms.c
index 461606d..7ef2d12 100644
--- a/src/sms.c
+++ b/src/sms.c
@@ -36,6 +36,7 @@
 #include "util.h"
 #include "smsutil.h"
 #include "storage.h"
+#include "smsagent.h"
 
 #define uninitialized_var(x) x = x
 
@@ -65,6 +66,7 @@ struct ofono_sms {
 	GKeyFile *settings;
 	char *imsi;
 	int bearer;
+	GSList *agents;
 	const struct ofono_sms_driver *driver;
 	void *driver_data;
 	struct ofono_atom *atom;
@@ -121,6 +123,26 @@ static int sms_bearer_from_string(const char *str)
 	return -1;
 }
 
+static ofono_bool_t sms_agent_type_from_string(const char *str,
+						enum sms_agent_type *outtype)
+{
+	if (!str)
+		return FALSE;
+
+	if (g_str_equal(str, "text/plain"))
+		*outtype = SMS_AGENT_TYPE_TEXT;
+	else if (g_str_equal(str, "text/x-vcard"))
+		*outtype = SMS_AGENT_TYPE_VCARD;
+	else if (g_str_equal(str, "text/calendar"))
+		*outtype = SMS_AGENT_TYPE_VCAL;
+	else if (g_str_equal(str, "application/vnd.oma.push"))
+		*outtype = SMS_AGENT_TYPE_WAP_PUSH;
+	else
+		return FALSE;
+
+	return TRUE;
+}
+
 static void set_bearer(struct ofono_sms *sms, int bearer)
 {
 	DBusConnection *conn = ofono_dbus_get_connection();
@@ -406,6 +428,91 @@ static DBusMessage *sms_set_property(DBusConnection *conn, DBusMessage *msg,
 	return __ofono_error_invalid_args(msg);
 }
 
+static void sms_agent_removed(struct sms_agent *agent, void *data)
+{
+	struct ofono_sms *sms = data;
+
+	sms->agents = g_slist_remove(sms->agents, agent);
+
+	sms_agent_destroy(agent);
+}
+
+static DBusMessage *sms_register_agent(DBusConnection *conn,
+					DBusMessage *msg, void *data)
+{
+	struct ofono_sms *sms = data;
+	struct sms_agent *agent;
+	GSList *l;
+	const char *path;
+	const char *name;
+	const char *typestr;
+	enum sms_agent_type type;
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+					DBUS_TYPE_STRING, &typestr,
+					DBUS_TYPE_INVALID))
+		return __ofono_error_invalid_args(msg);
+
+	if (!__ofono_dbus_valid_object_path(path))
+		return __ofono_error_invalid_format(msg);
+
+	if (!sms_agent_type_from_string(typestr, &type))
+		return __ofono_error_invalid_args(msg);
+
+	name = dbus_message_get_sender(msg);
+
+	for (l = sms->agents; l; l = l->next) {
+		struct sms_agent *old = l->data;
+
+		if (sms_agent_matches(old, path, name))
+			return __ofono_error_in_use(msg);
+	}
+
+	agent = sms_agent_create(path, name, type, sms_agent_removed, sms);
+	if (!agent)
+		return __ofono_error_failed(msg);
+
+	sms->agents = g_slist_append(sms->agents, agent);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *sms_unregister_agent(DBusConnection *conn,
+						DBusMessage *msg, void *data)
+{
+	struct ofono_sms *sms = data;
+	GSList *l;
+	const char *path;
+	const char *name;
+	int removed = 0;
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+					DBUS_TYPE_INVALID))
+		return __ofono_error_invalid_args(msg);
+
+	if (!__ofono_dbus_valid_object_path(path))
+		return __ofono_error_invalid_format(msg);
+
+	name = dbus_message_get_sender(msg);
+
+	for (l = sms->agents; l; l = l->next) {
+		struct sms_agent *agent = l->data;
+
+		if (!sms_agent_matches(agent, path, name))
+			continue;
+
+		sms->agents = g_slist_remove(sms->agents, agent);
+		sms_agent_destroy(agent);
+		removed = 1;
+		break;
+	}
+
+	if (!removed)
+		return __ofono_error_not_found(msg);
+
+	return dbus_message_new_method_return(msg);
+}
+
 /*
  * Destroy/release the contents of a 'struct tx_queue_entry'
  *
@@ -661,6 +768,8 @@ static GDBusMethodTable sms_manager_methods[] = {
 							G_DBUS_METHOD_FLAG_ASYNC },
 	{ "SendMessage",	"ss",	"",		sms_send_message,
 							G_DBUS_METHOD_FLAG_ASYNC },
+	{ "RegisterAgent",	"os",	"",		sms_register_agent },
+	{ "UnregisterAgent",	"o",	"",		sms_unregister_agent },
 	{ }
 };
 
@@ -671,12 +780,52 @@ static GDBusSignalTable sms_manager_signals[] = {
 	{ }
 };
 
-static void dispatch_app_datagram(struct ofono_sms *sms, int dst, int src,
-					unsigned char *buf, long len)
+static void agent_dispatch_cb(struct sms_agent *agent,
+				enum sms_agent_result result,
+				void *data)
 {
-	DBG("Got app datagram for dst port: %d, src port: %d",
-			dst, src);
-	DBG("Contents-Len: %ld", len);
+	struct ofono_sms *sms = data;
+
+	if (result == SMS_AGENT_RESULT_OK)
+		return;
+
+	sms->agents = g_slist_remove(sms->agents, agent);
+	sms_agent_destroy(agent);
+}
+
+static void dispatch_app_datagram(struct ofono_sms *sms, int dst, int src,
+					unsigned char *buf, long len,
+					const struct sms_address *addr,
+					const struct sms_scts *scts)
+
+{	char local_sent[128];
+	char remote_sent[128];
+	time_t ts;
+	struct tm remote;
+	struct tm local;
+	const char *local_str = local_sent;
+	const char *remote_str = remote_sent;
+	const char *sender;
+	GSList *l;
+
+	ts = sms_scts_to_time(scts, &remote);
+	localtime_r(&ts, &local);
+
+	strftime(local_sent, 127, "%Y-%m-%dT%H:%M:%S%z", &local);
+	local_sent[127] = '\0';
+
+	strftime(remote_sent, 127, "%Y-%m-%dT%H:%M:%S%z", &remote);
+	remote_sent[127] = '\0';
+
+	sender = sms_address_to_string(addr);
+
+	for (l = sms->agents; l; l = l->next) {
+		struct sms_agent *agent = l->data;
+
+		sms_agent_dispatch_data(agent, sender, remote_str, local_str,
+					src, dst, buf, len, agent_dispatch_cb,
+					sms, NULL);
+	}
 }
 
 static void dispatch_text_message(struct ofono_sms *sms,
@@ -691,12 +840,16 @@ static void dispatch_text_message(struct ofono_sms *sms,
 	DBusMessage *signal;
 	DBusMessageIter iter;
 	DBusMessageIter dict;
-	char buf[128];
+	char local_sent[128];
+	char remote_sent[128];
 	const char *signal_name;
 	time_t ts;
 	struct tm remote;
 	struct tm local;
-	const char *str = buf;
+	const char *local_str = local_sent;
+	const char *remote_str = remote_sent;
+	const char *sender;
+	GSList *l;
 
 	if (!message)
 		return;
@@ -723,26 +876,34 @@ static void dispatch_text_message(struct ofono_sms *sms,
 	ts = sms_scts_to_time(scts, &remote);
 	localtime_r(&ts, &local);
 
-	strftime(buf, 127, "%Y-%m-%dT%H:%M:%S%z", &local);
-	buf[127] = '\0';
-	ofono_dbus_dict_append(&dict, "LocalSentTime", DBUS_TYPE_STRING, &str);
+	strftime(local_sent, 127, "%Y-%m-%dT%H:%M:%S%z", &local);
+	local_sent[127] = '\0';
+	ofono_dbus_dict_append(&dict, "LocalSentTime", DBUS_TYPE_STRING, &local_str);
 
-	strftime(buf, 127, "%Y-%m-%dT%H:%M:%S%z", &remote);
-	buf[127] = '\0';
-	ofono_dbus_dict_append(&dict, "SentTime", DBUS_TYPE_STRING, &str);
+	strftime(remote_sent, 127, "%Y-%m-%dT%H:%M:%S%z", &remote);
+	remote_sent[127] = '\0';
+	ofono_dbus_dict_append(&dict, "SentTime", DBUS_TYPE_STRING, &remote_str);
 
-	str = sms_address_to_string(addr);
-	ofono_dbus_dict_append(&dict, "Sender", DBUS_TYPE_STRING, &str);
+	sender = sms_address_to_string(addr);
+	ofono_dbus_dict_append(&dict, "Sender", DBUS_TYPE_STRING, &sender);
 
 	dbus_message_iter_close_container(&iter, &dict);
 
 	g_dbus_send_message(conn, signal);
 
-	if (cls != SMS_CLASS_0) {
-		__ofono_history_sms_received(modem, sms->next_msg_id, str,
-						&remote, &local, message);
-		sms->next_msg_id += 1;
+	if (cls == SMS_CLASS_0)
+		return;
+
+	for (l = sms->agents; l; l = l->next) {
+		struct sms_agent *agent = l->data;
+
+		sms_agent_dispatch_text(agent, sender, remote_str, local_str,
+					message, agent_dispatch_cb, sms, NULL);
 	}
+
+	__ofono_history_sms_received(modem, sms->next_msg_id, sender,
+					&remote, &local, message);
+	sms->next_msg_id += 1;
 }
 
 static void sms_dispatch(struct ofono_sms *sms, GSList *sms_list)
@@ -835,7 +996,10 @@ static void sms_dispatch(struct ofono_sms *sms, GSList *sms_list)
 		if (!buf)
 			return;
 
-		dispatch_app_datagram(sms, dstport, srcport, buf, len);
+		s = sms_list->data;
+
+		dispatch_app_datagram(sms, dstport, srcport, buf, len,
+					&s->deliver.oaddr, &s->deliver.scts);
 
 		g_free(buf);
 	} else {
@@ -1157,6 +1321,9 @@ static void sms_remove(struct ofono_atom *atom)
 		sms->sr_assembly = NULL;
 	}
 
+	g_slist_foreach(sms->agents, (GFunc)sms_agent_destroy, NULL);
+	g_slist_free(sms->agents);
+
 	g_free(sms);
 }
 
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCHv2 6/6] Add test message agent
  2010-09-09  9:52 [PATCHv2 0/6] Add message agent interface Aki Niemi
                   ` (4 preceding siblings ...)
  2010-09-09  9:52 ` [PATCHv2 5/6] Add message agent support to sms atom Aki Niemi
@ 2010-09-09  9:52 ` Aki Niemi
  5 siblings, 0 replies; 7+ messages in thread
From: Aki Niemi @ 2010-09-09  9:52 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 2630 bytes --]

---
 test/sms-agent |   84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 84 insertions(+), 0 deletions(-)
 create mode 100755 test/sms-agent

diff --git a/test/sms-agent b/test/sms-agent
new file mode 100755
index 0000000..c3630fa
--- /dev/null
+++ b/test/sms-agent
@@ -0,0 +1,84 @@
+#!/usr/bin/python
+
+import gobject
+
+import sys
+import dbus
+import dbus.service
+import dbus.mainloop.glib
+
+class SmsAgent(dbus.service.Object):
+
+	def __init__(self, bus, path):
+		dbus.service.Object.__init__(self, bus, path)
+
+		print "Started agent %s at %s" % (bus, path)
+
+	@dbus.service.method("org.ofono.MessageAgent",
+				in_signature="", out_signature="")
+	def Release(self):
+		print "Release, quitting"
+		mainloop.quit()
+
+	@dbus.service.method("org.ofono.MessageAgent",
+				in_signature="sa{sv}", out_signature="")
+	def HandleTextMessage(self, message, props):
+		print "From: %s" % props["Sender"]
+		print "SentTime: %s" % props["SentTime"]
+		print "LocalSentTime: %s" % props["LocalSentTime"]
+		print "Text: %s" % message
+
+	@dbus.service.method("org.ofono.MessageAgent",
+					in_signature="aya{sv}", out_signature="")
+	def HandleDatagram(self, data, props):
+		print "From: %s" % props["Sender"]
+		try:
+			print "ContentType: %s" % props["ContentType"]
+		except KeyError:
+			print "DestinationPort: %s" % props["DestinationPort"]
+
+		print "SourcePort: %d" % props["SourcePort"]
+		print "SentTime: %s" % props["SentTime"]
+		print "LocalSentTime: %s" % props["LocalSentTime"]
+		print "Size: %d bytes" % len(data)
+
+		outstr = u''
+		for byte in data:
+			if byte > 128:
+				outstr += '?'
+			else:
+				outstr += chr(byte)
+
+		print outstr
+
+if __name__ == '__main__':
+	dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+	if len(sys.argv) < 2:
+		print "Usage: %s <media_type>" % sys.argv[0]
+		sys.exit(1)
+
+	bus = dbus.SystemBus()
+	manager = dbus.Interface(bus.get_object("org.ofono", "/"),
+						"org.ofono.Manager")
+
+	properties = manager.GetProperties()
+
+	for path in properties["Modems"]:
+		modem = dbus.Interface(bus.get_object('org.ofono', path),
+							'org.ofono.Modem')
+
+		properties = modem.GetProperties()
+
+		if "org.ofono.MessageManager" not in properties["Interfaces"]:
+			continue
+
+		sms = dbus.Interface(bus.get_object('org.ofono', path),
+					'org.ofono.MessageManager')
+
+	path = "/test/agent"
+	agent = SmsAgent(bus, path)
+	sms.RegisterAgent(path, sys.argv[1])
+
+	mainloop = gobject.MainLoop()
+	mainloop.run()
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2010-09-09  9:52 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-09  9:52 [PATCHv2 0/6] Add message agent interface Aki Niemi
2010-09-09  9:52 ` [PATCHv2 1/6] Add message agent interface documentation Aki Niemi
2010-09-09  9:52 ` [PATCHv2 2/6] Add message agent interface definition Aki Niemi
2010-09-09  9:52 ` [PATCHv2 3/6] Add message agent implementation Aki Niemi
2010-09-09  9:52 ` [PATCHv2 4/6] Add message agent implementation to build Aki Niemi
2010-09-09  9:52 ` [PATCHv2 5/6] Add message agent support to sms atom Aki Niemi
2010-09-09  9:52 ` [PATCHv2 6/6] Add test message agent Aki Niemi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.