1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2008 InspIRCd Development Team
6 * See: http://www.inspircd.org/wiki/index.php/Credits
8 * This program is free but copyrighted software; see
9 * the file COPYING for details.
11 * ---------------------------------------------------
14 #ifndef __INSP_SOCKET_H__
15 #define __INSP_SOCKET_H__
20 * States which a socket may be in
22 enum BufferedSocketState
24 /** Socket disconnected */
26 /** Socket connecting */
28 /** Socket fully connected */
30 /** Socket listening for connections */
32 /** Socket has an error */
37 * Error types which a socket may exhibit
39 enum BufferedSocketError
41 /** Socket connect timed out */
43 /** Socket could not be created */
45 /** Socket could not connect (refused) */
47 /** Socket could not bind to local port/ip */
49 /** Socket could not reslve host (depreciated) */
51 /** Socket could not write data */
53 /** No more file descriptors left to create socket! */
57 /* Required forward declarations */
61 using irc::sockets::insp_sockaddr;
62 using irc::sockets::insp_inaddr;
63 using irc::sockets::insp_ntoa;
64 using irc::sockets::insp_aton;
66 /** Used to time out socket connections
68 class CoreExport SocketTimeout : public Timer
71 /** BufferedSocket the class is attached to
74 /** Server instance creating the timeout class
76 InspIRCd* ServerInstance;
77 /** File descriptor of class this is attached to
81 /** Create a socket timeout class
82 * @param fd File descriptor of BufferedSocket
83 * @pram Instance server instance to attach to
84 * @param thesock BufferedSocket to attach to
85 * @param secs_from_now Seconds from now to time out
86 * @param now The current time
88 SocketTimeout(int fd, InspIRCd* Instance, BufferedSocket* thesock, long secs_from_now, time_t now) : Timer(secs_from_now, now), sock(thesock), ServerInstance(Instance), sfd(fd) { };
91 virtual void Tick(time_t now);
95 * BufferedSocket is an extendable socket class which modules
96 * can use for TCP socket support. It is fully integrated
97 * into InspIRCds socket loop and attaches its sockets to
98 * the core's instance of the SocketEngine class, meaning
99 * that any sockets you create have the same power and
100 * abilities as a socket created by the core itself.
101 * To use BufferedSocket, you must inherit a class from it,
102 * and use the BufferedSocket constructors to establish connections
105 class CoreExport BufferedSocket : public EventHandler
115 * Is hooked by a module for low level IO
120 * Instance we were created by
125 * Timeout class or NULL
127 SocketTimeout* Timeout;
132 unsigned long timeout_val;
135 * Socket output buffer (binary safe)
137 std::deque<std::string> outbuffer;
140 * The hostname connected to
145 * The port connected to, or the port
146 * this socket is listening on
151 * The state for this socket, either
152 * listening, connecting, connected
155 BufferedSocketState state;
158 * This value is true if the
159 * socket has timed out.
164 * Socket input buffer, used by read(). The class which
165 * extends BufferedSocket is expected to implement an extendable
166 * buffer which can grow much larger than 64k,
167 * this buffer is just designed to be temporary storage.
173 * The IP address being connected
174 * to stored in string form for
175 * easy retrieval by accessors.
180 * Used by accept() to indicate the
181 * sizes of the sockaddr_in structures
185 /** Flushes the write buffer
187 bool FlushWriteBuffer();
189 /** Set the queue sizes
190 * This private method sets the operating system queue
191 * sizes for this socket to 65535 so that it can queue
192 * more information without application-level queueing
193 * which was required in older software.
195 void SetQueues(int nfd);
197 /** When the socket has been marked as closing, this flag
198 * will be set to true, then the next time the socket is
199 * examined, the socket is deleted and closed.
203 /** Set to true when we're waiting for a write event.
204 * If this is true and a write event comes in, we
205 * call the write instead of the read method.
207 bool WaitingForWriteEvent;
211 * @param ip IP to bind to
212 * @return True is the binding succeeded
214 bool BindAddr(const std::string &ip);
217 * The default constructor does nothing
218 * and should not be used.
220 BufferedSocket(InspIRCd* SI);
223 * This constructor is used to associate
224 * an existing connecting with an BufferedSocket
225 * class. The given file descriptor must be
226 * valid, and when initialized, the BufferedSocket
227 * will be set with the given IP address
228 * and placed in CONNECTED state.
230 BufferedSocket(InspIRCd* SI, int newfd, const char* ip);
233 * This constructor is used to create a new
234 * socket, either listening for connections, or an outbound connection to another host.
235 * Note that if you specify a hostname in the 'ipaddr' parameter, this class will not
236 * connect. You must resolve your hostnames before passing them to BufferedSocket. To do so,
237 * you should use the nonblocking class 'Resolver'.
238 * @param ipaddr The IP to connect to, or bind to
239 * @param port The port number to connect to, or bind to
240 * @param listening true to listen on the given host:port pair, or false to connect to them
241 * @param maxtime Number of seconds to wait, if connecting, before the connection times out and an OnTimeout() event is generated
242 * @param connectbindip When creating an outbound connection, the IP to bind the connection to. If not defined, the port is not bound.
243 * @return On exit, GetState() returns I_ERROR if an error occured, and errno can be used to read the socket error.
245 BufferedSocket(InspIRCd* SI, const std::string &ipaddr, int port, bool listening, unsigned long maxtime, const std::string &connectbindip = "");
248 * This method is called when an outbound
249 * connection on your socket is completed.
250 * @return false to abort the connection, true to continue
252 virtual bool OnConnected();
255 * This method is called when an error occurs.
256 * A closed socket in itself is not an error,
257 * however errors also generate close events.
258 * @param e The error type which occured
260 virtual void OnError(BufferedSocketError e);
263 * When an established connection is terminated,
264 * the OnDisconnect method is triggered.
266 virtual int OnDisconnect();
269 * When there is data waiting to be read on a
270 * socket, the OnDataReady() method is called.
271 * Within this method, you *MUST* call the Read()
272 * method to read any pending data. At its lowest
273 * level, this event is signalled by the core via
274 * the socket engine. If you return false from this
275 * function, the core removes your socket from its
276 * list and erases it from the socket engine, then
277 * calls BufferedSocket::Close() and deletes it.
278 * @return false to close the socket
280 virtual bool OnDataReady();
283 * When it is ok to write to the socket, and a
284 * write event was requested, this method is
285 * triggered. Within this method you should call
286 * write() or send() etc, to send data to the
287 * other end of the socket. Further write events
288 * will not be triggered unless you call WantWrite().
289 * @return false to close the socket
291 virtual bool OnWriteReady();
294 * When an outbound connection fails, and the
295 * attempt times out, you will receive this event.
296 * The method will trigger once maxtime seconds are
297 * reached (as given in the constructor) just
298 * before the socket's descriptor is closed.
299 * A failed DNS lookup may cause this event if
300 * the DNS server is not responding, as well as
301 * a failed connect() call, because DNS lookups are
302 * nonblocking as implemented by this class.
304 virtual void OnTimeout();
307 * Whenever close() is called, OnClose() will be
308 * called first. Please note that this means
309 * OnClose will be called alongside OnError(),
310 * OnTimeout(), and Close(), and also when
311 * cancelling a listening socket by calling
312 * the destructor indirectly.
314 virtual void OnClose();
317 * Reads all pending bytes from the socket
318 * into a char* array which can be up to
319 * 16 kilobytes in length.
321 virtual const char* Read();
324 * Returns the IP address associated with
325 * this connection, or an empty string if
326 * no IP address exists.
331 * Writes a std::string to the socket. No carriage
332 * returns or linefeeds are appended to the string.
333 * @param data The data to send
335 virtual int Write(const std::string &data);
338 * If your socket is a listening socket, when a new
339 * connection comes in on the socket this method will
340 * be called. Given the new file descriptor in the
341 * parameters, and the IP, it is recommended you copy
342 * them to a new instance of your socket class,
345 * MySocket* newsocket = new MySocket(newfd,ip);
347 * Once you have done this, you can then associate the
348 * new socket with the core using Server::AddSocket().
350 virtual int OnIncomingConnection(int newfd, char* ip);
353 * Changes the socket's state. The core uses this
354 * to change socket states, and you should not call
357 void SetState(BufferedSocketState s);
360 * Call this to receive the next write event
361 * that comes along for this fd to the OnWriteReady
367 * Returns the current socket state.
369 BufferedSocketState GetState();
372 * Only the core should call this function.
373 * When called, it is assumed the socket is ready
374 * to read data, and the method call routes the
375 * event to the various methods of BufferedSocket
376 * for you to handle. This can also cause the
377 * socket's state to change.
382 * This method returns the socket's file descriptor
383 * as assigned by the operating system, or -1
384 * if no descriptor has been assigned.
389 * This method causes the socket to close, and may
390 * also be triggered by other methods such as OnTimeout
393 virtual void Close();
396 * The destructor may implicitly call OnClose(), and
397 * will close() and shutdown() the file descriptor
398 * used for this socket.
400 virtual ~BufferedSocket();
403 * This method attempts to connect to a hostname.
404 * This only occurs on a non-listening socket. This
405 * method is asyncronous.
407 virtual bool DoConnect();
410 * This method marks the socket closed.
411 * The next time the core examines a socket marked
412 * as closed, the socket will be closed and the
415 * NOTE: This method is DEPRECIATED and will be
420 /** Handle event from EventHandler parent class
422 void HandleEvent(EventType et, int errornum = 0);
424 /** Returns true if this socket is readable