]> jfr.im git - irc/quakenet/newserv.git/blame - serverlist/serverlist.c
serverlist: Implement lag checks using RPING.
[irc/quakenet/newserv.git] / serverlist / serverlist.c
CommitLineData
b7eccf5f
P
1/* Some utterly useless dog */
2
3#include "../core/schedule.h"
475b3d9d 4#include "../irc/irc.h"
b7eccf5f
P
5#include "../lib/irc_string.h"
6#include "../localuser/localuserchannel.h"
7#include "../control/control.h"
074a4529 8#include "../usercount/usercount.h"
240bbd21
CP
9#include "../lib/version.h"
10
11MODULE_VERSION("")
b7eccf5f
P
12
13#include <stdlib.h>
14#include <string.h>
15#include <stdarg.h>
475b3d9d 16#include <sys/time.h>
b7eccf5f
P
17
18int cmd_serverlist(void *sender, int cargc, char **cargv);
19void serverlist_hook_newserver(int hook, void *arg);
20void serverlist_hook_lostserver(int hook, void *arg);
21int serverlist_versionreply(void *source, int cargc, char **cargv);
475b3d9d
GB
22void serverlist_pingservers(void *arg);
23int serverlist_rpong(void *source, int cargc, char **cargv);
b7eccf5f
P
24
25struct {
26 int used;
27 time_t ts;
475b3d9d 28 int lag;
b7eccf5f
P
29 sstring *version1;
30 sstring *version2;
31} serverinfo[MAXSERVERS];
32
33void serverlist_doversion(void);
34
35
36void _init(void) {
37 registercontrolhelpcmd("serverlist",NO_OPER,1,&cmd_serverlist,"Usage: serverlist [pattern]\nShows all currently connected servers");
38 /* hooks for serverlist */
39 registerhook(HOOK_SERVER_NEWSERVER, &serverlist_hook_newserver);
40 registerhook(HOOK_SERVER_LOSTSERVER, &serverlist_hook_lostserver);
41 int i;
42
43 for (i = 0; i < MAXSERVERS; i++) {
44 if (serverlist[i].linkstate == LS_LINKED)
45 serverinfo[i].used = 1;
46 else
47 serverinfo[i].used = 0;
48
49 serverinfo[i].ts = getnettime();
475b3d9d 50 serverinfo[i].lag = -1;
b7eccf5f
P
51 serverinfo[i].version1 = NULL;
52 serverinfo[i].version2 = NULL;
53 }
54 registernumerichandler(351, &serverlist_versionreply, 2);
475b3d9d 55 registerserverhandler("RO", &serverlist_rpong, 4);
b7eccf5f 56
475b3d9d 57 schedulerecurring(time(NULL)+1, 0, 10, &serverlist_pingservers, NULL);
b7eccf5f
P
58}
59
60void _fini(void) {
61 int i;
62 for (i = 0; i < MAXSERVERS; i++) {
63 if (serverinfo[i].used) {
64 freesstring(serverinfo[i].version1);
65 freesstring(serverinfo[i].version2);
66 }
67 }
68 deregisternumerichandler(351, &serverlist_versionreply);
475b3d9d 69 deregisterserverhandler("RO", &serverlist_rpong);
b7eccf5f
P
70
71 deregisterhook(HOOK_SERVER_NEWSERVER, &serverlist_hook_newserver);
72 deregisterhook(HOOK_SERVER_LOSTSERVER, &serverlist_hook_lostserver);
73
74 deregistercontrolcmd("serverlist",cmd_serverlist);
475b3d9d
GB
75
76 deleteschedule(NULL, &serverlist_pingservers, NULL);
b7eccf5f
P
77}
78
79int cmd_serverlist(void *sender, int cargc, char **cargv) {
80 nick *np = (nick*)sender;
81 int a, i, ucount, acount, scount;
82
475b3d9d 83 controlreply(np, "%-7s %-30s %5s/%5s/%-5s %-7s %-16s %-10s %-20s", "Numeric", "Hostname", "ECl", "Cl", "MaxCl", "Flags", "Connected for", "Lag", "Version");
b7eccf5f
P
84
85 scount = acount = 0;
86
87 for (i = 0; i < MAXSERVERS; i++) {
88 if (serverlist[i].linkstate == LS_LINKED && (cargc < 1 || match2strings(cargv[0], serverlist[i].name->content))) {
89 ucount = 0;
90
19f8fda5 91 for (a = 0; a <= serverlist[i].maxusernum; a++)
b7eccf5f
P
92 if (servernicks[i][a] != NULL)
93 ucount++;
94
95 acount += ucount;
96 scount++;
97
475b3d9d 98 controlreply(np, "%-7d %-30s %5d/%5d/%-5d %-7s %-16s %-10d %-20s - %s", i, serverlist[i].name->content,
4f2ceb49
CP
99 servercount[i], ucount, serverlist[i].maxusernum,
100 printflags(serverlist[i].flags, smodeflags),
101 longtoduration(getnettime() - serverinfo[i].ts, 0),
475b3d9d 102 serverinfo[i].lag,
b7eccf5f
P
103 serverinfo[i].version1 ? serverinfo[i].version1->content : "Unknown",
104 serverinfo[i].version2 ? serverinfo[i].version2->content : "Unknown");
105 }
106 }
107
108 controlreply(np, "--- End of list. %d users and %d servers on the net.", acount, scount);
109
110 /* update version info for next time */
111 serverlist_doversion();
112
113 return CMD_OK;
114}
115
116int serverlist_versionreply(void *source, int cargc, char **cargv) {
117 int num;
118
119 if (cargc < 6)
120 return CMD_OK;
121
122 num = numerictolong(cargv[0], 2);
123
124 if (serverinfo[num].used) {
125 freesstring(serverinfo[num].version1);
126 freesstring(serverinfo[num].version2);
127
128 serverinfo[num].version1 = getsstring(cargv[3], strlen(cargv[3]));
129 serverinfo[num].version2 = getsstring(cargv[5], strlen(cargv[5]));
130 }
131 return CMD_OK;
132}
133
134void serverlist_doversion(void) {
135 int i;
136 char *num1, *numeric;
137
138 if (mynick == NULL)
139 return;
140
141 for (i = 0; i < MAXSERVERS; i++) {
142 if (serverlist[i].linkstate == LS_LINKED && serverinfo[i].version1 == NULL) {
143 numeric = longtonumeric(mynick->numeric,5);
144 num1 = (char*)malloc(strlen(numeric) + 1); /* bleh.. longtonumeric() is using static variables */
145 strcpy(num1, numeric);
146
147 irc_send("%s V :%s", num1, longtonumeric(i,2));
148 free(num1);
149 }
150 }
151}
152
153void serverlist_hook_newserver(int hook, void *arg) {
154 char *num1, *numeric;
074a4529 155 long num = (long)arg;
b7eccf5f
P
156
157 if (mynick == NULL)
158 return;
159
160 serverinfo[num].used = 1;
161 serverinfo[num].ts = getnettime();
162 serverinfo[num].version1 = NULL;
163 serverinfo[num].version2 = NULL;
164
165 numeric = longtonumeric(mynick->numeric,5);
166 num1 = (char*)malloc(strlen(numeric) + 1); /* bleh.. longtonumeric() is using static variables */
167 strcpy(num1, numeric);
168
169 irc_send("%s V :%s", num1, longtonumeric(num,2));
170
171 free(num1);
172}
173
174void serverlist_hook_lostserver(int hook, void *arg) {
074a4529 175 long num = (long)arg;
b7eccf5f
P
176
177 serverinfo[num].used = 0;
178 freesstring(serverinfo[num].version1);
179 freesstring(serverinfo[num].version2);
180}
181
475b3d9d
GB
182
183void serverlist_pingservers(void *arg) {
184 int i;
185 server *from, *to;
186 char fnum[10], tnum[10];
187 struct timeval tv;
188
189 if (!mynick)
190 return;
191
192 for(i=0;i<MAXSERVERS;i++) {
193 to = &serverlist[i];
194
195 if (to->parent == -1)
196 continue;
197
198 from = &serverlist[to->parent];
199
200 if (to->linkstate != LS_LINKED || from->linkstate != LS_LINKED)
201 continue;
202
203 strcpy(fnum, longtonumeric(to->parent,2));
204 strcpy(tnum, longtonumeric(i, 2));
205
206 if (from->parent == -1) { /* Are we the source? */
207 (void) gettimeofday(&tv, NULL);
208 irc_send("%s RI %s %s %jd %jd :RP", mynumeric->content, tnum, longtonumeric(mynick->numeric,5), (intmax_t)tv.tv_sec, (intmax_t)tv.tv_usec);
209 } else {
210 strcpy(fnum, longtonumeric(to->parent,2));
211 strcpy(tnum, longtonumeric(i, 2));
212 irc_send("%s RI %s %s :RP", longtonumeric(mynick->numeric,5), to->name->content, fnum);
213 }
214 }
215}
216
217int serverlist_rpong(void *source, int cargc, char **cargv) {
218 int to, lag;
219 struct timeval tv;
220
221 if (cargc < 4)
222 return CMD_ERROR;
223
224 if (cargc == 5) { /* From target to source server */
225 if (strcmp(cargv[4], "RP") != 0)
226 return CMD_OK;
227
228 to = numerictolong(source, 2);
229
230 (void) gettimeofday(&tv, NULL);
231 lag = (tv.tv_sec - strtoull(cargv[2], NULL, 10)) * 1000 + (tv.tv_usec - strtoull(cargv[3], NULL, 10)) / 1000;
232 } else { /* From source server to client */
233 if (strcmp(cargv[3], "RP") != 0)
234 return CMD_OK;
235
236 to = findserver(cargv[1]);
237
238 if (to == -1)
239 return CMD_ERROR;
240
241 lag = atoi(cargv[2]);
242 }
243
244 serverinfo[to].lag = lag;
245
246 return CMD_OK;
247}
248