3 * This module is responsible for tracking the active server tree.
6 #include "../parser/parser.h"
7 #include "../irc/irc_config.h"
8 #include "../irc/irc.h"
9 #include "../lib/base64.h"
10 #include "../lib/sstring.h"
11 #include "../core/error.h"
12 #include "../core/hooks.h"
13 #include "../core/config.h"
14 #include "../lib/version.h"
22 int findserver(const char *name
);
23 void completelink(int servernum
);
25 server serverlist
[MAXSERVERS
];
28 const flag smodeflags
[] = {
31 { 's', SMODE_SERVICE
},
32 { 'n', SMODE_OPERNAME
},
36 /* Initialise the server tree */
37 memset(serverlist
,0,MAXSERVERS
*sizeof(server
));
41 serverlist
[numerictolong(mynumeric
->content
,2)].parent
=-1;
42 serverlist
[numerictolong(mynumeric
->content
,2)].name
=getsstring(myserver
->content
,HOSTLEN
);
43 serverlist
[numerictolong(mynumeric
->content
,2)].description
=getcopyconfigitem("irc","serverdescription","newserv",100);
44 serverlist
[numerictolong(mynumeric
->content
,2)].maxusernum
=MAXLOCALUSER
;
45 serverlist
[numerictolong(mynumeric
->content
,2)].ts
=getnettime();
46 serverlist
[numerictolong(mynumeric
->content
,2)].linkstate
=LS_LINKED
;
47 /* remember to update the mode line in irc/irc.c */
48 serverlist
[numerictolong(mynumeric
->content
,2)].flags
=SMODE_SERVICE
|SMODE_IPV6
|SMODE_HUB
|SMODE_OPERNAME
;
50 /* Register the protocol messages we handle */
51 registerserverhandler("SERVER",&handleservermsg
,8);
52 registerserverhandler("S",&handleservermsg
,8);
53 registerserverhandler("SQ",&handlesquitmsg
,3);
54 registerserverhandler("EB",&handleeobmsg
,0);
56 /* And the events we hook */
57 registerhook(HOOK_IRC_DISCON
,&handledisconnect
);
63 /* Deregister everything */
64 deregisterserverhandler("SERVER",&handleservermsg
);
65 deregisterserverhandler("S",&handleservermsg
);
66 deregisterserverhandler("SQ",&handlesquitmsg
);
67 deregisterserverhandler("EB",&handleeobmsg
);
68 deregisterhook(HOOK_IRC_DISCON
,&handledisconnect
);
70 for (i
=0;i
<MAXSERVERS
;i
++) {
71 freesstring(serverlist
[i
].name
);
72 freesstring(serverlist
[i
].description
);
76 int handleservermsg(void *source
, int cargc
, char **cargv
) {
79 servernum
=numerictolong(cargv
[5],2);
81 if (serverlist
[servernum
].name
!=NULL
) {
82 Error("server",ERR_ERROR
,"New server %ld already exists in servertable.",servernum
);
86 serverlist
[servernum
].name
=getsstring(cargv
[0],HOSTLEN
);
87 serverlist
[servernum
].description
=getsstring(cargv
[cargc
-1],REALLEN
);
88 serverlist
[servernum
].maxusernum
=numerictolong(cargv
[5]+2,3);
89 serverlist
[servernum
].ts
=strtoull(cargv
[3], NULL
, 10);
90 serverlist
[servernum
].marker
=0;
91 setflags(&serverlist
[servernum
].flags
,SMODE_ALL
,cargv
[6],smodeflags
,REJECT_NONE
);
93 if (!strncmp((char *)source
,"INIT",4)) {
94 /* This is the initial server */
96 serverlist
[servernum
].parent
=numerictolong(mynumeric
->content
,2);
97 triggerhook(HOOK_IRC_SENDBURSTSERVERS
,NULL
);
98 triggerhook(HOOK_IRC_SENDBURSTNICKS
,NULL
);
99 triggerhook(HOOK_IRC_SENDBURSTBURSTS
,NULL
);
100 irc_send("%s EB",mynumeric
->content
);
101 triggerhook(HOOK_IRC_CONNECTED
,NULL
);
103 serverlist
[servernum
].parent
=numerictolong(source
,2);
106 /* Set up the initial server state -- this MUST be one of the "linking" states */
107 if (cargv
[4][0]=='J') {
108 serverlist
[servernum
].linkstate
=LS_LINKING
;
109 Error("server",ERR_DEBUG
,"Creating server %s in LS_LINKING state.",serverlist
[servernum
].name
->content
);
111 serverlist
[servernum
].linkstate
=LS_PLINKING
;
112 Error("server",ERR_DEBUG
,"Creating server %s in LS_PLINKING state.",serverlist
[servernum
].name
->content
);
115 triggerhook(HOOK_SERVER_NEWSERVER
,(void *)servernum
);
119 int handleeobmsg(void *source
, int cargc
, char **argv
) {
122 servernum
=numerictolong(source
,2);
123 completelink(servernum
);
125 if (servernum
==myhub
) {
127 irc_send("%s EA",mynumeric
->content
);
128 Error("server",ERR_INFO
,"Acknowledging end of burst");
129 triggerhook(HOOK_SERVER_END_OF_BURST
, NULL
);
135 int handlesquitmsg(void *source
, int cargc
, char **cargv
) {
136 long servernum
=findserver(cargv
[0]);
138 Error("server",ERR_WARNING
,"Received SQUIT for unknown server %s\n",cargv
[0]);
141 if (servernum
==myhub
) {
142 Error("server",ERR_WARNING
,"Rejected by our hub: %s",cargv
[cargc
-1]);
146 deleteserver(servernum
);
151 void handledisconnect(int hooknum
, void *arg
) {
158 void completelink(int servernum
) {
161 if (serverlist
[servernum
].name
==NULL
) {
162 Error("server",ERR_WARNING
,"Tried to complete link for server %d which doesn't exist.",servernum
);
166 /* Complete the link for all children in the PLINKING state. */
167 for (i
=0;i
<MAXSERVERS
;i
++) {
168 if (serverlist
[i
].parent
==servernum
&& serverlist
[i
].linkstate
==LS_PLINKING
) {
173 /* This server is now fully linked. */
174 serverlist
[servernum
].linkstate
=LS_LINKED
;
175 triggerhook(HOOK_SERVER_LINKED
, (void *)(long)servernum
);
176 Error("server",ERR_DEBUG
,"Setting link state on %s to LS_LINKED",serverlist
[servernum
].name
->content
);
179 void deleteserver(long servernum
) {
182 if (serverlist
[servernum
].name
==NULL
) {
183 Error("server",ERR_WARNING
,"Tried to remove server %ld which doesn't exist.",servernum
);
187 /* Delete all it's children first */
188 for (i
=0;i
<MAXSERVERS
;i
++) {
189 if (serverlist
[i
].parent
==servernum
&& serverlist
[i
].name
!=NULL
) {
194 /* Set state to SQUITting, then trigger hook */
195 Error("server",ERR_DEBUG
,"Setting link state on %s to LS_SQUIT",serverlist
[servernum
].name
->content
);
196 serverlist
[servernum
].linkstate
=LS_SQUIT
;
198 /* Until hooks have priorities we need something like this */
199 triggerhook(HOOK_SERVER_PRE_LOSTSERVER
,(void *)servernum
);
200 triggerhook(HOOK_SERVER_LOSTSERVER
,(void *)servernum
);
202 /* Now delete the actual server */
203 freesstring(serverlist
[servernum
].name
);
204 freesstring(serverlist
[servernum
].description
);
205 memset(&(serverlist
[servernum
]),0,sizeof(server
)); /* sets state back to LS_INVALID */
208 int findserver(const char *name
) {
211 for(i
=0;i
<MAXSERVERS
;i
++)
212 if (serverlist
[i
].name
!=NULL
&& !strncmp(serverlist
[i
].name
->content
,name
,serverlist
[i
].name
->length
))
218 unsigned int nextservermarker(void) {
220 static unsigned int servermarker
=0;
224 /* If we wrapped to zero, zap the marker on all hosts */
225 for (i
=0;i
<MAXSERVERS
;i
++)
226 serverlist
[i
].marker
=0;