]>
Commit | Line | Data |
---|---|---|
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 | 20 | MODULE_VERSION(""); |
87698d77 | 21 | |
c86edd1d Q |
22 | int findserver(const char *name); |
23 | void completelink(int servernum); | |
24 | ||
25 | server serverlist[MAXSERVERS]; | |
c3db6f7e | 26 | long myhub; |
c86edd1d | 27 | |
4f2ceb49 CP |
28 | const flag smodeflags[] = { |
29 | { 'h', SMODE_HUB }, | |
30 | { '6', SMODE_IPV6 }, | |
31 | { 's', SMODE_SERVICE }, | |
32 | { 'n', SMODE_OPERNAME }, | |
33 | { '\0', 0 } }; | |
34 | ||
c86edd1d Q |
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; | |
4f2ceb49 | 46 | /* remember to update the mode line in irc/irc.c */ |
843184e3 | 47 | serverlist[numerictolong(mynumeric->content,2)].flags=SMODE_SERVICE|SMODE_IPV6|SMODE_HUB|SMODE_OPERNAME; |
c86edd1d Q |
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++) { | |
707c5824 CP |
70 | freesstring(serverlist[i].name); |
71 | freesstring(serverlist[i].description); | |
c86edd1d Q |
72 | } |
73 | } | |
74 | ||
75 | int handleservermsg(void *source, int cargc, char **cargv) { | |
c3db6f7e | 76 | long servernum; |
c86edd1d Q |
77 | |
78 | servernum=numerictolong(cargv[5],2); | |
79 | ||
80 | if (serverlist[servernum].name!=NULL) { | |
c3db6f7e | 81 | Error("server",ERR_ERROR,"New server %ld already exists in servertable.",servernum); |
c86edd1d Q |
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); | |
4f2ceb49 CP |
88 | setflags(&serverlist[servernum].flags,SMODE_ALL,cargv[6],smodeflags,REJECT_NONE); |
89 | ||
c86edd1d Q |
90 | if (!strncmp((char *)source,"INIT",4)) { |
91 | /* This is the initial server */ | |
92 | myhub=servernum; | |
93 | serverlist[servernum].parent=numerictolong(mynumeric->content,2); | |
eb8dffd0 C |
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); | |
c86edd1d Q |
99 | } else { |
100 | serverlist[servernum].parent=numerictolong(source,2); | |
101 | } | |
102 | ||
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); | |
107 | } else { | |
108 | serverlist[servernum].linkstate=LS_PLINKING; | |
109 | Error("server",ERR_DEBUG,"Creating server %s in LS_PLINKING state.",serverlist[servernum].name->content); | |
110 | } | |
111 | ||
112 | triggerhook(HOOK_SERVER_NEWSERVER,(void *)servernum); | |
113 | return CMD_OK; | |
114 | } | |
115 | ||
116 | int handleeobmsg(void *source, int cargc, char **argv) { | |
c3db6f7e | 117 | long servernum; |
c86edd1d Q |
118 | |
119 | servernum=numerictolong(source,2); | |
120 | completelink(servernum); | |
121 | ||
122 | if (servernum==myhub) { | |
123 | /* Send EA */ | |
124 | irc_send("%s EA",mynumeric->content); | |
125 | Error("server",ERR_INFO,"Acknowledging end of burst"); | |
e609eb1f | 126 | triggerhook(HOOK_SERVER_END_OF_BURST, NULL); |
c86edd1d Q |
127 | } |
128 | ||
129 | return CMD_OK; | |
130 | } | |
131 | ||
132 | int handlesquitmsg(void *source, int cargc, char **cargv) { | |
c3db6f7e | 133 | long servernum=findserver(cargv[0]); |
c86edd1d Q |
134 | if (servernum<0) { |
135 | Error("server",ERR_WARNING,"Received SQUIT for unknown server %s\n",cargv[0]); | |
136 | return CMD_ERROR; | |
137 | } | |
138 | if (servernum==myhub) { | |
139 | Error("server",ERR_WARNING,"Rejected by our hub: %s",cargv[cargc-1]); | |
140 | irc_disconnected(); | |
141 | return CMD_OK; | |
142 | } | |
143 | deleteserver(servernum); | |
144 | ||
145 | return CMD_OK; | |
146 | } | |
147 | ||
148 | void handledisconnect(int hooknum, void *arg) { | |
149 | if (myhub>=0) { | |
150 | deleteserver(myhub); | |
151 | myhub=-1; | |
152 | } | |
153 | } | |
154 | ||
155 | void completelink(int servernum) { | |
156 | int i; | |
157 | ||
158 | if (serverlist[servernum].name==NULL) { | |
159 | Error("server",ERR_WARNING,"Tried to complete link for server %d which doesn't exist.",servernum); | |
160 | return; | |
161 | } | |
162 | ||
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) { | |
166 | completelink(i); | |
167 | } | |
168 | } | |
169 | ||
170 | /* This server is now fully linked. */ | |
171 | serverlist[servernum].linkstate=LS_LINKED; | |
c54295ef | 172 | triggerhook(HOOK_SERVER_LINKED, (void *)(long)servernum); |
c86edd1d Q |
173 | Error("server",ERR_DEBUG,"Setting link state on %s to LS_LINKED",serverlist[servernum].name->content); |
174 | } | |
175 | ||
c3db6f7e | 176 | void deleteserver(long servernum) { |
c86edd1d Q |
177 | int i; |
178 | ||
179 | if (serverlist[servernum].name==NULL) { | |
c3db6f7e | 180 | Error("server",ERR_WARNING,"Tried to remove server %ld which doesn't exist.",servernum); |
c86edd1d Q |
181 | return; |
182 | } | |
183 | ||
184 | /* Delete all it's children first */ | |
185 | for (i=0;i<MAXSERVERS;i++) { | |
186 | if (serverlist[i].parent==servernum && serverlist[i].name!=NULL) { | |
187 | deleteserver(i); | |
188 | } | |
189 | } | |
190 | ||
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; | |
e609eb1f CP |
194 | |
195 | /* Until hooks have priorities we need something like this */ | |
196 | triggerhook(HOOK_SERVER_PRE_LOSTSERVER,(void *)servernum); | |
c86edd1d Q |
197 | triggerhook(HOOK_SERVER_LOSTSERVER,(void *)servernum); |
198 | ||
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 */ | |
203 | } | |
204 | ||
205 | int findserver(const char *name) { | |
206 | int i; | |
207 | ||
208 | for(i=0;i<MAXSERVERS;i++) | |
209 | if (serverlist[i].name!=NULL && !strncmp(serverlist[i].name->content,name,serverlist[i].name->length)) | |
210 | return i; | |
211 | ||
212 | return -1; | |
213 | } | |
214 |