smsutil: add fuzzy address check for status report

This commit is contained in:
Petteri Tikander 2010-09-21 20:12:04 +03:00 committed by Denis Kenzior
parent 7596ecfbf6
commit 6c1ec61603
1 changed files with 87 additions and 16 deletions

View File

@ -2858,35 +2858,104 @@ gboolean status_report_assembly_report(struct status_report_assembly *assembly,
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 *straddr;
const char *r_addr, *s_addr;
struct sms_address addr;
GHashTable *id_table;
gpointer key, value;
gboolean delivered;
GHashTableIter iter;
GHashTableIter iter_addr, iter;
gboolean pending;
int i;
unsigned char *msgid;
unsigned int len, r_len, s_len;
/* We ignore temporary or tempfinal status reports */
if (sr_st_to_delivered(status_report->status_report.st,
&delivered) == FALSE)
return FALSE;
straddr = sms_address_to_string(&status_report->status_report.raddr);
id_table = g_hash_table_lookup(assembly->assembly_table, straddr);
r_addr = sms_address_to_string(&status_report->status_report.raddr);
id_table = g_hash_table_lookup(assembly->assembly_table, r_addr);
/* key (receiver address) does not exist in assembly */
if (id_table == NULL)
return FALSE;
/* key (receiver address) exists in assembly */
if (id_table != NULL) {
g_hash_table_iter_init(&iter, id_table);
while (g_hash_table_iter_next(&iter, &key, &value)) {
node = value;
/* Found an identical address from assembly. */
s_addr = r_addr;
if (node->mrs[offset] & bit)
break;
g_hash_table_iter_init(&iter, id_table);
while (g_hash_table_iter_next(&iter, &key, &value)) {
node = value;
node = NULL;
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;
}
}
/* Unable to find a message reference belonging to this address */
@ -2913,13 +2982,15 @@ gboolean status_report_assembly_report(struct status_report_assembly *assembly,
msgid = (unsigned char *) key;
sms_address_from_string(&addr, s_addr);
if (pending == TRUE && node->deliverable == TRUE) {
/*
* More status reports expected, and already received
* reports completed. Update backup file.
*/
sr_assembly_add_fragment_backup(assembly->imsi, node,
&status_report->status_report.raddr,
&addr,
msgid);
return FALSE;
@ -2932,14 +3003,14 @@ gboolean status_report_assembly_report(struct status_report_assembly *assembly,
memcpy(out_msgid, msgid, SMS_MSGID_LEN);
sr_assembly_remove_fragment_backup(assembly->imsi,
&status_report->status_report.raddr,
&addr,
msgid);
g_hash_table_iter_remove(&iter);
if (g_hash_table_size(id_table) == 0)
g_hash_table_remove(assembly->assembly_table,
status_report->status_report.raddr.address);
s_addr);
return TRUE;
}