gsm: fix return value of SMS send method

The introspection data specified the Send() method to return
an array of unsigned integers, presumably the indexes of the
messages just sent.  But the code wasn't doing that, leading
to a crash when dbus-glib tried to interpret garbage on the
return.

The problem is that sms_send_auth_cb() gave async_call_done()
as the callback for sending the SMS, but that method just calls
dbus_g_method_return() with no return arguments.  dbus-glib
interprets the arguments of dbus_g_method_return() according
to the XML introspection data, and thus it was attempting to
read the non-existent argument as an 'au' and getting garbage.

Fix that by actually returning an array of message indexes from
the SMS send code, and propagate that back to the SMS dbus
code so it can return something sensible.
This commit is contained in:
Dan Williams
2012-01-18 18:08:20 -06:00
parent fc3fd7b983
commit f9a32a47ed
3 changed files with 89 additions and 10 deletions

View File

@@ -20,6 +20,7 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "mm-generic-gsm.h"
#include "mm-modem-gsm-card.h"
@@ -4725,6 +4726,23 @@ mm_generic_gsm_get_charset (MMGenericGsm *self)
/*****************************************************************************/
/* MMModemGsmSms interface */
static void
sms_send_invoke (MMCallbackInfo *info)
{
MMModemGsmSmsSendFn callback = (MMModemGsmSmsSendFn) info->callback;
callback (MM_MODEM_GSM_SMS (info->modem),
mm_callback_info_get_data (info, "indexes"),
info->error,
info->user_data);
}
static void
free_indexes (gpointer data)
{
g_array_free ((GArray *) data, TRUE);
}
static void
sms_send_done (MMAtSerialPort *port,
GString *response,
@@ -4732,6 +4750,10 @@ sms_send_done (MMAtSerialPort *port,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
const char *p;
unsigned long num;
GArray *indexes = NULL;
guint32 idx = 0;
/* If the modem has already been removed, return without
* scheduling callback */
@@ -4740,7 +4762,25 @@ sms_send_done (MMAtSerialPort *port,
if (error)
info->error = g_error_copy (error);
else {
/* If the response happens to have a ">" in it from the interactive
* handling of the CMGS command, skip it.
*/
p = strchr (response->str, '+');
if (p && *p) {
/* Check for the message index */
p = mm_strip_tag (p, "+CMGS:");
if (p && *p) {
errno = 0;
num = strtoul (p, NULL, 10);
if ((num < G_MAXUINT32) && (errno == 0))
idx = (guint32) num;
}
}
indexes = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 1);
g_array_append_val (indexes, idx);
mm_callback_info_set_data (info, "indexes", indexes, free_indexes);
}
mm_callback_info_schedule (info);
}
@@ -4751,7 +4791,7 @@ sms_send (MMModemGsmSms *modem,
const char *smsc,
guint validity,
guint class,
MMModemFn callback,
MMModemGsmSmsSendFn callback,
gpointer user_data)
{
MMCallbackInfo *info;
@@ -4760,7 +4800,10 @@ sms_send (MMModemGsmSms *modem,
char *command;
MMAtSerialPort *port;
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
info = mm_callback_info_new_full (MM_MODEM (modem),
sms_send_invoke,
G_CALLBACK (callback),
user_data);
port = mm_generic_gsm_get_best_at_port (self, &info->error);
if (!port) {

View File

@@ -133,6 +133,14 @@ sms_list_done (MMModemGsmSms *self,
/*****************************************************************************/
static void
sms_send_invoke (MMCallbackInfo *info)
{
MMModemGsmSmsSendFn callback = (MMModemGsmSmsSendFn) info->callback;
callback (MM_MODEM_GSM_SMS (info->modem), NULL, info->error, info->user_data);
}
void
mm_modem_gsm_sms_send (MMModemGsmSms *self,
const char *number,
@@ -140,7 +148,7 @@ mm_modem_gsm_sms_send (MMModemGsmSms *self,
const char *smsc,
guint validity,
guint class,
MMModemFn callback,
MMModemGsmSmsSendFn callback,
gpointer user_data)
{
g_return_if_fail (MM_IS_MODEM_GSM_SMS (self));
@@ -150,9 +158,18 @@ mm_modem_gsm_sms_send (MMModemGsmSms *self,
if (MM_MODEM_GSM_SMS_GET_INTERFACE (self)->send)
MM_MODEM_GSM_SMS_GET_INTERFACE (self)->send (self, number, text, smsc, validity, class, callback, user_data);
else
async_call_not_supported (self, callback, user_data);
else {
MMCallbackInfo *info;
info = mm_callback_info_new_full (MM_MODEM (self),
sms_send_invoke,
G_CALLBACK (callback),
user_data);
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED,
"Operation not supported");
mm_callback_info_schedule (info);
}
}
static void
@@ -575,6 +592,20 @@ impl_gsm_modem_sms_save (MMModemGsmSms *modem,
/*****************************************************************************/
static void
send_sms_call_done (MMModemGsmSms *modem,
GArray *indexes,
GError *error,
gpointer user_data)
{
DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
if (error)
dbus_g_method_return_error (context, error);
else
dbus_g_method_return (context, indexes);
}
static void
sms_send_auth_cb (MMAuthRequest *req,
GObject *owner,
@@ -625,10 +656,10 @@ sms_send_auth_cb (MMAuthRequest *req,
done:
if (error) {
async_call_done (MM_MODEM (self), error, context);
send_sms_call_done (self, NULL, error, context);
g_error_free (error);
} else
mm_modem_gsm_sms_send (self, number, text, smsc, validity, class, async_call_done, context);
mm_modem_gsm_sms_send (self, number, text, smsc, validity, class, send_sms_call_done, context);
}
static void

View File

@@ -35,6 +35,11 @@ typedef void (*MMModemGsmSmsListFn) (MMModemGsmSms *modem,
GError *error,
gpointer user_data);
typedef void (*MMModemGsmSmsSendFn) (MMModemGsmSms *modem,
GArray *indexes,
GError *error,
gpointer user_data);
struct _MMModemGsmSms {
GTypeInterface g_iface;
@@ -45,7 +50,7 @@ struct _MMModemGsmSms {
const char *smsc,
guint validity,
guint class,
MMModemFn callback,
MMModemGsmSmsSendFn callback,
gpointer user_data);
void (*get) (MMModemGsmSms *modem,
@@ -80,7 +85,7 @@ void mm_modem_gsm_sms_send (MMModemGsmSms *self,
const char *smsc,
guint validity,
guint class,
MMModemFn callback,
MMModemGsmSmsSendFn callback,
gpointer user_data);
void mm_modem_gsm_sms_get (MMModemGsmSms *self,