diff options
-rw-r--r-- | ChangeLog.adoc | 1 | ||||
-rw-r--r-- | src/plugins/relay/irc/relay-irc.c | 362 | ||||
-rw-r--r-- | src/plugins/relay/irc/relay-irc.h | 12 | ||||
-rw-r--r-- | tests/unit/plugins/irc/test-irc-protocol.cpp | 21 | ||||
-rw-r--r-- | tests/unit/plugins/relay/irc/test-relay-irc.cpp | 186 |
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)); |