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
];
29 /* Initialise the server tree */
30 memset(serverlist
,0,MAXSERVERS
*sizeof(server
));
34 serverlist
[numerictolong(mynumeric
->content
,2)].parent
=-1;
35 serverlist
[numerictolong(mynumeric
->content
,2)].name
=getsstring(myserver
->content
,HOSTLEN
);
36 serverlist
[numerictolong(mynumeric
->content
,2)].description
=getcopyconfigitem("irc","serverdescription","newserv",100);
37 serverlist
[numerictolong(mynumeric
->content
,2)].maxusernum
=MAXLOCALUSER
;
38 serverlist
[numerictolong(mynumeric
->content
,2)].linkstate
=LS_LINKED
;
40 /* Register the protocol messages we handle */
41 registerserverhandler("SERVER",&handleservermsg
,8);
42 registerserverhandler("S",&handleservermsg
,8);
43 registerserverhandler("SQ",&handlesquitmsg
,3);
44 registerserverhandler("EB",&handleeobmsg
,0);
46 /* And the events we hook */
47 registerhook(HOOK_IRC_DISCON
,&handledisconnect
);
53 /* Deregister everything */
54 deregisterserverhandler("SERVER",&handleservermsg
);
55 deregisterserverhandler("S",&handleservermsg
);
56 deregisterserverhandler("SQ",&handlesquitmsg
);
57 deregisterserverhandler("EB",&handleeobmsg
);
58 deregisterhook(HOOK_IRC_DISCON
,&handledisconnect
);
60 for (i
=0;i
<MAXSERVERS
;i
++) {
61 if (serverlist
[i
].name
!=NULL
)
62 freesstring(serverlist
[i
].name
);
66 int handleservermsg(void *source
, int cargc
, char **cargv
) {
69 servernum
=numerictolong(cargv
[5],2);
71 if (serverlist
[servernum
].name
!=NULL
) {
72 Error("server",ERR_ERROR
,"New server %ld already exists in servertable.",servernum
);
76 serverlist
[servernum
].name
=getsstring(cargv
[0],HOSTLEN
);
77 serverlist
[servernum
].description
=getsstring(cargv
[cargc
-1],REALLEN
);
78 serverlist
[servernum
].maxusernum
=numerictolong(cargv
[5]+2,3);
80 if (!strncmp((char *)source
,"INIT",4)) {
81 /* This is the initial server */
83 serverlist
[servernum
].parent
=numerictolong(mynumeric
->content
,2);
85 serverlist
[servernum
].parent
=numerictolong(source
,2);
88 /* Set up the initial server state -- this MUST be one of the "linking" states */
89 if (cargv
[4][0]=='J') {
90 serverlist
[servernum
].linkstate
=LS_LINKING
;
91 Error("server",ERR_DEBUG
,"Creating server %s in LS_LINKING state.",serverlist
[servernum
].name
->content
);
93 serverlist
[servernum
].linkstate
=LS_PLINKING
;
94 Error("server",ERR_DEBUG
,"Creating server %s in LS_PLINKING state.",serverlist
[servernum
].name
->content
);
97 triggerhook(HOOK_SERVER_NEWSERVER
,(void *)servernum
);
101 int handleeobmsg(void *source
, int cargc
, char **argv
) {
104 servernum
=numerictolong(source
,2);
105 completelink(servernum
);
107 if (servernum
==myhub
) {
109 irc_send("%s EA",mynumeric
->content
);
110 Error("server",ERR_INFO
,"Acknowledging end of burst");
111 triggerhook(HOOK_SERVER_END_OF_BURST
, NULL
);
117 int handlesquitmsg(void *source
, int cargc
, char **cargv
) {
118 long servernum
=findserver(cargv
[0]);
120 Error("server",ERR_WARNING
,"Received SQUIT for unknown server %s\n",cargv
[0]);
123 if (servernum
==myhub
) {
124 Error("server",ERR_WARNING
,"Rejected by our hub: %s",cargv
[cargc
-1]);
128 deleteserver(servernum
);
133 void handledisconnect(int hooknum
, void *arg
) {
140 void completelink(int servernum
) {
143 if (serverlist
[servernum
].name
==NULL
) {
144 Error("server",ERR_WARNING
,"Tried to complete link for server %d which doesn't exist.",servernum
);
148 /* Complete the link for all children in the PLINKING state. */
149 for (i
=0;i
<MAXSERVERS
;i
++) {
150 if (serverlist
[i
].parent
==servernum
&& serverlist
[i
].linkstate
==LS_PLINKING
) {
155 /* This server is now fully linked. */
156 serverlist
[servernum
].linkstate
=LS_LINKED
;
157 triggerhook(HOOK_SERVER_LINKED
, (void *)servernum
);
158 Error("server",ERR_DEBUG
,"Setting link state on %s to LS_LINKED",serverlist
[servernum
].name
->content
);
161 void deleteserver(long servernum
) {
164 if (serverlist
[servernum
].name
==NULL
) {
165 Error("server",ERR_WARNING
,"Tried to remove server %ld which doesn't exist.",servernum
);
169 /* Delete all it's children first */
170 for (i
=0;i
<MAXSERVERS
;i
++) {
171 if (serverlist
[i
].parent
==servernum
&& serverlist
[i
].name
!=NULL
) {
176 /* Set state to SQUITting, then trigger hook */
177 Error("server",ERR_DEBUG
,"Setting link state on %s to LS_SQUIT",serverlist
[servernum
].name
->content
);
178 serverlist
[servernum
].linkstate
=LS_SQUIT
;
180 /* Until hooks have priorities we need something like this */
181 triggerhook(HOOK_SERVER_PRE_LOSTSERVER
,(void *)servernum
);
182 triggerhook(HOOK_SERVER_LOSTSERVER
,(void *)servernum
);
184 /* Now delete the actual server */
185 freesstring(serverlist
[servernum
].name
);
186 freesstring(serverlist
[servernum
].description
);
187 memset(&(serverlist
[servernum
]),0,sizeof(server
)); /* sets state back to LS_INVALID */
190 int findserver(const char *name
) {
193 for(i
=0;i
<MAXSERVERS
;i
++)
194 if (serverlist
[i
].name
!=NULL
&& !strncmp(serverlist
[i
].name
->content
,name
,serverlist
[i
].name
->length
))