]> jfr.im git - irc/quakenet/newserv.git/blob - server/server.c
4d818e98049dcf000ebc731a1ed60bdbf2717d03
[irc/quakenet/newserv.git] / server / server.c
1 /* server.c
2 *
3 * This module is responsible for tracking the active server tree.
4 */
5
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"
15 #include "server.h"
16
17 #include <stdio.h>
18 #include <string.h>
19
20 MODULE_VERSION("");
21
22 int findserver(const char *name);
23 void completelink(int servernum);
24
25 server serverlist[MAXSERVERS];
26 long myhub;
27
28 const flag smodeflags[] = {
29 { 'h', SMODE_HUB },
30 { '6', SMODE_IPV6 },
31 { 's', SMODE_SERVICE },
32 { 'n', SMODE_OPERNAME },
33 { '\0', 0 } };
34
35 void _init() {
36 /* Initialise the server tree */
37 memset(serverlist,0,MAXSERVERS*sizeof(server));
38
39 myhub=-1;
40
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;
48
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);
54
55 /* And the events we hook */
56 registerhook(HOOK_IRC_DISCON,&handledisconnect);
57 }
58
59 void _fini() {
60 int i;
61
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);
68
69 for (i=0;i<MAXSERVERS;i++) {
70 freesstring(serverlist[i].name);
71 freesstring(serverlist[i].description);
72 }
73 }
74
75 int handleservermsg(void *source, int cargc, char **cargv) {
76 long servernum;
77
78 servernum=numerictolong(cargv[5],2);
79
80 if (serverlist[servernum].name!=NULL) {
81 Error("server",ERR_ERROR,"New server %ld already exists in servertable.",servernum);
82 return CMD_ERROR;
83 }
84
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);
90
91 if (!strncmp((char *)source,"INIT",4)) {
92 /* This is the initial server */
93 myhub=servernum;
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);
100 } else {
101 serverlist[servernum].parent=numerictolong(source,2);
102 }
103
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);
108 } else {
109 serverlist[servernum].linkstate=LS_PLINKING;
110 Error("server",ERR_DEBUG,"Creating server %s in LS_PLINKING state.",serverlist[servernum].name->content);
111 }
112
113 triggerhook(HOOK_SERVER_NEWSERVER,(void *)servernum);
114 return CMD_OK;
115 }
116
117 int handleeobmsg(void *source, int cargc, char **argv) {
118 long servernum;
119
120 servernum=numerictolong(source,2);
121 completelink(servernum);
122
123 if (servernum==myhub) {
124 /* Send EA */
125 irc_send("%s EA",mynumeric->content);
126 Error("server",ERR_INFO,"Acknowledging end of burst");
127 triggerhook(HOOK_SERVER_END_OF_BURST, NULL);
128 }
129
130 return CMD_OK;
131 }
132
133 int handlesquitmsg(void *source, int cargc, char **cargv) {
134 long servernum=findserver(cargv[0]);
135 if (servernum<0) {
136 Error("server",ERR_WARNING,"Received SQUIT for unknown server %s\n",cargv[0]);
137 return CMD_ERROR;
138 }
139 if (servernum==myhub) {
140 Error("server",ERR_WARNING,"Rejected by our hub: %s",cargv[cargc-1]);
141 irc_disconnected();
142 return CMD_OK;
143 }
144 deleteserver(servernum);
145
146 return CMD_OK;
147 }
148
149 void handledisconnect(int hooknum, void *arg) {
150 if (myhub>=0) {
151 deleteserver(myhub);
152 myhub=-1;
153 }
154 }
155
156 void completelink(int servernum) {
157 int i;
158
159 if (serverlist[servernum].name==NULL) {
160 Error("server",ERR_WARNING,"Tried to complete link for server %d which doesn't exist.",servernum);
161 return;
162 }
163
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) {
167 completelink(i);
168 }
169 }
170
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);
175 }
176
177 void deleteserver(long servernum) {
178 int i;
179
180 if (serverlist[servernum].name==NULL) {
181 Error("server",ERR_WARNING,"Tried to remove server %ld which doesn't exist.",servernum);
182 return;
183 }
184
185 /* Delete all it's children first */
186 for (i=0;i<MAXSERVERS;i++) {
187 if (serverlist[i].parent==servernum && serverlist[i].name!=NULL) {
188 deleteserver(i);
189 }
190 }
191
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;
195
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);
199
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 */
204 }
205
206 int findserver(const char *name) {
207 int i;
208
209 for(i=0;i<MAXSERVERS;i++)
210 if (serverlist[i].name!=NULL && !strncmp(serverlist[i].name->content,name,serverlist[i].name->length))
211 return i;
212
213 return -1;
214 }
215
216 unsigned int nextservermarker(void) {
217 int i;
218 static unsigned int servermarker=0;
219
220 servermarker++;
221 if (!servermarker) {
222 /* If we wrapped to zero, zap the marker on all hosts */
223 for (i=0;i<MAXSERVERS;i++)
224 serverlist[i].marker=0;
225 servermarker++;
226 }
227
228 return servermarker;
229 }
230