Teach USSD to recognise password change strings.

This is slightly hacky, part of ussd.c responsible for registering services
is duplicated and parse_ss_control_string is modified to accept a fourth
SI fragment in the input string.
This commit is contained in:
Andrzej Zaborowski 2009-06-18 06:04:23 +02:00 committed by Denis Kenzior
parent 9156607bc9
commit f93376229a
6 changed files with 159 additions and 11 deletions

View File

@ -465,7 +465,7 @@ const char *ss_control_type_to_string(enum ss_control_type type)
gboolean parse_ss_control_string(char *str, int *ss_type,
char **sc, char **sia,
char **sib, char **sic,
char **dn)
char **sid, char **dn)
{
int len = strlen(str);
int cur = 0;
@ -533,6 +533,7 @@ gboolean parse_ss_control_string(char *str, int *ss_type,
NEXT_FIELD(c, *sia);
NEXT_FIELD(c, *sib);
NEXT_FIELD(c, *sic);
NEXT_FIELD(c, *sid);
if (*c == '\0')
ret = TRUE;

View File

@ -192,7 +192,7 @@ gboolean valid_ussd_string(const char *str);
gboolean parse_ss_control_string(char *str, int *ss_type,
char **sc, char **sia,
char **sib, char **sic,
char **dn);
char **sid, char **dn);
const char *ss_control_type_to_string(enum ss_control_type type);

View File

@ -28,6 +28,7 @@ struct ofono_modem {
void *userdata;
GSList *ss_control_list;
GSList *ss_passwd_list;
struct ofono_modem_data *modem_info;
struct network_registration_data *network_registration;

View File

@ -165,22 +165,148 @@ void ss_control_unregister(struct ofono_modem *modem, const char *str,
l->data);
}
struct ss_passwd_entry {
char *service;
ss_passwd_cb_t cb;
};
static struct ss_passwd_entry *ss_passwd_entry_create(const char *service,
ss_passwd_cb_t cb)
{
struct ss_passwd_entry *r;
r = g_try_new0(struct ss_passwd_entry, 1);
if (!r)
return r;
r->service = g_strdup(service);
r->cb = cb;
return r;
}
static void ss_passwd_entry_destroy(struct ss_passwd_entry *ca)
{
g_free(ca->service);
g_free(ca);
}
static gint ss_passwd_entry_compare(gconstpointer a, gconstpointer b)
{
const struct ss_passwd_entry *ca = a;
const struct ss_passwd_entry *cb = b;
int ret;
ret = strcmp(ca->service, cb->service);
if (ret)
return ret;
if (ca->cb < cb->cb)
return -1;
if (ca->cb > cb->cb)
return 1;
return 0;
}
static gint ss_passwd_entry_find_by_service(gconstpointer a, gconstpointer b)
{
const struct ss_passwd_entry *ca = a;
return strcmp(ca->service, b);
}
gboolean ss_passwd_register(struct ofono_modem *modem, const char *str,
ss_passwd_cb_t cb)
{
struct ss_passwd_entry *entry;
if (!modem)
return FALSE;
entry = ss_passwd_entry_create(str, cb);
if (!entry)
return FALSE;
modem->ss_passwd_list = g_slist_append(modem->ss_passwd_list, entry);
return TRUE;
}
void ss_passwd_unregister(struct ofono_modem *modem, const char *str,
ss_passwd_cb_t cb)
{
const struct ss_passwd_entry entry = { (char *)str, cb };
GSList *l;
if (!modem)
return;
l = g_slist_find_custom(modem->ss_passwd_list, &entry,
ss_passwd_entry_compare);
if (!l)
return;
ss_passwd_entry_destroy(l->data);
modem->ss_passwd_list = g_slist_remove(modem->ss_passwd_list,
l->data);
}
static gboolean recognized_passwd_change_string(struct ofono_modem *modem,
int type, char *sc,
char *sia, char *sib,
char *sic, char *sid,
char *dn, DBusMessage *msg)
{
GSList *l = modem->ss_passwd_list;
switch (type) {
case SS_CONTROL_TYPE_ACTIVATION:
case SS_CONTROL_TYPE_REGISTRATION:
break;
default:
return FALSE;
}
if (strcmp(sc, "03") || strlen(dn) || strcmp(sic, sid))
return FALSE;
while ((l = g_slist_find_custom(l, sia,
ss_passwd_entry_find_by_service)) != NULL) {
struct ss_passwd_entry *entry = l->data;
if (entry->cb(modem, sia, sib, sic, msg))
return TRUE;
l = l->next;
}
return FALSE;
}
static gboolean recognized_control_string(struct ofono_modem *modem,
const char *ss_str,
DBusMessage *msg)
{
char *str = g_strdup(ss_str);
char *sc, *sia, *sib, *sic, *dn;
char *sc, *sia, *sib, *sic, *sid, *dn;
int type;
gboolean ret = FALSE;
ofono_debug("parsing control string");
if (parse_ss_control_string(str, &type, &sc, &sia, &sib, &sic, &dn)) {
if (parse_ss_control_string(str, &type, &sc,
&sia, &sib, &sic, &sid, &dn)) {
GSList *l = modem->ss_control_list;
ofono_debug("Got parse result: %d, %s, %s, %s, %s, %s",
type, sc, sia, sib, sic, dn);
ofono_debug("Got parse result: %d, %s, %s, %s, %s, %s, %s",
type, sc, sia, sib, sic, sid, dn);
while ((l = g_slist_find_custom(l, sc,
ss_control_entry_find_by_service)) != NULL) {
@ -193,6 +319,13 @@ static gboolean recognized_control_string(struct ofono_modem *modem,
l = l->next;
}
/* A password change string needs to be treated separately
* because it uses a fourth SI and is thus not a valid
* control string. */
if (recognized_passwd_change_string(modem, type, sc,
sia, sib, sic, sid, dn, msg))
goto out;
}
/* TODO: Handle all strings that control voice calls */
@ -205,9 +338,6 @@ static gboolean recognized_control_string(struct ofono_modem *modem,
* by SEND and are not valid USSD requests.
*/
/* TODO: Handle Password registration according to 22.030 Section 6.5.4
*/
out:
g_free(str);

View File

@ -26,8 +26,18 @@ typedef gboolean (*ss_control_cb_t)(struct ofono_modem *modem,
const char *sic, const char *dn,
DBusMessage *msg);
typedef gboolean (*ss_passwd_cb_t)(struct ofono_modem *modem, const char *sc,
const char *old, const char *new,
DBusMessage *msg);
gboolean ss_control_register(struct ofono_modem *modem, const char *str,
ss_control_cb_t cb);
void ss_control_unregister(struct ofono_modem *modem, const char *str,
ss_control_cb_t cb);
gboolean ss_passwd_register(struct ofono_modem *modem, const char *str,
ss_passwd_cb_t cb);
void ss_passwd_unregister(struct ofono_modem *modem, const char *str,
ss_passwd_cb_t cb);

View File

@ -57,6 +57,7 @@ static void test_invalid()
char *sia;
char *sib;
char *sic;
char *sid;
char *dn;
int type;
@ -71,7 +72,9 @@ static void test_invalid()
str = strdup(invalid_strings[i]);
ret = parse_ss_control_string(str, &type, &sc,
&sia, &sib, &sic, &dn);
&sia, &sib, &sic, &sid, &dn);
if (strlen(sid))
ret = FALSE;
g_assert(ret == FALSE);
@ -105,6 +108,7 @@ static void test_valid()
char *sia;
char *sib;
char *sic;
char *sid;
char *dn;
int type;
gboolean ret;
@ -119,7 +123,9 @@ static void test_valid()
str = strdup(valid_strings[i]);
ret = parse_ss_control_string(str, &type, &sc,
&sia, &sib, &sic, &dn);
&sia, &sib, &sic, &sid, &dn);
if (strlen(sid))
ret = FALSE;
g_assert(ret == TRUE);