Added SILC Thread Queue API
[runtime.git] / apps / irssi / src / silc / core / silc-lag.c
1 #include "module.h"
2 #include "signals.h"
3 #include "misc.h"
4 #include "settings.h"
5
6 #include "silc-servers.h"
7
8 static int timeout_tag;
9 static SilcBool lag_event_pong(SilcClient client,
10                                SilcClientConnection conn,
11                                SilcCommand command,
12                                SilcStatus status,
13                                SilcStatus error,
14                                void *context,
15                                va_list ap);
16
17 static void lag_get(SILC_SERVER_REC *server)
18 {
19         SilcBuffer idp;
20         g_get_current_time(&server->lag_sent);
21         server->lag_last_check = time(NULL);
22
23         /* Send PING */
24         idp = silc_id_payload_encode(&server->conn->remote_id.u.server_id,
25                                      SILC_ID_SERVER);
26         silc_client_command_send(silc_client, server->conn,
27                                  SILC_COMMAND_PING, lag_event_pong, server,
28                                  1, 1, silc_buffer_data(idp),
29                                  silc_buffer_len(idp));
30         silc_buffer_free(idp);
31 }
32
33 static SilcBool lag_event_pong(SilcClient client,
34                                SilcClientConnection conn,
35                                SilcCommand command,
36                                SilcStatus status,
37                                SilcStatus error,
38                                void *context,
39                                va_list ap)
40 {
41         SILC_SERVER_REC *server = context;
42         GTimeVal now;
43
44         if (status != SILC_STATUS_OK) {
45                 /* if the ping failed for some reason, try it again */
46                 lag_get(server);
47                 return TRUE;
48         }
49
50         if (server->lag_sent.tv_sec == 0) {
51                 /* not expecting lag reply. */
52                 return TRUE;
53         }
54
55         g_get_current_time(&now);
56         server->lag = (int) get_timeval_diff(&now, &server->lag_sent);
57         memset(&server->lag_sent, 0, sizeof(server->lag_sent));
58
59         signal_emit("server lag", 1, server);
60
61         return TRUE;
62 }
63
64 static int sig_check_lag(void)
65 {
66         GSList *tmp, *next;
67         time_t now;
68         int lag_check_time, max_lag;
69
70         lag_check_time = settings_get_time("lag_check_time") / 1000;
71         max_lag = settings_get_time("lag_max_before_disconnect") / 1000;
72
73         if (lag_check_time <= 0)
74                 return 1;
75
76         now = time(NULL);
77         for (tmp = servers; tmp != NULL; tmp = next) {
78                 SILC_SERVER_REC *rec = tmp->data;
79
80                 next = tmp->next;
81                 if (!IS_SILC_SERVER(rec))
82                         continue;
83
84                 if (rec->lag_sent.tv_sec != 0) {
85                         /* waiting for lag reply */
86                         if (max_lag > 1 && now-rec->lag_sent.tv_sec > max_lag) {
87                                 /* too much lag, disconnect */
88                                 signal_emit("server lag disconnect", 1, rec);
89                                 rec->connection_lost = TRUE;
90                                 server_disconnect((SERVER_REC *) rec);
91                         }
92                 } else if (rec->lag_last_check+lag_check_time < now &&
93                          rec->connected) {
94                         /* no commands in buffer - get the lag */
95                         lag_get(rec);
96                 }
97         }
98
99         return 1;
100 }
101
102 void silc_lag_init(void)
103 {
104         /* silc-client will need those... silc-plugin uses irc defaults */
105         settings_add_time("misc", "lag_check_time", "1min");
106         settings_add_time("misc", "lag_max_before_disconnect", "5min");
107
108         timeout_tag = g_timeout_add(1000, (GSourceFunc) sig_check_lag, NULL);
109 }
110
111 void silc_lag_deinit(void)
112 {
113         g_source_remove(timeout_tag);
114 }