]>
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]; | |
26 | int myhub; | |
27 | ||
28 | void _init() { | |
29 | /* Initialise the server tree */ | |
30 | memset(serverlist,0,MAXSERVERS*sizeof(server)); | |
31 | ||
32 | myhub=-1; | |
33 | ||
34 | serverlist[numerictolong(mynumeric->content,2)].parent=-1; | |
35 | serverlist[numerictolong(mynumeric->content,2)].name=getsstring(myserver->content,HOSTLEN); | |
36 | serverlist[numerictolong(mynumeric->content,2)].description=getcopyconfigitem("irc","serverdescription","newserv",100); | |
37 | serverlist[numerictolong(mynumeric->content,2)].maxusernum=MAXLOCALUSER; | |
38 | serverlist[numerictolong(mynumeric->content,2)].linkstate=LS_LINKED; | |
39 | ||
40 | /* Register the protocol messages we handle */ | |
41 | registerserverhandler("SERVER",&handleservermsg,8); | |
42 | registerserverhandler("S",&handleservermsg,8); | |
43 | registerserverhandler("SQ",&handlesquitmsg,3); | |
44 | registerserverhandler("EB",&handleeobmsg,0); | |
45 | ||
46 | /* And the events we hook */ | |
47 | registerhook(HOOK_IRC_DISCON,&handledisconnect); | |
48 | } | |
49 | ||
50 | void _fini() { | |
51 | int i; | |
52 | ||
53 | /* Deregister everything */ | |
54 | deregisterserverhandler("SERVER",&handleservermsg); | |
55 | deregisterserverhandler("S",&handleservermsg); | |
56 | deregisterserverhandler("SQ",&handlesquitmsg); | |
57 | deregisterserverhandler("EB",&handleeobmsg); | |
58 | deregisterhook(HOOK_IRC_DISCON,&handledisconnect); | |
59 | ||
60 | for (i=0;i<MAXSERVERS;i++) { | |
61 | if (serverlist[i].name!=NULL) | |
62 | freesstring(serverlist[i].name); | |
63 | } | |
64 | } | |
65 | ||
66 | int handleservermsg(void *source, int cargc, char **cargv) { | |
67 | int servernum; | |
68 | ||
69 | servernum=numerictolong(cargv[5],2); | |
70 | ||
71 | if (serverlist[servernum].name!=NULL) { | |
72 | Error("server",ERR_ERROR,"New server %d already exists in servertable.",servernum); | |
73 | return CMD_ERROR; | |
74 | } | |
75 | ||
76 | serverlist[servernum].name=getsstring(cargv[0],HOSTLEN); | |
77 | serverlist[servernum].description=getsstring(cargv[cargc-1],REALLEN); | |
78 | serverlist[servernum].maxusernum=numerictolong(cargv[5]+2,3); | |
79 | ||
80 | if (!strncmp((char *)source,"INIT",4)) { | |
81 | /* This is the initial server */ | |
82 | myhub=servernum; | |
83 | serverlist[servernum].parent=numerictolong(mynumeric->content,2); | |
84 | } else { | |
85 | serverlist[servernum].parent=numerictolong(source,2); | |
86 | } | |
87 | ||
88 | /* Set up the initial server state -- this MUST be one of the "linking" states */ | |
89 | if (cargv[4][0]=='J') { | |
90 | serverlist[servernum].linkstate=LS_LINKING; | |
91 | Error("server",ERR_DEBUG,"Creating server %s in LS_LINKING state.",serverlist[servernum].name->content); | |
92 | } else { | |
93 | serverlist[servernum].linkstate=LS_PLINKING; | |
94 | Error("server",ERR_DEBUG,"Creating server %s in LS_PLINKING state.",serverlist[servernum].name->content); | |
95 | } | |
96 | ||
97 | triggerhook(HOOK_SERVER_NEWSERVER,(void *)servernum); | |
98 | return CMD_OK; | |
99 | } | |
100 | ||
101 | int handleeobmsg(void *source, int cargc, char **argv) { | |
102 | int servernum; | |
103 | ||
104 | servernum=numerictolong(source,2); | |
105 | completelink(servernum); | |
106 | ||
107 | if (servernum==myhub) { | |
108 | /* Send EA */ | |
109 | irc_send("%s EA",mynumeric->content); | |
110 | Error("server",ERR_INFO,"Acknowledging end of burst"); | |
e609eb1f | 111 | triggerhook(HOOK_SERVER_END_OF_BURST, NULL); |
c86edd1d Q |
112 | } |
113 | ||
114 | return CMD_OK; | |
115 | } | |
116 | ||
117 | int handlesquitmsg(void *source, int cargc, char **cargv) { | |
118 | int servernum=findserver(cargv[0]); | |
119 | if (servernum<0) { | |
120 | Error("server",ERR_WARNING,"Received SQUIT for unknown server %s\n",cargv[0]); | |
121 | return CMD_ERROR; | |
122 | } | |
123 | if (servernum==myhub) { | |
124 | Error("server",ERR_WARNING,"Rejected by our hub: %s",cargv[cargc-1]); | |
125 | irc_disconnected(); | |
126 | return CMD_OK; | |
127 | } | |
128 | deleteserver(servernum); | |
129 | ||
130 | return CMD_OK; | |
131 | } | |
132 | ||
133 | void handledisconnect(int hooknum, void *arg) { | |
134 | if (myhub>=0) { | |
135 | deleteserver(myhub); | |
136 | myhub=-1; | |
137 | } | |
138 | } | |
139 | ||
140 | void completelink(int servernum) { | |
141 | int i; | |
142 | ||
143 | if (serverlist[servernum].name==NULL) { | |
144 | Error("server",ERR_WARNING,"Tried to complete link for server %d which doesn't exist.",servernum); | |
145 | return; | |
146 | } | |
147 | ||
148 | /* Complete the link for all children in the PLINKING state. */ | |
149 | for (i=0;i<MAXSERVERS;i++) { | |
150 | if (serverlist[i].parent==servernum && serverlist[i].linkstate==LS_PLINKING) { | |
151 | completelink(i); | |
152 | } | |
153 | } | |
154 | ||
155 | /* This server is now fully linked. */ | |
156 | serverlist[servernum].linkstate=LS_LINKED; | |
157 | Error("server",ERR_DEBUG,"Setting link state on %s to LS_LINKED",serverlist[servernum].name->content); | |
158 | } | |
159 | ||
160 | void deleteserver(int servernum) { | |
161 | int i; | |
162 | ||
163 | if (serverlist[servernum].name==NULL) { | |
164 | Error("server",ERR_WARNING,"Tried to remove server %d which doesn't exist.",servernum); | |
165 | return; | |
166 | } | |
167 | ||
168 | /* Delete all it's children first */ | |
169 | for (i=0;i<MAXSERVERS;i++) { | |
170 | if (serverlist[i].parent==servernum && serverlist[i].name!=NULL) { | |
171 | deleteserver(i); | |
172 | } | |
173 | } | |
174 | ||
175 | /* Set state to SQUITting, then trigger hook */ | |
176 | Error("server",ERR_DEBUG,"Setting link state on %s to LS_SQUIT",serverlist[servernum].name->content); | |
177 | serverlist[servernum].linkstate=LS_SQUIT; | |
e609eb1f CP |
178 | |
179 | /* Until hooks have priorities we need something like this */ | |
180 | triggerhook(HOOK_SERVER_PRE_LOSTSERVER,(void *)servernum); | |
c86edd1d Q |
181 | triggerhook(HOOK_SERVER_LOSTSERVER,(void *)servernum); |
182 | ||
183 | /* Now delete the actual server */ | |
184 | freesstring(serverlist[servernum].name); | |
185 | freesstring(serverlist[servernum].description); | |
186 | memset(&(serverlist[servernum]),0,sizeof(server)); /* sets state back to LS_INVALID */ | |
187 | } | |
188 | ||
189 | int findserver(const char *name) { | |
190 | int i; | |
191 | ||
192 | for(i=0;i<MAXSERVERS;i++) | |
193 | if (serverlist[i].name!=NULL && !strncmp(serverlist[i].name->content,name,serverlist[i].name->length)) | |
194 | return i; | |
195 | ||
196 | return -1; | |
197 | } | |
198 |