PageRenderTime 115ms CodeModel.GetById 5ms RepoModel.GetById 4ms app.codeStats 0ms

/dep/sockets/include/TcpSocket.h

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