2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2013 Attila Molnar <attilamolnar@hush.com>
6 * This file is part of InspIRCd. InspIRCd is free software: you can
7 * redistribute it and/or modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation, version 2.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 class IOHookProvider : public refcountbase, public ServiceProvider
26 const bool middlehook;
38 * @param mod Module that owns the IOHookProvider
39 * @param Name Name of the provider
40 * @param hooktype One of IOHookProvider::Type
41 * @param middle True if the IOHook instances created by this hook are subclasses of IOHookMiddle, false otherwise
43 IOHookProvider(Module* mod, const std::string& Name, Type hooktype = IOH_UNKNOWN, bool middle = false)
44 : ServiceProvider(mod, Name, SERVICE_IOHOOK), middlehook(middle), type(hooktype) { }
46 /** Check if the IOHook provided can appear in the non-last position of a hook chain.
47 * That is the case if and only if the IOHook instances created are subclasses of IOHookMiddle.
48 * @return True if the IOHooks provided are subclasses of IOHookMiddle
50 bool IsMiddle() const { return middlehook; }
52 /** Called when the provider should hook an incoming connection and act as being on the server side of the connection.
53 * This occurs when a bind block has a hook configured and the listener accepts a connection.
54 * @param sock Socket to hook
55 * @param client Client IP address and port
56 * @param server Server IP address and port
58 virtual void OnAccept(StreamSocket* sock, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) = 0;
60 /** Called when the provider should hook an outgoing connection and act as being on the client side of the connection.
61 * @param sock Socket to hook
63 virtual void OnConnect(StreamSocket* sock) = 0;
66 class IOHook : public classbase
69 /** The IOHookProvider for this hook, contains information about the hook,
70 * such as the module providing it and the hook type.
72 reference<IOHookProvider> prov;
75 * @param provider IOHookProvider that creates this object
77 IOHook(IOHookProvider* provider)
81 * Called when the hooked socket has data to write, or when the socket engine returns it as writable
82 * @param sock Hooked socket
83 * @param sendq Send queue to send data from
84 * @return 1 if the sendq has been completely emptied, 0 if there is
85 * still data to send, and -1 if there was an error
87 virtual int OnStreamSocketWrite(StreamSocket* sock, StreamSocket::SendQueue& sendq) = 0;
89 /** Called immediately before the hooked socket is closed. When this event is called, shutdown()
90 * has not yet been called on the socket.
91 * @param sock Hooked socket
93 virtual void OnStreamSocketClose(StreamSocket* sock) = 0;
96 * Called when the hooked socket has data to read
97 * @param sock Hooked socket
98 * @param recvq The receive queue that new data should be appended to
99 * @return 1 if new data has been read, 0 if no new data is ready (but the
100 * socket is still connected), -1 if there was an error or close
102 virtual int OnStreamSocketRead(StreamSocket* sock, std::string& recvq) = 0;
105 class IOHookMiddle : public IOHook
107 /** Data already processed by the IOHook waiting to go down the chain
109 StreamSocket::SendQueue sendq;
111 /** Data waiting to go up the chain
115 /** Next IOHook in the chain
120 /** Get all queued up data which has not yet been passed up the hook chain
121 * @return RecvQ containing the data
123 std::string& GetRecvQ() { return precvq; }
125 /** Get all queued up data which is ready to go down the hook chain
126 * @return SendQueue containing all data waiting to go down the hook chain
128 StreamSocket::SendQueue& GetSendQ() { return sendq; }
132 * @param provider IOHookProvider that creates this object
134 IOHookMiddle(IOHookProvider* provider)
140 /** Get all queued up data which is ready to go down the hook chain
141 * @return SendQueue containing all data waiting to go down the hook chain
143 const StreamSocket::SendQueue& GetSendQ() const { return sendq; }
145 /** Get the next IOHook in the chain
146 * @return Next hook in the chain or NULL if this is the last hook
148 IOHook* GetNextHook() const { return nexthook; }
150 /** Set the next hook in the chain
151 * @param hook Hook to set as the next hook in the chain
153 void SetNextHook(IOHook* hook) { nexthook = hook; }
155 /** Check if a hook is capable of being the non-last hook in a hook chain and if so, cast it to an IOHookMiddle object.
156 * @param hook IOHook to check
157 * @return IOHookMiddle referring to the same hook or NULL
159 static IOHookMiddle* ToMiddleHook(IOHook* hook)
161 if (hook->prov->IsMiddle())
162 return static_cast<IOHookMiddle*>(hook);
166 friend class StreamSocket;