1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2010 InspIRCd Development Team
6 * See: http://wiki.inspircd.org/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 has an error */
35 * Error types which a socket may exhibit
37 enum BufferedSocketError
41 /** Socket was closed by peer */
43 /** Socket connect timed out */
45 /** Socket could not be created */
47 /** Socket could not connect (refused) */
49 /** Socket could not bind to local port/ip */
51 /** Socket could not write data */
53 /** No more file descriptors left to create socket! */
55 /** Some other error */
59 /* Required forward declarations */
62 /** Used to time out socket connections
64 class CoreExport SocketTimeout : public Timer
67 /** BufferedSocket the class is attached to
71 /** File descriptor of class this is attached to
76 /** Create a socket timeout class
77 * @param fd File descriptor of BufferedSocket
78 * @pram Instance server instance to attach to
79 * @param thesock BufferedSocket to attach to
80 * @param secs_from_now Seconds from now to time out
81 * @param now The current time
83 SocketTimeout(int fd, BufferedSocket* thesock, long secs_from_now, time_t now) : Timer(secs_from_now, now), sock(thesock), sfd(fd) { }
87 virtual void Tick(time_t now);
91 * StreamSocket is a class that wraps a TCP socket and handles send
92 * and receive queues, including passing them to IO hooks
94 class CoreExport StreamSocket : public EventHandler
96 /** Module that handles raw I/O for this socket, or NULL */
97 reference<Module> IOHook;
98 /** Private send queue. Note that individual strings may be shared
100 std::deque<std::string> sendq;
101 /** Length, in bytes, of the sendq */
103 /** Error - if nonempty, the socket is dead, and this is the reason. */
108 StreamSocket() : sendq_len(0) {}
109 inline Module* GetIOHook();
110 inline void AddIOHook(Module* m);
111 inline void DelIOHook();
112 /** Handle event from socket engine.
113 * This will call OnDataReady if there is *new* data in recvq
115 virtual void HandleEvent(EventType et, int errornum = 0);
116 /** Dispatched from HandleEvent */
117 virtual void DoRead();
118 /** Dispatched from HandleEvent */
119 virtual void DoWrite();
121 /** Sets the error message for this socket. Once set, the socket is dead. */
122 void SetError(const std::string& err) { if (error.empty()) error = err; }
124 /** Gets the error message for this socket. */
125 const std::string& getError() const { return error; }
127 /** Called when new data is present in recvq */
128 virtual void OnDataReady() = 0;
129 /** Called when the socket gets an error from socket engine or IO hook */
130 virtual void OnError(BufferedSocketError e) = 0;
132 /** Send the given data out the socket, either now or when writes unblock
134 void WriteData(const std::string& data);
135 /** Convenience function: read a line from the socket
136 * @param line The line read
137 * @param delim The line delimiter
138 * @return true if a line was read
140 bool GetNextLine(std::string& line, char delim = '\n');
141 /** Useful for implementing sendq exceeded */
142 inline const size_t getSendQSize() const { return sendq_len; }
145 * Close the socket, remove from socket engine, etc
147 virtual void Close();
148 /** This ensures that close is called prior to destructor */
149 virtual CullResult cull();
152 * BufferedSocket is an extendable socket class which modules
153 * can use for TCP socket support. It is fully integrated
154 * into InspIRCds socket loop and attaches its sockets to
155 * the core's instance of the SocketEngine class, meaning
156 * that all use is fully asynchronous.
158 * To use BufferedSocket, you must inherit a class from it.
160 class CoreExport BufferedSocket : public StreamSocket
163 /** Timeout object or NULL
165 SocketTimeout* Timeout;
168 * The state for this socket, either
169 * listening, connecting, connected
172 BufferedSocketState state;
176 * This constructor is used to associate
177 * an existing connecting with an BufferedSocket
178 * class. The given file descriptor must be
179 * valid, and when initialized, the BufferedSocket
180 * will be placed in CONNECTED state.
182 BufferedSocket(int newfd);
184 /** Begin connection to the given address
185 * This will create a socket, register with socket engine, and start the asynchronous
186 * connection process. If an error is detected at this point (such as out of file descriptors),
187 * OnError will be called; otherwise, the state will become CONNECTING.
188 * @param dest Address to connect to
189 * @param bind Address to bind to (if NULL, no bind will be done)
190 * @param timeout Time to wait for connection
192 void DoConnect(const std::string &ipaddr, int aport, unsigned long maxtime, const std::string &connectbindip);
194 /** This method is called when an outbound connection on your socket is
197 virtual void OnConnected();
199 /** When there is data waiting to be read on a socket, the OnDataReady()
202 virtual void OnDataReady() = 0;
205 * When an outbound connection fails, and the attempt times out, you
206 * will receive this event. The method will trigger once maxtime
207 * seconds are reached (as given in the constructor) just before the
208 * socket's descriptor is closed. A failed DNS lookup may cause this
209 * event if the DNS server is not responding, as well as a failed
210 * connect() call, because DNS lookups are nonblocking as implemented by
213 virtual void OnTimeout();
215 virtual ~BufferedSocket();
217 virtual void DoWrite();
218 BufferedSocketError BeginConnect(const irc::sockets::sockaddrs& dest, const irc::sockets::sockaddrs& bind, unsigned long timeout);
219 BufferedSocketError BeginConnect(const std::string &ipaddr, int aport, unsigned long maxtime, const std::string &connectbindip);
224 inline Module* StreamSocket::GetIOHook() { return IOHook; }
225 inline void StreamSocket::AddIOHook(Module* m) { IOHook = m; }
226 inline void StreamSocket::DelIOHook() { IOHook = NULL; }