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)].linkstate
=LS_LINKED
;
46 /* remember to update the mode line in irc/irc.c */
47 serverlist
[numerictolong(mynumeric
->content
,2)].flags
=SMODE_SERVICE
|SMODE_IPV6
|SMODE_HUB
|SMODE_OPERNAME
;
49 /* Register the protocol messages we handle */
50 registerserverhandler("SERVER",&handleservermsg
,8);
51 registerserverhandler("S",&handleservermsg
,8);
52 registerserverhandler("SQ",&handlesquitmsg
,3);
53 registerserverhandler("EB",&handleeobmsg
,0);
55 /* And the events we hook */
56 registerhook(HOOK_IRC_DISCON
,&handledisconnect
);
62 /* Deregister everything */
63 deregisterserverhandler("SERVER",&handleservermsg
);
64 deregisterserverhandler("S",&handleservermsg
);
65 deregisterserverhandler("SQ",&handlesquitmsg
);
66 deregisterserverhandler("EB",&handleeobmsg
);
67 deregisterhook(HOOK_IRC_DISCON
,&handledisconnect
);
69 for (i
=0;i
<MAXSERVERS
;i
++) {
70 freesstring(serverlist
[i
].name
);
71 freesstring(serverlist
[i
].description
);
75 int handleservermsg(void *source
, int cargc
, char **cargv
) {
78 servernum
=numerictolong(cargv
[5],2);
80 if (serverlist
[servernum
].name
!=NULL
) {
81 Error("server",ERR_ERROR
,"New server %ld already exists in servertable.",servernum
);
85 serverlist
[servernum
].name
=getsstring(cargv
[0],HOSTLEN
);
86 serverlist
[servernum
].description
=getsstring(cargv
[cargc
-1],REALLEN
);
87 serverlist
[servernum
].maxusernum
=numerictolong(cargv
[5]+2,3);
88 serverlist
[servernum
].marker
=0;
89 setflags(&serverlist
[servernum
].flags
,SMODE_ALL
,cargv
[6],smodeflags
,REJECT_NONE
);
91 if (!strncmp((char *)source
,"INIT",4)) {
92 /* This is the initial server */
94 serverlist
[servernum
].parent
=numerictolong(mynumeric
->content
,2);
95 triggerhook(HOOK_IRC_SENDBURSTSERVERS
,NULL
);
96 triggerhook(HOOK_IRC_SENDBURSTNICKS
,NULL
);
97 triggerhook(HOOK_IRC_SENDBURSTBURSTS
,NULL
);
98 irc_send("%s EB",mynumeric
->content
);
99 triggerhook(HOOK_IRC_CONNECTED
,NULL
);
101 serverlist
[servernum
].parent
=numerictolong(source
,2);
104 /* Set up the initial server state -- this MUST be one of the "linking" states */
105 if (cargv
[4][0]=='J') {
106 serverlist
[servernum
].linkstate
=LS_LINKING
;
107 Error("server",ERR_DEBUG
,"Creating server %s in LS_LINKING state.",serverlist
[servernum
].name
->content
);
109 serverlist
[servernum
].linkstate
=LS_PLINKING
;
110 Error("server",ERR_DEBUG
,"Creating server %s in LS_PLINKING state.",serverlist
[servernum
].name
->content
);
113 triggerhook(HOOK_SERVER_NEWSERVER
,(void *)servernum
);
117 int handleeobmsg(void *source
, int cargc
, char **argv
) {
120 servernum
=numerictolong(source
,2);
121 completelink(servernum
);
123 if (servernum
==myhub
) {
125 irc_send("%s EA",mynumeric
->content
);
126 Error("server",ERR_INFO
,"Acknowledging end of burst");
127 triggerhook(HOOK_SERVER_END_OF_BURST
, NULL
);
133 int handlesquitmsg(void *source
, int cargc
, char **cargv
) {
134 long servernum
=findserver(cargv
[0]);
136 Error("server",ERR_WARNING
,"Received SQUIT for unknown server %s\n",cargv
[0]);
139 if (servernum
==myhub
) {
140 Error("server",ERR_WARNING
,"Rejected by our hub: %s",cargv
[cargc
-1]);
144 deleteserver(servernum
);
149 void handledisconnect(int hooknum
, void *arg
) {
156 void completelink(int servernum
) {
159 if (serverlist
[servernum
].name
==NULL
) {
160 Error("server",ERR_WARNING
,"Tried to complete link for server %d which doesn't exist.",servernum
);
164 /* Complete the link for all children in the PLINKING state. */
165 for (i
=0;i
<MAXSERVERS
;i
++) {
166 if (serverlist
[i
].parent
==servernum
&& serverlist
[i
].linkstate
==LS_PLINKING
) {
171 /* This server is now fully linked. */
172 serverlist
[servernum
].linkstate
=LS_LINKED
;
173 triggerhook(HOOK_SERVER_LINKED
, (void *)(long)servernum
);
174 Error("server",ERR_DEBUG
,"Setting link state on %s to LS_LINKED",serverlist
[servernum
].name
->content
);
177 void deleteserver(long servernum
) {
180 if (serverlist
[servernum
].name
==NULL
) {
181 Error("server",ERR_WARNING
,"Tried to remove server %ld which doesn't exist.",servernum
);
185 /* Delete all it's children first */
186 for (i
=0;i
<MAXSERVERS
;i
++) {
187 if (serverlist
[i
].parent
==servernum
&& serverlist
[i
].name
!=NULL
) {
192 /* Set state to SQUITting, then trigger hook */
193 Error("server",ERR_DEBUG
,"Setting link state on %s to LS_SQUIT",serverlist
[servernum
].name
->content
);
194 serverlist
[servernum
].linkstate
=LS_SQUIT
;
196 /* Until hooks have priorities we need something like this */
197 triggerhook(HOOK_SERVER_PRE_LOSTSERVER
,(void *)servernum
);
198 triggerhook(HOOK_SERVER_LOSTSERVER
,(void *)servernum
);
200 /* Now delete the actual server */
201 freesstring(serverlist
[servernum
].name
);
202 freesstring(serverlist
[servernum
].description
);
203 memset(&(serverlist
[servernum
]),0,sizeof(server
)); /* sets state back to LS_INVALID */
206 int findserver(const char *name
) {
209 for(i
=0;i
<MAXSERVERS
;i
++)
210 if (serverlist
[i
].name
!=NULL
&& !strncmp(serverlist
[i
].name
->content
,name
,serverlist
[i
].name
->length
))
216 unsigned int nextservermarker(void) {
218 static unsigned int servermarker
=0;
222 /* If we wrapped to zero, zap the marker on all hosts */
223 for (i
=0;i
<MAXSERVERS
;i
++)
224 serverlist
[i
].marker
=0;