sms: Implement text and datagram watch

Allow setting a watch for incoming text and datagram messages on the
sms atom.
This commit is contained in:
Aki Niemi 2010-10-01 17:24:28 +03:00
parent 297b14ca8b
commit 5a85a57cc3
2 changed files with 171 additions and 17 deletions

View File

@ -229,12 +229,37 @@ enum ofono_sms_submit_flag {
};
typedef void (*ofono_sms_txq_submit_cb_t)(gboolean ok, void *data);
typedef void (*ofono_sms_text_notify_cb_t)(const char *from,
const struct tm *remote,
const struct tm *local,
const char *text,
void *data);
typedef void (*ofono_sms_datagram_notify_cb_t)(const char *from,
const struct tm *remote,
const struct tm *local,
int dst, int src,
const unsigned char *buffer,
unsigned int len,
void *data);
int __ofono_sms_txq_submit(struct ofono_sms *sms, GSList *list,
unsigned int flags, struct ofono_uuid *uuid,
ofono_sms_txq_submit_cb_t cb,
void *data, ofono_destroy_func destroy);
unsigned int __ofono_sms_text_watch_add(struct ofono_sms *sms,
ofono_sms_text_notify_cb_t cb,
void *data, ofono_destroy_func destroy);
gboolean __ofono_sms_text_watch_remove(struct ofono_sms *sms,
unsigned int id);
unsigned int __ofono_sms_datagram_watch_add(struct ofono_sms *sms,
ofono_sms_datagram_notify_cb_t cb,
int dst, int src, void *data,
ofono_destroy_func destroy);
gboolean __ofono_sms_datagram_watch_remove(struct ofono_sms *sms,
unsigned int id);
#include <ofono/sim.h>
#include <ofono/stk.h>

163
src/sms.c
View File

@ -62,6 +62,12 @@ struct message {
enum message_state state;
};
struct sms_handler {
struct ofono_watchlist_item item;
int dst;
int src;
};
struct ofono_sms {
int flags;
DBusMessage *pending;
@ -82,6 +88,8 @@ struct ofono_sms {
ofono_bool_t use_delivery_reports;
struct status_report_assembly *sr_assembly;
GHashTable *messages;
struct ofono_watchlist *text_handlers;
struct ofono_watchlist *datagram_handlers;
};
struct pending_pdu {
@ -108,6 +116,11 @@ static gboolean uuid_equal(gconstpointer v1, gconstpointer v2)
return memcmp(v1, v2, OFONO_SHA1_UUID_LEN) == 0;
}
static gboolean port_equal(int received, int expected)
{
return expected == -1 || received == expected;
}
static guint uuid_hash(gconstpointer v)
{
const struct ofono_uuid *uuid = v;
@ -170,6 +183,77 @@ static void append_message_properties(struct message *m, DBusMessageIter *dict)
ofono_dbus_dict_append(dict, "State", DBUS_TYPE_STRING, &state);
}
static unsigned int add_sms_handler(struct ofono_watchlist *watchlist,
int dst, int src, void *notify,
void *data, ofono_destroy_func destroy)
{
struct sms_handler *handler;
if (!notify)
return 0;
handler = g_try_new0(struct sms_handler, 1);
if (!handler)
return 0;
handler->dst = dst;
handler->src = src;
handler->item.notify = notify;
handler->item.notify_data = data;
handler->item.destroy = destroy;
return __ofono_watchlist_add_item(watchlist,
(struct ofono_watchlist_item *)handler);
}
unsigned int __ofono_sms_text_watch_add(struct ofono_sms *sms,
ofono_sms_text_notify_cb_t cb,
void *data, ofono_destroy_func destroy)
{
if (!sms)
return 0;
DBG("%p", sms);
return add_sms_handler(sms->text_handlers, -1, -1, cb, data, destroy);
}
gboolean __ofono_sms_text_watch_remove(struct ofono_sms *sms,
unsigned int id)
{
if (!sms)
return FALSE;
DBG("%p", sms);
return __ofono_watchlist_remove_item(sms->text_handlers, id);
}
unsigned int __ofono_sms_datagram_watch_add(struct ofono_sms *sms,
ofono_sms_datagram_notify_cb_t cb,
int dst, int src, void *data,
ofono_destroy_func destroy)
{
if (!sms)
return 0;
DBG("%p: dst %d, src %d", sms, dst, src);
return add_sms_handler(sms->datagram_handlers, dst, src, cb, data,
destroy);
}
gboolean __ofono_sms_datagram_watch_remove(struct ofono_sms *sms,
unsigned int id)
{
if (!sms)
return FALSE;
DBG("%p", sms);
return __ofono_watchlist_remove_item(sms->datagram_handlers, id);
}
static DBusMessage *message_get_properties(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@ -1064,12 +1148,35 @@ static gboolean compute_incoming_msgid(GSList *sms_list,
return TRUE;
}
static void dispatch_app_datagram(struct ofono_sms *sms, int dst, int src,
unsigned char *buf, long len)
static void dispatch_app_datagram(struct ofono_sms *sms,
const struct ofono_uuid *uuid,
int dst, int src,
unsigned char *buf, unsigned len,
const struct sms_address *addr,
const struct sms_scts *scts)
{
DBG("Got app datagram for dst port: %d, src port: %d",
dst, src);
DBG("Contents-Len: %ld", len);
const char *sender = sms_address_to_string(addr);
time_t ts;
struct tm remote;
struct tm local;
ofono_sms_datagram_notify_cb_t notify;
struct sms_handler *h;
GSList *l;
ts = sms_scts_to_time(scts, &remote);
localtime_r(&ts, &local);
for (l = sms->datagram_handlers->items; l; l = l->next) {
h = l->data;
notify = h->item.notify;
if (!port_equal(dst, h->dst) || !port_equal(src, h->src))
continue;
notify(sender, &remote, &local, dst, src, buf, len,
h->item.notify_data);
}
}
static void dispatch_text_message(struct ofono_sms *sms,
@ -1091,6 +1198,9 @@ static void dispatch_text_message(struct ofono_sms *sms,
struct tm remote;
struct tm local;
const char *str = buf;
ofono_sms_text_notify_cb_t notify;
struct sms_handler *h;
GSList *l;
if (!message)
return;
@ -1132,15 +1242,25 @@ static void dispatch_text_message(struct ofono_sms *sms,
g_dbus_send_message(conn, signal);
if (cls != SMS_CLASS_0)
__ofono_history_sms_received(modem, uuid, str,
&remote, &local, message);
if (cls == SMS_CLASS_0)
return;
for (l = sms->text_handlers->items; l; l = l->next) {
h = l->data;
notify = h->item.notify;
notify(str, &remote, &local, message, h->item.notify_data);
}
__ofono_history_sms_received(modem, uuid, str, &remote, &local,
message);
}
static void sms_dispatch(struct ofono_sms *sms, GSList *sms_list)
{
GSList *l;
const struct sms *s;
struct ofono_uuid uuid;
enum sms_charset uninitialized_var(old_charset);
enum sms_class cls;
int srcport = -1;
@ -1214,6 +1334,11 @@ static void sms_dispatch(struct ofono_sms *sms, GSList *sms_list)
}
}
if (!compute_incoming_msgid(sms_list, &uuid))
return;
s = sms_list->data;
/* Handle datagram */
if (old_charset == SMS_CHARSET_8BIT) {
unsigned char *buf;
@ -1230,23 +1355,18 @@ static void sms_dispatch(struct ofono_sms *sms, GSList *sms_list)
if (!buf)
return;
dispatch_app_datagram(sms, dstport, srcport, buf, len);
dispatch_app_datagram(sms, &uuid, dstport, srcport, buf, len,
&s->deliver.oaddr, &s->deliver.scts);
g_free(buf);
} else {
struct ofono_uuid uuid;
char *message = sms_decode_text(sms_list);
if (!message)
return;
if (compute_incoming_msgid(sms_list, &uuid)) {
s = sms_list->data;
dispatch_text_message(sms, &uuid, message, cls,
&s->deliver.oaddr,
&s->deliver.scts);
}
dispatch_text_message(sms, &uuid, message, cls,
&s->deliver.oaddr, &s->deliver.scts);
g_free(message);
}
@ -1527,6 +1647,12 @@ static void sms_unregister(struct ofono_atom *atom)
g_hash_table_destroy(sms->messages);
sms->messages = NULL;
}
__ofono_watchlist_free(sms->text_handlers);
sms->text_handlers = NULL;
__ofono_watchlist_free(sms->datagram_handlers);
sms->datagram_handlers = NULL;
}
static void sms_remove(struct ofono_atom *atom)
@ -1741,6 +1867,9 @@ void ofono_sms_register(struct ofono_sms *sms)
sms->driver->bearer_set(sms, sms->bearer,
bearer_init_callback, sms);
sms->text_handlers = __ofono_watchlist_new(g_free);
sms->datagram_handlers = __ofono_watchlist_new(g_free);
__ofono_atom_register(sms->atom, sms_unregister);
}