]> jfr.im git - irc/quakenet/newserv.git/blame - server/server.c
TRUSTS: require sqlite
[irc/quakenet/newserv.git] / server / server.c
CommitLineData
c86edd1d
Q
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"
87698d77 14#include "../lib/version.h"
c86edd1d
Q
15#include "server.h"
16
17#include <stdio.h>
18#include <string.h>
19
70b0a4e5 20MODULE_VERSION("");
87698d77 21
c86edd1d
Q
22int findserver(const char *name);
23void completelink(int servernum);
24
25server serverlist[MAXSERVERS];
c3db6f7e 26long myhub;
c86edd1d 27
4f2ceb49
CP
28const flag smodeflags[] = {
29 { 'h', SMODE_HUB },
30 { '6', SMODE_IPV6 },
31 { 's', SMODE_SERVICE },
32 { 'n', SMODE_OPERNAME },
33 { '\0', 0 } };
34
c86edd1d
Q
35void _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;
618cddb2 45 serverlist[numerictolong(mynumeric->content,2)].ts=getnettime();
c86edd1d 46 serverlist[numerictolong(mynumeric->content,2)].linkstate=LS_LINKED;
4f2ceb49 47 /* remember to update the mode line in irc/irc.c */
843184e3 48 serverlist[numerictolong(mynumeric->content,2)].flags=SMODE_SERVICE|SMODE_IPV6|SMODE_HUB|SMODE_OPERNAME;
c86edd1d
Q
49
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);
55
56 /* And the events we hook */
57 registerhook(HOOK_IRC_DISCON,&handledisconnect);
58}
59
60void _fini() {
61 int i;
62
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);
69
70 for (i=0;i<MAXSERVERS;i++) {
707c5824
CP
71 freesstring(serverlist[i].name);
72 freesstring(serverlist[i].description);
c86edd1d
Q
73 }
74}
75
76int handleservermsg(void *source, int cargc, char **cargv) {
c3db6f7e 77 long servernum;
c86edd1d
Q
78
79 servernum=numerictolong(cargv[5],2);
80
81 if (serverlist[servernum].name!=NULL) {
c3db6f7e 82 Error("server",ERR_ERROR,"New server %ld already exists in servertable.",servernum);
c86edd1d
Q
83 return CMD_ERROR;
84 }
85
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);
618cddb2 89 serverlist[servernum].ts=strtoull(cargv[3], NULL, 10);
d78b74df 90 serverlist[servernum].marker=0;
4f2ceb49
CP
91 setflags(&serverlist[servernum].flags,SMODE_ALL,cargv[6],smodeflags,REJECT_NONE);
92
c86edd1d
Q
93 if (!strncmp((char *)source,"INIT",4)) {
94 /* This is the initial server */
95 myhub=servernum;
96 serverlist[servernum].parent=numerictolong(mynumeric->content,2);
eb8dffd0
C
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);
c86edd1d
Q
102 } else {
103 serverlist[servernum].parent=numerictolong(source,2);
104 }
105
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);
110 } else {
111 serverlist[servernum].linkstate=LS_PLINKING;
112 Error("server",ERR_DEBUG,"Creating server %s in LS_PLINKING state.",serverlist[servernum].name->content);
113 }
114
115 triggerhook(HOOK_SERVER_NEWSERVER,(void *)servernum);
116 return CMD_OK;
117}
118
119int handleeobmsg(void *source, int cargc, char **argv) {
c3db6f7e 120 long servernum;
c86edd1d
Q
121
122 servernum=numerictolong(source,2);
123 completelink(servernum);
124
125 if (servernum==myhub) {
126 /* Send EA */
127 irc_send("%s EA",mynumeric->content);
128 Error("server",ERR_INFO,"Acknowledging end of burst");
e609eb1f 129 triggerhook(HOOK_SERVER_END_OF_BURST, NULL);
c86edd1d
Q
130 }
131
132 return CMD_OK;
133}
134
135int handlesquitmsg(void *source, int cargc, char **cargv) {
c3db6f7e 136 long servernum=findserver(cargv[0]);
c86edd1d
Q
137 if (servernum<0) {
138 Error("server",ERR_WARNING,"Received SQUIT for unknown server %s\n",cargv[0]);
139 return CMD_ERROR;
140 }
141 if (servernum==myhub) {
142 Error("server",ERR_WARNING,"Rejected by our hub: %s",cargv[cargc-1]);
6c510e06 143 irc_disconnected(0);
c86edd1d
Q
144 return CMD_OK;
145 }
146 deleteserver(servernum);
147
148 return CMD_OK;
149}
150
151void handledisconnect(int hooknum, void *arg) {
152 if (myhub>=0) {
153 deleteserver(myhub);
154 myhub=-1;
155 }
156}
157
158void completelink(int servernum) {
159 int i;
160
161 if (serverlist[servernum].name==NULL) {
162 Error("server",ERR_WARNING,"Tried to complete link for server %d which doesn't exist.",servernum);
163 return;
164 }
165
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) {
169 completelink(i);
170 }
171 }
172
173 /* This server is now fully linked. */
174 serverlist[servernum].linkstate=LS_LINKED;
c54295ef 175 triggerhook(HOOK_SERVER_LINKED, (void *)(long)servernum);
c86edd1d
Q
176 Error("server",ERR_DEBUG,"Setting link state on %s to LS_LINKED",serverlist[servernum].name->content);
177}
178
c3db6f7e 179void deleteserver(long servernum) {
c86edd1d
Q
180 int i;
181
182 if (serverlist[servernum].name==NULL) {
c3db6f7e 183 Error("server",ERR_WARNING,"Tried to remove server %ld which doesn't exist.",servernum);
c86edd1d
Q
184 return;
185 }
186
187 /* Delete all it's children first */
188 for (i=0;i<MAXSERVERS;i++) {
189 if (serverlist[i].parent==servernum && serverlist[i].name!=NULL) {
190 deleteserver(i);
191 }
192 }
193
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;
e609eb1f
CP
197
198 /* Until hooks have priorities we need something like this */
199 triggerhook(HOOK_SERVER_PRE_LOSTSERVER,(void *)servernum);
c86edd1d
Q
200 triggerhook(HOOK_SERVER_LOSTSERVER,(void *)servernum);
201
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 */
206}
207
208int findserver(const char *name) {
209 int i;
210
211 for(i=0;i<MAXSERVERS;i++)
212 if (serverlist[i].name!=NULL && !strncmp(serverlist[i].name->content,name,serverlist[i].name->length))
213 return i;
214
215 return -1;
216}
217
d78b74df
CP
218unsigned int nextservermarker(void) {
219 int i;
220 static unsigned int servermarker=0;
221
222 servermarker++;
223 if (!servermarker) {
224 /* If we wrapped to zero, zap the marker on all hosts */
225 for (i=0;i<MAXSERVERS;i++)
226 serverlist[i].marker=0;
227 servermarker++;
228 }
229
230 return servermarker;
231}
232