summaryrefslogtreecommitdiffstats
path: root/src/smsutil.c
diff options
context:
space:
mode:
authorDenis Kenzior <denkenz@gmail.com>2010-09-22 16:27:30 -0500
committerDenis Kenzior <denkenz@gmail.com>2010-09-22 16:27:30 -0500
commitc12632dfef55c3970a9fac58559fb028dc30306f (patch)
tree51c6b31ec4eb9ea8144975f507a056fc63479de5 /src/smsutil.c
parent46d43a0d887341eeedbaa7115eb6031a935ff075 (diff)
downloadofono-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.c200
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;
}