1 /*
2  servers-reconnect.c : irssi
3 
4     Copyright (C) 1999-2000 Timo Sirainen
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License along
17     with this program; if not, write to the Free Software Foundation, Inc.,
18     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20 
21 #include "module.h"
22 #include "commands.h"
23 #include "network.h"
24 #include "signals.h"
25 
26 #include "modes.h"
27 #include "irc-servers.h"
28 
29 #include "settings.h"
30 
sig_server_connect_copy(SERVER_CONNECT_REC ** dest,IRC_SERVER_CONNECT_REC * src)31 static void sig_server_connect_copy(SERVER_CONNECT_REC **dest,
32 				    IRC_SERVER_CONNECT_REC *src)
33 {
34 	IRC_SERVER_CONNECT_REC *rec;
35 
36 	g_return_if_fail(dest != NULL);
37 	if (!IS_IRC_SERVER_CONNECT(src))
38 		return;
39 
40 	rec = g_new0(IRC_SERVER_CONNECT_REC, 1);
41 	rec->chat_type = IRC_PROTOCOL;
42 	rec->max_cmds_at_once = src->max_cmds_at_once;
43 	rec->cmd_queue_speed = src->cmd_queue_speed;
44         rec->max_query_chans = src->max_query_chans;
45 	rec->max_kicks = src->max_kicks;
46 	rec->max_modes = src->max_modes;
47 	rec->max_msgs = src->max_msgs;
48 	rec->max_whois = src->max_whois;
49 	rec->usermode = g_strdup(src->usermode);
50 	rec->alternate_nick = g_strdup(src->alternate_nick);
51 	rec->sasl_mechanism = src->sasl_mechanism;
52 	rec->sasl_username = g_strdup(src->sasl_username);
53 	rec->sasl_password = g_strdup(src->sasl_password);
54 	*dest = (SERVER_CONNECT_REC *) rec;
55 }
56 
sig_server_reconnect_save_status(IRC_SERVER_CONNECT_REC * conn,IRC_SERVER_REC * server)57 static void sig_server_reconnect_save_status(IRC_SERVER_CONNECT_REC *conn,
58 					     IRC_SERVER_REC *server)
59 {
60 	if (!IS_IRC_SERVER_CONNECT(conn) || !IS_IRC_SERVER(server) ||
61 	    !server->connected)
62 		return;
63 
64 	g_free_not_null(conn->channels);
65 	conn->channels = irc_server_get_channels(server);
66 
67 	g_free_not_null(conn->usermode);
68 	conn->usermode = g_strdup(server->wanted_usermode);
69 }
70 
sig_connected(IRC_SERVER_REC * server)71 static void sig_connected(IRC_SERVER_REC *server)
72 {
73 	if (!IS_IRC_SERVER(server) || !server->connrec->reconnection)
74 		return;
75 
76 	if (server->connrec->away_reason != NULL)
77 		irc_server_send_away(server, server->connrec->away_reason);
78 }
79 
event_nick_collision(IRC_SERVER_REC * server,const char * data)80 static void event_nick_collision(IRC_SERVER_REC *server, const char *data)
81 {
82 	time_t new_connect;
83 
84 	if (!IS_IRC_SERVER(server))
85 		return;
86 
87 	/* after server kills us because of nick collision, we want to
88 	   connect back immediately. but no matter how hard they kill us,
89 	   don't connect to the server more than once in every 10 seconds. */
90 
91 	new_connect = server->connect_time+10 -
92 		settings_get_time("server_reconnect_time")/1000;
93 	if (server->connect_time > new_connect)
94 		server->connect_time = new_connect;
95 
96         server->nick_collision = TRUE;
97 }
98 
event_kill(IRC_SERVER_REC * server,const char * data,const char * nick,const char * addr)99 static void event_kill(IRC_SERVER_REC *server, const char *data,
100 		       const char *nick, const char *addr)
101 {
102 	if (addr != NULL && !server->nick_collision) {
103 		/* don't reconnect if we were killed by an oper (not server) */
104 		server->no_reconnect = TRUE;
105 	}
106 }
107 
irc_servers_reconnect_init(void)108 void irc_servers_reconnect_init(void)
109 {
110 	signal_add("server connect copy", (SIGNAL_FUNC) sig_server_connect_copy);
111 	signal_add("server reconnect save status", (SIGNAL_FUNC) sig_server_reconnect_save_status);
112 	signal_add("event connected", (SIGNAL_FUNC) sig_connected);
113 	signal_add("event 436", (SIGNAL_FUNC) event_nick_collision);
114 	signal_add("event kill", (SIGNAL_FUNC) event_kill);
115 }
116 
irc_servers_reconnect_deinit(void)117 void irc_servers_reconnect_deinit(void)
118 {
119 	signal_remove("server connect copy", (SIGNAL_FUNC) sig_server_connect_copy);
120 	signal_remove("server reconnect save status", (SIGNAL_FUNC) sig_server_reconnect_save_status);
121 	signal_remove("event connected", (SIGNAL_FUNC) sig_connected);
122 	signal_remove("event 436", (SIGNAL_FUNC) event_nick_collision);
123 	signal_remove("event kill", (SIGNAL_FUNC) event_kill);
124 }
125