diff options
author | Timo Sirainen <cras@irssi.org> | 2001-02-19 02:15:15 +0000 |
---|---|---|
committer | cras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564> | 2001-02-19 02:15:15 +0000 |
commit | b8375d471fe245f454b1cdf15f5379fe17a1c928 (patch) | |
tree | 336e8df6842147615f666a7dc3f24be97bec11cf /src/core/chat-commands.c | |
parent | fa1715b5155c88749af8ecedfeffc97a4502fd9c (diff) | |
download | irssi-b8375d471fe245f454b1cdf15f5379fe17a1c928.zip |
Connection updates: moved /SERVER and /CONNECT to core from irc.
Several other related multiprotocol updates.
Removed /SILCSERVER from SILC, /CONNECT and /SERVER should work
properly now. Rejoining channels after reconnection works.
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@1245 dbcabf3a-b0e7-0310-adc4-f8d773084564
Diffstat (limited to 'src/core/chat-commands.c')
-rw-r--r-- | src/core/chat-commands.c | 221 |
1 files changed, 220 insertions, 1 deletions
diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c index 22dc9e4f..a22e24d2 100644 --- a/src/core/chat-commands.c +++ b/src/core/chat-commands.c @@ -19,14 +19,223 @@ */ #include "module.h" +#include "network.h" #include "signals.h" #include "commands.h" #include "special-vars.h" +#include "settings.h" -#include "servers.h" #include "chat-protocols.h" +#include "servers.h" +#include "servers-setup.h" +#include "servers-reconnect.h" #include "window-item-def.h" +static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr) +{ + CHAT_PROTOCOL_REC *proto; + SERVER_CONNECT_REC *conn; + GHashTable *optlist; + char *addr, *portstr, *password, *nick, *chatnet, *host; + void *free_arg; + + g_return_val_if_fail(data != NULL, NULL); + + if (!cmd_get_params(data, &free_arg, 4 | PARAM_FLAG_OPTIONS, + "connect", &optlist, &addr, &portstr, + &password, &nick)) + return NULL; + if (plus_addr != NULL) *plus_addr = *addr == '+'; + if (*addr == '+') addr++; + if (*addr == '\0') { + signal_emit("error command", 1, + GINT_TO_POINTER(CMDERR_NOT_ENOUGH_PARAMS)); + cmd_params_free(free_arg); + return NULL; + } + + if (strcmp(password, "-") == 0) + *password = '\0'; + + /* check if -<chatnet> option is used to specify chat protocol */ + proto = chat_protocol_find_net(optlist); + + /* connect to server */ + conn = server_create_conn(proto != NULL ? proto->id : -1, + addr, atoi(portstr), password, nick); + if (proto == NULL) + proto = chat_protocol_find_id(conn->chat_type); + + if (g_hash_table_lookup(optlist, "6") != NULL) + conn->family = AF_INET6; + else if (g_hash_table_lookup(optlist, "4") != NULL) + conn->family = AF_INET; + + chatnet = g_hash_table_lookup(optlist, proto->chatnet); + if (chatnet != NULL) { + g_free_not_null(conn->chatnet); + conn->chatnet = g_strdup(chatnet); + } + + host = g_hash_table_lookup(optlist, "host"); + if (host != NULL && *host != '\0') { + IPADDR ip; + + if (net_gethostbyname(host, &ip, conn->family) == 0) { + if (conn->own_ip == NULL) + conn->own_ip = g_new(IPADDR, 1); + memcpy(conn->own_ip, &ip, sizeof(IPADDR)); + } + } + + cmd_params_free(free_arg); + return conn; +} + +/* SYNTAX: CONNECT [-4 | -6] [-ircnet <ircnet>] [-host <hostname>] + <address>|<chatnet> [<port> [<password> [<nick>]]] */ +static void cmd_connect(const char *data) +{ + SERVER_CONNECT_REC *conn; + + conn = get_server_connect(data, NULL); + if (conn != NULL) + CHAT_PROTOCOL(conn)->server_connect(conn); +} + +static RECONNECT_REC *find_reconnect_server(int chat_type, + const char *addr, int port) +{ + RECONNECT_REC *match, *last_proto_match; + GSList *tmp; + int count; + + g_return_val_if_fail(addr != NULL, NULL); + + /* check if there's a reconnection to the same host and maybe even + the same port */ + match = last_proto_match = NULL; count = 0; + for (tmp = reconnects; tmp != NULL; tmp = tmp->next) { + RECONNECT_REC *rec = tmp->data; + + if (rec->conn->chat_type == chat_type) { + count++; last_proto_match = rec; + if (g_strcasecmp(rec->conn->address, addr) == 0) { + if (rec->conn->port == port) + return rec; + match = rec; + } + } + } + + if (count == 1) { + /* only one reconnection with wanted protocol, + we probably want to use it */ + return last_proto_match; + } + + return match; +} + +static void update_reconnection(SERVER_CONNECT_REC *conn, SERVER_REC *server) +{ + SERVER_CONNECT_REC *oldconn; + RECONNECT_REC *recon; + + conn->reconnection = TRUE; + + if (server != NULL) { + oldconn = server->connrec; + reconnect_save_status(conn, server); + } else { + /* maybe we can reconnect some server from + reconnection queue */ + recon = find_reconnect_server(conn->chat_type, + conn->address, conn->port); + if (recon == NULL) return; + + oldconn = recon->conn; + server_reconnect_destroy(recon, FALSE); + + conn->away_reason = g_strdup(oldconn->away_reason); + conn->channels = g_strdup(oldconn->channels); + } + + if (conn->chatnet == NULL && oldconn->chatnet != NULL) + conn->chatnet = g_strdup(oldconn->chatnet); + + if (server != NULL) { + signal_emit("command disconnect", 2, + "* Changing server", server); + } else { + server_connect_free(oldconn); + } +} + +/* SYNTAX: SERVER [-4 | -6] [-ircnet <ircnet>] [-host <hostname>] + [+]<address>|<chatnet> [<port> [<password> [<nick>]]] */ +static void cmd_server(const char *data, SERVER_REC *server) +{ + SERVER_CONNECT_REC *conn; + int plus_addr; + + g_return_if_fail(data != NULL); + + /* create connection record */ + conn = get_server_connect(data, &plus_addr); + if (conn != NULL) { + if (!plus_addr) + update_reconnection(conn, server); + CHAT_PROTOCOL(conn)->server_connect(conn); + } +} + +/* SYNTAX: DISCONNECT *|<tag> [<message>] */ +static void cmd_disconnect(const char *data, SERVER_REC *server) +{ + char *tag, *msg; + void *free_arg; + + g_return_if_fail(data != NULL); + + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &tag, &msg)) + return; + + if (*tag != '\0' && strcmp(tag, "*") != 0) + server = server_find_tag(tag); + if (server == NULL) cmd_param_error(CMDERR_NOT_CONNECTED); + + if (*msg == '\0') msg = (char *) settings_get_str("quit_message"); + signal_emit("server quit", 2, server, msg); + + cmd_params_free(free_arg); + server_disconnect(server); +} + +/* SYNTAX: QUIT [<message>] */ +static void cmd_quit(const char *data) +{ + GSList *tmp, *next; + const char *quitmsg; + char *str; + + g_return_if_fail(data != NULL); + + quitmsg = *data != '\0' ? data : + settings_get_str("quit_message"); + + /* disconnect from every server */ + for (tmp = servers; tmp != NULL; tmp = next) { + next = tmp->next; + + str = g_strdup_printf("* %s", quitmsg); + cmd_disconnect(str, tmp->data); + g_free(str); + } + + signal_emit("gui exit", 0); +} + /* SYNTAX: JOIN [-invite] [-<server tag>] <channels> [<keys>] */ static void cmd_join(const char *data, SERVER_REC *server) { @@ -101,13 +310,23 @@ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item) void chat_commands_init(void) { + command_bind("server", NULL, (SIGNAL_FUNC) cmd_server); + command_bind("connect", NULL, (SIGNAL_FUNC) cmd_connect); + command_bind("disconnect", NULL, (SIGNAL_FUNC) cmd_disconnect); + command_bind("quit", NULL, (SIGNAL_FUNC) cmd_quit); command_bind("join", NULL, (SIGNAL_FUNC) cmd_join); command_bind("msg", NULL, (SIGNAL_FUNC) cmd_msg); + + command_set_options("connect", "4 6 +host"); command_set_options("join", "invite"); } void chat_commands_deinit(void) { + command_unbind("server", (SIGNAL_FUNC) cmd_server); + command_unbind("connect", (SIGNAL_FUNC) cmd_connect); + command_unbind("disconnect", (SIGNAL_FUNC) cmd_disconnect); + command_unbind("quit", (SIGNAL_FUNC) cmd_quit); command_unbind("join", (SIGNAL_FUNC) cmd_join); command_unbind("msg", (SIGNAL_FUNC) cmd_msg); } |