Skip to content

Commit

Permalink
[sms] Add support for sending SMS data messages. Fixes JB#56657
Browse files Browse the repository at this point in the history
This adds a new D-Bus API call "SendDataMessage" to be used for sending
a SMS data message. This is required especially by AML but can be
utilized for other uses as well.

The given message data is defined as a byte array so pre-encoded data
is only supported. Additionally source and destination ports as well as
flags are to be defined for the SMS data message. Flag
OFONO_SMS_DATA_FLAG_DELIVERY_REPORT (0x01) determine the need for
delivery reports. Other flags may be added later on.

This also implements the filter functionality for the SMS data messages.
This can be utilized by the plugins to react to the sent SMS data
messages appropriately.
  • Loading branch information
LaakkonenJussi committed Mar 9, 2022
1 parent 6c77fa2 commit b015849
Show file tree
Hide file tree
Showing 4 changed files with 289 additions and 0 deletions.
4 changes: 4 additions & 0 deletions ofono/include/sms.h
Expand Up @@ -60,6 +60,10 @@ struct ofono_sms_driver {
ofono_sms_bearer_set_cb_t, void *data);
};

enum ofono_sms_data_flag {
OFONO_SMS_DATA_FLAG_DELIVERY_REPORT = 0x01,
};

void ofono_sms_deliver_notify(struct ofono_sms *sms, const unsigned char *pdu,
int len, int tpdu_len);
void ofono_sms_status_notify(struct ofono_sms *sms, const unsigned char *pdu,
Expand Down
8 changes: 8 additions & 0 deletions ofono/src/ofono.h
Expand Up @@ -575,6 +575,9 @@ enum sms_class;

typedef void (*sms_send_text_cb_t)(struct ofono_sms *sms,
const struct sms_address *addr, const char *text, void *data);
typedef void (*sms_send_datagram_cb_t)(struct ofono_sms *sms,
const struct sms_address *addr, int dstport, int srcport,
unsigned char *bytes, unsigned int len, int flags, void *data);

typedef void (*sms_dispatch_recv_text_cb_t)
(struct ofono_sms *sms, const struct ofono_uuid *uuid,
Expand All @@ -594,6 +597,11 @@ void __ofono_sms_filter_chain_send_text(struct sms_filter_chain *chain,
const struct sms_address *addr, const char *text,
sms_send_text_cb_t sender, ofono_destroy_func destroy,
void *data);
void __ofono_sms_filter_chain_send_datagram(struct sms_filter_chain *chain,
const struct sms_address *addr, int dstport, int srcport,
unsigned char *bytes, int len, int flags,
sms_send_datagram_cb_t sender, ofono_destroy_func destroy,
void *data);

/* Does g_free(buf) when done */
void __ofono_sms_filter_chain_recv_datagram(struct sms_filter_chain *chain,
Expand Down
171 changes: 171 additions & 0 deletions ofono/src/sms-filter.c
Expand Up @@ -85,6 +85,19 @@ struct sms_filter_chain_send_text {
struct ofono_sms_address addr;
};

struct sms_filter_chain_send_datagram {
struct sms_filter_message message;
sms_send_datagram_cb_t send;
ofono_destroy_func destroy;
void *data;
int dst_port;
int src_port;
unsigned char *bytes;
unsigned int len;
int flags;
struct ofono_sms_address addr;
};

struct sms_filter_chain_recv_text {
struct sms_filter_message message;
sms_dispatch_recv_text_cb_t default_handler;
Expand Down Expand Up @@ -445,6 +458,140 @@ static struct sms_filter_message *sms_filter_send_text_new
return &send_msg->message;
}

/* sms_filter_chain_send_datagram */

static inline struct sms_filter_chain_send_datagram
*sms_filter_chain_send_datagram_cast
(struct sms_filter_message *msg)
{
return CAST(msg, struct sms_filter_chain_send_datagram, message);
}

static gboolean sms_filter_chain_send_datagram_can_process
(const struct ofono_sms_filter *filter)
{
return filter->filter_send_datagram != NULL;
}

static void sms_datagram_set_bytes(
struct sms_filter_chain_send_datagram *msg,
const unsigned char *bytes, unsigned int len)
{
msg->bytes = g_malloc0(sizeof(unsigned char) * len);
memcpy(msg->bytes, bytes, len);
msg->len = len;
}

static void sms_filter_chain_send_datagram_process_cb
(enum ofono_sms_filter_result res,
const struct ofono_sms_address *addr,
int dst_port, int src_port,
const unsigned char *bytes,
unsigned int len, void *data)
{
struct sms_filter_chain_send_datagram *msg = data;

if (res != OFONO_SMS_FILTER_DROP) {
/* Update the message */
if (&msg->addr != addr) {
msg->addr = *addr;
}
if (msg->bytes != bytes) {
g_free(msg->bytes);
sms_datagram_set_bytes(msg, bytes, len);
}

msg->dst_port = dst_port;
msg->src_port = src_port;
}

sms_filter_message_processed(&msg->message, res);
}

static guint sms_filter_chain_send_datagram_process
(const struct ofono_sms_filter *filter,
struct sms_filter_message *msg)
{
struct sms_filter_chain_send_datagram *send_msg =
sms_filter_chain_send_datagram_cast(msg);
struct sms_filter_chain *chain = msg->chain;

return filter->filter_send_datagram(chain->modem, &send_msg->addr,
send_msg->dst_port, send_msg->src_port,
send_msg->bytes, send_msg->len,
sms_filter_chain_send_datagram_process_cb,
send_msg);
}

static void sms_filter_chain_send_datagram_passthrough
(struct sms_filter_message *msg)
{
struct sms_filter_chain_send_datagram *send_msg =
sms_filter_chain_send_datagram_cast(msg);

if (send_msg->send) {
struct sms_filter_chain *chain = msg->chain;
struct sms_address addr;

sms_filter_convert_sms_address_back(&addr, &send_msg->addr);
send_msg->send(chain->sms, &addr, send_msg->dst_port,
send_msg->src_port, send_msg->bytes,
send_msg->len, send_msg->flags,
send_msg->data);
}
}

static void sms_filter_chain_send_datagram_destroy
(struct sms_filter_message *msg)
{
struct sms_filter_chain_send_datagram *send_msg =
sms_filter_chain_send_datagram_cast(msg);

if (send_msg->destroy) {
send_msg->destroy(send_msg->data);
}
}

static void sms_filter_chain_send_datagram_free
(struct sms_filter_message *msg)
{
struct sms_filter_chain_send_datagram *send_msg =
sms_filter_chain_send_datagram_cast(msg);

g_free(send_msg->bytes);
g_free(send_msg);
}

static struct sms_filter_message *sms_filter_send_datagram_new
(struct sms_filter_chain *chain, const struct sms_address *addr,
int dst_port, int src_port, unsigned char *bytes,
unsigned int len, int flags, sms_send_datagram_cb_t send,
void *data, ofono_destroy_func destroy)
{
static const struct sms_filter_message_fn send_datagram_fn = {
.name = "outgoing SMS data message",
.can_process = sms_filter_chain_send_datagram_can_process,
.process = sms_filter_chain_send_datagram_process,
.passthrough = sms_filter_chain_send_datagram_passthrough,
.destroy = sms_filter_chain_send_datagram_destroy,
.free = sms_filter_chain_send_datagram_free
};

struct sms_filter_chain_send_datagram *send_msg =
g_new0(struct sms_filter_chain_send_datagram, 1);

sms_filter_message_init(&send_msg->message, chain, &send_datagram_fn);
sms_filter_convert_sms_address(&send_msg->addr, addr);
send_msg->send = send;
send_msg->destroy = destroy;
send_msg->data = data;
sms_datagram_set_bytes(send_msg, bytes, len);
send_msg->dst_port = dst_port;
send_msg->src_port = src_port;
send_msg->flags = flags;
return &send_msg->message;
}

/* sms_filter_chain_recv_text */

static inline struct sms_filter_chain_recv_text *
Expand Down Expand Up @@ -711,6 +858,30 @@ void __ofono_sms_filter_chain_send_text(struct sms_filter_chain *chain,
}
}

void __ofono_sms_filter_chain_send_datagram(struct sms_filter_chain *chain,
const struct sms_address *addr, int dstport,
int srcport, unsigned char *bytes, int len,
int flags, sms_send_datagram_cb_t sender,
ofono_destroy_func destroy, void *data)
{
if (chain) {
if (sms_filter_list) {
sms_filter_message_process
(sms_filter_send_datagram_new(chain, addr,
dstport, srcport, bytes, len,
flags, sender, data, destroy));
return;
}
if (sender) {
sender(chain->sms, addr, dstport, srcport, bytes, len,
flags, data);
}
}
if (destroy) {
destroy(data);
}
}

/* Does g_free(buf) when done */
void __ofono_sms_filter_chain_recv_datagram(struct sms_filter_chain *chain,
const struct ofono_uuid *uuid, int dst_port, int src_port,
Expand Down
106 changes: 106 additions & 0 deletions ofono/src/sms.c
Expand Up @@ -1043,6 +1043,60 @@ static void sms_send_message_submit(struct ofono_sms *sms,
message->pending = NULL;
}

static void sms_send_data_message_submit(struct ofono_sms *sms,
const struct sms_address *addr, int dstport,
int srcport, unsigned char *bytes, unsigned int len,
int flags, void *data)
{
struct sms_message_data *message = data;
const char *to = sms_address_to_string(addr);
GSList *msg_list = NULL;
gboolean use_16bit_ref = FALSE;
gboolean use_delivery_reports;
int err;
struct ofono_uuid uuid;
enum ofono_sms_submit_flag submit_flags;

if (bytes == NULL) {
__ofono_dbus_pending_reply(&message->pending,
__ofono_error_invalid_format(message->pending));
return;
}

use_delivery_reports = flags & OFONO_SMS_DATA_FLAG_DELIVERY_REPORT;
msg_list = sms_datagram_prepare(to, bytes, len, sms->ref,
use_16bit_ref, srcport, dstport, TRUE,
use_delivery_reports);

if (msg_list == NULL) {
__ofono_dbus_pending_reply(&message->pending,
__ofono_error_invalid_format(message->pending));
return;
}

submit_flags = OFONO_SMS_SUBMIT_FLAG_RETRY;
submit_flags |= OFONO_SMS_SUBMIT_FLAG_EXPOSE_DBUS;

if (use_delivery_reports)
submit_flags |= OFONO_SMS_SUBMIT_FLAG_REQUEST_SR;

err = __ofono_sms_txq_submit(sms, msg_list, submit_flags, &uuid,
message_queued, message->pending);

g_slist_free_full(msg_list, g_free);

if (err < 0) {
__ofono_dbus_pending_reply(&message->pending,
__ofono_error_failed(message->pending));
return;
}

/* Ownership has been transfered to the message queue */
message->pending = NULL;

DBG("SMS data sent");
}

static void sms_send_message_destroy(void *data)
{
struct sms_message_data *message = data;
Expand Down Expand Up @@ -1099,6 +1153,49 @@ static DBusMessage *sms_send_message(DBusConnection *conn, DBusMessage *msg,
return NULL;
}

static DBusMessage *sms_send_data_message(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct ofono_sms *sms = data;
const char *to;
unsigned char *bytes = NULL;
struct sms_message_data *message;
struct sms_address addr;
dbus_int32_t srcport;
dbus_int32_t dstport;
dbus_uint32_t flags;
int len;

if (!ofono_dbus_access_method_allowed(dbus_message_get_sender(msg),
OFONO_DBUS_ACCESS_INTF_MESSAGEMGR,
OFONO_DBUS_ACCESS_MESSAGEMGR_SEND_MESSAGE, NULL))
return __ofono_error_access_denied(msg);

if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &to,
DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
&bytes, &len,
DBUS_TYPE_INT32, &srcport,
DBUS_TYPE_INT32, &dstport,
DBUS_TYPE_UINT32, &flags,
DBUS_TYPE_INVALID))
return __ofono_error_invalid_args(msg);

if (valid_phone_number_format(to) == FALSE)
return __ofono_error_invalid_format(msg);

message = g_new0(struct sms_message_data, 1);
message->pending = dbus_message_ref(msg);

sms_address_from_string(&addr, to);
__ofono_sms_filter_chain_send_datagram(sms->filter_chain, &addr,
dstport, srcport, bytes, len, flags,
sms_send_data_message_submit,
sms_send_message_destroy, message);


return NULL;
}

static DBusMessage *sms_get_messages(DBusConnection *conn, DBusMessage *msg,
void *data)
{
Expand Down Expand Up @@ -1216,6 +1313,15 @@ static const GDBusMethodTable sms_manager_methods[] = {
GDBUS_ARGS({ "to", "s" }, { "text", "s" }),
GDBUS_ARGS({ "path", "o" }),
sms_send_message) },
{ GDBUS_ASYNC_METHOD("SendDataMessage",
GDBUS_ARGS(
{ "to", "s" },
{ "data", "ay" },
{ "srcport", "i"},
{ "dstport", "i"},
{ "flags", "u"}),
GDBUS_ARGS({ "path", "o" }),
sms_send_data_message) },
{ GDBUS_METHOD("GetMessages",
NULL, GDBUS_ARGS({ "messages", "a(oa{sv})" }),
sms_get_messages) },
Expand Down

0 comments on commit b015849

Please sign in to comment.