mirror of git://git.sysmocom.de/ofono
smsutil: Reflow the fuzzy matching code
Make a bit more readable
This commit is contained in:
parent
46d43a0d88
commit
c12632dfef
212
src/smsutil.c
212
src/smsutil.c
|
@ -2850,121 +2850,123 @@ static gboolean sr_st_to_delivered(enum sms_st st, gboolean *delivered)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static struct id_table_node *find_by_mr_and_mark(GHashTable *id_table,
|
||||
unsigned char mr,
|
||||
GHashTableIter *out_iter,
|
||||
unsigned char **out_id)
|
||||
{
|
||||
unsigned int offset = mr / 32;
|
||||
unsigned int bit = 1 << (mr % 32);
|
||||
gpointer key, value;
|
||||
struct id_table_node *node;
|
||||
|
||||
g_hash_table_iter_init(out_iter, id_table);
|
||||
while (g_hash_table_iter_next(out_iter, &key, &value)) {
|
||||
node = value;
|
||||
|
||||
/* Address and MR matched */
|
||||
if (node->mrs[offset] & bit) {
|
||||
node->mrs[offset] ^= bit;
|
||||
*out_id = key;
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Key (receiver address) does not exist in assembly. Some networks can change
|
||||
* address to international format, although address is sent in the national
|
||||
* format. Handle also change from national to international format.
|
||||
* Notify these special cases by comparing only last six digits of the assembly
|
||||
* addresses and received address. If address contains less than six digits,
|
||||
* compare only existing digits.
|
||||
*/
|
||||
static struct id_table_node *fuzzy_lookup(struct status_report_assembly *assy,
|
||||
const struct sms *sr,
|
||||
const char **out_addr,
|
||||
GHashTableIter *out_iter,
|
||||
unsigned char **out_msgid)
|
||||
{
|
||||
GHashTableIter iter_addr;
|
||||
gpointer key, value;
|
||||
const char *r_addr;
|
||||
|
||||
r_addr = sms_address_to_string(&sr->status_report.raddr);
|
||||
g_hash_table_iter_init(&iter_addr, assy->assembly_table);
|
||||
|
||||
while (g_hash_table_iter_next(&iter_addr, &key, &value)) {
|
||||
const char *s_addr = key;
|
||||
GHashTable *id_table = value;
|
||||
unsigned int len, r_len, s_len;
|
||||
unsigned int i;
|
||||
struct id_table_node *node;
|
||||
|
||||
if (r_addr[0] == '+' && s_addr[0] == '+')
|
||||
continue;
|
||||
|
||||
if (r_addr[0] != '+' && s_addr[0] != '+')
|
||||
continue;
|
||||
|
||||
r_len = strlen(r_addr);
|
||||
s_len = strlen(s_addr);
|
||||
|
||||
len = MIN(6, MIN(r_len, s_len));
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
if (s_addr[s_len - i - 1] != r_addr[r_len - i - 1])
|
||||
break;
|
||||
|
||||
/* Not all digits matched. */
|
||||
if (i < len)
|
||||
continue;
|
||||
|
||||
/* Address matched. Check message reference. */
|
||||
node = find_by_mr_and_mark(id_table, sr->status_report.mr,
|
||||
out_iter, out_msgid);
|
||||
if (node != NULL) {
|
||||
*out_addr = s_addr;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean status_report_assembly_report(struct status_report_assembly *assembly,
|
||||
const struct sms *status_report,
|
||||
const struct sms *sr,
|
||||
unsigned char *out_msgid,
|
||||
gboolean *out_delivered)
|
||||
{
|
||||
unsigned int offset = status_report->status_report.mr / 32;
|
||||
unsigned int bit = 1 << (status_report->status_report.mr % 32);
|
||||
struct id_table_node *node = NULL;
|
||||
const char *r_addr, *s_addr;
|
||||
struct sms_address addr;
|
||||
const char *straddr;
|
||||
GHashTable *id_table;
|
||||
gpointer key, value;
|
||||
GHashTableIter iter;
|
||||
struct sms_address addr;
|
||||
struct id_table_node *node;
|
||||
gboolean delivered;
|
||||
GHashTableIter iter_addr, iter;
|
||||
gboolean pending;
|
||||
int i;
|
||||
unsigned char *msgid;
|
||||
unsigned int len, r_len, s_len;
|
||||
int i;
|
||||
|
||||
/* We ignore temporary or tempfinal status reports */
|
||||
if (sr_st_to_delivered(status_report->status_report.st,
|
||||
&delivered) == FALSE)
|
||||
if (sr_st_to_delivered(sr->status_report.st, &delivered) == FALSE)
|
||||
return FALSE;
|
||||
|
||||
r_addr = sms_address_to_string(&status_report->status_report.raddr);
|
||||
id_table = g_hash_table_lookup(assembly->assembly_table, r_addr);
|
||||
straddr = sms_address_to_string(&sr->status_report.raddr);
|
||||
id_table = g_hash_table_lookup(assembly->assembly_table, straddr);
|
||||
|
||||
/* key (receiver address) exists in assembly */
|
||||
if (id_table != NULL) {
|
||||
|
||||
/* Found an identical address from assembly. */
|
||||
s_addr = r_addr;
|
||||
|
||||
g_hash_table_iter_init(&iter, id_table);
|
||||
while (g_hash_table_iter_next(&iter, &key, &value)) {
|
||||
node = value;
|
||||
|
||||
if (node->mrs[offset] & bit)
|
||||
break;
|
||||
|
||||
node = NULL;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Key (receiver address) does not exist in assembly.
|
||||
* Some networks can change address to international format,
|
||||
* although address is sent in the national format.
|
||||
* Handle also change from national to international format.
|
||||
* So notify these special cases by comparing only
|
||||
* last six digits of the assembly addresses and received address.
|
||||
* If address contains less than six digits,
|
||||
* compare only existing digits.
|
||||
*/
|
||||
else {
|
||||
g_hash_table_iter_init(&iter_addr, assembly->assembly_table);
|
||||
|
||||
/*
|
||||
* Go through all addresses using 'fuzzy' address-comparation.
|
||||
* Each address can relate to 1-n msg_ids.
|
||||
*/
|
||||
while (g_hash_table_iter_next(&iter_addr, (gpointer) &s_addr,
|
||||
(gpointer) &id_table)) {
|
||||
|
||||
/* Notify international <-> national conversions */
|
||||
if (((r_addr[0] == '+') && (s_addr[0] != '+')) ||
|
||||
((r_addr[0] != '+') && (s_addr[0] == '+'))) {
|
||||
|
||||
r_len = strlen(r_addr);
|
||||
s_len = strlen(s_addr);
|
||||
|
||||
len = MIN(6, MIN(r_len, s_len));
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (s_addr[s_len - i - 1] !=
|
||||
r_addr[r_len - i - 1])
|
||||
break;
|
||||
}
|
||||
|
||||
/* Not all digits matched. */
|
||||
if (i < len)
|
||||
continue;
|
||||
}
|
||||
/* No conversions */
|
||||
else
|
||||
continue;
|
||||
|
||||
/* Address matched. Check message reference. */
|
||||
g_hash_table_iter_init(&iter, id_table);
|
||||
while (g_hash_table_iter_next(&iter, &key, &value)) {
|
||||
node = value;
|
||||
|
||||
/* Address and MR matched */
|
||||
if (node->mrs[offset] & bit)
|
||||
break;
|
||||
|
||||
node = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Received address with MR matched with one
|
||||
* of the stored addresses and MR, so no need
|
||||
* to continue searching.
|
||||
*/
|
||||
if (node)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (id_table != NULL)
|
||||
node = find_by_mr_and_mark(id_table, sr->status_report.mr,
|
||||
&iter, &msgid);
|
||||
else
|
||||
node = fuzzy_lookup(assembly, sr, &straddr, &iter, &msgid);
|
||||
|
||||
/* Unable to find a message reference belonging to this address */
|
||||
if (node == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Mr belongs to this node. */
|
||||
node->mrs[offset] ^= bit;
|
||||
|
||||
node->deliverable = node->deliverable && delivered;
|
||||
|
||||
/* If we haven't sent the entire message yet, wait until sent */
|
||||
|
@ -2980,9 +2982,7 @@ gboolean status_report_assembly_report(struct status_report_assembly *assembly,
|
|||
}
|
||||
}
|
||||
|
||||
msgid = (unsigned char *) key;
|
||||
|
||||
sms_address_from_string(&addr, s_addr);
|
||||
sms_address_from_string(&addr, straddr);
|
||||
|
||||
if (pending == TRUE && node->deliverable == TRUE) {
|
||||
/*
|
||||
|
@ -2990,8 +2990,7 @@ gboolean status_report_assembly_report(struct status_report_assembly *assembly,
|
|||
* reports completed. Update backup file.
|
||||
*/
|
||||
sr_assembly_add_fragment_backup(assembly->imsi, node,
|
||||
&addr,
|
||||
msgid);
|
||||
&addr, msgid);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -3002,15 +3001,12 @@ gboolean status_report_assembly_report(struct status_report_assembly *assembly,
|
|||
if (out_msgid)
|
||||
memcpy(out_msgid, msgid, SMS_MSGID_LEN);
|
||||
|
||||
sr_assembly_remove_fragment_backup(assembly->imsi,
|
||||
&addr,
|
||||
msgid);
|
||||
|
||||
sr_assembly_remove_fragment_backup(assembly->imsi, &addr, msgid);
|
||||
id_table = g_hash_table_iter_get_hash_table(&iter);
|
||||
g_hash_table_iter_remove(&iter);
|
||||
|
||||
if (g_hash_table_size(id_table) == 0)
|
||||
g_hash_table_remove(assembly->assembly_table,
|
||||
s_addr);
|
||||
g_hash_table_remove(assembly->assembly_table, straddr);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue