[9938] Correct premature call of TalkedToCreature.
[getmangos.git] / dep / include / sockets / TcpSocket.h
blob515f5aa6cc7e06a7d2db1c0d977426d894e07827
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
39 #include <string.h>
41 #define TCP_BUFSIZE_READ 16400
42 #define TCP_OUTPUT_CAPACITY 1024000
45 #ifdef SOCKETS_NAMESPACE
46 namespace SOCKETS_NAMESPACE {
47 #endif
49 class SocketAddress;
52 /** Socket implementation for TCP.
53 \ingroup basic */
54 class TcpSocket : public StreamSocket
56 /** \defgroup internal Internal utility */
57 protected:
58 /** Buffer class containing one read/write circular buffer.
59 \ingroup internal */
60 class CircularBuffer
62 public:
63 CircularBuffer(size_t size);
64 ~CircularBuffer();
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 */
78 size_t GetLength();
79 /** pointer to circular buffer beginning */
80 const char *GetStart();
81 /** return number of bytes from circular buffer beginning to buffer physical end */
82 size_t GetL();
83 /** return free space in buffer, number of bytes until buffer overrun */
84 size_t Space();
86 /** return total number of bytes written to this buffer, ever */
87 unsigned long ByteCounter(bool clear = false);
89 private:
90 CircularBuffer(const CircularBuffer& /*s*/) {}
91 CircularBuffer& operator=(const CircularBuffer& ) { return *this; }
92 char *buf;
93 size_t m_max;
94 size_t m_q;
95 size_t m_b;
96 size_t m_t;
97 unsigned long m_count;
99 /** Output buffer struct.
100 \ingroup internal */
101 struct OUTPUT {
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);
106 size_t Space() {
107 return TCP_OUTPUT_CAPACITY - _t;
109 void Add(const char *buf, size_t len) {
110 memcpy(_buf + _t, buf, len);
111 _t += len;
112 _q += len;
114 size_t Remove(size_t len) {
115 _b += len;
116 _q -= len;
117 return _q;
119 const char *Buf() {
120 return _buf + _b;
122 size_t Len() {
123 return _q;
125 size_t _b;
126 size_t _t;
127 size_t _q;
128 char _buf[TCP_OUTPUT_CAPACITY];
130 typedef std::list<OUTPUT *> output_l;
132 public:
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);
140 ~TcpSocket();
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
146 socket handler...
147 \param ip IP address
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);
151 #ifdef ENABLE_IPV6
152 #ifdef IPPROTO_IPV6
153 /** Open connection.
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);
158 #endif
159 #endif
160 bool Open(SocketAddress&,bool skip_socks = false);
161 bool Open(SocketAddress&,SocketAddress& bind_address,bool skip_socks = false);
162 /** Open connection.
163 \param host Hostname
164 \param port Port number */
165 bool Open(const std::string &host,port_t port);
167 /** Connect timeout callback. */
168 void OnConnectTimeout();
169 #ifdef _WIN32
170 /** Connection failed reported as exception on win32 */
171 void OnException();
172 #endif
174 /** Close file descriptor - internal use only.
175 \sa SetCloseAndDelete */
176 int Close();
178 /** Send a string.
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' */
218 bool OnSocks4Read();
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);
223 #ifdef ENABLE_IPV6
224 void OnResolved(int id,in6_addr& a,port_t port);
225 #endif
226 #endif
227 #ifdef HAVE_OPENSSL
228 /** Callback for 'New' ssl support - replaces SSLSocket. Internal use. */
229 void OnSSLConnect();
230 /** Callback for 'New' ssl support - replaces SSLSocket. Internal use. */
231 void OnSSLAccept();
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();
238 #endif
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. */
244 bool Reconnect();
245 /** Flag to determine if a reconnect is in progress. */
246 void SetIsReconnect(bool x = true);
247 /** Socket is reconnecting. */
248 bool IsReconnect();
249 #endif
251 void DisableInputBuffer(bool = true);
253 void OnOptions(int,int,int,SOCKET);
255 void SetLineProtocol(bool = true);
257 // TCP options
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();
268 protected:
269 TcpSocket(const TcpSocket& );
270 void OnRead();
271 void OnRead( char *buf, size_t n );
272 void OnWrite();
273 #ifdef HAVE_OPENSSL
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. */
295 bool SSLNegotiate();
296 /** SSL; Get ssl password. */
297 const std::string& GetPassword();
298 #endif
300 CircularBuffer ibuf; ///< Circular input buffer
302 private:
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
319 #endif
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;
325 #ifdef HAVE_OPENSSL
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
331 #endif
333 #ifdef ENABLE_SOCKS4
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
339 #endif
341 #ifdef ENABLE_RESOLVER
342 int m_resolver_id; ///< Resolver id (if any) for current Open call
343 #endif
345 #ifdef ENABLE_RECONNECT
346 bool m_b_reconnect; ///< Reconnect on lost connection flag
347 bool m_b_is_reconnect; ///< Trying to reconnect
348 #endif
353 #ifdef SOCKETS_NAMESPACE
355 #endif
357 #endif // _SOCKETS_TcpSocket_H