Chunk is purely a wrapper class, any 'state variables', like 'characters in room...
[UnsignedByte.git] / src / Sockets / TcpSocket.h
blob73494b2f68f31e5b341df0ce445e17000b3f8058
1 /** \file TcpSocket.h
2 ** \date 2004-02-13
3 ** \author grymse@alhem.net
4 **/
5 /*
6 Copyright (C) 2004-2007 Anders Hedstrom
8 This library is made available under the terms of the GNU GPL.
10 If you would like to use this library in a closed-source application,
11 a separate license agreement is available. For information about
12 the closed-source license agreement for the C++ sockets library,
13 please visit http://www.alhem.net/Sockets/license.html and/or
14 email license@alhem.net.
16 This program is free software; you can redistribute it and/or
17 modify it under the terms of the GNU General Public License
18 as published by the Free Software Foundation; either version 2
19 of the License, or (at your option) any later version.
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #ifndef _SOCKETS_TcpSocket_H
31 #define _SOCKETS_TcpSocket_H
32 #include "sockets-config.h"
33 #include "StreamSocket.h"
34 #ifdef HAVE_OPENSSL
35 #include <openssl/ssl.h>
36 #include "SSLInitializer.h"
37 #endif
40 #define TCP_BUFSIZE_READ 16400
41 #define TCP_OUTPUT_CAPACITY 1024000
44 #ifdef SOCKETS_NAMESPACE
45 namespace SOCKETS_NAMESPACE {
46 #endif
48 class SocketAddress;
51 /** Socket implementation for TCP.
52 \ingroup basic */
53 class TcpSocket : public StreamSocket
55 /** \defgroup internal Internal utility */
56 protected:
57 /** Buffer class containing one read/write circular buffer.
58 \ingroup internal */
59 class CircularBuffer
61 public:
62 CircularBuffer(size_t size);
63 ~CircularBuffer();
65 /** append l bytes from p to buffer */
66 bool Write(const char *p,size_t l);
67 /** copy l bytes from buffer to dest */
68 bool Read(char *dest,size_t l);
69 /** skip l bytes from buffer */
70 bool Remove(size_t l);
71 /** read l bytes from buffer, returns as string. */
72 std::string ReadString(size_t l);
74 /** total buffer length */
75 size_t GetLength();
76 /** pointer to circular buffer beginning */
77 const char *GetStart();
78 /** return number of bytes from circular buffer beginning to buffer physical end */
79 size_t GetL();
80 /** return free space in buffer, number of bytes until buffer overrun */
81 size_t Space();
83 /** return total number of bytes written to this buffer, ever */
84 unsigned long ByteCounter(bool clear = false);
86 private:
87 CircularBuffer(const CircularBuffer& s) {}
88 CircularBuffer& operator=(const CircularBuffer& ) { return *this; }
89 char *buf;
90 size_t m_max;
91 size_t m_q;
92 size_t m_b;
93 size_t m_t;
94 unsigned long m_count;
96 /** Output buffer struct.
97 \ingroup internal */
98 struct OUTPUT {
99 OUTPUT() : _b(0), _t(0), _q(0) {}
100 OUTPUT(const char *buf, size_t len) : _b(0), _t(len), _q(len) {
101 memcpy(_buf, buf, len);
103 size_t Space() {
104 return TCP_OUTPUT_CAPACITY - _t;
106 void Add(const char *buf, size_t len) {
107 memcpy(_buf + _t, buf, len);
108 _t += len;
109 _q += len;
111 size_t Remove(size_t len) {
112 _b += len;
113 _q -= len;
114 return _q;
116 const char *Buf() {
117 return _buf + _b;
119 size_t Len() {
120 return _q;
122 size_t _b;
123 size_t _t;
124 size_t _q;
125 char _buf[TCP_OUTPUT_CAPACITY];
127 typedef std::list<OUTPUT *> output_l;
129 public:
130 /** Constructor with standard values on input/output buffers. */
131 TcpSocket(ISocketHandler& );
132 /** Constructor with custom values for i/o buffer.
133 \param h ISocketHandler reference
134 \param isize Input buffer size
135 \param osize Output buffer size */
136 TcpSocket(ISocketHandler& h,size_t isize,size_t osize);
137 ~TcpSocket();
139 /** Open a connection to a remote server.
140 If you want your socket to connect to a server,
141 always call Open before Add'ing a socket to the sockethandler.
142 If not, the connection attempt will not be monitored by the
143 socket handler...
144 \param ip IP address
145 \param port Port number
146 \param skip_socks Do not use socks4 even if configured */
147 bool Open(ipaddr_t ip,port_t port,bool skip_socks = false);
148 #ifdef ENABLE_IPV6
149 #ifdef IPPROTO_IPV6
150 /** Open connection.
151 \param ip Ipv6 address
152 \param port Port number
153 \param skip_socks Do not use socks4 even if configured */
154 bool Open(in6_addr ip,port_t port,bool skip_socks = false);
155 #endif
156 #endif
157 bool Open(SocketAddress&,bool skip_socks = false);
158 bool Open(SocketAddress&,SocketAddress& bind_address,bool skip_socks = false);
159 /** Open connection.
160 \param host Hostname
161 \param port Port number */
162 bool Open(const std::string &host,port_t port);
164 /** Connect timeout callback. */
165 void OnConnectTimeout();
166 #ifdef _WIN32
167 /** Connection failed reported as exception on win32 */
168 void OnException();
169 #endif
171 /** Close file descriptor - internal use only.
172 \sa SetCloseAndDelete */
173 int Close();
175 /** Send a string.
176 \param s String to send
177 \param f Dummy flags -- not used */
178 void Send(const std::string &s,int f = 0);
179 /** Send string using printf formatting. */
180 void Sendf(const char *format, ...);
181 /** Send buffer of bytes.
182 \param buf Buffer pointer
183 \param len Length of data
184 \param f Dummy flags -- not used */
185 void SendBuf(const char *buf,size_t len,int f = 0);
186 /** This callback is executed after a successful read from the socket.
187 \param buf Pointer to the data
188 \param len Length of the data */
189 virtual void OnRawData(const char *buf,size_t len);
191 /** Called when output buffer has been sent. */
192 virtual void OnWriteComplete();
193 /** Number of bytes in input buffer. */
194 size_t GetInputLength();
195 /** Number of bytes in output buffer. */
196 size_t GetOutputLength();
198 /** Callback fires when a socket in line protocol has read one full line.
199 \param line Line read */
200 void OnLine(const std::string& line);
201 /** Get counter of number of bytes received. */
202 uint64_t GetBytesReceived(bool clear = false);
203 /** Get counter of number of bytes sent. */
204 uint64_t GetBytesSent(bool clear = false);
206 /** Socks4 specific callback. */
207 void OnSocks4Connect();
208 /** Socks4 specific callback. */
209 void OnSocks4ConnectFailed();
210 /** Socks4 specific callback.
211 \return 'need_more' */
212 bool OnSocks4Read();
214 #ifdef ENABLE_RESOLVER
215 /** Callback executed when resolver thread has finished a resolve request. */
216 void OnResolved(int id,ipaddr_t a,port_t port);
217 #ifdef ENABLE_IPV6
218 void OnResolved(int id,in6_addr& a,port_t port);
219 #endif
220 #endif
221 #ifdef HAVE_OPENSSL
222 /** Callback for 'New' ssl support - replaces SSLSocket. Internal use. */
223 void OnSSLConnect();
224 /** Callback for 'New' ssl support - replaces SSLSocket. Internal use. */
225 void OnSSLAccept();
226 /** This method must be implemented to initialize
227 the ssl context for an outgoing connection. */
228 virtual void InitSSLClient();
229 /** This method must be implemented to initialize
230 the ssl context for an incoming connection. */
231 virtual void InitSSLServer();
232 #endif
234 #ifdef ENABLE_RECONNECT
235 /** Flag that says a broken connection will try to reconnect. */
236 void SetReconnect(bool = true);
237 /** Check reconnect on lost connection flag status. */
238 bool Reconnect();
239 /** Flag to determine if a reconnect is in progress. */
240 void SetIsReconnect(bool x = true);
241 /** Socket is reconnecting. */
242 bool IsReconnect();
243 #endif
245 void DisableInputBuffer(bool = true);
247 void OnOptions(int,int,int,SOCKET);
249 void SetLineProtocol(bool = true);
251 // TCP options
252 bool SetTcpNodelay(bool = true);
254 virtual int Protocol();
256 protected:
257 TcpSocket(const TcpSocket& );
258 void OnRead();
259 void OnWrite();
260 #ifdef HAVE_OPENSSL
261 /** SSL; Initialize ssl context for a client socket.
262 \param meth_in SSL method */
263 void InitializeContext(const std::string& context, SSL_METHOD *meth_in = NULL);
264 /** SSL; Initialize ssl context for a server socket.
265 \param keyfile Combined private key/certificate file
266 \param password Password for private key
267 \param meth_in SSL method */
268 void InitializeContext(const std::string& context, const std::string& keyfile, const std::string& password, SSL_METHOD *meth_in = NULL);
269 /** SSL; Password callback method. */
270 static int SSL_password_cb(char *buf,int num,int rwflag,void *userdata);
271 /** SSL; Get pointer to ssl context structure. */
272 virtual SSL_CTX *GetSslContext();
273 /** SSL; Get pointer to ssl structure. */
274 virtual SSL *GetSsl();
275 /** ssl; still negotiating connection. */
276 bool SSLNegotiate();
277 /** SSL; Get ssl password. */
278 const std::string& GetPassword();
279 #endif
281 CircularBuffer ibuf; ///< Circular input buffer
283 private:
284 TcpSocket& operator=(const TcpSocket& ) { return *this; }
286 /** the actual send() */
287 int TryWrite(const char *buf, size_t len);
288 /** add data to output buffer top */
289 void Buffer(const char *buf, size_t len);
292 bool m_b_input_buffer_disabled;
293 uint64_t m_bytes_sent;
294 uint64_t m_bytes_received;
295 bool m_skip_c; ///< Skip second char of CRLF or LFCR sequence in OnRead
296 char m_c; ///< First char in CRLF or LFCR sequence
297 protected: std::string m_line; ///< Current line in line protocol mode
298 private:
299 #ifdef SOCKETS_DYNAMIC_TEMP
300 char *m_buf; ///< temporary read buffer
301 #endif
302 output_l m_obuf; ///< output buffer
303 OUTPUT *m_obuf_top; ///< output buffer on top
305 #ifdef HAVE_OPENSSL
306 static SSLInitializer m_ssl_init;
307 SSL_CTX *m_ssl_ctx; ///< ssl context
308 SSL *m_ssl; ///< ssl 'socket'
309 BIO *m_sbio; ///< ssl bio
310 std::string m_password; ///< ssl password
311 #endif
313 #ifdef ENABLE_SOCKS4
314 int m_socks4_state; ///< socks4 support
315 char m_socks4_vn; ///< socks4 support, temporary variable
316 char m_socks4_cd; ///< socks4 support, temporary variable
317 unsigned short m_socks4_dstport; ///< socks4 support
318 unsigned long m_socks4_dstip; ///< socks4 support
319 #endif
321 #ifdef ENABLE_RESOLVER
322 int m_resolver_id; ///< Resolver id (if any) for current Open call
323 #endif
325 #ifdef ENABLE_RECONNECT
326 bool m_b_reconnect; ///< Reconnect on lost connection flag
327 bool m_b_is_reconnect; ///< Trying to reconnect
328 #endif
333 #ifdef SOCKETS_NAMESPACE
335 #endif
337 #endif // _SOCKETS_TcpSocket_H