2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2019 Robby <robby@chatbelgie.be>
5 * Copyright (C) 2013, 2016-2017 Attila Molnar <attilamolnar@hush.com>
7 * This file is part of InspIRCd. InspIRCd is free software: you can
8 * redistribute it and/or modify it under the terms of the GNU General Public
9 * License as published by the Free Software Foundation, version 2.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 class IOHookProvider : public refcountbase, public ServiceProvider
27 const bool middlehook;
39 * @param mod Module that owns the IOHookProvider
40 * @param Name Name of the provider
41 * @param hooktype One of IOHookProvider::Type
42 * @param middle True if the IOHook instances created by this hook are subclasses of IOHookMiddle, false otherwise
44 IOHookProvider(Module* mod, const std::string& Name, Type hooktype = IOH_UNKNOWN, bool middle = false)
45 : ServiceProvider(mod, Name, SERVICE_IOHOOK), middlehook(middle), type(hooktype) { }
47 /** Check if the IOHook provided can appear in the non-last position of a hook chain.
48 * That is the case if and only if the IOHook instances created are subclasses of IOHookMiddle.
49 * @return True if the IOHooks provided are subclasses of IOHookMiddle
51 bool IsMiddle() const { return middlehook; }
53 /** Called when the provider should hook an incoming connection and act as being on the server-side of the connection.
54 * This occurs when a bind block has a hook configured and the listener accepts a connection.
55 * @param sock Socket to hook
56 * @param client Client IP address and port
57 * @param server Server IP address and port
59 virtual void OnAccept(StreamSocket* sock, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) = 0;
61 /** Called when the provider should hook an outgoing connection and act as being on the client side of the connection.
62 * @param sock Socket to hook
64 virtual void OnConnect(StreamSocket* sock) = 0;
67 class IOHook : public classbase
70 /** The IOHookProvider for this hook, contains information about the hook,
71 * such as the module providing it and the hook type.
73 reference<IOHookProvider> prov;
76 * @param provider IOHookProvider that creates this object
78 IOHook(IOHookProvider* provider)
82 * Called when the hooked socket has data to write, or when the socket engine returns it as writable
83 * @param sock Hooked socket
84 * @param sendq Send queue to send data from
85 * @return 1 if the sendq has been completely emptied, 0 if there is
86 * still data to send, and -1 if there was an error
88 virtual int OnStreamSocketWrite(StreamSocket* sock, StreamSocket::SendQueue& sendq) = 0;
90 /** Called immediately before the hooked socket is closed. When this event is called, shutdown()
91 * has not yet been called on the socket.
92 * @param sock Hooked socket
94 virtual void OnStreamSocketClose(StreamSocket* sock) = 0;
97 * Called when the hooked socket has data to read
98 * @param sock Hooked socket
99 * @param recvq The receive queue that new data should be appended to
100 * @return 1 if new data has been read, 0 if no new data is ready (but the
101 * socket is still connected), -1 if there was an error or close
103 virtual int OnStreamSocketRead(StreamSocket* sock, std::string& recvq) = 0;
106 class IOHookMiddle : public IOHook
108 /** Data already processed by the IOHook waiting to go down the chain
110 StreamSocket::SendQueue sendq;
112 /** Data waiting to go up the chain
116 /** Next IOHook in the chain
121 /** Get all queued up data which has not yet been passed up the hook chain
122 * @return RecvQ containing the data
124 std::string& GetRecvQ() { return precvq; }
126 /** Get all queued up data which is ready to go down the hook chain
127 * @return SendQueue containing all data waiting to go down the hook chain
129 StreamSocket::SendQueue& GetSendQ() { return sendq; }
133 * @param provider IOHookProvider that creates this object
135 IOHookMiddle(IOHookProvider* provider)
141 /** Get all queued up data which is ready to go down the hook chain
142 * @return SendQueue containing all data waiting to go down the hook chain
144 const StreamSocket::SendQueue& GetSendQ() const { return sendq; }
146 /** Get the next IOHook in the chain
147 * @return Next hook in the chain or NULL if this is the last hook
149 IOHook* GetNextHook() const { return nexthook; }
151 /** Set the next hook in the chain
152 * @param hook Hook to set as the next hook in the chain
154 void SetNextHook(IOHook* hook) { nexthook = hook; }
156 /** 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.
157 * @param hook IOHook to check
158 * @return IOHookMiddle referring to the same hook or NULL
160 static IOHookMiddle* ToMiddleHook(IOHook* hook)
162 if (hook->prov->IsMiddle())
163 return static_cast<IOHookMiddle*>(hook);
167 friend class StreamSocket;