1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2007 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__
21 #include "inspircd_config.h"
23 #include "inspsocket.h"
27 * States which a socket may be in
31 /** Socket disconnected */
33 /** Socket connecting */
35 /** Socket fully connected */
37 /** Socket listening for connections */
39 /** Socket has an error */
44 * Error types which a socket may exhibit
48 /** Socket connect timed out */
50 /** Socket could not be created */
52 /** Socket could not connect (refused) */
54 /** Socket could not bind to local port/ip */
56 /** Socket could not reslve host (depreciated) */
58 /** Socket could not write data */
60 /** No more file descriptors left to create socket! */
64 /* Required forward declarations */
68 using irc::sockets::insp_sockaddr;
69 using irc::sockets::insp_inaddr;
70 using irc::sockets::insp_ntoa;
71 using irc::sockets::insp_aton;
73 /** Used to time out socket connections
75 class CoreExport SocketTimeout : public InspTimer
78 /** InspSocket the class is attached to
81 /** Server instance creating the timeout class
83 InspIRCd* ServerInstance;
84 /** File descriptor of class this is attached to
88 /** Create a socket timeout class
89 * @param fd File descriptor of InspSocket
90 * @pram Instance server instance to attach to
91 * @param thesock InspSocket to attach to
92 * @param secs_from_now Seconds from now to time out
93 * @param now The current time
95 SocketTimeout(int fd, InspIRCd* Instance, InspSocket* thesock, long secs_from_now, time_t now) : InspTimer(secs_from_now, now), sock(thesock), ServerInstance(Instance), sfd(fd) { };
98 virtual void Tick(time_t now);
102 * InspSocket is an extendable socket class which modules
103 * can use for TCP socket support. It is fully integrated
104 * into InspIRCds socket loop and attaches its sockets to
105 * the core's instance of the SocketEngine class, meaning
106 * that any sockets you create have the same power and
107 * abilities as a socket created by the core itself.
108 * To use InspSocket, you must inherit a class from it,
109 * and use the InspSocket constructors to establish connections
112 class CoreExport InspSocket : public EventHandler
122 * Is hooked by a module for low level IO
127 * Instance we were created by
132 * Timeout class or NULL
134 SocketTimeout* Timeout;
139 unsigned long timeout_val;
142 * Socket output buffer (binary safe)
144 std::deque<std::string> outbuffer;
147 * The hostname connected to
152 * The port connected to, or the port
153 * this socket is listening on
158 * The state for this socket, either
159 * listening, connecting, connected
162 InspSocketState state;
165 * This value is true if the
166 * socket has timed out.
171 * Socket input buffer, used by read(). The class which
172 * extends InspSocket is expected to implement an extendable
173 * buffer which can grow much larger than 64k,
174 * this buffer is just designed to be temporary storage.
180 * The IP address being connected
181 * to stored in string form for
182 * easy retrieval by accessors.
187 * Used by accept() to indicate the
188 * sizes of the sockaddr_in structures
192 /** Flushes the write buffer
194 bool FlushWriteBuffer();
196 /** Set the queue sizes
197 * This private method sets the operating system queue
198 * sizes for this socket to 65535 so that it can queue
199 * more information without application-level queueing
200 * which was required in older software.
202 void SetQueues(int nfd);
204 /** When the socket has been marked as closing, this flag
205 * will be set to true, then the next time the socket is
206 * examined, the socket is deleted and closed.
210 /** Set to true when we're waiting for a write event.
211 * If this is true and a write event comes in, we
212 * call the write instead of the read method.
214 bool WaitingForWriteEvent;
218 * @param ip IP to bind to
219 * @return True is the binding succeeded
221 bool BindAddr(const std::string &ip);
224 * The default constructor does nothing
225 * and should not be used.
227 InspSocket(InspIRCd* SI);
230 * This constructor is used to associate
231 * an existing connecting with an InspSocket
232 * class. The given file descriptor must be
233 * valid, and when initialized, the InspSocket
234 * will be set with the given IP address
235 * and placed in CONNECTED state.
237 InspSocket(InspIRCd* SI, int newfd, const char* ip);
240 * This constructor is used to create a new
241 * socket, either listening for connections, or an outbound connection to another host.
242 * Note that if you specify a hostname in the 'ipaddr' parameter, this class will not
243 * connect. You must resolve your hostnames before passing them to InspSocket. To do so,
244 * you should use the nonblocking class 'Resolver'.
245 * @param ipaddr The IP to connect to, or bind to
246 * @param port The port number to connect to, or bind to
247 * @param listening true to listen on the given host:port pair, or false to connect to them
248 * @param maxtime Number of seconds to wait, if connecting, before the connection times out and an OnTimeout() event is generated
249 * @param connectbindip When creating an outbound connection, the IP to bind the connection to. If not defined, the port is not bound.
250 * @return On exit, GetState() returns I_ERROR if an error occured, and errno can be used to read the socket error.
252 InspSocket(InspIRCd* SI, const std::string &ipaddr, int port, bool listening, unsigned long maxtime, const std::string &connectbindip = "");
255 * This method is called when an outbound
256 * connection on your socket is completed.
257 * @return false to abort the connection, true to continue
259 virtual bool OnConnected();
262 * This method is called when an error occurs.
263 * A closed socket in itself is not an error,
264 * however errors also generate close events.
265 * @param e The error type which occured
267 virtual void OnError(InspSocketError e);
270 * When an established connection is terminated,
271 * the OnDisconnect method is triggered.
273 virtual int OnDisconnect();
276 * When there is data waiting to be read on a
277 * socket, the OnDataReady() method is called.
278 * Within this method, you *MUST* call the Read()
279 * method to read any pending data. At its lowest
280 * level, this event is signalled by the core via
281 * the socket engine. If you return false from this
282 * function, the core removes your socket from its
283 * list and erases it from the socket engine, then
284 * calls InspSocket::Close() and deletes it.
285 * @return false to close the socket
287 virtual bool OnDataReady();
290 * When it is ok to write to the socket, and a
291 * write event was requested, this method is
292 * triggered. Within this method you should call
293 * write() or send() etc, to send data to the
294 * other end of the socket. Further write events
295 * will not be triggered unless you call WantWrite().
296 * @return false to close the socket
298 virtual bool OnWriteReady();
301 * When an outbound connection fails, and the
302 * attempt times out, you will receive this event.
303 * The method will trigger once maxtime seconds are
304 * reached (as given in the constructor) just
305 * before the socket's descriptor is closed.
306 * A failed DNS lookup may cause this event if
307 * the DNS server is not responding, as well as
308 * a failed connect() call, because DNS lookups are
309 * nonblocking as implemented by this class.
311 virtual void OnTimeout();
314 * Whenever close() is called, OnClose() will be
315 * called first. Please note that this means
316 * OnClose will be called alongside OnError(),
317 * OnTimeout(), and Close(), and also when
318 * cancelling a listening socket by calling
319 * the destructor indirectly.
321 virtual void OnClose();
324 * Reads all pending bytes from the socket
325 * into a char* array which can be up to
326 * 16 kilobytes in length.
328 virtual char* Read();
331 * Returns the IP address associated with
332 * this connection, or an empty string if
333 * no IP address exists.
338 * Writes a std::string to the socket. No carriage
339 * returns or linefeeds are appended to the string.
340 * @param data The data to send
342 virtual int Write(const std::string &data);
345 * If your socket is a listening socket, when a new
346 * connection comes in on the socket this method will
347 * be called. Given the new file descriptor in the
348 * parameters, and the IP, it is recommended you copy
349 * them to a new instance of your socket class,
352 * MySocket* newsocket = new MySocket(newfd,ip);
354 * Once you have done this, you can then associate the
355 * new socket with the core using Server::AddSocket().
357 virtual int OnIncomingConnection(int newfd, char* ip);
360 * Changes the socket's state. The core uses this
361 * to change socket states, and you should not call
364 void SetState(InspSocketState s);
367 * Call this to receive the next write event
368 * that comes along for this fd to the OnWriteReady
374 * Returns the current socket state.
376 InspSocketState GetState();
379 * Only the core should call this function.
380 * When called, it is assumed the socket is ready
381 * to read data, and the method call routes the
382 * event to the various methods of InspSocket
383 * for you to handle. This can also cause the
384 * socket's state to change.
389 * This method returns the socket's file descriptor
390 * as assigned by the operating system, or -1
391 * if no descriptor has been assigned.
396 * This method causes the socket to close, and may
397 * also be triggered by other methods such as OnTimeout
400 virtual void Close();
403 * The destructor may implicitly call OnClose(), and
404 * will close() and shutdown() the file descriptor
405 * used for this socket.
407 virtual ~InspSocket();
410 * This method attempts to connect to a hostname.
411 * This only occurs on a non-listening socket. This
412 * method is asyncronous.
414 virtual bool DoConnect();
417 * This method marks the socket closed.
418 * The next time the core examines a socket marked
419 * as closed, the socket will be closed and the
422 * NOTE: This method is DEPRECIATED and will be
427 /** Handle event from EventHandler parent class
429 void HandleEvent(EventType et, int errornum = 0);
431 /** Returns true if this socket is readable