]>
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)].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 |