]>
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); | |
94 | } else { | |
95 | serverlist[servernum].parent=numerictolong(source,2); | |
96 | } | |
97 | ||
98 | /* Set up the initial server state -- this MUST be one of the "linking" states */ | |
99 | if (cargv[4][0]=='J') { | |
100 | serverlist[servernum].linkstate=LS_LINKING; | |
101 | Error("server",ERR_DEBUG,"Creating server %s in LS_LINKING state.",serverlist[servernum].name->content); | |
102 | } else { | |
103 | serverlist[servernum].linkstate=LS_PLINKING; | |
104 | Error("server",ERR_DEBUG,"Creating server %s in LS_PLINKING state.",serverlist[servernum].name->content); | |
105 | } | |
106 | ||
107 | triggerhook(HOOK_SERVER_NEWSERVER,(void *)servernum); | |
108 | return CMD_OK; | |
109 | } | |
110 | ||
111 | int handleeobmsg(void *source, int cargc, char **argv) { | |
c3db6f7e | 112 | long servernum; |
c86edd1d Q |
113 | |
114 | servernum=numerictolong(source,2); | |
115 | completelink(servernum); | |
116 | ||
117 | if (servernum==myhub) { | |
118 | /* Send EA */ | |
119 | irc_send("%s EA",mynumeric->content); | |
120 | Error("server",ERR_INFO,"Acknowledging end of burst"); | |
e609eb1f | 121 | triggerhook(HOOK_SERVER_END_OF_BURST, NULL); |
c86edd1d Q |
122 | } |
123 | ||
124 | return CMD_OK; | |
125 | } | |
126 | ||
127 | int handlesquitmsg(void *source, int cargc, char **cargv) { | |
c3db6f7e | 128 | long servernum=findserver(cargv[0]); |
c86edd1d Q |
129 | if (servernum<0) { |
130 | Error("server",ERR_WARNING,"Received SQUIT for unknown server %s\n",cargv[0]); | |
131 | return CMD_ERROR; | |
132 | } | |
133 | if (servernum==myhub) { | |
134 | Error("server",ERR_WARNING,"Rejected by our hub: %s",cargv[cargc-1]); | |
135 | irc_disconnected(); | |
136 | return CMD_OK; | |
137 | } | |
138 | deleteserver(servernum); | |
139 | ||
140 | return CMD_OK; | |
141 | } | |
142 | ||
143 | void handledisconnect(int hooknum, void *arg) { | |
144 | if (myhub>=0) { | |
145 | deleteserver(myhub); | |
146 | myhub=-1; | |
147 | } | |
148 | } | |
149 | ||
150 | void completelink(int servernum) { | |
151 | int i; | |
152 | ||
153 | if (serverlist[servernum].name==NULL) { | |
154 | Error("server",ERR_WARNING,"Tried to complete link for server %d which doesn't exist.",servernum); | |
155 | return; | |
156 | } | |
157 | ||
158 | /* Complete the link for all children in the PLINKING state. */ | |
159 | for (i=0;i<MAXSERVERS;i++) { | |
160 | if (serverlist[i].parent==servernum && serverlist[i].linkstate==LS_PLINKING) { | |
161 | completelink(i); | |
162 | } | |
163 | } | |
164 | ||
165 | /* This server is now fully linked. */ | |
166 | serverlist[servernum].linkstate=LS_LINKED; | |
c54295ef | 167 | triggerhook(HOOK_SERVER_LINKED, (void *)(long)servernum); |
c86edd1d Q |
168 | Error("server",ERR_DEBUG,"Setting link state on %s to LS_LINKED",serverlist[servernum].name->content); |
169 | } | |
170 | ||
c3db6f7e | 171 | void deleteserver(long servernum) { |
c86edd1d Q |
172 | int i; |
173 | ||
174 | if (serverlist[servernum].name==NULL) { | |
c3db6f7e | 175 | Error("server",ERR_WARNING,"Tried to remove server %ld which doesn't exist.",servernum); |
c86edd1d Q |
176 | return; |
177 | } | |
178 | ||
179 | /* Delete all it's children first */ | |
180 | for (i=0;i<MAXSERVERS;i++) { | |
181 | if (serverlist[i].parent==servernum && serverlist[i].name!=NULL) { | |
182 | deleteserver(i); | |
183 | } | |
184 | } | |
185 | ||
186 | /* Set state to SQUITting, then trigger hook */ | |
187 | Error("server",ERR_DEBUG,"Setting link state on %s to LS_SQUIT",serverlist[servernum].name->content); | |
188 | serverlist[servernum].linkstate=LS_SQUIT; | |
e609eb1f CP |
189 | |
190 | /* Until hooks have priorities we need something like this */ | |
191 | triggerhook(HOOK_SERVER_PRE_LOSTSERVER,(void *)servernum); | |
c86edd1d Q |
192 | triggerhook(HOOK_SERVER_LOSTSERVER,(void *)servernum); |
193 | ||
194 | /* Now delete the actual server */ | |
195 | freesstring(serverlist[servernum].name); | |
196 | freesstring(serverlist[servernum].description); | |
197 | memset(&(serverlist[servernum]),0,sizeof(server)); /* sets state back to LS_INVALID */ | |
198 | } | |
199 | ||
200 | int findserver(const char *name) { | |
201 | int i; | |
202 | ||
203 | for(i=0;i<MAXSERVERS;i++) | |
204 | if (serverlist[i].name!=NULL && !strncmp(serverlist[i].name->content,name,serverlist[i].name->length)) | |
205 | return i; | |
206 | ||
207 | return -1; | |
208 | } | |
209 |