summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.adoc1
-rw-r--r--src/plugins/relay/irc/relay-irc.c362
-rw-r--r--src/plugins/relay/irc/relay-irc.h12
-rw-r--r--tests/unit/plugins/irc/test-irc-protocol.cpp21
-rw-r--r--tests/unit/plugins/relay/irc/test-relay-irc.cpp186
5 files changed, 483 insertions, 99 deletions
diff --git a/ChangeLog.adoc b/ChangeLog.adoc
index 1546d955d..356f2378e 100644
--- a/ChangeLog.adoc
+++ b/ChangeLog.adoc
@@ -66,6 +66,7 @@ New features::
* relay: rename "ssl" options and protocol to "tls"
* relay: make TLS certificate/key loading error handling more verbose (issue #1558)
* relay: add modifiers "relay_client_irc_in", "relay_client_irc_out1" and "relay_client_irc_out"
+ * relay: add support of capability "echo-message" (issue #1949)
Bug fixes::
diff --git a/src/plugins/relay/irc/relay-irc.c b/src/plugins/relay/irc/relay-irc.c
index 6685b29ec..23fe74104 100644
--- a/src/plugins/relay/irc/relay-irc.c
+++ b/src/plugins/relay/irc/relay-irc.c
@@ -43,7 +43,7 @@ char *relay_irc_ignore_commands[] = { "cap", "pong", "quit", NULL };
char *relay_irc_backlog_commands_tags[RELAY_IRC_NUM_CMD] =
{ "irc_join", "irc_part", "irc_quit", "irc_nick", "irc_privmsg" };
char *relay_irc_server_capabilities[RELAY_IRC_NUM_CAPAB] =
-{ "server-time" };
+{ "server-time", "echo-message" };
/*
@@ -301,6 +301,46 @@ end:
}
/*
+ * Parses CAP command received from IRC server.
+ */
+
+void
+relay_irc_parse_cap_message (struct t_relay_client *client,
+ struct t_hashtable *parsed_msg)
+{
+ const char *ptr_param;
+ char str_param[64], **caps;
+ int i, index, num_caps;
+
+ /* only CAP ACK is parsed */
+ ptr_param = weechat_hashtable_get (parsed_msg, "param2");
+ if (!ptr_param || (weechat_strcasecmp (ptr_param, "ACK") != 0))
+ return;
+
+ index = 3;
+ while (1)
+ {
+ snprintf (str_param, sizeof (str_param), "param%d", index);
+ ptr_param = weechat_hashtable_get (parsed_msg, str_param);
+ if (!ptr_param)
+ break;
+ caps = weechat_string_split (ptr_param, " ", NULL, 0, 0, &num_caps);
+ if (caps)
+ {
+ for (i = 0; i < num_caps; i++)
+ {
+ if (strcmp (caps[i], "-echo-message") == 0)
+ RELAY_IRC_DATA(client, irc_cap_echo_message) = 0;
+ else if (strcmp (caps[i], "echo-message") == 0)
+ RELAY_IRC_DATA(client, irc_cap_echo_message) = 1;
+ }
+ weechat_string_free_split (caps);
+ }
+ index++;
+ }
+}
+
+/*
* Callback for signal "irc_in2".
*
* This is called when something is received on IRC server, and message can be
@@ -354,6 +394,12 @@ relay_irc_signal_irc_in2_cb (const void *pointer, void *data,
irc_args + 1 : irc_args);
}
+ /* if capabilities have changed, parse them to update in client */
+ if (irc_command && (weechat_strcasecmp (irc_command, "cap") == 0))
+ {
+ relay_irc_parse_cap_message (client, hash_parsed);
+ }
+
/* relay all commands to client, but not ping/pong */
if (irc_command
&& (weechat_strcasecmp (irc_command, "ping") != 0)
@@ -496,29 +542,36 @@ relay_irc_signal_irc_outtags_cb (const void *pointer, void *data,
&& irc_channel && irc_channel[0]
&& relay_irc_command_relayed (irc_command))
{
- /* get host for nick (it is self nick) */
- snprintf (str_infolist_args, sizeof (str_infolist_args),
- "%s,%s,%s",
- client->protocol_args,
- irc_channel,
- RELAY_IRC_DATA(client, nick));
-
- host = NULL;
- infolist_nick = weechat_infolist_get ("irc_nick", NULL,
- str_infolist_args);
- if (infolist_nick && weechat_infolist_next (infolist_nick))
- host = weechat_infolist_string (infolist_nick, "host");
-
- /* send message to client */
- relay_irc_sendf (client,
- ":%s%s%s %s",
- RELAY_IRC_DATA(client, nick),
- (host && host[0]) ? "!" : "",
- (host && host[0]) ? host : "",
- ptr_message);
+ /*
+ * relay command only if capability echo-message is NOS enabled
+ * in IRC server (otherwise message would be displayed two times)
+ */
+ if (!RELAY_IRC_DATA(client, irc_cap_echo_message))
+ {
+ /* get host for nick (it is self nick) */
+ snprintf (str_infolist_args, sizeof (str_infolist_args),
+ "%s,%s,%s",
+ client->protocol_args,
+ irc_channel,
+ RELAY_IRC_DATA(client, nick));
+
+ host = NULL;
+ infolist_nick = weechat_infolist_get ("irc_nick", NULL,
+ str_infolist_args);
+ if (infolist_nick && weechat_infolist_next (infolist_nick))
+ host = weechat_infolist_string (infolist_nick, "host");
+
+ /* send message to client */
+ relay_irc_sendf (client,
+ ":%s%s%s %s",
+ RELAY_IRC_DATA(client, nick),
+ (host && host[0]) ? "!" : "",
+ (host && host[0]) ? host : "",
+ ptr_message);
- if (infolist_nick)
- weechat_infolist_free (infolist_nick);
+ if (infolist_nick)
+ weechat_infolist_free (infolist_nick);
+ }
}
if (irc_channel)
free (irc_channel);
@@ -1286,6 +1339,125 @@ relay_irc_hook_signals (struct t_relay_client *client)
}
/*
+ * Compares two capabilities.
+ *
+ * Returns:
+ * < 0: capability 1 < capability 2
+ * 0: capability 1 == capability 2
+ * > 0: capability 1 > capability 2
+ */
+
+int
+relay_irc_capability_compare_cb (void *data,
+ struct t_arraylist *arraylist,
+ void *pointer1,
+ void *pointer2)
+{
+ /* make C compiler happy */
+ (void) data;
+ (void) arraylist;
+
+ return (weechat_strcmp ((const char *)pointer1, (const char *)pointer2));
+}
+
+/*
+ * Frees a capability in list.
+ */
+
+void
+relay_irc_capability_free_db (void *data,
+ struct t_arraylist *arraylist,
+ void *pointer)
+{
+ /* make C compiler happy */
+ (void) data;
+ (void) arraylist;
+
+ free (pointer);
+}
+
+/*
+ * Checks if a capability is currently enabled in IRC server.
+ *
+ * Returns:
+ * 1: capability is enabled in server
+ * 0: capability is NOT enabled in server
+ */
+
+int
+relay_irc_cap_enabled (struct t_relay_client *client, const char *capability)
+{
+ char str_info[1024], *info;
+ int rc;
+
+ if (!client || !capability || !capability[0])
+ return 0;
+
+ snprintf (str_info, sizeof (str_info),
+ "%s,%s",
+ client->protocol_args,
+ capability);
+
+ info = weechat_info_get ("irc_server_cap", str_info);
+ rc = (info && (strcmp (info, "1") == 0)) ? 1 : 0;
+ if (info)
+ free (info);
+ return rc;
+}
+
+/*
+ * Returns an integer with bits set for each supported capability (ie that
+ * is either always supported, or enabled in the IRC server).
+ */
+
+int
+relay_irc_get_supported_caps (struct t_relay_client *client)
+{
+ int i, caps, check_server;
+
+ caps = 0;
+ for (i = 0; i < RELAY_IRC_NUM_CAPAB; i++)
+ {
+ check_server = RELAY_IRC_CAPAB_FOLLOW_SERVER & (1 << i);
+ if (!check_server
+ || relay_irc_cap_enabled (client, relay_irc_server_capabilities[i]))
+ {
+ caps |= (1 << i);
+ }
+ }
+
+ return caps;
+}
+
+/*
+ * Returns a sorted list of supported all server capabilities by relay (even
+ * those that should not be sent to clients when the IRC server doesn't
+ * support them).
+ *
+ * Note: result must be freed after use.
+ */
+
+struct t_arraylist *
+relay_irc_get_list_caps ()
+{
+ struct t_arraylist *list_capab;
+ int i;
+
+ list_capab = weechat_arraylist_new (
+ 8, 1, 0,
+ &relay_irc_capability_compare_cb, NULL,
+ &relay_irc_capability_free_db, NULL);
+
+ for (i = 0; i < RELAY_IRC_NUM_CAPAB; i++)
+ {
+ weechat_arraylist_add (list_capab,
+ strdup (relay_irc_server_capabilities[i]));
+ }
+
+ return list_capab;
+}
+
+/*
* Processes the "CAP" irc command (received from client)
*/
@@ -1293,8 +1465,11 @@ void
relay_irc_recv_command_capab (struct t_relay_client *client,
int num_params, const char **params)
{
- char str_capab[1024], *str_caps;
- int i, capability, server_caps, num_caps_received, caps_ok;
+ struct t_arraylist *list_caps;
+ char **str_caps, **caps;
+ const char *ptr_cap;
+ int i, j, capability, server_caps, num_caps_received, caps_ok, size;
+ int num_caps, supported_caps;
if (num_params < 1)
return;
@@ -1302,17 +1477,37 @@ relay_irc_recv_command_capab (struct t_relay_client *client,
if (weechat_strcasecmp (params[0], "ls") == 0)
{
/* return the list of supported server capabilities */
- str_capab[0] = '\0';
- for (i = 0; i < RELAY_IRC_NUM_CAPAB; i++)
+ list_caps = relay_irc_get_list_caps ();
+ if (list_caps)
{
- if (str_capab[0])
- strcat (str_capab, " ");
- strcat (str_capab, relay_irc_server_capabilities[i]);
- relay_irc_sendf (client,
- ":%s CAP %s LS :%s",
- RELAY_IRC_DATA(client, address),
- (RELAY_IRC_DATA(client, nick)) ? RELAY_IRC_DATA(client, nick) : "nick",
- str_capab);
+ supported_caps = relay_irc_get_supported_caps (client);
+ str_caps = weechat_string_dyn_alloc (256);
+ if (str_caps)
+ {
+ size = weechat_arraylist_size (list_caps);
+ for (i = 0; i < size; i++)
+ {
+ ptr_cap = (const char *)weechat_arraylist_get (list_caps, i);
+ capability = relay_irc_search_server_capability (ptr_cap);
+ if (capability >= 0)
+ {
+ if (supported_caps & (1 << capability))
+ {
+ if ((*str_caps)[0])
+ weechat_string_dyn_concat (str_caps, " ", -1);
+ weechat_string_dyn_concat (str_caps, ptr_cap, -1);
+ }
+ }
+ }
+ relay_irc_sendf (
+ client,
+ ":%s CAP %s LS :%s",
+ RELAY_IRC_DATA(client, address),
+ (RELAY_IRC_DATA(client, nick)) ? RELAY_IRC_DATA(client, nick) : "nick",
+ *str_caps);
+ weechat_string_dyn_free (str_caps, 1);
+ }
+ weechat_arraylist_free (list_caps);
}
if (!RELAY_IRC_DATA(client, connected))
RELAY_IRC_DATA(client, cap_ls_received) = 1;
@@ -1320,49 +1515,63 @@ relay_irc_recv_command_capab (struct t_relay_client *client,
else if (weechat_strcasecmp (params[0], "req") == 0)
{
/* client is asking for one or more server capabilities */
- num_caps_received = 0;
- caps_ok = 0;
- server_caps = RELAY_IRC_DATA(client, server_capabilities);
- for (i = 1; i < num_params; i++)
+ list_caps = relay_irc_get_list_caps ();
+ if (list_caps)
{
- if (!params[i][0])
- continue;
- num_caps_received++;
- capability = relay_irc_search_server_capability (params[i]);
- if (capability >= 0)
+ supported_caps = relay_irc_get_supported_caps (client);
+ num_caps_received = 0;
+ caps_ok = 1;
+ server_caps = RELAY_IRC_DATA(client, server_capabilities);
+ str_caps = weechat_string_dyn_alloc (256);
+ if (str_caps)
{
- caps_ok = 1;
- server_caps |= 1 << capability;
+ for (i = 1; i < num_params; i++)
+ {
+ if (!params[i][0])
+ continue;
+ if ((*str_caps)[0])
+ weechat_string_dyn_concat (str_caps, " ", -1);
+ weechat_string_dyn_concat (str_caps, params[i], -1);
+ caps = weechat_string_split (params[i], " ", NULL, 0, 0,
+ &num_caps);
+ if (caps)
+ {
+ for (j = 0; j < num_caps; j++)
+ {
+ num_caps_received++;
+ capability = relay_irc_search_server_capability (caps[j]);
+ if ((capability >= 0) && (supported_caps & (1 << capability)))
+ server_caps |= 1 << capability;
+ else
+ caps_ok = 0;
+ }
+ weechat_string_free_split (caps);
+ }
+ }
+ if (num_caps_received == 0)
+ caps_ok = 0;
+ if (caps_ok)
+ RELAY_IRC_DATA(client, server_capabilities) = server_caps;
+ relay_irc_sendf (
+ client,
+ ":%s CAP %s %s :%s",
+ RELAY_IRC_DATA(client, address),
+ (RELAY_IRC_DATA(client, nick)) ? RELAY_IRC_DATA(client, nick) : "nick",
+ (caps_ok) ? "ACK" : "NAK",
+ *str_caps);
+ weechat_string_dyn_free (str_caps, 1);
}
- else
+ /*
+ * if the CAP REQ command is received without arguments, we consider
+ * the CAP END is received; this is a workaround for clients like
+ * Atomic which are sending "CAP REQ :" (see issue #1040)
+ */
+ if (num_caps_received == 0)
{
- caps_ok = 0;
- break;
+ if (!RELAY_IRC_DATA(client, connected))
+ RELAY_IRC_DATA(client, cap_end_received) = 1;
}
- }
- if (caps_ok)
- RELAY_IRC_DATA(client, server_capabilities) = server_caps;
- str_caps = (num_params > 1) ?
- weechat_string_rebuild_split_string (params, " ", 1, -1) : NULL;
- relay_irc_sendf (
- client,
- ":%s CAP %s %s :%s",
- RELAY_IRC_DATA(client, address),
- (RELAY_IRC_DATA(client, nick)) ? RELAY_IRC_DATA(client, nick) : "nick",
- (caps_ok) ? "ACK" : "NAK",
- (str_caps) ? str_caps : "");
- if (str_caps)
- free (str_caps);
-
- /*
- * if the CAP REQ command is received without arguments, we consider
- * the CAP END is received; this is a workaround for clients like
- * Atomic which are sending "CAP REQ :" (see issue #1040)
- */
- if (num_caps_received == 0)
- {
- if (!RELAY_IRC_DATA(client, connected))
- RELAY_IRC_DATA(client, cap_end_received) = 1;
+ weechat_arraylist_free (list_caps);
}
}
else if (weechat_strcasecmp (params[0], "end") == 0)
@@ -1568,6 +1777,8 @@ relay_irc_recv (struct t_relay_client *client, const char *data)
}
RELAY_IRC_DATA(client, connected) = 1;
+ RELAY_IRC_DATA(client, irc_cap_echo_message) = relay_irc_cap_enabled (
+ client, "echo-message");
/*
* send nick to client if server nick is different of nick asked
@@ -1940,6 +2151,7 @@ relay_irc_alloc (struct t_relay_client *client)
RELAY_IRC_DATA(client, cap_ls_received) = 0;
RELAY_IRC_DATA(client, cap_end_received) = 0;
RELAY_IRC_DATA(client, connected) = 0;
+ RELAY_IRC_DATA(client, irc_cap_echo_message) = 0;
RELAY_IRC_DATA(client, server_capabilities) = 0;
RELAY_IRC_DATA(client, hook_signal_irc_in2) = NULL;
RELAY_IRC_DATA(client, hook_signal_irc_outtags) = NULL;
@@ -1974,6 +2186,7 @@ relay_irc_alloc_with_infolist (struct t_relay_client *client,
RELAY_IRC_DATA(client, cap_ls_received) = weechat_infolist_integer (infolist, "cap_ls_received");
RELAY_IRC_DATA(client, cap_end_received) = weechat_infolist_integer (infolist, "cap_end_received");
RELAY_IRC_DATA(client, connected) = weechat_infolist_integer (infolist, "connected");
+ RELAY_IRC_DATA(client, irc_cap_echo_message) = weechat_infolist_integer (infolist, "irc_cap_echo_message");
RELAY_IRC_DATA(client, server_capabilities) = weechat_infolist_integer (infolist, "server_capabilities");
if (RELAY_IRC_DATA(client, connected))
{
@@ -2074,6 +2287,8 @@ relay_irc_add_to_infolist (struct t_infolist_item *item,
return 0;
if (!weechat_infolist_new_var_integer (item, "cap_end_received", RELAY_IRC_DATA(client, cap_end_received)))
return 0;
+ if (!weechat_infolist_new_var_integer (item, "irc_cap_echo_message", RELAY_IRC_DATA(client, irc_cap_echo_message)))
+ return 0;
if (!weechat_infolist_new_var_integer (item, "server_capabilities", RELAY_IRC_DATA(client, server_capabilities)))
return 0;
if (!weechat_infolist_new_var_pointer (item, "hook_signal_irc_in2", RELAY_IRC_DATA(client, hook_signal_irc_in2)))
@@ -2104,6 +2319,7 @@ relay_irc_print_log (struct t_relay_client *client)
weechat_log_printf (" cap_ls_received . . . . : %d", RELAY_IRC_DATA(client, cap_ls_received));
weechat_log_printf (" cap_end_received. . . . : %d", RELAY_IRC_DATA(client, cap_end_received));
weechat_log_printf (" connected . . . . . . . : %d", RELAY_IRC_DATA(client, connected));
+ weechat_log_printf (" irc_cap_echo_message. . : %d", RELAY_IRC_DATA(client, irc_cap_echo_message));
weechat_log_printf (" server_capabilities . . : %d", RELAY_IRC_DATA(client, server_capabilities));
weechat_log_printf (" hook_signal_irc_in2 . . : 0x%lx", RELAY_IRC_DATA(client, hook_signal_irc_in2));
weechat_log_printf (" hook_signal_irc_outtags : 0x%lx", RELAY_IRC_DATA(client, hook_signal_irc_outtags));
diff --git a/src/plugins/relay/irc/relay-irc.h b/src/plugins/relay/irc/relay-irc.h
index 8898487f5..b26ae3446 100644
--- a/src/plugins/relay/irc/relay-irc.h
+++ b/src/plugins/relay/irc/relay-irc.h
@@ -26,6 +26,9 @@ enum t_relay_status;
#define RELAY_IRC_DATA(client, var) \
(((struct t_relay_irc_data *)client->protocol_data)->var)
+#define RELAY_IRC_CAPAB_FOLLOW_SERVER \
+ (1 << RELAY_IRC_CAPAB_ECHO_MESSAGE)
+
struct t_relay_irc_data
{
char *address; /* client address (used when sending */
@@ -37,6 +40,8 @@ struct t_relay_irc_data
int cap_end_received; /* 1 if CAP END was received */
int connected; /* 1 if client is connected as IRC */
/* client */
+ int irc_cap_echo_message; /* 1 if cap echo-message is enabled */
+ /* in IRC server */
int server_capabilities; /* server capabilities enabled (one */
/* bit per capability) */
struct t_hook *hook_signal_irc_in2; /* signal "irc_in2" */
@@ -56,9 +61,16 @@ enum t_relay_irc_command
RELAY_IRC_NUM_CMD,
};
+/*
+ * IMPORTANT:
+ * - only add newly supported caps at the end of list
+ * - these caps are sorted before being sent as "available" to the clients
+ */
+
enum t_relay_irc_server_capab
{
RELAY_IRC_CAPAB_SERVER_TIME = 0,
+ RELAY_IRC_CAPAB_ECHO_MESSAGE,
/* number of server capabilities */
RELAY_IRC_NUM_CAPAB,
};
diff --git a/tests/unit/plugins/irc/test-irc-protocol.cpp b/tests/unit/plugins/irc/test-irc-protocol.cpp
index 15288b866..44ac3fc0c 100644
--- a/tests/unit/plugins/irc/test-irc-protocol.cpp
+++ b/tests/unit/plugins/irc/test-irc-protocol.cpp
@@ -212,16 +212,16 @@ extern char *irc_protocol_cap_to_enable (const char *capabilities,
"irc_join,irc_smart_filter,nick_bob,host_user_b@host_b," \
"log4");
-struct t_irc_server *ptr_server = NULL;
-struct t_arraylist *sent_messages = NULL;
-struct t_hook *hook_signal_irc_out = NULL;
-
TEST_GROUP(IrcProtocol)
{
};
TEST_GROUP(IrcProtocolWithServer)
{
+ struct t_irc_server *ptr_server = NULL;
+ struct t_arraylist *sent_messages = NULL;
+ struct t_hook *hook_signal_irc_out = NULL;
+
void server_recv (const char *command)
{
char str_command[4096];
@@ -289,13 +289,15 @@ TEST_GROUP(IrcProtocolWithServer)
void *signal_data)
{
/* make C++ compiler happy */
- (void) pointer;
(void) data;
(void) signal;
(void) type_data;
if (signal_data)
- arraylist_add (sent_messages, strdup ((const char *)signal_data));
+ {
+ arraylist_add ((struct t_arraylist *)pointer,
+ strdup ((const char *)signal_data));
+ }
return WEECHAT_RC_OK;
}
@@ -350,9 +352,10 @@ TEST_GROUP(IrcProtocolWithServer)
if (!hook_signal_irc_out)
{
- hook_signal_irc_out = hook_signal (NULL,
- IRC_FAKE_SERVER ",irc_out1_*",
- &signal_irc_out_cb, NULL, NULL);
+ hook_signal_irc_out = hook_signal (
+ NULL,
+ IRC_FAKE_SERVER ",irc_out1_*",
+ &signal_irc_out_cb, sent_messages, NULL);
}
/*
diff --git a/tests/unit/plugins/relay/irc/test-relay-irc.cpp b/tests/unit/plugins/relay/irc/test-relay-irc.cpp
index b3966f768..52b6bbe85 100644
--- a/tests/unit/plugins/relay/irc/test-relay-irc.cpp
+++ b/tests/unit/plugins/relay/irc/test-relay-irc.cpp
@@ -34,6 +34,7 @@ extern "C"
#include "src/core/wee-hook.h"
#include "src/core/wee-string.h"
#include "src/plugins/plugin.h"
+#include "src/plugins/irc/irc-server.h"
#include "src/plugins/relay/relay.h"
#include "src/plugins/relay/relay-client.h"
#include "src/plugins/relay/relay-config.h"
@@ -46,11 +47,17 @@ extern int relay_irc_search_server_capability (const char *capability);
extern struct t_hashtable *relay_irc_message_parse (const char *message);
extern void relay_irc_sendf (struct t_relay_client *client,
const char *format, ...);
+extern void relay_irc_parse_cap_message (struct t_relay_client *client,
+ struct t_hashtable *parsed_msg);
extern int relay_irc_tag_relay_client_id (const char *tags);
extern void relay_irc_input_send (struct t_relay_client *client,
const char *irc_channel,
const char *options,
const char *format, ...);
+extern int relay_irc_cap_enabled (struct t_relay_client *client,
+ const char *capability);
+extern int relay_irc_get_supported_caps (struct t_relay_client *client);
+extern struct t_arraylist *relay_irc_get_list_caps ();
}
#define CLIENT_RECV(__irc_msg) \
@@ -113,19 +120,20 @@ extern void relay_irc_input_send (struct t_relay_client *client,
FAIL(string_dyn_free (msg, 0)); \
}
-struct t_relay_server *ptr_relay_server = NULL;
-struct t_relay_client *ptr_relay_client = NULL;
-struct t_arraylist *sent_messages_client = NULL;
-struct t_arraylist *sent_messages_irc = NULL;
-struct t_hook *hook_modifier_relay_irc_out = NULL;
-struct t_hook *hook_signal_irc_input_send = NULL;
-
TEST_GROUP(RelayIrc)
{
};
TEST_GROUP(RelayIrcWithClient)
{
+ struct t_irc_server *ptr_server = NULL;
+ struct t_relay_server *ptr_relay_server = NULL;
+ struct t_relay_client *ptr_relay_client = NULL;
+ struct t_arraylist *sent_messages_client = NULL;
+ struct t_arraylist *sent_messages_irc = NULL;
+ struct t_hook *hook_modifier_relay_irc_out = NULL;
+ struct t_hook *hook_signal_irc_input_send = NULL;
+
void test_client_recv (const char *data)
{
record_start ();
@@ -189,13 +197,12 @@ TEST_GROUP(RelayIrcWithClient)
const char *string)
{
/* make C++ compiler happy */
- (void) pointer;
(void) data;
(void) modifier;
(void) modifier_data;
if (string)
- arraylist_add (sent_messages_client, strdup (string));
+ arraylist_add ((struct t_arraylist *)pointer, strdup (string));
return NULL;
}
@@ -206,14 +213,13 @@ TEST_GROUP(RelayIrcWithClient)
void *signal_data)
{
/* make C++ compiler happy */
- (void) pointer;
(void) data;
(void) signal;
(void) type_data;
if (signal_data)
{
- arraylist_add (sent_messages_irc,
+ arraylist_add ((struct t_arraylist *)pointer,
strdup ((const char *)signal_data));
}
@@ -291,7 +297,7 @@ TEST_GROUP(RelayIrcWithClient)
hook_modifier_relay_irc_out = hook_modifier (
NULL,
"relay_client_irc_out1",
- &modifier_relay_irc_out_cb, NULL, NULL);
+ &modifier_relay_irc_out_cb, sent_messages_client, NULL);
}
if (!hook_signal_irc_input_send)
@@ -299,13 +305,16 @@ TEST_GROUP(RelayIrcWithClient)
hook_signal_irc_input_send = hook_signal (
NULL,
"irc_input_send",
- &signal_irc_input_send_cb, NULL, NULL);
+ &signal_irc_input_send_cb, sent_messages_irc, NULL);
}
/* create a fake server (no I/O) */
run_cmd_quiet ("/mute /server add test fake:127.0.0.1 "
"-nicks=nick1,nick2,nick3");
+ /* get the server pointer */
+ ptr_server = irc_server_search ("test");
+
/* connect to the fake server */
run_cmd_quiet ("/connect test");
@@ -333,14 +342,15 @@ TEST_GROUP(RelayIrcWithClient)
void teardown ()
{
relay_client_free (ptr_relay_client);
- relay_server_free (ptr_relay_server);
+ ptr_relay_client = NULL;
+ relay_server_free (ptr_relay_server);
ptr_relay_server = NULL;
- ptr_relay_client = NULL;
/* disconnect and delete the fake server */
run_cmd_quiet ("/mute /disconnect test");
run_cmd_quiet ("/mute /server del test");
+ ptr_server = NULL;
/* restore auto-open of relay buffer */
config_file_option_reset (relay_config_look_auto_open_buffer, 1);
@@ -413,6 +423,7 @@ TEST(RelayIrc, RelayIrcSearchServerCapability)
LONGS_EQUAL(-1, relay_irc_search_server_capability ("unknown"));
CHECK(relay_irc_search_server_capability ("server-time") >= 0);
+ CHECK(relay_irc_search_server_capability ("echo-message") >= 0);
}
/*
@@ -490,6 +501,42 @@ TEST(RelayIrcWithClient, RelayIrcSendf)
/*
* Tests functions:
+ * relay_irc_parse_cap_message
+ */
+
+TEST(RelayIrcWithClient, RelayIrcParseCapMessage)
+{
+ struct t_hashtable *hashtable;
+
+ LONGS_EQUAL(0, RELAY_IRC_DATA(ptr_relay_client, irc_cap_echo_message));
+
+ /* CAP NAK: ignored */
+ hashtable = relay_irc_message_parse (":server CAP * NAK echo-message");
+ relay_irc_parse_cap_message (ptr_relay_client, hashtable);
+ LONGS_EQUAL(0, RELAY_IRC_DATA(ptr_relay_client, irc_cap_echo_message));
+ hashtable_free (hashtable);
+
+ /* CAP ACK with unknown capability */
+ hashtable = relay_irc_message_parse (":server CAP * ACK unknown");
+ relay_irc_parse_cap_message (ptr_relay_client, hashtable);
+ LONGS_EQUAL(0, RELAY_IRC_DATA(ptr_relay_client, irc_cap_echo_message));
+ hashtable_free (hashtable);
+
+ /* CAP ACK with extended-join and echo-message */
+ hashtable = relay_irc_message_parse (":server CAP * ACK extended-join echo-message");
+ relay_irc_parse_cap_message (ptr_relay_client, hashtable);
+ LONGS_EQUAL(1, RELAY_IRC_DATA(ptr_relay_client, irc_cap_echo_message));
+ hashtable_free (hashtable);
+
+ /* CAP ACK with -extended-join and -echo-message */
+ hashtable = relay_irc_message_parse (":server CAP * ACK -extended-join -echo-message");
+ relay_irc_parse_cap_message (ptr_relay_client, hashtable);
+ LONGS_EQUAL(0, RELAY_IRC_DATA(ptr_relay_client, irc_cap_echo_message));
+ hashtable_free (hashtable);
+}
+
+/*
+ * Tests functions:
* relay_irc_signal_irc_in2_cb
*/
@@ -609,6 +656,92 @@ TEST(RelayIrc, RelayIrcHookSignals)
/*
* Tests functions:
+ * relay_irc_capability_compare_cb
+ */
+
+TEST(RelayIrc, RelayIrcCapabilityCompareCb)
+{
+ /* TODO: write tests */
+}
+
+/*
+ * Tests functions:
+ * relay_irc_capability_free_db
+ */
+
+TEST(RelayIrc, RelayIrcCapabilityFreeDb)
+{
+ /* TODO: write tests */
+}
+
+/*
+ * Tests functions:
+ * relay_irc_cap_enabled
+ */
+
+TEST(RelayIrcWithClient, RelayIrcCapEnabled)
+{
+ LONGS_EQUAL(0, relay_irc_cap_enabled (NULL, NULL));
+ LONGS_EQUAL(0, relay_irc_cap_enabled (NULL, "echo-message"));
+ LONGS_EQUAL(0, relay_irc_cap_enabled (ptr_relay_client, NULL));
+ LONGS_EQUAL(0, relay_irc_cap_enabled (ptr_relay_client, ""));
+
+ LONGS_EQUAL(0, relay_irc_cap_enabled (ptr_relay_client, "echo-message"));
+
+ hashtable_set (ptr_server->cap_list, "echo-message", NULL);
+ LONGS_EQUAL(1, relay_irc_cap_enabled (ptr_relay_client, "echo-message"));
+ hashtable_remove (ptr_server->cap_list, "echo-message");
+
+ LONGS_EQUAL(0, relay_irc_cap_enabled (ptr_relay_client, "echo-message"));
+}
+
+/*
+ * Tests functions:
+ * relay_irc_get_supported_caps
+ */
+
+TEST(RelayIrcWithClient, RelayIrcGetSupportedCaps)
+{
+ int supported_caps;
+
+ supported_caps = relay_irc_get_supported_caps (ptr_relay_client);
+ LONGS_EQUAL(1 << RELAY_IRC_CAPAB_SERVER_TIME, supported_caps);
+
+ hashtable_set (ptr_server->cap_list, "echo-message", NULL);
+ supported_caps = relay_irc_get_supported_caps (ptr_relay_client);
+ LONGS_EQUAL((1 << RELAY_IRC_CAPAB_SERVER_TIME)
+ | (1 << RELAY_IRC_CAPAB_ECHO_MESSAGE),
+ supported_caps);
+ hashtable_remove (ptr_server->cap_list, "echo-message");
+}
+
+/*
+ * Tests functions:
+ * relay_irc_get_list_caps
+ */
+
+TEST(RelayIrc, RelayGetListCaps)
+{
+ struct t_arraylist *list_caps;
+ int i, size;
+
+ list_caps = relay_irc_get_list_caps ();
+ CHECK(list_caps);
+ size = arraylist_size (list_caps);
+ LONGS_EQUAL(RELAY_IRC_NUM_CAPAB, size);
+
+ /* check that it's properly sorted */
+ for (i = 1; i < size; i++)
+ {
+ CHECK(strcmp ((const char *)arraylist_get (list_caps, i - 1),
+ (const char *)arraylist_get (list_caps, i)) < 0);
+ }
+
+ arraylist_free (list_caps);
+}
+
+/*
+ * Tests functions:
* relay_irc_recv_command_capab
*/
@@ -629,13 +762,21 @@ TEST(RelayIrcWithClient, RelayIrcRecvCommandCapab)
POINTERS_EQUAL(1, RELAY_IRC_DATA(ptr_relay_client, cap_ls_received));
POINTERS_EQUAL(0, RELAY_IRC_DATA(ptr_relay_client, cap_end_received));
+ /* enable "echo-message" in IRC server and list supported capabilities */
+ hashtable_set (ptr_server->cap_list, "echo-message", NULL);
+ CLIENT_RECV(":alice!user@host CAP LS");
+ CHECK_SENT_CLIENT(":weechat.relay.irc CAP nick LS :echo-message server-time");
+ POINTERS_EQUAL(1, RELAY_IRC_DATA(ptr_relay_client, cap_ls_received));
+ POINTERS_EQUAL(0, RELAY_IRC_DATA(ptr_relay_client, cap_end_received));
+ hashtable_remove (ptr_server->cap_list, "echo-message");
+
/* request unknown capability: reject */
CLIENT_RECV(":alice!user@host CAP REQ unknown");
CHECK_SENT_CLIENT(":weechat.relay.irc CAP nick NAK :unknown");
POINTERS_EQUAL(0, RELAY_IRC_DATA(ptr_relay_client, server_capabilities));
POINTERS_EQUAL(0, RELAY_IRC_DATA(ptr_relay_client, cap_end_received));
- /* request supported capability: accept */
+ /* request 1 supported capability: accept */
CLIENT_RECV(":alice!user@host CAP REQ server-time");
CHECK_SENT_CLIENT(":weechat.relay.irc CAP nick ACK :server-time");
CHECK(RELAY_IRC_DATA(ptr_relay_client, server_capabilities)
@@ -643,7 +784,18 @@ TEST(RelayIrcWithClient, RelayIrcRecvCommandCapab)
POINTERS_EQUAL(0, RELAY_IRC_DATA(ptr_relay_client, cap_end_received));
RELAY_IRC_DATA(ptr_relay_client, server_capabilities) = 0;
- /* request unknown + supported capabilities: reject */
+ /* request 2 supported capabilities: accept */
+ hashtable_set (ptr_server->cap_list, "echo-message", NULL);
+ CLIENT_RECV(":alice!user@host CAP REQ :server-time echo-message");
+ CHECK_SENT_CLIENT(":weechat.relay.irc CAP nick ACK :server-time echo-message");
+ CHECK(RELAY_IRC_DATA(ptr_relay_client, server_capabilities)
+ & ((1 << RELAY_IRC_CAPAB_SERVER_TIME)
+ | (1 << RELAY_IRC_CAPAB_ECHO_MESSAGE)));
+ POINTERS_EQUAL(0, RELAY_IRC_DATA(ptr_relay_client, cap_end_received));
+ RELAY_IRC_DATA(ptr_relay_client, server_capabilities) = 0;
+ hashtable_remove (ptr_server->cap_list, "echo-message");
+
+ /* request unknown + supported capabilities: reject both */
CLIENT_RECV(":alice!user@host CAP REQ :server-time unknown");
CHECK_SENT_CLIENT(":weechat.relay.irc CAP nick NAK :server-time unknown");
POINTERS_EQUAL(0, RELAY_IRC_DATA(ptr_relay_client, server_capabilities));