about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/command/command.c10
-rw-r--r--src/command/commands.c20
-rw-r--r--src/command/commands.h1
-rw-r--r--src/server_events.c10
-rw-r--r--src/server_events.h1
-rw-r--r--src/xmpp/iq.c40
-rw-r--r--src/xmpp/stanza.c5
-rw-r--r--src/xmpp/stanza.h2
-rw-r--r--src/xmpp/xmpp.h1
9 files changed, 86 insertions, 4 deletions
diff --git a/src/command/command.c b/src/command/command.c
index 49dc7396..f0e86710 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -722,6 +722,14 @@ static struct cmd_t command_defs[] =
           "A value of 0 will switch off autopinging the server.",
           NULL } } },
 
+    { "/ping",
+        cmd_ping, parse_args, 0, 1, NULL,
+        { "/ping [target]", "Send ping IQ request.",
+        { "/ping [rarget]",
+          "--------------",
+          "Sends an IQ ping stanza to the specificed target.",
+          NULL } } },
+
     { "/autoaway",
         cmd_autoaway, parse_args_with_freetext, 2, 2, &cons_autoaway_setting,
         { "/autoaway setting value", "Set auto idle/away properties.",
@@ -1592,7 +1600,7 @@ _cmd_complete_parameters(char *input, int *size)
             }
         }
 
-        gchar *resource_choices[] = { "/caps", "/software" };
+        gchar *resource_choices[] = { "/caps", "/software", "/ping" };
         for (i = 0; i < ARRAY_SIZE(resource_choices); i++) {
             result = autocomplete_param_with_func(input, size, resource_choices[i],
                 roster_find_resource);
diff --git a/src/command/commands.c b/src/command/commands.c
index 5e33f823..bd383f69 100644
--- a/src/command/commands.c
+++ b/src/command/commands.c
@@ -2577,6 +2577,26 @@ cmd_autoping(gchar **args, struct cmd_help_t help)
 }
 
 gboolean
+cmd_ping(gchar **args, struct cmd_help_t help)
+{
+    jabber_conn_status_t conn_status = jabber_get_connection_status();
+
+    if (conn_status != JABBER_CONNECTED) {
+        cons_show("You are not currenlty connected.");
+        return TRUE;
+    }
+
+    iq_send_ping(args[0]);
+
+    if (args[0] == NULL) {
+        cons_show("Pinged server...");
+    } else {
+        cons_show("Pinged %s...", args[0]);
+    }
+    return TRUE;
+}
+
+gboolean
 cmd_autoaway(gchar **args, struct cmd_help_t help)
 {
     char *setting = args[0];
diff --git a/src/command/commands.h b/src/command/commands.h
index 3f7c45bb..7eddc127 100644
--- a/src/command/commands.h
+++ b/src/command/commands.h
@@ -124,5 +124,6 @@ gboolean cmd_wins(gchar **args, struct cmd_help_t help);
 gboolean cmd_xa(gchar **args, struct cmd_help_t help);
 gboolean cmd_alias(gchar **args, struct cmd_help_t help);
 gboolean cmd_xmlconsole(gchar **args, struct cmd_help_t help);
+gboolean cmd_ping(gchar **args, struct cmd_help_t help);
 
 #endif
diff --git a/src/server_events.c b/src/server_events.c
index 0ec07576..eda847d2 100644
--- a/src/server_events.c
+++ b/src/server_events.c
@@ -579,3 +579,13 @@ handle_xmpp_stanza(const char * const msg)
 {
     ui_handle_stanza(msg);
 }
+
+void
+handle_ping_result(const char * const from, int millis)
+{
+    if (from == NULL) {
+        cons_show("Ping response from server: %dms.", millis);
+    } else {
+        cons_show("Ping response from %s: %dms.", from, millis);
+    }
+}
diff --git a/src/server_events.h b/src/server_events.h
index 82c0d58d..54d04b54 100644
--- a/src/server_events.h
+++ b/src/server_events.h
@@ -94,5 +94,6 @@ void handle_message_error(const char * const from, const char * const type,
 void handle_presence_error(const char *from, const char * const type,
     const char *err_msg);
 void handle_xmpp_stanza(const char * const msg);
+void handle_ping_result(const char * const from, int millis);
 
 #endif
diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c
index b4fc8176..17269fe2 100644
--- a/src/xmpp/iq.c
+++ b/src/xmpp/iq.c
@@ -75,6 +75,8 @@ 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);
+static int _manual_pong_handler(xmpp_conn_t *const conn,
+    xmpp_stanza_t * const stanza, void * const userdata);
 static int _ping_timed_handler(xmpp_conn_t * const conn,
     void * const userdata);
 
@@ -186,6 +188,21 @@ _iq_destroy_instant_room(const char * const room_jid)
     xmpp_stanza_release(iq);
 }
 
+static void
+_iq_send_ping(const char * const target)
+{
+    xmpp_conn_t * const conn = connection_get_conn();
+    xmpp_ctx_t * const ctx = connection_get_ctx();
+    xmpp_stanza_t *iq = stanza_create_ping_iq(ctx, target);
+    char *id = xmpp_stanza_get_id(iq);
+
+    GDateTime *now = g_date_time_new_now_local();
+    xmpp_id_handler_add(conn, _manual_pong_handler, id, now);
+
+    xmpp_send(conn, iq);
+    xmpp_stanza_release(iq);
+}
+
 static int
 _error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
     void * const userdata)
@@ -241,13 +258,33 @@ _pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
 }
 
 static int
+_manual_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
+    void * const userdata)
+{
+    GDateTime *sent = (GDateTime *)userdata;
+    GDateTime *now = g_date_time_new_now_local();
+
+    GTimeSpan elapsed = g_date_time_difference(now, sent);
+    int elapsed_millis = elapsed / 1000;
+
+    g_date_time_unref(sent);
+    g_date_time_unref(now);
+
+    char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
+
+    handle_ping_result(from, elapsed_millis);
+
+    return 0;
+}
+
+static int
 _ping_timed_handler(xmpp_conn_t * const conn, void * const userdata)
 {
     xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
 
     if (jabber_get_connection_status() == JABBER_CONNECTED) {
 
-        xmpp_stanza_t *iq = stanza_create_ping_iq(ctx);
+        xmpp_stanza_t *iq = stanza_create_ping_iq(ctx, NULL);
         char *id = xmpp_stanza_get_id(iq);
 
         // add pong handler
@@ -762,4 +799,5 @@ iq_init_module(void)
     iq_set_autoping = _iq_set_autoping;
     iq_confirm_instant_room = _iq_confirm_instant_room;
     iq_destroy_instant_room = _iq_destroy_instant_room;
+    iq_send_ping = _iq_send_ping;
 }
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index 51e63ccc..09de1211 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -579,11 +579,14 @@ stanza_contains_chat_state(xmpp_stanza_t *stanza)
 }
 
 xmpp_stanza_t *
-stanza_create_ping_iq(xmpp_ctx_t *ctx)
+stanza_create_ping_iq(xmpp_ctx_t *ctx, const char * const target)
 {
     xmpp_stanza_t *iq = xmpp_stanza_new(ctx);
     xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
     xmpp_stanza_set_type(iq, STANZA_TYPE_GET);
+    if (target != NULL) {
+        xmpp_stanza_set_attribute(iq, STANZA_ATTR_TO, target);
+    }
     char *id = create_unique_id("ping");
     xmpp_stanza_set_id(iq, id);
     free(id);
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index eb309e19..3d925787 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -185,7 +185,7 @@ xmpp_stanza_t* stanza_create_room_leave_presence(xmpp_ctx_t *ctx,
 xmpp_stanza_t* stanza_create_presence(xmpp_ctx_t * const ctx);
 
 xmpp_stanza_t* stanza_create_roster_iq(xmpp_ctx_t *ctx);
-xmpp_stanza_t* stanza_create_ping_iq(xmpp_ctx_t *ctx);
+xmpp_stanza_t* stanza_create_ping_iq(xmpp_ctx_t *ctx, const char * const target);
 xmpp_stanza_t* stanza_create_disco_info_iq(xmpp_ctx_t *ctx, const char * const id,
     const char * const to, const char * const node);
 
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index fb15e7af..78703230 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -141,6 +141,7 @@ void (*iq_disco_items_request)(gchar *jid);
 void (*iq_set_autoping)(int seconds);
 void (*iq_confirm_instant_room)(const char * const room_jid);
 void (*iq_destroy_instant_room)(const char * const room_jid);
+void (*iq_send_ping)(const char * const target);
 
 // caps functions
 Capabilities* (*caps_get)(const char * const caps_str);