diff options
author | Denis Kenzior <denkenz@gmail.com> | 2010-09-22 16:27:30 -0500 |
---|---|---|
committer | Denis Kenzior <denkenz@gmail.com> | 2010-09-22 16:27:30 -0500 |
commit | c12632dfef55c3970a9fac58559fb028dc30306f (patch) | |
tree | 51c6b31ec4eb9ea8144975f507a056fc63479de5 /src/smsutil.c | |
parent | 46d43a0d887341eeedbaa7115eb6031a935ff075 (diff) | |
download | ofono-c12632dfef55c3970a9fac58559fb028dc30306f.tar.bz2 |
smsutil: Reflow the fuzzy matching code
Make a bit more readable
Diffstat (limited to 'src/smsutil.c')
-rw-r--r-- | src/smsutil.c | 200 |
1 files changed, 98 insertions, 102 deletions
diff --git a/src/smsutil.c b/src/smsutil.c index 89b922e8..04bdb0e0 100644 --- a/src/smsutil.c +++ b/src/smsutil.c @@ -2850,121 +2850,123 @@ static gboolean sr_st_to_delivered(enum sms_st st, gboolean *delivered) return FALSE; } -gboolean status_report_assembly_report(struct status_report_assembly *assembly, - const struct sms *status_report, - unsigned char *out_msgid, - gboolean *out_delivered) +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 = 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; - GHashTable *id_table; + unsigned int offset = mr / 32; + unsigned int bit = 1 << (mr % 32); gpointer key, value; - gboolean delivered; - 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; - - 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) exists in assembly */ - if (id_table != NULL) { - - /* Found an identical address from assembly. */ - s_addr = r_addr; + struct id_table_node *node; - g_hash_table_iter_init(&iter, id_table); - while (g_hash_table_iter_next(&iter, &key, &value)) { - node = value; + g_hash_table_iter_init(out_iter, id_table); + while (g_hash_table_iter_next(out_iter, &key, &value)) { + node = value; - if (node->mrs[offset] & bit) - break; + /* Address and MR matched */ + if (node->mrs[offset] & bit) { + node->mrs[offset] ^= bit; + *out_id = key; - node = NULL; + return node; } } - /* - * 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] == '+'))) { + return NULL; +} - r_len = strlen(r_addr); - s_len = strlen(s_addr); +/* + * 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; - len = MIN(6, MIN(r_len, s_len)); + r_addr = sms_address_to_string(&sr->status_report.raddr); + g_hash_table_iter_init(&iter_addr, assy->assembly_table); - for (i = 0; i < len; i++) { - if (s_addr[s_len - i - 1] != - r_addr[r_len - i - 1]) - break; - } + 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; - /* Not all digits matched. */ - if (i < len) - continue; - } - /* No conversions */ - else - continue; + if (r_addr[0] == '+' && s_addr[0] == '+') + 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; + if (r_addr[0] != '+' && s_addr[0] != '+') + continue; - /* Address and MR matched */ - if (node->mrs[offset] & bit) - break; + r_len = strlen(r_addr); + s_len = strlen(s_addr); - node = NULL; - } + len = MIN(6, MIN(r_len, s_len)); - /* - * Received address with MR matched with one - * of the stored addresses and MR, so no need - * to continue searching. - */ - if (node) + 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 *sr, + unsigned char *out_msgid, + gboolean *out_delivered) +{ + const char *straddr; + GHashTable *id_table; + GHashTableIter iter; + struct sms_address addr; + struct id_table_node *node; + gboolean delivered; + gboolean pending; + unsigned char *msgid; + int i; + + /* We ignore temporary or tempfinal status reports */ + if (sr_st_to_delivered(sr->status_report.st, &delivered) == FALSE) + return FALSE; + + straddr = sms_address_to_string(&sr->status_report.raddr); + id_table = g_hash_table_lookup(assembly->assembly_table, straddr); + + 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; } |