From e263e00a85428e08f84e002a56456201a450811c Mon Sep 17 00:00:00 2001 From: James Booth Date: Wed, 26 Nov 2014 21:59:36 +0000 Subject: [PATCH] Refactored parsing caps --- src/jid.c | 14 ++++++++ src/jid.h | 2 ++ src/xmpp/presence.c | 73 +++++++++++++++++--------------------- src/xmpp/stanza.c | 86 ++++++++++++++++----------------------------- src/xmpp/stanza.h | 13 ++++--- tests/test_jid.c | 18 ++++++++++ tests/test_jid.h | 2 ++ tests/testsuite.c | 2 ++ 8 files changed, 111 insertions(+), 99 deletions(-) diff --git a/src/jid.c b/src/jid.c index 8e3813bc..690f36ca 100644 --- a/src/jid.c +++ b/src/jid.c @@ -176,3 +176,17 @@ get_nick_from_full_jid(const char * const full_room_jid) return nick_part; } + + +/* + * get the fulljid, fall back to the barejid + */ +char * +jid_fulljid_or_barejid(Jid *jid) +{ + if (jid->fulljid) { + return jid->fulljid; + } else { + return jid->barejid; + } +} \ No newline at end of file diff --git a/src/jid.h b/src/jid.h index 39a4585a..64c147f9 100644 --- a/src/jid.h +++ b/src/jid.h @@ -56,4 +56,6 @@ gboolean jid_is_valid_room_form(Jid *jid); char * create_fulljid(const char * const barejid, const char * const resource); char * get_nick_from_full_jid(const char * const full_room_jid); +char * jid_fulljid_or_barejid(Jid *jid); + #endif diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c index 389540e8..963815a8 100644 --- a/src/xmpp/presence.c +++ b/src/xmpp/presence.c @@ -500,43 +500,30 @@ _unavailable_handler(xmpp_conn_t * const conn, } static void -_handle_caps(xmpp_stanza_t *const stanza) +_handle_caps(char *jid, XMPPCaps *caps) { - char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); - - if (from) { - char *hash = stanza_caps_get_hash(stanza); - - // hash supported xep-0115 - if (g_strcmp0(hash, "sha-1") == 0) { - log_info("Hash %s supported"); - - char *ver = stanza_get_caps_ver(stanza); - if (ver) { - if (caps_contains(ver)) { - log_info("Capabilities cached: %s", ver); - caps_map(from, ver); - } else { - log_info("Capabilities not cached: %s, sending service discovery request", ver); - char *node = stanza_caps_get_node(stanza); - char *id = create_unique_id("caps"); - - iq_send_caps_request(from, id, node, ver); - - free(id); - } - } - - // no hash, or not supported - } else { - if (hash) { - log_info("Hash %s not supported, not sending service discovery request"); - // send service discovery request, cache against from full jid + // hash supported xep-0115 + if (g_strcmp0(caps->hash, "sha-1") == 0) { + log_info("Hash %s supported", caps->hash); + if (caps->ver) { + if (caps_contains(caps->ver)) { + log_info("Capabilities cached: %s", caps->ver); + caps_map(jid, caps->ver); } else { - log_info("No hash specified, not sending service discovery request"); - // do legacy + log_info("Capabilities not cached: %s, sending service discovery request", caps->ver); + char *id = create_unique_id("caps"); + iq_send_caps_request(jid, id, caps->node, caps->ver); + free(id); } } + + // no hash, or not supported + } else if (caps->hash) { + log_info("Hash %s not supported, not sending service discovery request", caps->hash); + // send service discovery request, cache against from full jid + } else { + log_info("No hash specified, not sending service discovery request"); + // do legacy } } @@ -580,18 +567,21 @@ _available_handler(xmpp_conn_t * const conn, break; } return 1; - } else if (xmpp_presence->jid->fulljid) { - log_debug("Presence available handler fired for: %s", xmpp_presence->jid->fulljid); } else { - log_debug("Presence available handler fired for: %s", xmpp_presence->jid->barejid); + char *jid = jid_fulljid_or_barejid(xmpp_presence->jid); + log_debug("Presence available handler fired for: %s", jid); } const char *my_jid_str = xmpp_conn_get_jid(conn); Jid *my_jid = jid_create(my_jid_str); - if ((g_strcmp0(my_jid->fulljid, xmpp_presence->jid->fulljid) != 0) && (stanza_contains_caps(stanza))) { + + XMPPCaps *caps = stanza_parse_caps(stanza); + if ((g_strcmp0(my_jid->fulljid, xmpp_presence->jid->fulljid) != 0) && caps) { log_info("Presence contains capabilities."); - _handle_caps(stanza); + char *jid = jid_fulljid_or_barejid(xmpp_presence->jid); + _handle_caps(jid, caps); } + stanza_free_caps(caps); Resource *resource = stanza_resource_from_presence(xmpp_presence); @@ -627,6 +617,7 @@ _send_caps_request(char *node, char *caps_key, char *id, char *from) log_debug("No node string, not sending discovery IQ."); } } + static int _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { @@ -757,10 +748,12 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * // room occupant online } else { // send disco info for capabilities, if not cached - if (stanza_contains_caps(stanza)) { + XMPPCaps *caps = stanza_parse_caps(stanza); + if (caps) { log_info("Presence contains capabilities."); - _handle_caps(stanza); + _handle_caps(from, caps); } + stanza_free_caps(caps); char *actor = stanza_get_actor(stanza); char *reason = stanza_get_reason(stanza); diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index e0943b1f..1766fe26 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -1313,72 +1313,30 @@ stanza_get_idle_time(xmpp_stanza_t * const stanza) } } -gboolean -stanza_contains_caps(xmpp_stanza_t * const stanza) +XMPPCaps* +stanza_parse_caps(xmpp_stanza_t * const stanza) { - xmpp_stanza_t *caps = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C); + xmpp_stanza_t *caps_st = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C); - if (!caps) { - return FALSE; - } - - char *ns = xmpp_stanza_get_ns(caps); - if (g_strcmp0(ns, STANZA_NS_CAPS) != 0) { - return FALSE; - } - - return TRUE; -} - -char * -stanza_caps_get_hash(xmpp_stanza_t * const stanza) -{ - xmpp_stanza_t *caps = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C); - - if (!caps) { + if (!caps_st) { return NULL; } - char *ns = xmpp_stanza_get_ns(caps); + char *ns = xmpp_stanza_get_ns(caps_st); if (g_strcmp0(ns, STANZA_NS_CAPS) != 0) { return NULL; } - return xmpp_stanza_get_attribute(caps, STANZA_ATTR_HASH); -} + char *hash = xmpp_stanza_get_attribute(caps_st, STANZA_ATTR_HASH); + char *node = xmpp_stanza_get_attribute(caps_st, STANZA_ATTR_NODE); + char *ver = xmpp_stanza_get_attribute(caps_st, STANZA_ATTR_VER); -char * -stanza_caps_get_node(xmpp_stanza_t * const stanza) -{ - xmpp_stanza_t *caps = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C); + XMPPCaps *caps = (XMPPCaps *)malloc(sizeof(XMPPCaps)); + caps->hash = hash ? strdup(hash) : NULL; + caps->node = node ? strdup(node) : NULL; + caps->ver = ver ? strdup(ver) : NULL; - if (!caps) { - return NULL; - } - - char *ns = xmpp_stanza_get_ns(caps); - if (g_strcmp0(ns, STANZA_NS_CAPS) != 0) { - return NULL; - } - - return xmpp_stanza_get_attribute(caps, STANZA_ATTR_NODE); -} - -char * -stanza_get_caps_ver(xmpp_stanza_t * const stanza) -{ - xmpp_stanza_t *caps = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_C); - - if (!caps) { - return NULL; - } - - char *ns = xmpp_stanza_get_ns(caps); - if (g_strcmp0(ns, STANZA_NS_CAPS) != 0) { - return NULL; - } - - return xmpp_stanza_get_attribute(caps, STANZA_ATTR_VER); + return caps; } char * @@ -1593,6 +1551,23 @@ stanza_resource_from_presence(XMPPPresence *presence) return resource; } +void +stanza_free_caps(XMPPCaps *caps) +{ + if (caps) { + if (caps->hash) { + free(caps->hash); + } + if (caps->node) { + free(caps->node); + } + if (caps->ver) { + free(caps->ver); + } + FREE_SET_NULL(caps); + } +} + void stanza_free_presence(XMPPPresence *presence) { @@ -1609,6 +1584,7 @@ stanza_free_presence(XMPPPresence *presence) if (presence->status) { free(presence->status); } + FREE_SET_NULL(presence); } } diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index d6a3b042..e60e9fe1 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -157,6 +157,12 @@ #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo" +typedef struct caps_stanza_t { + char *hash; + char *node; + char *ver; +} XMPPCaps; + typedef struct presence_stanza_t { Jid *jid; char *show; @@ -233,10 +239,6 @@ xmpp_stanza_t* stanza_create_room_kick_iq(xmpp_ctx_t * const ctx, const char * c int stanza_get_idle_time(xmpp_stanza_t * const stanza); char * stanza_get_caps_str(xmpp_stanza_t * const stanza); -gboolean stanza_contains_caps(xmpp_stanza_t * const stanza); -char * stanza_caps_get_hash(xmpp_stanza_t * const stanza); -char * stanza_get_caps_ver(xmpp_stanza_t * const stanza); -char * stanza_caps_get_node(xmpp_stanza_t * const stanza); DataForm * stanza_create_form(xmpp_stanza_t * const stanza); void stanza_destroy_form(DataForm *form); @@ -278,4 +280,7 @@ Resource* stanza_resource_from_presence(XMPPPresence *presence); XMPPPresence* stanza_parse_presence(xmpp_stanza_t *stanza, int *err); void stanza_free_presence(XMPPPresence *presence); +XMPPCaps* stanza_parse_caps(xmpp_stanza_t * const stanza); +void stanza_free_caps(XMPPCaps *caps); + #endif diff --git a/tests/test_jid.c b/tests/test_jid.c index df8096d1..ff5f4c9a 100644 --- a/tests/test_jid.c +++ b/tests/test_jid.c @@ -165,3 +165,21 @@ void create_full_with_trailing_slash(void **state) assert_string_equal("room@conference.domain.org", result->barejid); assert_string_equal("room@conference.domain.org/nick/", result->fulljid); } + +void returns_fulljid_when_exists(void **state) +{ + Jid *jid = jid_create("localpart@domainpart/resourcepart"); + + char *result = jid_fulljid_or_barejid(jid); + + assert_string_equal("localpart@domainpart/resourcepart", result); +} + +void returns_barejid_when_fulljid_not_exists(void **state) +{ + Jid *jid = jid_create("localpart@domainpart"); + + char *result = jid_fulljid_or_barejid(jid); + + assert_string_equal("localpart@domainpart", result); +} \ No newline at end of file diff --git a/tests/test_jid.h b/tests/test_jid.h index 95de541f..9b96d0b8 100644 --- a/tests/test_jid.h +++ b/tests/test_jid.h @@ -21,3 +21,5 @@ void create_with_slash_in_resource(void **state); void create_with_at_in_resource(void **state); void create_with_at_and_slash_in_resource(void **state); void create_full_with_trailing_slash(void **state); +void returns_fulljid_when_exists(void **state); +void returns_barejid_when_fulljid_not_exists(void **state); diff --git a/tests/testsuite.c b/tests/testsuite.c index ad6dc219..4273add5 100644 --- a/tests/testsuite.c +++ b/tests/testsuite.c @@ -131,6 +131,8 @@ int main(int argc, char* argv[]) { unit_test(create_with_at_in_resource), unit_test(create_with_at_and_slash_in_resource), unit_test(create_full_with_trailing_slash), + unit_test(returns_fulljid_when_exists), + unit_test(returns_barejid_when_fulljid_not_exists), unit_test(parse_null_returns_null), unit_test(parse_empty_returns_null),