From 2a92169351f88ab3bfe1acf15628878c5e8ef520 Mon Sep 17 00:00:00 2001 From: James Booth Date: Wed, 5 Aug 2015 00:26:29 +0100 Subject: [PATCH 1/4] Use id handler for software version requests, handle errors --- src/ui/core.c | 18 ++++++++++++++ src/ui/ui.h | 1 + src/xmpp/iq.c | 33 ++++++++++++++++++++----- src/xmpp/stanza.c | 6 ++++- tests/functionaltests/functionaltests.c | 1 + tests/functionaltests/test_software.c | 25 +++++++++++++++++++ tests/functionaltests/test_software.h | 1 + 7 files changed, 78 insertions(+), 7 deletions(-) diff --git a/src/ui/core.c b/src/ui/core.c index bbaebe31..9cbd873a 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -2792,6 +2792,24 @@ ui_hide_roster(void) } } +void +ui_handle_software_version_error(const char * const roomjid, const char * const message) +{ + GString *message_str = g_string_new(""); + + ProfWin *window = wins_get_console(); + g_string_printf(message_str, "Could not get software version"); + + if (message) { + g_string_append(message_str, ": "); + g_string_append(message_str, message); + } + + win_print(window, '-', 0, NULL, 0, THEME_ERROR, "", message_str->str); + + g_string_free(message_str, TRUE); +} + static void _win_show_history(ProfChatWin *chatwin, const char * const contact) { diff --git a/src/ui/ui.h b/src/ui/ui.h index fd81f68a..d22a5c7f 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -203,6 +203,7 @@ void ui_redraw_all_room_rosters(void); void ui_show_all_room_rosters(void); void ui_hide_all_room_rosters(void); gboolean ui_chat_win_exists(const char * const barejid); +void ui_handle_software_version_error(const char * const roomjid, const char * const message); gboolean ui_tidy_wins(void); void ui_prune_wins(void); diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 18abad36..7ed44363 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -67,10 +67,10 @@ typedef struct p_room_info_data_t { static int _error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); static int _ping_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); static int _version_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); +static int _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); static int _disco_info_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); static int _disco_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); static int _room_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); -static int _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); static int _disco_items_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); static int _disco_items_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); static int _destroy_room_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); @@ -103,7 +103,6 @@ iq_add_handlers(void) HANDLE(XMPP_NS_DISCO_ITEMS, STANZA_TYPE_RESULT, _disco_items_result_handler); HANDLE(STANZA_NS_VERSION, STANZA_TYPE_GET, _version_get_handler); - HANDLE(STANZA_NS_VERSION, STANZA_TYPE_RESULT, _version_result_handler); HANDLE(STANZA_NS_PING, STANZA_TYPE_GET, _ping_get_handler); @@ -301,6 +300,10 @@ iq_send_software_version(const char * const fulljid) xmpp_conn_t * const conn = connection_get_conn(); xmpp_ctx_t * const ctx = connection_get_ctx(); xmpp_stanza_t *iq = stanza_create_software_version_iq(ctx, fulljid); + + char *id = xmpp_stanza_get_id(iq); + xmpp_id_handler_add(conn, _version_result_handler, id, NULL); + xmpp_send(conn, iq); xmpp_stanza_release(iq); } @@ -836,16 +839,34 @@ _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, log_debug("IQ version result handler fired."); } + char *type = xmpp_stanza_get_type(stanza); + char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); + + if (g_strcmp0(type, STANZA_TYPE_RESULT) != 0) { + if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { + char *error_message = stanza_get_error_message(stanza); + ui_handle_software_version_error(from, error_message); + free(error_message); + } else { + ui_handle_software_version_error(from, "unknown error"); + log_error("Software version result with unrecognised type attribute."); + } + + return 0; + } + const char *jid = xmpp_stanza_get_attribute(stanza, "from"); xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY); if (query == NULL) { - return 1; + log_error("Software version result recieved with no query element."); + return 0; } char *ns = xmpp_stanza_get_ns(query); if (g_strcmp0(ns, STANZA_NS_VERSION) != 0) { - return 1; + log_error("Software version result recieved without namespace."); + return 0; } char *name_str = NULL; @@ -880,7 +901,7 @@ _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, jid_destroy(jidp); - return 1; + return 0; } static int @@ -1567,4 +1588,4 @@ _disco_items_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stan g_slist_free_full(items, (GDestroyNotify)_item_destroy); return 1; -} \ No newline at end of file +} diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index be85c330..bb32932a 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -877,7 +877,11 @@ stanza_create_software_version_iq(xmpp_ctx_t *ctx, const char * const fulljid) xmpp_stanza_t *iq = xmpp_stanza_new(ctx); xmpp_stanza_set_name(iq, STANZA_NAME_IQ); xmpp_stanza_set_type(iq, STANZA_TYPE_GET); - xmpp_stanza_set_id(iq, "sv"); + + char *id = create_unique_id("sv"); + xmpp_stanza_set_id(iq, id); + free(id); + xmpp_stanza_set_attribute(iq, "to", fulljid); xmpp_stanza_t *query = xmpp_stanza_new(ctx); diff --git a/tests/functionaltests/functionaltests.c b/tests/functionaltests/functionaltests.c index a253fe63..cbedf401 100644 --- a/tests/functionaltests/functionaltests.c +++ b/tests/functionaltests/functionaltests.c @@ -79,6 +79,7 @@ int main(int argc, char* argv[]) { PROF_FUNC_TEST(send_software_version_request), PROF_FUNC_TEST(display_software_version_result), + PROF_FUNC_TEST(shows_message_when_software_version_error), }; return run_tests(all_tests); diff --git a/tests/functionaltests/test_software.c b/tests/functionaltests/test_software.c index aeb3f8f5..9b063c20 100644 --- a/tests/functionaltests/test_software.c +++ b/tests/functionaltests/test_software.c @@ -57,3 +57,28 @@ display_software_version_result(void **state) prof_output_exact("Name : Profanity"); prof_output_exact("Version : 0.4.7dev.master.2cb2f83"); } + +void +shows_message_when_software_version_error(void **state) +{ + prof_connect(); + stbbr_send( + "" + "10" + "I'm here" + "" + ); + prof_output_exact("Buddy1 (mobile) is online, \"I'm here\""); + + stbbr_for_query("jabber:iq:version", + "" + "" + "" + "" + "" + "" + ); + prof_input("/software buddy1@localhost/laptop"); + + prof_output_exact("Could not get software version: service-unavailable"); +} diff --git a/tests/functionaltests/test_software.h b/tests/functionaltests/test_software.h index b031e264..985d7002 100644 --- a/tests/functionaltests/test_software.h +++ b/tests/functionaltests/test_software.h @@ -1,3 +1,4 @@ void send_software_version_request(void **state); void display_software_version_result(void **state); +void shows_message_when_software_version_error(void **state); From ac3e7dd9e899013ca08ed7fbe3b0cfcbd823f7bd Mon Sep 17 00:00:00 2001 From: James Booth Date: Wed, 5 Aug 2015 00:48:50 +0100 Subject: [PATCH 2/4] Handle software version requests for gateways that return from domainpart --- src/xmpp/iq.c | 10 +++++++-- tests/functionaltests/functionaltests.c | 1 + tests/functionaltests/test_presence.c | 1 + tests/functionaltests/test_software.c | 28 +++++++++++++++++++++++++ tests/functionaltests/test_software.h | 1 + 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 7ed44363..3221fc2c 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -302,7 +302,7 @@ iq_send_software_version(const char * const fulljid) xmpp_stanza_t *iq = stanza_create_software_version_iq(ctx, fulljid); char *id = xmpp_stanza_get_id(iq); - xmpp_id_handler_add(conn, _version_result_handler, id, NULL); + xmpp_id_handler_add(conn, _version_result_handler, id, strdup(fulljid)); xmpp_send(conn, iq); xmpp_stanza_release(iq); @@ -893,13 +893,19 @@ _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, presence = string_from_resource_presence(occupant->presence); } else { PContact contact = roster_get_contact(jidp->barejid); + if (!contact) { + jid_destroy(jidp); + jidp = jid_create((char*)userdata); + contact = roster_get_contact(jidp->barejid); + } Resource *resource = p_contact_get_resource(contact, jidp->resourcepart); presence = string_from_resource_presence(resource->presence); } - cons_show_software_version(jid, presence, name_str, version_str, os_str); + cons_show_software_version(jidp->fulljid, presence, name_str, version_str, os_str); jid_destroy(jidp); + free(userdata); return 0; } diff --git a/tests/functionaltests/functionaltests.c b/tests/functionaltests/functionaltests.c index cbedf401..a9dfea68 100644 --- a/tests/functionaltests/functionaltests.c +++ b/tests/functionaltests/functionaltests.c @@ -80,6 +80,7 @@ int main(int argc, char* argv[]) { PROF_FUNC_TEST(send_software_version_request), PROF_FUNC_TEST(display_software_version_result), PROF_FUNC_TEST(shows_message_when_software_version_error), + PROF_FUNC_TEST(display_software_version_result_when_from_domainpart), }; return run_tests(all_tests); diff --git a/tests/functionaltests/test_presence.c b/tests/functionaltests/test_presence.c index 936d9405..7f37f2fd 100644 --- a/tests/functionaltests/test_presence.c +++ b/tests/functionaltests/test_presence.c @@ -242,6 +242,7 @@ presence_received(void **state) assert_true(prof_output_exact("Buddy1 (mobile) is online, \"I'm here\"")); } +// Typical use case for gateways that don't support resources void presence_missing_resource_defaults(void **state) { diff --git a/tests/functionaltests/test_software.c b/tests/functionaltests/test_software.c index 9b063c20..08c3edff 100644 --- a/tests/functionaltests/test_software.c +++ b/tests/functionaltests/test_software.c @@ -82,3 +82,31 @@ shows_message_when_software_version_error(void **state) prof_output_exact("Could not get software version: service-unavailable"); } + +// Typical use case for gateways that don't support resources +void +display_software_version_result_when_from_domainpart(void **state) +{ + prof_connect(); + stbbr_send( + "" + "10" + "I'm here" + "" + ); + prof_output_exact("Buddy1 is online, \"I'm here\""); + + stbbr_for_query("jabber:iq:version", + "" + "" + "Some Gateway" + "1.0" + "" + "" + ); + prof_input("/software buddy1@localhost/__prof_default"); + + prof_output_exact("buddy1@localhost/__prof_default:"); + prof_output_exact("Name : Some Gateway"); + prof_output_exact("Version : 1.0"); +} diff --git a/tests/functionaltests/test_software.h b/tests/functionaltests/test_software.h index 985d7002..6d75f049 100644 --- a/tests/functionaltests/test_software.h +++ b/tests/functionaltests/test_software.h @@ -1,4 +1,5 @@ void send_software_version_request(void **state); void display_software_version_result(void **state); void shows_message_when_software_version_error(void **state); +void display_software_version_result_when_from_domainpart(void **state); From 0b7c79ac13b80b12c776437b8ad603a808583686 Mon Sep 17 00:00:00 2001 From: James Booth Date: Wed, 5 Aug 2015 01:01:46 +0100 Subject: [PATCH 3/4] Use original JID in software version request in MUC --- src/xmpp/iq.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 3221fc2c..58eded8c 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -886,18 +886,17 @@ _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, os_str = xmpp_stanza_get_text(os); } - Jid *jidp = jid_create(jid); + if (g_strcmp0(jid, (char*)userdata) != 0) { + log_warning("From attribute specified different JID, using original JID."); + } + + Jid *jidp = jid_create((char*)userdata); const char *presence = NULL; if (muc_active(jidp->barejid)) { Occupant *occupant = muc_roster_item(jidp->barejid, jidp->resourcepart); presence = string_from_resource_presence(occupant->presence); } else { PContact contact = roster_get_contact(jidp->barejid); - if (!contact) { - jid_destroy(jidp); - jidp = jid_create((char*)userdata); - contact = roster_get_contact(jidp->barejid); - } Resource *resource = p_contact_get_resource(contact, jidp->resourcepart); presence = string_from_resource_presence(resource->presence); } From af38ddc9e73024b0871696263c37dfb4954a03de Mon Sep 17 00:00:00 2001 From: James Booth Date: Wed, 5 Aug 2015 01:14:41 +0100 Subject: [PATCH 4/4] Handle resource not found on sofware version request --- src/xmpp/iq.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 58eded8c..a07fbf73 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -898,6 +898,10 @@ _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, } else { PContact contact = roster_get_contact(jidp->barejid); Resource *resource = p_contact_get_resource(contact, jidp->resourcepart); + if (!resource) { + ui_handle_software_version_error(jidp->fulljid, "Unknown resource"); + return 0; + } presence = string_from_resource_presence(resource->presence); }