From db7a0b227e8e51d40908471206f5cd287c99fa92 Mon Sep 17 00:00:00 2001 From: defanor Date: Sun, 12 Nov 2023 16:46:38 +0300 Subject: Skip full capabilities string composition A hash is composed more directly now: parts of the string are fed into a hash function instead of being concatenated first. --- src/rexmpp.c | 148 ++++++++++++++++------------------------------------------- 1 file changed, 39 insertions(+), 109 deletions(-) diff --git a/src/rexmpp.c b/src/rexmpp.c index d76b72a..5bfa375 100644 --- a/src/rexmpp.c +++ b/src/rexmpp.c @@ -112,128 +112,58 @@ void rexmpp_log (rexmpp_t *s, int priority, const char *format, ...) } } -char *rexmpp_capabilities_string (rexmpp_t *s, rexmpp_xml_t *info) { - /* Assuming the info is sorted already. Would be better to sort it - here (todo). */ +char *rexmpp_capabilities_hash (rexmpp_t *s, + rexmpp_xml_t *info) +{ + /* Assuming the info is sorted already. Might be useful to sort it + here. */ + rexmpp_digest_t digest_ctx; + if (rexmpp_digest_init(&digest_ctx, REXMPP_DIGEST_SHA1)) { + rexmpp_log(s, LOG_ERR, "Failed to initialize a digest object"); + return NULL; + } + rexmpp_xml_t *cur; - int buf_len = 1024, str_len = 0; - char *str = malloc(buf_len); for (cur = info; cur; cur = cur->next) { if (strcmp(cur->alt.elem.qname.name, "identity") == 0) { - int cur_len = 5; /* ///< for an empty identity */ - - /* Collect the properties we'll need. */ - const char *category = rexmpp_xml_find_attr_val(cur, "category"); - const char *type = rexmpp_xml_find_attr_val(cur, "type"); - const char *lang = rexmpp_xml_find_attr_val(cur, "xml:lang"); - const char *name = rexmpp_xml_find_attr_val(cur, "name"); - - /* Calculate the length needed. */ - if (category != NULL) { - cur_len += strlen(category); - } - if (type != NULL) { - cur_len += strlen(type); - } - if (lang != NULL) { - cur_len += strlen(lang); - } - if (name != NULL) { - cur_len += strlen(name); - } - - /* Reallocate the buffer if necessary. */ - if (cur_len > buf_len - str_len) { - while (cur_len > buf_len - str_len) { - buf_len *= 2; + const char *identity_strings[4] = + { rexmpp_xml_find_attr_val(cur, "category"), + rexmpp_xml_find_attr_val(cur, "type"), + rexmpp_xml_find_attr_val(cur, "xml:lang"), + rexmpp_xml_find_attr_val(cur, "name") + }; + int i; + for (i = 0; i < 4; i++) { + if (identity_strings[i] != NULL) { + rexmpp_digest_update(&digest_ctx, + identity_strings[i], + strlen(identity_strings[i])); } - char *new_str = realloc(str, buf_len); - if (new_str == NULL) { - rexmpp_log(s, LOG_ERR, - "Failed to reallocate the capabilities string: %s", - strerror(errno)); - free(str); - return NULL; - } - str = new_str; - } - - /* Fill the data. */ - if (category != NULL) { - strcpy(str + str_len, category); - str_len += strlen(category); - } - str[str_len] = '/'; - str_len++; - if (type != NULL) { - strcpy(str + str_len, type); - str_len += strlen(type); - } - str[str_len] = '/'; - str_len++; - if (lang != NULL) { - strcpy(str + str_len, lang); - str_len += strlen(lang); - } - str[str_len] = '/'; - str_len++; - if (name != NULL) { - strcpy(str + str_len, name); - str_len += strlen(name); + rexmpp_digest_update(&digest_ctx, (i < 3) ? "/" : "<", 1); } - str[str_len] = '<'; - str_len++; } else if (strcmp(cur->alt.elem.qname.name, "feature") == 0) { const char *var = rexmpp_xml_find_attr_val(cur, "var"); - int cur_len = 2 + strlen(var); - if (cur_len > buf_len - str_len) { - while (cur_len > buf_len - str_len) { - buf_len *= 2; - } - char *new_str = realloc(str, buf_len); - if (new_str == NULL) { - rexmpp_log(s, LOG_ERR, - "Failed to reallocate the capabilities string: %s", - strerror(errno)); - free(str); - return NULL; - } - str = new_str; + if (var != NULL) { + rexmpp_digest_update(&digest_ctx, var, strlen(var)); + rexmpp_digest_update(&digest_ctx, "<", 1); + } else { + rexmpp_log(s, LOG_ERR, "Found an empty feature var"); } - strcpy(str + str_len, var); - str_len += strlen(var); - str[str_len] = '<'; - str_len++; } else { rexmpp_log(s, LOG_ERR, - "Unsupported node type in disco info: %s", cur->alt.elem.qname.name); + "Unsupported node type in disco info: %s", + cur->alt.elem.qname.name); } } - str[str_len] = '\0'; - return str; -} -char *rexmpp_capabilities_hash (rexmpp_t *s, - rexmpp_xml_t *info) -{ - char *out = NULL; - size_t out_len = 0; - char *str = rexmpp_capabilities_string(s, info); - if (str != NULL) { - size_t sha1_len = rexmpp_digest_len(REXMPP_DIGEST_SHA1); - char *sha1 = malloc(sha1_len); - if (sha1 != NULL) { - if (rexmpp_digest_buffer(REXMPP_DIGEST_SHA1, - str, strlen(str), - sha1, sha1_len) == 0) - { - rexmpp_base64_to(sha1, sha1_len, &out, &out_len); - } - free(sha1); - } - free(str); - } - return out; + size_t digest_len = rexmpp_digest_len(REXMPP_DIGEST_SHA1); + char *digest_buf = malloc(digest_len); + rexmpp_digest_finish(&digest_ctx, digest_buf, digest_len); + char *digest_base64 = NULL; + size_t digest_base64_len = 0; + rexmpp_base64_to(digest_buf, digest_len, &digest_base64, &digest_base64_len); + free(digest_buf); + return digest_base64; } rexmpp_xml_t *rexmpp_find_event (rexmpp_t *s, -- cgit v1.2.3