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"
40 #define TCP_BUFSIZE_READ 16400
41 #define TCP_OUTPUT_CAPACITY 1024000
44 #ifdef SOCKETS_NAMESPACE
45 namespace SOCKETS_NAMESPACE
{
51 /** Socket implementation for TCP.
53 class TcpSocket
: public StreamSocket
55 /** \defgroup internal Internal utility */
57 /** Buffer class containing one read/write circular buffer.
62 CircularBuffer(size_t size
);
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 */
76 /** pointer to circular buffer beginning */
77 const char *GetStart();
78 /** return number of bytes from circular buffer beginning to buffer physical end */
80 /** return free space in buffer, number of bytes until buffer overrun */
83 /** return total number of bytes written to this buffer, ever */
84 unsigned long ByteCounter(bool clear
= false);
87 CircularBuffer(const CircularBuffer
& s
) {}
88 CircularBuffer
& operator=(const CircularBuffer
& ) { return *this; }
94 unsigned long m_count
;
96 /** Output buffer struct.
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
);
104 return TCP_OUTPUT_CAPACITY
- _t
;
106 void Add(const char *buf
, size_t len
) {
107 memcpy(_buf
+ _t
, buf
, len
);
111 size_t Remove(size_t len
) {
125 char _buf
[TCP_OUTPUT_CAPACITY
];
127 typedef std::list
<OUTPUT
*> output_l
;
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
);
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
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);
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);
157 bool Open(SocketAddress
&,bool skip_socks
= false);
158 bool Open(SocketAddress
&,SocketAddress
& bind_address
,bool skip_socks
= false);
161 \param port Port number */
162 bool Open(const std::string
&host
,port_t port
);
164 /** Connect timeout callback. */
165 void OnConnectTimeout();
167 /** Connection failed reported as exception on win32 */
171 /** Close file descriptor - internal use only.
172 \sa SetCloseAndDelete */
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' */
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
);
218 void OnResolved(int id
,in6_addr
& a
,port_t port
);
222 /** Callback for 'New' ssl support - replaces SSLSocket. Internal use. */
224 /** Callback for 'New' ssl support - replaces SSLSocket. Internal use. */
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();
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. */
239 /** Flag to determine if a reconnect is in progress. */
240 void SetIsReconnect(bool x
= true);
241 /** Socket is reconnecting. */
245 void DisableInputBuffer(bool = true);
247 void OnOptions(int,int,int,SOCKET
);
249 void SetLineProtocol(bool = true);
252 bool SetTcpNodelay(bool = true);
254 virtual int Protocol();
257 TcpSocket(const TcpSocket
& );
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. */
277 /** SSL; Get ssl password. */
278 const std::string
& GetPassword();
281 CircularBuffer ibuf
; ///< Circular input buffer
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
299 #ifdef SOCKETS_DYNAMIC_TEMP
300 char *m_buf
; ///< temporary read buffer
302 output_l m_obuf
; ///< output buffer
303 OUTPUT
*m_obuf_top
; ///< output buffer on top
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
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
321 #ifdef ENABLE_RESOLVER
322 int m_resolver_id
; ///< Resolver id (if any) for current Open call
325 #ifdef ENABLE_RECONNECT
326 bool m_b_reconnect
; ///< Reconnect on lost connection flag
327 bool m_b_is_reconnect
; ///< Trying to reconnect
333 #ifdef SOCKETS_NAMESPACE
337 #endif // _SOCKETS_TcpSocket_H