]>
Commit | Line | Data |
---|---|---|
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)].ts=getnettime(); | |
46 | serverlist[numerictolong(mynumeric->content,2)].linkstate=LS_LINKED; | |
47 | /* remember to update the mode line in irc/irc.c */ | |
48 | serverlist[numerictolong(mynumeric->content,2)].flags=SMODE_SERVICE|SMODE_IPV6|SMODE_HUB|SMODE_OPERNAME; | |
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 | ||
60 | void _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++) { | |
71 | freesstring(serverlist[i].name); | |
72 | freesstring(serverlist[i].description); | |
73 | } | |
74 | } | |
75 | ||
76 | int handleservermsg(void *source, int cargc, char **cargv) { | |
77 | long servernum; | |
78 | ||
79 | servernum=numerictolong(cargv[5],2); | |
80 | ||
81 | if (serverlist[servernum].name!=NULL) { | |
82 | Error("server",ERR_ERROR,"New server %ld already exists in servertable.",servernum); | |
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); | |
89 | serverlist[servernum].ts=strtoull(cargv[3], NULL, 10); | |
90 | serverlist[servernum].marker=0; | |
91 | setflags(&serverlist[servernum].flags,SMODE_ALL,cargv[6],smodeflags,REJECT_NONE); | |
92 | ||
93 | if (!strncmp((char *)source,"INIT",4)) { | |
94 | /* This is the initial server */ | |
95 | myhub=servernum; | |
96 | serverlist[servernum].parent=numerictolong(mynumeric->content,2); | |
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); | |
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 | ||
119 | int handleeobmsg(void *source, int cargc, char **argv) { | |
120 | long servernum; | |
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"); | |
129 | triggerhook(HOOK_SERVER_END_OF_BURST, NULL); | |
130 | } | |
131 | ||
132 | return CMD_OK; | |
133 | } | |
134 | ||
135 | int handlesquitmsg(void *source, int cargc, char **cargv) { | |
136 | long servernum=findserver(cargv[0]); | |
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]); | |
143 | irc_disconnected(); | |
144 | return CMD_OK; | |
145 | } | |
146 | deleteserver(servernum); | |
147 | ||
148 | return CMD_OK; | |
149 | } | |
150 | ||
151 | void handledisconnect(int hooknum, void *arg) { | |
152 | if (myhub>=0) { | |
153 | deleteserver(myhub); | |
154 | myhub=-1; | |
155 | } | |
156 | } | |
157 | ||
158 | void 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; | |
175 | triggerhook(HOOK_SERVER_LINKED, (void *)(long)servernum); | |
176 | Error("server",ERR_DEBUG,"Setting link state on %s to LS_LINKED",serverlist[servernum].name->content); | |
177 | } | |
178 | ||
179 | void deleteserver(long servernum) { | |
180 | int i; | |
181 | ||
182 | if (serverlist[servernum].name==NULL) { | |
183 | Error("server",ERR_WARNING,"Tried to remove server %ld which doesn't exist.",servernum); | |
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; | |
197 | ||
198 | /* Until hooks have priorities we need something like this */ | |
199 | triggerhook(HOOK_SERVER_PRE_LOSTSERVER,(void *)servernum); | |
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 | ||
208 | int 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 | ||
218 | unsigned 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 |