1 /* Some utterly useless dog */
3 #include "../core/schedule.h"
4 #include "../irc/irc.h"
5 #include "../lib/irc_string.h"
6 #include "../localuser/localuserchannel.h"
7 #include "../control/control.h"
8 #include "../usercount/usercount.h"
9 #include "../lib/version.h"
10 #include "../serverlist/serverlist.h"
11 #include "../core/config.h"
12 #include "../lib/strlfunc.h"
23 int cmd_serverlist(void *sender
, int cargc
, char **cargv
);
24 void serverlist_hook_newserver(int hook
, void *arg
);
25 void serverlist_hook_lostserver(int hook
, void *arg
);
26 int serverlist_versionreply(void *source
, int cargc
, char **cargv
);
27 void serverlist_pingservers(void *arg
);
28 int serverlist_rpong(void *source
, int cargc
, char **cargv
);
30 const flag servertypeflags
[] = {
31 { 'c', SERVERTYPEFLAG_CLIENT_SERVER
},
32 { 'h', SERVERTYPEFLAG_HUB
},
33 { 's', SERVERTYPEFLAG_SERVICE
},
34 { 'Q', SERVERTYPEFLAG_CHANSERV
},
35 { 'S', SERVERTYPEFLAG_SPAMSCAN
},
36 { 'X', SERVERTYPEFLAG_CRITICAL_SERVICE
},
47 } serverinfo
[MAXSERVERS
];
49 void serverlist_doversion(void);
51 static sstring
*s_server
, *q_server
;
52 static pcre
*service_re
, *hub_re
, *not_client_re
;
54 static pcre
*compilefree(sstring
*re
) {
59 r
= pcre_compile(re
->content
, 0, &err
, &erroffset
, NULL
);
61 Error("serverlist", ERR_WARNING
, "Unable to compile RE %s (offset: %d, reason: %s)", re
->content
, erroffset
, err
);
71 registercontrolhelpcmd("serverlist",NO_OPER
,1,&cmd_serverlist
,"Usage: serverlist [pattern]\nShows all currently connected servers");
72 /* hooks for serverlist */
73 registerhook(HOOK_SERVER_NEWSERVER
, &serverlist_hook_newserver
);
74 registerhook(HOOK_SERVER_LOSTSERVER
, &serverlist_hook_lostserver
);
77 q_server
= getcopyconfigitem("serverlist", "q_server", "CServe.quakenet.org", HOSTLEN
);
78 s_server
= getcopyconfigitem("serverlist", "s_server", "services2.uk.quakenet.org", HOSTLEN
);
80 service_re
= compilefree(getcopyconfigitem("serverlist", "service_re", "^services\\d*\\..*$", 256));
81 hub_re
= compilefree(getcopyconfigitem("serverlist", "hub_re", "^hub\\d*\\..*$", 256));
82 not_client_re
= compilefree(getcopyconfigitem("serverlist", "not_client_re", "^(testserv\\d*\\.).*$", 256));
84 for (i
= 0; i
< MAXSERVERS
; i
++) {
85 if (serverlist
[i
].linkstate
== LS_LINKED
)
86 serverinfo
[i
].used
= 1;
88 serverinfo
[i
].used
= 0;
90 serverinfo
[i
].ts
= getnettime();
91 serverinfo
[i
].lag
= -1;
92 serverinfo
[i
].version1
= NULL
;
93 serverinfo
[i
].version2
= NULL
;
94 serverinfo
[i
].type
= getservertype(&serverlist
[i
]);
96 registernumerichandler(351, &serverlist_versionreply
, 2);
97 registerserverhandler("RO", &serverlist_rpong
, 4);
99 schedulerecurring(time(NULL
)+1, 0, 60, &serverlist_pingservers
, NULL
);
104 for (i
= 0; i
< MAXSERVERS
; i
++) {
105 if (serverinfo
[i
].used
) {
106 freesstring(serverinfo
[i
].version1
);
107 freesstring(serverinfo
[i
].version2
);
110 deregisternumerichandler(351, &serverlist_versionreply
);
111 deregisterserverhandler("RO", &serverlist_rpong
);
113 deregisterhook(HOOK_SERVER_NEWSERVER
, &serverlist_hook_newserver
);
114 deregisterhook(HOOK_SERVER_LOSTSERVER
, &serverlist_hook_lostserver
);
116 deregistercontrolcmd("serverlist",cmd_serverlist
);
118 deleteschedule(NULL
, &serverlist_pingservers
, NULL
);
120 freesstring(q_server
);
121 freesstring(s_server
);
122 pcre_free(service_re
);
124 pcre_free(not_client_re
);
127 int cmd_serverlist(void *sender
, int cargc
, char **cargv
) {
128 nick
*np
= (nick
*)sender
;
129 int a
, i
, ucount
, acount
, scount
;
133 controlreply(np
, "%-7s %-30s %5s/%5s/%-5s %-7s %-7s %-20s %-8s %-20s", "Numeric", "Hostname", "ECl", "Cl", "MaxCl", "Flags", "Type", "Connected for", "Lag", "Version");
137 for (i
= 0; i
< MAXSERVERS
; i
++) {
138 if (serverlist
[i
].linkstate
== LS_LINKED
&& (cargc
< 1 || match2strings(cargv
[0], serverlist
[i
].name
->content
))) {
141 for (a
= 0; a
<= serverlist
[i
].maxusernum
; a
++)
142 if (servernicks
[i
][a
] != NULL
)
148 if (serverinfo
[i
].lag
== -1)
151 snprintf(lagstr
, sizeof(lagstr
), "%d", serverinfo
[i
].lag
);
153 strlcpy(buf
, printflags(serverinfo
[i
].type
, servertypeflags
), sizeof(buf
));
155 controlreply(np
, "%-7d %-30s %5d/%5d/%-5d %-7s %-7s %-20s %-8s %-20s - %s", i
, serverlist
[i
].name
->content
,
156 servercount
[i
], ucount
, serverlist
[i
].maxusernum
,
157 printflags(serverlist
[i
].flags
, smodeflags
), buf
,
158 longtoduration(getnettime() - serverinfo
[i
].ts
, 0),
160 serverinfo
[i
].version1
? serverinfo
[i
].version1
->content
: "Unknown",
161 serverinfo
[i
].version2
? serverinfo
[i
].version2
->content
: "Unknown");
165 controlreply(np
, "--- End of list. %d users and %d servers on the net.", acount
, scount
);
167 /* update version info for next time */
168 serverlist_doversion();
173 int serverlist_versionreply(void *source
, int cargc
, char **cargv
) {
179 num
= numerictolong(cargv
[0], 2);
181 if (serverinfo
[num
].used
) {
182 freesstring(serverinfo
[num
].version1
);
183 freesstring(serverinfo
[num
].version2
);
185 serverinfo
[num
].version1
= getsstring(cargv
[3], strlen(cargv
[3]));
186 serverinfo
[num
].version2
= getsstring(cargv
[5], strlen(cargv
[5]));
191 void serverlist_doversion(void) {
193 char *num1
, *numeric
;
198 for (i
= 0; i
< MAXSERVERS
; i
++) {
199 if (serverlist
[i
].linkstate
== LS_LINKED
&& serverinfo
[i
].version1
== NULL
) {
200 numeric
= longtonumeric(mynick
->numeric
,5);
201 num1
= (char*)malloc(strlen(numeric
) + 1); /* bleh.. longtonumeric() is using static variables */
202 strcpy(num1
, numeric
);
204 irc_send("%s V :%s", num1
, longtonumeric(i
,2));
210 void serverlist_hook_newserver(int hook
, void *arg
) {
211 char *num1
, *numeric
;
212 long num
= (long)arg
;
214 serverinfo
[num
].used
= 1;
215 serverinfo
[num
].ts
= getnettime();
216 serverinfo
[num
].version1
= NULL
;
217 serverinfo
[num
].version2
= NULL
;
218 serverinfo
[num
].type
= getservertype(&serverlist
[num
]);
220 if (mynick
== NULL
) /* bleh this is buggy... doesn't do it when mynick appears */
223 numeric
= longtonumeric(mynick
->numeric
,5);
224 num1
= (char*)malloc(strlen(numeric
) + 1); /* bleh.. longtonumeric() is using static variables */
225 strcpy(num1
, numeric
);
227 irc_send("%s V :%s", num1
, longtonumeric(num
,2));
232 void serverlist_hook_lostserver(int hook
, void *arg
) {
233 long num
= (long)arg
;
235 serverinfo
[num
].used
= 0;
236 freesstring(serverinfo
[num
].version1
);
237 freesstring(serverinfo
[num
].version2
);
240 flag_t
getservertype(server
*server
) {
245 if(server
== NULL
|| server
->name
== NULL
)
248 server_name
= server
->name
->content
;
249 server_len
= server
->name
->length
;
251 if(server
->flags
& SMODE_SERVICE
)
252 result
|=SERVERTYPEFLAG_SERVICE
;
254 if(!strcmp(server_name
, q_server
->content
)) {
255 result
|=SERVERTYPEFLAG_CHANSERV
;
256 result
|=SERVERTYPEFLAG_CRITICAL_SERVICE
;
257 } else if(!strcmp(server_name
, s_server
->content
)) {
258 result
|=SERVERTYPEFLAG_SPAMSCAN
;
259 result
|=SERVERTYPEFLAG_CRITICAL_SERVICE
;
261 if(service_re
&& (pcre_exec(service_re
, NULL
, server_name
, server_len
, 0, 0, NULL
, 0) >= 0)) {
262 /* matches service re */
263 if((server
->flags
& SMODE_SERVICE
) == 0) {
264 /* is not a service */
265 Error("serverlist", ERR_WARNING
, "Non-service server (%s) matched service RE.", server_name
);
268 /* does not match service re */
269 if((server
->flags
& SMODE_SERVICE
) != 0) {
270 result
|=SERVERTYPEFLAG_SERVICE
;
271 Error("serverlist", ERR_WARNING
, "Service server (%s) that does not match service RE.", server_name
);
276 if(hub_re
&& (pcre_exec(hub_re
, NULL
, server_name
, server_len
, 0, 0, NULL
, 0) >= 0)) {
277 if((server
->flags
& SMODE_HUB
) != 0) {
278 result
|=SERVERTYPEFLAG_HUB
;
280 Error("serverlist", ERR_WARNING
, "Server matched hub re but isn't a hub (%s).", server_name
);
284 if(not_client_re
&& (pcre_exec(not_client_re
, NULL
, server_name
, server_len
, 0, 0, NULL
, 0) >= 0)) {
286 } else if(result
== 0) {
287 result
|=SERVERTYPEFLAG_CLIENT_SERVER
;
293 void serverlist_pingservers(void *arg
) {
296 char fnum
[10], tnum
[10];
302 for(i
=0;i
<MAXSERVERS
;i
++) {
305 if (to
->parent
== -1)
308 from
= &serverlist
[to
->parent
];
310 if (to
->linkstate
!= LS_LINKED
|| from
->linkstate
!= LS_LINKED
)
313 strcpy(fnum
, longtonumeric(to
->parent
,2));
314 strcpy(tnum
, longtonumeric(i
, 2));
316 if (from
->parent
== -1) { /* Are we the source? */
317 (void) gettimeofday(&tv
, NULL
);
318 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
);
320 strcpy(fnum
, longtonumeric(to
->parent
,2));
321 strcpy(tnum
, longtonumeric(i
, 2));
322 irc_send("%s RI %s %s :RP", longtonumeric(mynick
->numeric
,5), to
->name
->content
, fnum
);
327 int serverlist_rpong(void *source
, int cargc
, char **cargv
) {
334 if (cargc
== 5) { /* From target to source server */
335 if (strcmp(cargv
[4], "RP") != 0)
338 to
= numerictolong(source
, 2);
340 (void) gettimeofday(&tv
, NULL
);
341 lag
= (tv
.tv_sec
- strtoull(cargv
[2], NULL
, 10)) * 1000 + (tv
.tv_usec
- strtoull(cargv
[3], NULL
, 10)) / 1000;
342 } else { /* From source server to client */
343 if (strcmp(cargv
[3], "RP") != 0)
346 to
= findserver(cargv
[1]);
351 lag
= atoi(cargv
[2]);
354 serverinfo
[to
].lag
= lag
;