---
 plugins/messaging-agent.c |  403 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 403 insertions(+), 0 deletions(-)
 create mode 100644 plugins/messaging-agent.c

diff --git a/plugins/messaging-agent.c b/plugins/messaging-agent.c
new file mode 100644
index 0000000..fa93fe8
--- /dev/null
+++ b/plugins/messaging-agent.c
@@ -0,0 +1,403 @@
+/*
+ *
+ *  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
+
+#include <string.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <gdbus.h>
+
+#include <ofono.h>
+#include <smsagent.h>
+
+#define MESSAGING_INTERFACE OFONO_SERVICE ".Messaging"
+#define MESSAGING_AGENT_INTERFACE OFONO_SERVICE ".MessagingAgent"
+
+struct messaging_context_data {
+       struct ofono_history_context *context;
+       GSList *agents;
+};
+
+struct messaging_agent_data {
+       struct messaging_context_data *data;
+       struct sms_agent *agent;
+};
+
+static void messaging_agent_delete(void *data)
+{
+       struct messaging_agent_data *agent_data = data;
+
+       if (!g_slist_find(agent_data->data->agents, agent_data))
+               return;
+
+       DBG("modem=%s: agent=%p",
+               ofono_modem_get_path(agent_data->data->context->modem),
+               agent_data->agent);
+
+       agent_data->data->agents = g_slist_remove(agent_data->data->agents,
+                                                       agent_data);
+       g_free(agent_data);
+}
+
+static void messaging_agents_delete(gpointer user)
+{
+       struct messaging_context_data *data = user;
+
+       DBG("modem=%s", ofono_modem_get_path(data->context->modem));
+
+       while (data->agents) {
+               struct messaging_agent_data *agent_data = data->agents->data;
+               sms_agent_free(agent_data->agent);
+       }
+}
+
+static DBusMessage *messaging_agent_register(DBusConnection *conn,
+                                               DBusMessage *msg, void *param)
+{
+       const char *agent_path;
+       const char *agent_bus = dbus_message_get_sender(msg);
+       struct messaging_context_data *data = param;
+       struct messaging_agent_data *agent_data;
+       GSList *node;
+
+       if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH,
+                       &agent_path, DBUS_TYPE_INVALID) == FALSE)
+               return __ofono_error_invalid_args(msg);
+
+       if (!__ofono_dbus_valid_object_path(agent_path))
+               return __ofono_error_invalid_format(msg);
+
+       for (node = data->agents; node; node = g_slist_next(node)) {
+
+               agent_data = node->data;
+
+               if (sms_agent_matches(agent_data->agent, agent_bus,
+                                       agent_path) == TRUE)
+                       return __ofono_error_busy(msg);
+       }
+
+       agent_data = g_try_new0(struct messaging_agent_data, 1);
+       if (agent_data == NULL)
+               return __ofono_error_failed(msg);
+
+       agent_data->data = data;
+       agent_data->agent = sms_agent_new(MESSAGING_AGENT_INTERFACE,
+                               dbus_message_get_sender(msg), agent_path);
+       if (agent_data->agent == NULL) {
+               g_free(agent_data);
+               return __ofono_error_failed(msg);
+       }
+
+       data->agents = g_slist_append(data->agents, agent_data);
+
+       DBG("modem=%s: agent=%p %s:%s:%s",
+               ofono_modem_get_path(data->context->modem), agent_data->agent,
+               dbus_message_get_sender(msg), agent_path,
+               MESSAGING_AGENT_INTERFACE);
+
+       sms_agent_set_removed_notify(agent_data->agent, messaging_agent_delete,
+                                       agent_data);
+
+       return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *messaging_agent_unregister(DBusConnection *conn,
+                                               DBusMessage *msg, void *param)
+{
+       const char *agent_path;
+       const char *agent_bus = dbus_message_get_sender(msg);
+       struct messaging_context_data *data = param;
+       GSList *node;
+
+       DBG("");
+
+       if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &agent_path,
+                               DBUS_TYPE_INVALID) == FALSE)
+               return __ofono_error_invalid_args(msg);
+
+       for (node = data->agents; node; node = g_slist_next(node)) {
+
+               struct messaging_agent_data *agent_data = node->data;
+
+               if (sms_agent_matches(agent_data->agent,
+                                       agent_bus, agent_path) == FALSE)
+                       continue;
+
+               sms_agent_free(agent_data->agent);
+               return dbus_message_new_method_return(msg);
+       }
+
+       return __ofono_error_failed(msg);
+}
+
+struct messaging_agent_dict_entry {
+       char *s;
+       char *v;
+};
+
+static GSList *messaging_agent_dict_entry_append(GSList *l, char *s, char *v)
+{
+       struct messaging_agent_dict_entry *e;
+
+       e = g_try_new0(struct messaging_agent_dict_entry, 1);
+       if (e == NULL)
+               return NULL;
+
+       e->s = g_strdup(s);
+       e->v = g_strdup(v);
+       if (e->s == NULL || e->v == NULL) {
+               g_free(e);
+               return NULL;
+       }
+
+       return g_slist_append(l, e);
+}
+
+static void messaging_agent_dict_delete(GSList *l)
+{
+       while (l) {
+               struct messaging_agent_dict_entry *e = l->data;
+
+               l = g_slist_remove(l, l->data);
+               g_free(e->s);
+               g_free(e->v);
+               g_free(e);
+       }
+}
+
+static void messaging_agent_dict_append_cb(DBusMessageIter *dict, void *param)
+{
+       GSList *node;
+
+       for (node = (GSList *)param; node; node = g_slist_next(node)) {
+
+               struct messaging_agent_dict_entry *e = node->data;
+
+               ofono_dbus_dict_append(dict, e->s, DBUS_TYPE_STRING, &e->v);
+       }
+}
+
+static void messaging_agent_sms_received(struct ofono_history_context *context,
+                                               const struct ofono_uuid *uuid,
+                                               const char *from,
+                                               const struct tm *remote,
+                                               const struct tm *local,
+                                               const char *text)
+{
+       GSList *node;
+       GSList *entries = NULL;
+       struct messaging_context_data *data = context->data;
+
+       entries = messaging_agent_dict_entry_append(entries, (char *)"UUID",
+                                       (char *)ofono_uuid_to_str(uuid));
+
+       for (node = data->agents; node; node = g_slist_next(node)) {
+               struct messaging_agent_data *agent_data = node->data;
+
+               DBG("modem=%s -> agent=%p: text=\"%s\"",
+                       ofono_modem_get_path(data->context->modem),
+                       agent_data->agent, text);
+
+               sms_agent_dispatch_datagram(agent_data->agent,
+                                       "MessageReceived",
+                                       from, remote, local,
+                                       (unsigned char *)text,
+                                       strlen(text), NULL, NULL,
+                                       messaging_agent_dict_append_cb,
+                                       (void *)entries, NULL);
+       }
+
+       messaging_agent_dict_delete(entries);
+}
+
+static void messaging_agent_sms_send_pending(
+                               struct ofono_history_context *context,
+                               const struct ofono_uuid *uuid,
+                               const char *to, time_t when,
+                               const char *text)
+{
+       GSList *node;
+       GSList *entries = NULL;
+       struct messaging_context_data *data = context->data;
+
+       entries = messaging_agent_dict_entry_append(entries, (char *)"UUID",
+                                       (char *)ofono_uuid_to_str(uuid));
+
+       for (node = data->agents; node; node = g_slist_next(node)) {
+               struct messaging_agent_data *agent_data = node->data;
+
+               DBG("modem=%s -> agent=%p: text=\"%s\"",
+                       ofono_modem_get_path(data->context->modem),
+                       agent_data->agent, text);
+
+               sms_agent_dispatch_datagram(agent_data->agent,
+                                               "MessageSendPending",
+                                               to, localtime(&when),
+                                               localtime(&when),
+                                               (unsigned char *)text,
+                                               strlen(text), NULL, NULL,
+                                               messaging_agent_dict_append_cb,
+                                               (void *)entries, NULL);
+       }
+
+       messaging_agent_dict_delete(entries);
+}
+
+#undef _
+#define _(_x) case _x: return #_x
+
+static char *messaging_agent_sms_status(enum ofono_history_sms_status s)
+{
+       switch (s) {
+               _(OFONO_HISTORY_SMS_STATUS_PENDING);
+               _(OFONO_HISTORY_SMS_STATUS_SUBMITTED);
+               _(OFONO_HISTORY_SMS_STATUS_SUBMIT_FAILED);
+               _(OFONO_HISTORY_SMS_STATUS_DELIVERED);
+               _(OFONO_HISTORY_SMS_STATUS_DELIVER_FAILED);
+       }
+       return "OFONO_HISTORY_SMS_STATUS_<UNKNOWN>";
+}
+
+static void messaging_agent_sms_send_status(
+                                       struct ofono_history_context *context,
+                                       const struct ofono_uuid *uuid,
+                                       time_t when,
+                                       enum ofono_history_sms_status s)
+{
+       GSList *node;
+       GSList *entries = NULL;
+       struct messaging_context_data *data = context->data;
+
+       entries = messaging_agent_dict_entry_append(entries, (char *)"UUID",
+                       (char *)ofono_uuid_to_str(uuid));
+       entries = messaging_agent_dict_entry_append(entries, (char *)"Status",
+                       (char *)messaging_agent_sms_status(s));
+
+       for (node = data->agents; node; node = g_slist_next(node)) {
+               struct messaging_agent_data *agent_data = node->data;
+
+               DBG("modem=%s -> agent=%p: status=%s",
+                       ofono_modem_get_path(data->context->modem),
+                       agent_data->agent,
+                       messaging_agent_sms_status(s));
+
+               sms_agent_dispatch_datagram(agent_data->agent,
+                                               "MessageSendStatus",
+                                               NULL, localtime(&when),
+                                               localtime(&when), NULL, 0,
+                                               NULL, NULL,
+                                               messaging_agent_dict_append_cb,
+                                               (void *)entries, NULL);
+       }
+
+       messaging_agent_dict_delete(entries);
+}
+
+static GDBusMethodTable messaging_agent_methods[] = {
+       { "AgentRegister",      "o", "", messaging_agent_register },
+       { "AgentUnregister",    "o", "", messaging_agent_unregister },
+       { }
+};
+
+static int messaging_agent_probe(struct ofono_history_context *context)
+{
+       if (context->data) {
+               ofono_error("modem=%s: data already exists: data=%p",
+                               ofono_modem_get_path(context->modem),
+                               context->data);
+               return -EEXIST;
+       }
+
+       context->data = g_try_new0(struct messaging_context_data, 1);
+       if (context->data == NULL)
+               return -ENOMEM;
+
+       memset(context->data, 0, sizeof(struct messaging_context_data));
+       ((struct messaging_context_data *)context->data)->context = context;
+
+       DBG("modem=%s: data=%p", ofono_modem_get_path(context->modem),
+               context->data);
+
+       if (!g_dbus_register_interface(ofono_dbus_get_connection(),
+                                       ofono_modem_get_path(context->modem),
+                                       MESSAGING_INTERFACE,
+                                       messaging_agent_methods,
+                                       NULL, NULL, context->data, NULL)) {
+               ofono_error("Can't register dbus interface %s",
+                               MESSAGING_INTERFACE);
+               return -1;
+       }
+
+       ofono_modem_add_interface(context->modem, MESSAGING_INTERFACE);
+
+       return 0;
+}
+
+static void messaging_agent_remove(struct ofono_history_context *context)
+{
+       DBG("modem=%s data=%p", ofono_modem_get_path(context->modem),
+               context->data);
+
+       messaging_agents_delete(context->data);
+
+       ofono_modem_remove_interface(context->modem, MESSAGING_INTERFACE);
+
+       if (!g_dbus_unregister_interface(ofono_dbus_get_connection(),
+               ofono_modem_get_path(context->modem),
+               MESSAGING_INTERFACE))
+               ofono_error("Can't unregister dbus interface %s",
+                               MESSAGING_INTERFACE);
+
+       g_free(context->data);
+}
+
+static struct ofono_history_driver messaging_agent_driver = {
+       .name = "Messaging Agent",
+       .probe = messaging_agent_probe,
+       .remove = messaging_agent_remove,
+       .sms_received = messaging_agent_sms_received,
+       .sms_send_pending = messaging_agent_sms_send_pending,
+       .sms_send_status = messaging_agent_sms_send_status,
+};
+
+static int messaging_agent_init()
+{
+       DBG("");
+
+       ofono_history_driver_register(&messaging_agent_driver);
+
+       return 0;
+}
+
+static void messaging_agent_exit()
+{
+       DBG("");
+
+       ofono_history_driver_unregister(&messaging_agent_driver);
+}
+
+OFONO_PLUGIN_DEFINE(messaging_agent, "Messaging Agent", VERSION,
+                       OFONO_PLUGIN_PRIORITY_DEFAULT,
+                       messaging_agent_init, messaging_agent_exit)
-- 
1.7.1

_______________________________________________
ofono mailing list
[email protected]
http://lists.ofono.org/listinfo/ofono

Reply via email to