]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/inspsocket.h
Merge pull request #1018 from SaberUK/insp20+hidekills
[user/henk/code/inspircd.git] / include / inspsocket.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
5  *   Copyright (C) 2007-2008 Robin Burchell <robin+git@viroteck.net>
6  *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
7  *   Copyright (C) 2006-2007 Craig Edwards <craigedwards@brainbox.cc>
8  *   Copyright (C) 2006 Oliver Lupton <oliverlupton@gmail.com>
9  *
10  * This file is part of InspIRCd.  InspIRCd is free software: you can
11  * redistribute it and/or modify it under the terms of the GNU General Public
12  * License as published by the Free Software Foundation, version 2.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23
24 #ifndef INSPSOCKET_H
25 #define INSPSOCKET_H
26
27 #include "timer.h"
28
29 /**
30  * States which a socket may be in
31  */
32 enum BufferedSocketState
33 {
34         /** Socket disconnected */
35         I_DISCONNECTED,
36         /** Socket connecting */
37         I_CONNECTING,
38         /** Socket fully connected */
39         I_CONNECTED,
40         /** Socket has an error */
41         I_ERROR
42 };
43
44 /**
45  * Error types which a socket may exhibit
46  */
47 enum BufferedSocketError
48 {
49         /** No error */
50         I_ERR_NONE,
51         /** Socket was closed by peer */
52         I_ERR_DISCONNECT,
53         /** Socket connect timed out */
54         I_ERR_TIMEOUT,
55         /** Socket could not be created */
56         I_ERR_SOCKET,
57         /** Socket could not connect (refused) */
58         I_ERR_CONNECT,
59         /** Socket could not bind to local port/ip */
60         I_ERR_BIND,
61         /** Socket could not write data */
62         I_ERR_WRITE,
63         /** No more file descriptors left to create socket! */
64         I_ERR_NOMOREFDS,
65         /** Some other error */
66         I_ERR_OTHER
67 };
68
69 /* Required forward declarations */
70 class BufferedSocket;
71
72 /** Used to time out socket connections
73  */
74 class CoreExport SocketTimeout : public Timer
75 {
76  private:
77         /** BufferedSocket the class is attached to
78          */
79         BufferedSocket* sock;
80
81         /** File descriptor of class this is attached to
82          */
83         int sfd;
84
85  public:
86         /** Create a socket timeout class
87          * @param fd File descriptor of BufferedSocket
88          * @param thesock BufferedSocket to attach to
89          * @param secs_from_now Seconds from now to time out
90          * @param now The current time
91          */
92         SocketTimeout(int fd, BufferedSocket* thesock, long secs_from_now, time_t now) : Timer(secs_from_now, now), sock(thesock), sfd(fd) { }
93
94         /** Handle tick event
95          */
96         virtual void Tick(time_t now);
97 };
98
99 /**
100  * StreamSocket is a class that wraps a TCP socket and handles send
101  * and receive queues, including passing them to IO hooks
102  */
103 class CoreExport StreamSocket : public EventHandler
104 {
105         /** Module that handles raw I/O for this socket, or NULL */
106         reference<Module> IOHook;
107         /** Private send queue. Note that individual strings may be shared
108          */
109         std::deque<std::string> sendq;
110         /** Length, in bytes, of the sendq */
111         size_t sendq_len;
112         /** Error - if nonempty, the socket is dead, and this is the reason. */
113         std::string error;
114  protected:
115         std::string recvq;
116  public:
117         StreamSocket() : sendq_len(0) {}
118         inline Module* GetIOHook();
119         inline void AddIOHook(Module* m);
120         inline void DelIOHook();
121         /** Handle event from socket engine.
122          * This will call OnDataReady if there is *new* data in recvq
123          */
124         virtual void HandleEvent(EventType et, int errornum = 0);
125         /** Dispatched from HandleEvent */
126         virtual void DoRead();
127         /** Dispatched from HandleEvent */
128         virtual void DoWrite();
129
130         /** Sets the error message for this socket. Once set, the socket is dead. */
131         void SetError(const std::string& err) { if (error.empty()) error = err; }
132
133         /** Gets the error message for this socket. */
134         const std::string& getError() const { return error; }
135
136         /** Called when new data is present in recvq */
137         virtual void OnDataReady() = 0;
138         /** Called when the socket gets an error from socket engine or IO hook */
139         virtual void OnError(BufferedSocketError e) = 0;
140
141         /** Send the given data out the socket, either now or when writes unblock
142          */
143         void WriteData(const std::string& data);
144         /** Convenience function: read a line from the socket
145          * @param line The line read
146          * @param delim The line delimiter
147          * @return true if a line was read
148          */
149         bool GetNextLine(std::string& line, char delim = '\n');
150         /** Useful for implementing sendq exceeded */
151         inline size_t getSendQSize() const { return sendq_len; }
152
153         /**
154          * Close the socket, remove from socket engine, etc
155          */
156         virtual void Close();
157         /** This ensures that close is called prior to destructor */
158         virtual CullResult cull();
159 };
160 /**
161  * BufferedSocket is an extendable socket class which modules
162  * can use for TCP socket support. It is fully integrated
163  * into InspIRCds socket loop and attaches its sockets to
164  * the core's instance of the SocketEngine class, meaning
165  * that all use is fully asynchronous.
166  *
167  * To use BufferedSocket, you must inherit a class from it.
168  */
169 class CoreExport BufferedSocket : public StreamSocket
170 {
171  public:
172         /** Timeout object or NULL
173          */
174         SocketTimeout* Timeout;
175
176         /**
177          * The state for this socket, either
178          * listening, connecting, connected
179          * or error.
180          */
181         BufferedSocketState state;
182
183         BufferedSocket();
184         /**
185          * This constructor is used to associate
186          * an existing connecting with an BufferedSocket
187          * class. The given file descriptor must be
188          * valid, and when initialized, the BufferedSocket
189          * will be placed in CONNECTED state.
190          */
191         BufferedSocket(int newfd);
192
193         /** Begin connection to the given address
194          * This will create a socket, register with socket engine, and start the asynchronous
195          * connection process. If an error is detected at this point (such as out of file descriptors),
196          * OnError will be called; otherwise, the state will become CONNECTING.
197          * @param ipaddr Address to connect to
198          * @param aport Port to connect on
199          * @param maxtime Time to wait for connection
200          * @param connectbindip Address to bind to (if NULL, no bind will be done)
201          */
202         void DoConnect(const std::string &ipaddr, int aport, unsigned long maxtime, const std::string &connectbindip);
203
204         /** This method is called when an outbound connection on your socket is
205          * completed.
206          */
207         virtual void OnConnected();
208
209         /** When there is data waiting to be read on a socket, the OnDataReady()
210          * method is called.
211          */
212         virtual void OnDataReady() = 0;
213
214         /**
215          * When an outbound connection fails, and the attempt times out, you
216          * will receive this event.  The method will trigger once maxtime
217          * seconds are reached (as given in the constructor) just before the
218          * socket's descriptor is closed.  A failed DNS lookup may cause this
219          * event if the DNS server is not responding, as well as a failed
220          * connect() call, because DNS lookups are nonblocking as implemented by
221          * this class.
222          */
223         virtual void OnTimeout();
224
225         virtual ~BufferedSocket();
226  protected:
227         virtual void DoWrite();
228         BufferedSocketError BeginConnect(const irc::sockets::sockaddrs& dest, const irc::sockets::sockaddrs& bind, unsigned long timeout);
229         BufferedSocketError BeginConnect(const std::string &ipaddr, int aport, unsigned long maxtime, const std::string &connectbindip);
230 };
231
232 #include "modules.h"
233
234 inline Module* StreamSocket::GetIOHook() { return IOHook; }
235 inline void StreamSocket::AddIOHook(Module* m) { IOHook = m; }
236 inline void StreamSocket::DelIOHook() { IOHook = NULL; }
237 #endif