3 ** \author grymse@alhem.net
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"
35 #include <openssl/ssl.h>
36 #include "SSLInitializer.h"
41 #define TCP_BUFSIZE_READ 16400
42 #define TCP_OUTPUT_CAPACITY 1024000
45 #ifdef SOCKETS_NAMESPACE
46 namespace SOCKETS_NAMESPACE
{
52 /** Socket implementation for TCP.
54 class TcpSocket
: public StreamSocket
56 /** \defgroup internal Internal utility */
58 /** Buffer class containing one read/write circular buffer.
63 CircularBuffer(size_t size
);
66 /** append l bytes from p to buffer */
67 bool Write(const char *p
,size_t l
);
68 /** copy l bytes from buffer to dest */
69 bool Read(char *dest
,size_t l
);
70 /** copy l bytes from buffer to dest, dont touch buffer pointers */
71 bool SoftRead(char *dest
, size_t l
);
72 /** skip l bytes from buffer */
73 bool Remove(size_t l
);
74 /** read l bytes from buffer, returns as string. */
75 std::string
ReadString(size_t l
);
77 /** total buffer length */
79 /** pointer to circular buffer beginning */
80 const char *GetStart();
81 /** return number of bytes from circular buffer beginning to buffer physical end */
83 /** return free space in buffer, number of bytes until buffer overrun */
86 /** return total number of bytes written to this buffer, ever */
87 unsigned long ByteCounter(bool clear
= false);
90 CircularBuffer(const CircularBuffer
& /*s*/) {}
91 CircularBuffer
& operator=(const CircularBuffer
& ) { return *this; }
97 unsigned long m_count
;
99 /** Output buffer struct.
102 OUTPUT() : _b(0), _t(0), _q(0) {}
103 OUTPUT(const char *buf
, size_t len
) : _b(0), _t(len
), _q(len
) {
104 memcpy(_buf
, buf
, len
);
107 return TCP_OUTPUT_CAPACITY
- _t
;
109 void Add(const char *buf
, size_t len
) {
110 memcpy(_buf
+ _t
, buf
, len
);
114 size_t Remove(size_t len
) {
128 char _buf
[TCP_OUTPUT_CAPACITY
];
130 typedef std::list
<OUTPUT
*> output_l
;
133 /** Constructor with standard values on input/output buffers. */
134 TcpSocket(ISocketHandler
& );
135 /** Constructor with custom values for i/o buffer.
136 \param h ISocketHandler reference
137 \param isize Input buffer size
138 \param osize Output buffer size */
139 TcpSocket(ISocketHandler
& h
,size_t isize
,size_t osize
);
142 /** Open a connection to a remote server.
143 If you want your socket to connect to a server,
144 always call Open before Add'ing a socket to the sockethandler.
145 If not, the connection attempt will not be monitored by the
148 \param port Port number
149 \param skip_socks Do not use socks4 even if configured */
150 bool Open(ipaddr_t ip
,port_t port
,bool skip_socks
= false);
154 \param ip Ipv6 address
155 \param port Port number
156 \param skip_socks Do not use socks4 even if configured */
157 bool Open(in6_addr ip
,port_t port
,bool skip_socks
= false);
160 bool Open(SocketAddress
&,bool skip_socks
= false);
161 bool Open(SocketAddress
&,SocketAddress
& bind_address
,bool skip_socks
= false);
164 \param port Port number */
165 bool Open(const std::string
&host
,port_t port
);
167 /** Connect timeout callback. */
168 void OnConnectTimeout();
170 /** Connection failed reported as exception on win32 */
174 /** Close file descriptor - internal use only.
175 \sa SetCloseAndDelete */
179 \param s String to send
180 \param f Dummy flags -- not used */
181 void Send(const std::string
&s
,int f
= 0);
182 /** Send string using printf formatting. */
183 void Sendf(const char *format
, ...);
184 /** Send buffer of bytes.
185 \param buf Buffer pointer
186 \param len Length of data
187 \param f Dummy flags -- not used */
188 void SendBuf(const char *buf
,size_t len
,int f
= 0);
189 /** This callback is executed after a successful read from the socket.
190 \param buf Pointer to the data
191 \param len Length of the data */
192 virtual void OnRawData(const char *buf
,size_t len
);
194 /** Called when output buffer has been sent.
195 Note: Will only be called IF the output buffer has been used.
196 Send's that was successful without needing the output buffer
197 will not generate a call to this method. */
198 virtual void OnWriteComplete();
199 /** Number of bytes in input buffer. */
200 size_t GetInputLength();
201 /** Number of bytes in output buffer. */
202 size_t GetOutputLength();
204 /** Callback fires when a socket in line protocol has read one full line.
205 \param line Line read */
206 void OnLine(const std::string
& line
);
207 /** Get counter of number of bytes received. */
208 uint64_t GetBytesReceived(bool clear
= false);
209 /** Get counter of number of bytes sent. */
210 uint64_t GetBytesSent(bool clear
= false);
212 /** Socks4 specific callback. */
213 void OnSocks4Connect();
214 /** Socks4 specific callback. */
215 void OnSocks4ConnectFailed();
216 /** Socks4 specific callback.
217 \return 'need_more' */
220 #ifdef ENABLE_RESOLVER
221 /** Callback executed when resolver thread has finished a resolve request. */
222 void OnResolved(int id
,ipaddr_t a
,port_t port
);
224 void OnResolved(int id
,in6_addr
& a
,port_t port
);
228 /** Callback for 'New' ssl support - replaces SSLSocket. Internal use. */
230 /** Callback for 'New' ssl support - replaces SSLSocket. Internal use. */
232 /** This method must be implemented to initialize
233 the ssl context for an outgoing connection. */
234 virtual void InitSSLClient();
235 /** This method must be implemented to initialize
236 the ssl context for an incoming connection. */
237 virtual void InitSSLServer();
240 #ifdef ENABLE_RECONNECT
241 /** Flag that says a broken connection will try to reconnect. */
242 void SetReconnect(bool = true);
243 /** Check reconnect on lost connection flag status. */
245 /** Flag to determine if a reconnect is in progress. */
246 void SetIsReconnect(bool x
= true);
247 /** Socket is reconnecting. */
251 void DisableInputBuffer(bool = true);
253 void OnOptions(int,int,int,SOCKET
);
255 void SetLineProtocol(bool = true);
258 bool SetTcpNodelay(bool = true);
260 virtual int Protocol();
262 /** Trigger limit for callback OnTransferLimit. */
263 void SetTransferLimit(size_t sz
);
264 /** This callback fires when the output buffer drops below the value
265 set by SetTransferLimit. Default: 0 (disabled). */
266 virtual void OnTransferLimit();
269 TcpSocket(const TcpSocket
& );
271 void OnRead( char *buf
, size_t n
);
274 /** SSL; Initialize ssl context for a client socket.
275 \param meth_in SSL method */
276 void InitializeContext(const std::string
& context
, SSL_METHOD
*meth_in
= NULL
);
277 /** SSL; Initialize ssl context for a server socket.
278 \param keyfile Combined private key/certificate file
279 \param password Password for private key
280 \param meth_in SSL method */
281 void InitializeContext(const std::string
& context
, const std::string
& keyfile
, const std::string
& password
, SSL_METHOD
*meth_in
= NULL
);
282 /** SSL; Initialize ssl context for a server socket.
283 \param certfile Separate certificate file
284 \param keyfile Combined private key/certificate file
285 \param password Password for private key
286 \param meth_in SSL method */
287 void InitializeContext(const std::string
& context
, const std::string
& certfile
, const std::string
& keyfile
, const std::string
& password
, SSL_METHOD
*meth_in
= NULL
);
288 /** SSL; Password callback method. */
289 static int SSL_password_cb(char *buf
,int num
,int rwflag
,void *userdata
);
290 /** SSL; Get pointer to ssl context structure. */
291 virtual SSL_CTX
*GetSslContext();
292 /** SSL; Get pointer to ssl structure. */
293 virtual SSL
*GetSsl();
294 /** ssl; still negotiating connection. */
296 /** SSL; Get ssl password. */
297 const std::string
& GetPassword();
300 CircularBuffer ibuf
; ///< Circular input buffer
303 TcpSocket
& operator=(const TcpSocket
& ) { return *this; }
305 /** the actual send() */
306 int TryWrite(const char *buf
, size_t len
);
307 /** add data to output buffer top */
308 void Buffer(const char *buf
, size_t len
);
311 bool m_b_input_buffer_disabled
;
312 uint64_t m_bytes_sent
;
313 uint64_t m_bytes_received
;
314 bool m_skip_c
; ///< Skip second char of CRLF or LFCR sequence in OnRead
315 char m_c
; ///< First char in CRLF or LFCR sequence
316 std::string m_line
; ///< Current line in line protocol mode
317 #ifdef SOCKETS_DYNAMIC_TEMP
318 char *m_buf
; ///< temporary read buffer
320 output_l m_obuf
; ///< output buffer
321 OUTPUT
*m_obuf_top
; ///< output buffer on top
322 size_t m_transfer_limit
;
323 size_t m_output_length
;
326 static SSLInitializer m_ssl_init
;
327 SSL_CTX
*m_ssl_ctx
; ///< ssl context
328 SSL
*m_ssl
; ///< ssl 'socket'
329 BIO
*m_sbio
; ///< ssl bio
330 std::string m_password
; ///< ssl password
334 int m_socks4_state
; ///< socks4 support
335 char m_socks4_vn
; ///< socks4 support, temporary variable
336 char m_socks4_cd
; ///< socks4 support, temporary variable
337 unsigned short m_socks4_dstport
; ///< socks4 support
338 unsigned long m_socks4_dstip
; ///< socks4 support
341 #ifdef ENABLE_RESOLVER
342 int m_resolver_id
; ///< Resolver id (if any) for current Open call
345 #ifdef ENABLE_RECONNECT
346 bool m_b_reconnect
; ///< Reconnect on lost connection flag
347 bool m_b_is_reconnect
; ///< Trying to reconnect
353 #ifdef SOCKETS_NAMESPACE
357 #endif // _SOCKETS_TcpSocket_H