]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_spanningtree/treesocket.h
Support port binding here
[user/henk/code/inspircd.git] / src / modules / m_spanningtree / treesocket.h
1 #ifndef __TREESOCKET_H__
2 #define __TREESOCKET_H__
3
4 #include "configreader.h"
5 #include "users.h"
6 #include "channels.h"
7 #include "modules.h"
8 #include "commands/cmd_whois.h"
9 #include "commands/cmd_stats.h"
10 #include "socket.h"
11 #include "inspircd.h"
12 #include "wildcard.h"
13 #include "xline.h"
14 #include "transport.h"
15
16 #include "m_spanningtree/utils.h"
17
18 /*
19  * The server list in InspIRCd is maintained as two structures
20  * which hold the data in different ways. Most of the time, we
21  * want to very quicky obtain three pieces of information:
22  *
23  * (1) The information on a server
24  * (2) The information on the server we must send data through
25  *     to actually REACH the server we're after
26  * (3) Potentially, the child/parent objects of this server
27  *
28  * The InspIRCd spanning protocol provides easy access to these
29  * by storing the data firstly in a recursive structure, where
30  * each item references its parent item, and a dynamic list
31  * of child items, and another structure which stores the items
32  * hashed, linearly. This means that if we want to find a server
33  * by name quickly, we can look it up in the hash, avoiding
34  * any O(n) lookups. If however, during a split or sync, we want
35  * to apply an operation to a server, and any of its child objects
36  * we can resort to recursion to walk the tree structure.
37  * Any socket can have one of five states at any one time.
38  * The LISTENER state indicates a socket which is listening
39  * for connections. It cannot receive data itself, only incoming
40  * sockets.
41  * The CONNECTING state indicates an outbound socket which is
42  * waiting to be writeable.
43  * The WAIT_AUTH_1 state indicates the socket is outbound and
44  * has successfully connected, but has not yet sent and received
45  * SERVER strings.
46  * The WAIT_AUTH_2 state indicates that the socket is inbound
47  * (allocated by a LISTENER) but has not yet sent and received
48  * SERVER strings.
49  * The CONNECTED state represents a fully authorized, fully
50  * connected server.
51  */
52 enum ServerState { LISTENER, CONNECTING, WAIT_AUTH_1, WAIT_AUTH_2, CONNECTED };
53
54 /** Every SERVER connection inbound or outbound is represented by
55  * an object of type TreeSocket.
56  * TreeSockets, being inherited from InspSocket, can be tied into
57  * the core socket engine, and we cn therefore receive activity events
58  * for them, just like activex objects on speed. (yes really, that
59  * is a technical term!) Each of these which relates to a locally
60  * connected server is assocated with it, by hooking it onto a
61  * TreeSocket class using its constructor. In this way, we can
62  * maintain a list of servers, some of which are directly connected,
63  * some of which are not.
64  */
65 class TreeSocket : public InspSocket
66 {
67         SpanningTreeUtilities* Utils;
68         std::string myhost;
69         std::string in_buffer;
70         ServerState LinkState;
71         std::string InboundServerName;
72         std::string InboundDescription;
73         int num_lost_users;
74         int num_lost_servers;
75         time_t NextPing;
76         bool LastPingWasGood;
77         bool bursting;
78         unsigned int keylength;
79         std::string ModuleList;
80         std::map<std::string,std::string> CapKeys;
81         Module* Hook;
82
83  public:
84
85         /** Because most of the I/O gubbins are encapsulated within
86          * InspSocket, we just call the superclass constructor for
87          * most of the action, and append a few of our own values
88          * to it.
89          */
90         TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, std::string host, int port, bool listening, unsigned long maxtime, Module* HookMod = NULL);
91
92         TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, std::string host, int port, bool listening, unsigned long maxtime, const std::string &ServerName, const std::string &bindto, Module* HookMod = NULL);
93
94         /** When a listening socket gives us a new file descriptor,
95          * we must associate it with a socket without creating a new
96          * connection. This constructor is used for this purpose.
97          */
98         TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, int newfd, char* ip, Module* HookMod = NULL);
99
100         ServerState GetLinkState();
101
102         Module* GetHook();
103
104         ~TreeSocket();
105
106         /** When an outbound connection finishes connecting, we receive
107          * this event, and must send our SERVER string to the other
108          * side. If the other side is happy, as outlined in the server
109          * to server docs on the inspircd.org site, the other side
110          * will then send back its own server string.
111          */
112         virtual bool OnConnected();
113
114         virtual void OnError(InspSocketError e);
115
116         virtual int OnDisconnect();
117
118         /** Recursively send the server tree with distances as hops.
119          * This is used during network burst to inform the other server
120          * (and any of ITS servers too) of what servers we know about.
121          * If at any point any of these servers already exist on the other
122          * end, our connection may be terminated. The hopcounts given
123          * by this function are relative, this doesn't matter so long as
124          * they are all >1, as all the remote servers re-calculate them
125          * to be relative too, with themselves as hop 0.
126          */
127         void SendServers(TreeServer* Current, TreeServer* s, int hops);
128
129         std::string MyCapabilities();
130
131         void SendCapabilities();
132
133         /* Check a comma seperated list for an item */
134         bool HasItem(const std::string &list, const std::string &item);
135
136         /* Isolate and return the elements that are different between two comma seperated lists */
137         std::string ListDifference(const std::string &one, const std::string &two);
138
139         bool Capab(const std::deque<std::string> &params);
140
141         /** This function forces this server to quit, removing this server
142          * and any users on it (and servers and users below that, etc etc).
143          * It's very slow and pretty clunky, but luckily unless your network
144          * is having a REAL bad hair day, this function shouldnt be called
145          * too many times a month ;-)
146          */
147         void SquitServer(std::string &from, TreeServer* Current);
148
149         /** This is a wrapper function for SquitServer above, which
150          * does some validation first and passes on the SQUIT to all
151          * other remaining servers.
152          */
153         void Squit(TreeServer* Current, const std::string &reason);
154
155         /** FMODE command - server mode with timestamp checks */
156         bool ForceMode(const std::string &source, std::deque<std::string> &params);
157
158         /** FTOPIC command */
159         bool ForceTopic(const std::string &source, std::deque<std::string> &params);
160
161         /** FJOIN, similar to TS6 SJOIN, but not quite. */
162         bool ForceJoin(const std::string &source, std::deque<std::string> &params);
163
164         /** NICK command */
165         bool IntroduceClient(const std::string &source, std::deque<std::string> &params);
166
167         /** Send one or more FJOINs for a channel of users.
168          * If the length of a single line is more than 480-NICKMAX
169          * in length, it is split over multiple lines.
170          */
171         void SendFJoins(TreeServer* Current, chanrec* c);
172
173         /** Send G, Q, Z and E lines */
174         void SendXLines(TreeServer* Current);
175
176         /** Send channel modes and topics */
177         void SendChannelModes(TreeServer* Current);
178
179         /** send all users and their oper state/modes */
180         void SendUsers(TreeServer* Current);
181
182         /** This function is called when we want to send a netburst to a local
183          * server. There is a set order we must do this, because for example
184          * users require their servers to exist, and channels require their
185          * users to exist. You get the idea.
186          */
187         void DoBurst(TreeServer* s);
188
189         /** This function is called when we receive data from a remote
190          * server. We buffer the data in a std::string (it doesnt stay
191          * there for long), reading using InspSocket::Read() which can
192          * read up to 16 kilobytes in one operation.
193          *
194          * IF THIS FUNCTION RETURNS FALSE, THE CORE CLOSES AND DELETES
195          * THE SOCKET OBJECT FOR US.
196          */
197         virtual bool OnDataReady();
198
199         int WriteLine(std::string line);
200
201         /* Handle ERROR command */
202         bool Error(std::deque<std::string> &params);
203
204         /** remote MOTD. leet, huh? */
205         bool Motd(const std::string &prefix, std::deque<std::string> &params);
206
207         /** remote ADMIN. leet, huh? */
208         bool Admin(const std::string &prefix, std::deque<std::string> &params);
209
210         bool Stats(const std::string &prefix, std::deque<std::string> &params);
211
212         /** Because the core won't let users or even SERVERS set +o,
213          * we use the OPERTYPE command to do this.
214          */
215         bool OperType(const std::string &prefix, std::deque<std::string> &params);
216
217         /** Because Andy insists that services-compatible servers must
218          * implement SVSNICK and SVSJOIN, that's exactly what we do :p
219          */
220         bool ForceNick(const std::string &prefix, std::deque<std::string> &params);
221
222         /*
223          * Remote SQUIT (RSQUIT). Routing works similar to SVSNICK: Route it to the server that the target is connected to locally,
224          * then let that server do the dirty work (squit it!). Example:
225          * A -> B -> C -> D: oper on A squits D, A routes to B, B routes to C, C notices D connected locally, kills it. -- w00t
226          */
227         bool RemoteSquit(const std::string &prefix, std::deque<std::string> &params);
228
229         bool ServiceJoin(const std::string &prefix, std::deque<std::string> &params);
230
231         bool RemoteRehash(const std::string &prefix, std::deque<std::string> &params);
232
233         bool RemoteKill(const std::string &prefix, std::deque<std::string> &params);
234
235         bool LocalPong(const std::string &prefix, std::deque<std::string> &params);
236
237         bool MetaData(const std::string &prefix, std::deque<std::string> &params);
238
239         bool ServerVersion(const std::string &prefix, std::deque<std::string> &params);
240
241         bool ChangeHost(const std::string &prefix, std::deque<std::string> &params);
242
243         bool AddLine(const std::string &prefix, std::deque<std::string> &params);
244
245         bool ChangeName(const std::string &prefix, std::deque<std::string> &params);
246
247         bool Whois(const std::string &prefix, std::deque<std::string> &params);
248
249         bool Push(const std::string &prefix, std::deque<std::string> &params);
250
251         bool HandleSetTime(const std::string &prefix, std::deque<std::string> &params);
252
253         bool Time(const std::string &prefix, std::deque<std::string> &params);
254
255         bool LocalPing(const std::string &prefix, std::deque<std::string> &params);
256
257         bool RemoveStatus(const std::string &prefix, std::deque<std::string> &params);
258
259         bool RemoteServer(const std::string &prefix, std::deque<std::string> &params);
260
261         bool Outbound_Reply_Server(std::deque<std::string> &params);
262
263         bool Inbound_Server(std::deque<std::string> &params);
264
265         void Split(const std::string &line, std::deque<std::string> &n);
266
267         bool ProcessLine(std::string &line);
268
269         virtual std::string GetName();
270
271         virtual void OnTimeout();
272
273         virtual void OnClose();
274
275         virtual int OnIncomingConnection(int newsock, char* ip);
276 };
277
278 #endif