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 setflags(&serverlist
[servernum
].flags
,SMODE_ALL
,cargv
[6],smodeflags
,REJECT_NONE
);
90 if (!strncmp((char *)source
,"INIT",4)) {
91 /* This is the initial server */
93 serverlist
[servernum
].parent
=numerictolong(mynumeric
->content
,2);
94 triggerhook(HOOK_IRC_SENDBURSTSERVERS
,NULL
);
95 triggerhook(HOOK_IRC_SENDBURSTNICKS
,NULL
);
96 triggerhook(HOOK_IRC_SENDBURSTBURSTS
,NULL
);
97 irc_send("%s EB",mynumeric
->content
);
98 triggerhook(HOOK_IRC_CONNECTED
,NULL
);
100 serverlist
[servernum
].parent
=numerictolong(source
,2);
103 /* Set up the initial server state -- this MUST be one of the "linking" states */
104 if (cargv
[4][0]=='J') {
105 serverlist
[servernum
].linkstate
=LS_LINKING
;
106 Error("server",ERR_DEBUG
,"Creating server %s in LS_LINKING state.",serverlist
[servernum
].name
->content
);
108 serverlist
[servernum
].linkstate
=LS_PLINKING
;
109 Error("server",ERR_DEBUG
,"Creating server %s in LS_PLINKING state.",serverlist
[servernum
].name
->content
);
112 triggerhook(HOOK_SERVER_NEWSERVER
,(void *)servernum
);
116 int handleeobmsg(void *source
, int cargc
, char **argv
) {
119 servernum
=numerictolong(source
,2);
120 completelink(servernum
);
122 if (servernum
==myhub
) {
124 irc_send("%s EA",mynumeric
->content
);
125 Error("server",ERR_INFO
,"Acknowledging end of burst");
126 triggerhook(HOOK_SERVER_END_OF_BURST
, NULL
);
132 int handlesquitmsg(void *source
, int cargc
, char **cargv
) {
133 long servernum
=findserver(cargv
[0]);
135 Error("server",ERR_WARNING
,"Received SQUIT for unknown server %s\n",cargv
[0]);
138 if (servernum
==myhub
) {
139 Error("server",ERR_WARNING
,"Rejected by our hub: %s",cargv
[cargc
-1]);
143 deleteserver(servernum
);
148 void handledisconnect(int hooknum
, void *arg
) {
155 void completelink(int servernum
) {
158 if (serverlist
[servernum
].name
==NULL
) {
159 Error("server",ERR_WARNING
,"Tried to complete link for server %d which doesn't exist.",servernum
);
163 /* Complete the link for all children in the PLINKING state. */
164 for (i
=0;i
<MAXSERVERS
;i
++) {
165 if (serverlist
[i
].parent
==servernum
&& serverlist
[i
].linkstate
==LS_PLINKING
) {
170 /* This server is now fully linked. */
171 serverlist
[servernum
].linkstate
=LS_LINKED
;
172 triggerhook(HOOK_SERVER_LINKED
, (void *)(long)servernum
);
173 Error("server",ERR_DEBUG
,"Setting link state on %s to LS_LINKED",serverlist
[servernum
].name
->content
);
176 void deleteserver(long servernum
) {
179 if (serverlist
[servernum
].name
==NULL
) {
180 Error("server",ERR_WARNING
,"Tried to remove server %ld which doesn't exist.",servernum
);
184 /* Delete all it's children first */
185 for (i
=0;i
<MAXSERVERS
;i
++) {
186 if (serverlist
[i
].parent
==servernum
&& serverlist
[i
].name
!=NULL
) {
191 /* Set state to SQUITting, then trigger hook */
192 Error("server",ERR_DEBUG
,"Setting link state on %s to LS_SQUIT",serverlist
[servernum
].name
->content
);
193 serverlist
[servernum
].linkstate
=LS_SQUIT
;
195 /* Until hooks have priorities we need something like this */
196 triggerhook(HOOK_SERVER_PRE_LOSTSERVER
,(void *)servernum
);
197 triggerhook(HOOK_SERVER_LOSTSERVER
,(void *)servernum
);
199 /* Now delete the actual server */
200 freesstring(serverlist
[servernum
].name
);
201 freesstring(serverlist
[servernum
].description
);
202 memset(&(serverlist
[servernum
]),0,sizeof(server
)); /* sets state back to LS_INVALID */
205 int findserver(const char *name
) {
208 for(i
=0;i
<MAXSERVERS
;i
++)
209 if (serverlist
[i
].name
!=NULL
&& !strncmp(serverlist
[i
].name
->content
,name
,serverlist
[i
].name
->length
))