~ubuntu-branches/ubuntu/trusty/irssi-plugin-xmpp/trusty

« back to all changes in this revision

Viewing changes to src/core/xep/ping.c

  • Committer: Bazaar Package Importer
  • Author(s): David Ammouial
  • Date: 2009-05-12 12:14:44 UTC
  • mfrom: (1.1.3 upstream) (2.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20090512121444-5jeho5h3zsy4oij7
Tags: 0.13+cvs20090406-1
* New CVS snapshot, built against irssi-dev 0.8.13:
  - New features and bugfixes.
  - Fix segfault when successfully identified (Closes: #521227).
  - Fix build error (Closes: #527697)
* Depend on irssi >=0.8.13, build-depend on irssi-dev >=0.8.13.
* Bump Standards-Version to 3.8.1 (no changes needed).
* Add INTERNAL to documentation files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: ping.c,v 1.10 2009/04/03 11:21:35 cdidier Exp $
 
3
 *
 
4
 * Copyright (C) 2007,2008,2009 Colin DIDIER
 
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 version 2 as
 
8
 * published by the Free Software Foundation.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License along
 
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
18
 */
 
19
 
 
20
/*
 
21
 * XEP-0199: XMPP Ping
 
22
 * and lagmeter
 
23
 */
 
24
 
 
25
#include <string.h>
 
26
#include <time.h>
 
27
 
 
28
#include "module.h"
 
29
#include "misc.h"
 
30
#include "settings.h"
 
31
#include "signals.h"
 
32
 
 
33
#include "xmpp-servers.h"
 
34
#include "xmpp-commands.h"
 
35
#include "tool_datalist.h"
 
36
#include "disco.h"
 
37
#include "tools.h"
 
38
 
 
39
#define XMLNS_PING "urn:xmpp:ping"
 
40
 
 
41
struct ping_data {
 
42
        char     *id;
 
43
        GTimeVal  time;
 
44
};
 
45
 
 
46
static int       timeout_tag;
 
47
static GSList   *supported_servers;
 
48
static DATALIST *pings;
 
49
 
 
50
static void
 
51
request_ping(XMPP_SERVER_REC *server, const char *dest)
 
52
{
 
53
        struct ping_data *pd;
 
54
        LmMessage *lmsg;
 
55
        LmMessageNode *node;
 
56
        char *recoded;
 
57
 
 
58
        recoded = xmpp_recode_in(dest);
 
59
        lmsg = lm_message_new_with_sub_type(recoded,
 
60
            LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET);
 
61
        g_free(recoded);
 
62
        node = lm_message_node_add_child(lmsg->node, "ping", NULL);
 
63
        lm_message_node_set_attribute(node, XMLNS, XMLNS_PING);
 
64
        if (strcmp(dest, server->domain) == 0) {
 
65
                g_free(server->ping_id);
 
66
                server->ping_id =
 
67
                    g_strdup(lm_message_node_get_attribute(lmsg->node, "id"));
 
68
                g_get_current_time(&server->lag_sent);
 
69
                server->lag_last_check = time(NULL);
 
70
        } else {
 
71
                pd = g_new0(struct ping_data, 1);
 
72
                pd->id =
 
73
                    g_strdup(lm_message_node_get_attribute(lmsg->node, "id"));
 
74
                g_get_current_time(&pd->time);
 
75
                datalist_add(pings, server, dest, pd);
 
76
        }
 
77
        signal_emit("xmpp send iq", 2, server, lmsg);
 
78
        lm_message_unref(lmsg);
 
79
}
 
80
 
 
81
static void
 
82
send_ping(XMPP_SERVER_REC *server, const char *dest, const char *id)
 
83
{
 
84
        LmMessage *lmsg;
 
85
        char *recoded;
 
86
 
 
87
        recoded = xmpp_recode_in(dest);
 
88
        lmsg = lm_message_new_with_sub_type(recoded,
 
89
            LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_RESULT);
 
90
        g_free(recoded);
 
91
        if (id != NULL)
 
92
                lm_message_node_set_attribute(lmsg->node, "id", id);
 
93
        signal_emit("xmpp send iq", 2, server, lmsg);
 
94
        lm_message_unref(lmsg);
 
95
}
 
96
 
 
97
static void
 
98
sig_recv_iq(XMPP_SERVER_REC *server, LmMessage *lmsg, const int type,
 
99
    const char *id, const char *from, const char *to)
 
100
{
 
101
        DATALIST_REC *rec;
 
102
        LmMessageNode *node;
 
103
        GTimeVal now;
 
104
        struct ping_data *pd;
 
105
 
 
106
        if (type == LM_MESSAGE_SUB_TYPE_RESULT) {
 
107
                /* pong response from server of our ping */
 
108
                if (server->ping_id != NULL && strcmp(from, server->domain) == 0
 
109
                && strcmp(id, server->ping_id) == 0) {
 
110
                        g_get_current_time(&now);
 
111
                        server->lag =
 
112
                            (int)get_timeval_diff(&now, &server->lag_sent);
 
113
                        memset(&server->lag_sent, 0, sizeof(server->lag_sent));
 
114
                        g_free_and_null(server->ping_id);
 
115
                        signal_emit("server lag", 1, server);
 
116
                } else if (lmsg->node->children == NULL
 
117
                    && (rec = datalist_find(pings, server, from)) != NULL) {
 
118
                        pd = rec->data;
 
119
                        if (strcmp(id, pd->id) == 0) {
 
120
                                g_get_current_time(&now);
 
121
                                signal_emit("xmpp ping", 3, server, from,
 
122
                                    get_timeval_diff(&now, &pd->time));
 
123
                        }
 
124
                }
 
125
        } else if (type == LM_MESSAGE_SUB_TYPE_GET) {
 
126
                node = lm_find_node(lmsg->node, "query", XMLNS, XMLNS_PING);
 
127
                if (node != NULL)
 
128
                        send_ping(server, from,
 
129
                            lm_message_node_get_attribute(lmsg->node, "id"));
 
130
        }
 
131
}
 
132
 
 
133
static void
 
134
sig_server_features(XMPP_SERVER_REC *server)
 
135
{
 
136
        if (disco_have_feature(server->server_features, XMLNS_PING))
 
137
                supported_servers = g_slist_prepend(supported_servers, server);
 
138
}
 
139
 
 
140
static void
 
141
sig_disconnected(XMPP_SERVER_REC *server)
 
142
{
 
143
        if (!IS_XMPP_SERVER(server))
 
144
                return;
 
145
        supported_servers = g_slist_remove(supported_servers, server);
 
146
        datalist_cleanup(pings, server);
 
147
}
 
148
 
 
149
static int
 
150
check_ping_func(void)
 
151
{
 
152
        GSList *tmp;
 
153
        XMPP_SERVER_REC *server;
 
154
        time_t now;
 
155
        int lag_check_time, max_lag;
 
156
 
 
157
        lag_check_time = settings_get_time("lag_check_time")/1000;
 
158
        max_lag = settings_get_time("lag_max_before_disconnect")/1000;
 
159
        if (lag_check_time <= 0)
 
160
                return 1;
 
161
        now = time(NULL);
 
162
        for (tmp = supported_servers; tmp != NULL; tmp = tmp->next) {
 
163
                server = XMPP_SERVER(tmp->data);
 
164
                if (server->lag_sent.tv_sec != 0) {
 
165
                        /* waiting for lag reply */
 
166
                        if (max_lag > 1 &&
 
167
                            (now - server->lag_sent.tv_sec) > max_lag) {
 
168
                                /* too much lag - disconnect */
 
169
                                signal_emit("server lag disconnect", 1,
 
170
                                    server);
 
171
                                server->connection_lost = TRUE;
 
172
                                server_disconnect(SERVER(server));
 
173
                        }
 
174
                } else if ((server->lag_last_check + lag_check_time) < now &&
 
175
                    server->connected) {
 
176
                        /* no commands in buffer - get the lag */
 
177
                        request_ping(server, server->domain);
 
178
                }
 
179
        }
 
180
        return 1;
 
181
}
 
182
 
 
183
/* SYNTAX: PING [[<jid>[/<resource>]]|[<name]] */
 
184
static void
 
185
cmd_ping(const char *data, XMPP_SERVER_REC *server, WI_ITEM_REC *item)
 
186
{
 
187
        char *cmd_dest, *dest;
 
188
        void *free_arg;
 
189
 
 
190
        CMD_XMPP_SERVER(server);
 
191
        if (!cmd_get_params(data, &free_arg, 1, &cmd_dest))
 
192
                return;
 
193
        dest = xmpp_get_dest(cmd_dest, server, item);
 
194
        request_ping(server, dest);
 
195
        g_free(dest);
 
196
        cmd_params_free(free_arg);
 
197
}
 
198
 
 
199
static void
 
200
freedata_func(DATALIST_REC *rec)
 
201
{
 
202
        g_free(((struct ping_data *)rec->data)->id);
 
203
        g_free(rec->data);
 
204
}
 
205
 
 
206
void
 
207
ping_init(void)
 
208
{
 
209
        supported_servers = NULL;
 
210
        pings = datalist_new(freedata_func);
 
211
        disco_add_feature(XMLNS_PING);
 
212
        signal_add("xmpp recv iq", sig_recv_iq);
 
213
        signal_add("xmpp server features", sig_server_features);
 
214
        signal_add("server disconnected", sig_disconnected);
 
215
        command_bind_xmpp("ping", NULL, (SIGNAL_FUNC)cmd_ping);
 
216
        timeout_tag = g_timeout_add(1000, (GSourceFunc)check_ping_func, NULL);
 
217
}
 
218
 
 
219
void
 
220
ping_deinit(void)
 
221
{
 
222
        g_source_remove(timeout_tag);
 
223
        signal_remove("xmpp recv iq", sig_recv_iq);
 
224
        signal_remove("xmpp server features", sig_server_features);
 
225
        signal_remove("server disconnected", sig_disconnected);
 
226
        command_unbind("ping", (SIGNAL_FUNC)cmd_ping);
 
227
        g_slist_free(supported_servers);
 
228
        datalist_destroy(pings);
 
229
}