diff options
Diffstat (limited to 'dep/src/sockets/TcpSocket.cpp')
-rw-r--r-- | dep/src/sockets/TcpSocket.cpp | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/dep/src/sockets/TcpSocket.cpp b/dep/src/sockets/TcpSocket.cpp index 902f631a6af..c4efa05d5bf 100644 --- a/dep/src/sockets/TcpSocket.cpp +++ b/dep/src/sockets/TcpSocket.cpp @@ -4,20 +4,25 @@ **/ /* Copyright (C) 2004-2007 Anders Hedstrom + This library is made available under the terms of the GNU GPL. + If you would like to use this library in a closed-source application, a separate license agreement is available. For information about the closed-source license agreement for the C++ sockets library, please visit http://www.alhem.net/Sockets/license.html and/or email license@alhem.net. + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. @@ -41,27 +46,32 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #include <map> #include <cstdio> + #include "TcpSocket.h" #include "Utility.h" #include "Ipv4Address.h" #include "Ipv6Address.h" #include "Mutex.h" #include "IFile.h" + #ifdef SOCKETS_NAMESPACE namespace SOCKETS_NAMESPACE { #endif + //#ifdef _DEBUG //#define DEB(x) x //#else #define DEB(x) //#endif + // statics #ifdef HAVE_OPENSSL SSLInitializer TcpSocket::m_ssl_init; #endif + // thanks, q #ifdef _MSC_VER #pragma warning(disable:4355) @@ -99,6 +109,7 @@ TcpSocket::TcpSocket(ISocketHandler& h) : StreamSocket(h) #pragma warning(default:4355) #endif + #ifdef _MSC_VER #pragma warning(disable:4355) #endif @@ -135,6 +146,7 @@ TcpSocket::TcpSocket(ISocketHandler& h,size_t isize,size_t osize) : StreamSocket #pragma warning(default:4355) #endif + TcpSocket::~TcpSocket() { #ifdef SOCKETS_DYNAMIC_TEMP @@ -156,6 +168,7 @@ TcpSocket::~TcpSocket() #endif } + bool TcpSocket::Open(ipaddr_t ip,port_t port,bool skip_socks) { Ipv4Address ad(ip, port); @@ -163,6 +176,7 @@ bool TcpSocket::Open(ipaddr_t ip,port_t port,bool skip_socks) return Open(ad, local, skip_socks); } + #ifdef ENABLE_IPV6 #ifdef IPPROTO_IPV6 bool TcpSocket::Open(in6_addr ip,port_t port,bool skip_socks) @@ -173,12 +187,14 @@ bool TcpSocket::Open(in6_addr ip,port_t port,bool skip_socks) #endif #endif + bool TcpSocket::Open(SocketAddress& ad,bool skip_socks) { Ipv4Address bind_ad("0.0.0.0", 0); return Open(ad, bind_ad, skip_socks); } + bool TcpSocket::Open(SocketAddress& ad,SocketAddress& bind_ad,bool skip_socks) { if (!ad.IsValid()) @@ -206,6 +222,7 @@ bool TcpSocket::Open(SocketAddress& ad,SocketAddress& bind_ad,bool skip_socks) { CopyConnection( pools ); delete pools; + SetIsClient(); SetCallOnConnect(); // ISocketHandler must call OnConnect Handler().LogError(this, "SetCallOnConnect", 0, "Found pooled connection", LOG_LEVEL_INFO); @@ -297,11 +314,13 @@ bool TcpSocket::Open(SocketAddress& ad,SocketAddress& bind_ad,bool skip_socks) Attach(s); SetCallOnConnect(); // ISocketHandler must call OnConnect } + // 'true' means connected or connecting(not yet connected) // 'false' means something failed return true; //!Connecting(); } + bool TcpSocket::Open(const std::string &host,port_t port) { #ifdef ENABLE_IPV6 @@ -350,6 +369,7 @@ bool TcpSocket::Open(const std::string &host,port_t port) #endif } + #ifdef ENABLE_RESOLVER void TcpSocket::OnResolved(int id,ipaddr_t a,port_t port) { @@ -381,6 +401,7 @@ DEB( fprintf(stderr, "TcpSocket::OnResolved id %d addr %x port %d\n", id, a, } } + #ifdef ENABLE_IPV6 void TcpSocket::OnResolved(int id,in6_addr& a,port_t port) { @@ -408,6 +429,7 @@ void TcpSocket::OnResolved(int id,in6_addr& a,port_t port) #endif #endif + void TcpSocket::OnRead() { int n = 0; @@ -520,6 +542,7 @@ DEB( fprintf(stderr, "SSL read problem, errcode = %d\n",n);) OnRead( buf, n ); } + void TcpSocket::OnRead( char *buf, size_t n ) { // unbuffered @@ -597,15 +620,18 @@ void TcpSocket::OnRead( char *buf, size_t n ) #endif } + void TcpSocket::OnWriteComplete() { } + void TcpSocket::OnWrite() { if (Connecting()) { int err = SoError(); + // don't reset connecting flag on error here, we want the OnConnectFailed timeout later on if (!err) // ok { @@ -616,6 +642,7 @@ void TcpSocket::OnWrite() } Handler().LogError(this, "tcp: connect failed", err, StrError(err), LOG_LEVEL_FATAL); Set(false, false); // no more monitoring because connection failed + // failed #ifdef ENABLE_SOCKS4 if (Socks4()) @@ -643,6 +670,7 @@ void TcpSocket::OnWrite() // try send next block in buffer // if full block is sent, repeat // if all blocks are sent, reset m_wfds + bool repeat = false; size_t sz = m_transfer_limit ? GetOutputLength() : 0; do @@ -671,10 +699,12 @@ void TcpSocket::OnWrite() } } } while (repeat); + if (m_transfer_limit && sz > m_transfer_limit && GetOutputLength() < m_transfer_limit) { OnTransferLimit(); } + // check output buffer set, set/reset m_wfds accordingly { bool br; @@ -688,6 +718,7 @@ void TcpSocket::OnWrite() } } + int TcpSocket::TryWrite(const char *buf, size_t len) { int n = 0; @@ -756,6 +787,7 @@ DEB( int errnr = SSL_get_error(m_ssl, n); return n; } + void TcpSocket::Buffer(const char *buf, size_t len) { size_t ptr = 0; @@ -787,11 +819,13 @@ void TcpSocket::Buffer(const char *buf, size_t len) } } + void TcpSocket::Send(const std::string &str,int i) { SendBuf(str.c_str(),str.size(),i); } + void TcpSocket::SendBuf(const char *buf,size_t len,int) { if (!Ready() && !Connecting()) @@ -828,6 +862,7 @@ void TcpSocket::SendBuf(const char *buf,size_t len,int) // else // try_send // if any data is unsent, buffer it and set m_wfds + // check output buffer set, set/reset m_wfds accordingly { bool br; @@ -841,10 +876,12 @@ void TcpSocket::SendBuf(const char *buf,size_t len,int) } } + void TcpSocket::OnLine(const std::string& ) { } + #ifdef _MSC_VER #pragma warning(disable:4355) #endif @@ -857,6 +894,7 @@ TcpSocket::TcpSocket(const TcpSocket& s) #pragma warning(default:4355) #endif + #ifdef ENABLE_SOCKS4 void TcpSocket::OnSocks4Connect() { @@ -891,6 +929,7 @@ void TcpSocket::OnSocks4Connect() m_socks4_state = 0; } + void TcpSocket::OnSocks4ConnectFailed() { Handler().LogError(this,"OnSocks4ConnectFailed",0,"connection to socks4 server failed, trying direct connection",LOG_LEVEL_WARNING); @@ -906,6 +945,7 @@ void TcpSocket::OnSocks4ConnectFailed() } } + bool TcpSocket::OnSocks4Read() { switch (m_socks4_state) @@ -934,6 +974,7 @@ bool TcpSocket::OnSocks4Read() { ibuf.Read( (char *)&m_socks4_dstip, 4); SetSocks4(false); + switch (m_socks4_cd) { case 90: @@ -964,6 +1005,7 @@ bool TcpSocket::OnSocks4Read() } #endif + void TcpSocket::Sendf(const char *format, ...) { va_list ap; @@ -978,6 +1020,7 @@ void TcpSocket::Sendf(const char *format, ...) Send( slask ); } + #ifdef HAVE_OPENSSL void TcpSocket::OnSSLConnect() { @@ -1021,6 +1064,7 @@ DEB( fprintf(stderr, " m_sbio is NULL\n");) } } + void TcpSocket::OnSSLAccept() { SetNonblocking(true); @@ -1059,6 +1103,7 @@ DEB( fprintf(stderr, " m_sbio is NULL\n");) } } + bool TcpSocket::SSLNegotiate() { if (!IsSSLServer()) // client @@ -1155,17 +1200,20 @@ DEB( fprintf(stderr, "SSL_accept() failed - closing socket, retur return false; } + void TcpSocket::InitSSLClient() { InitializeContext("", SSLv23_method()); } + void TcpSocket::InitSSLServer() { Handler().LogError(this, "InitSSLServer", 0, "You MUST implement your own InitSSLServer method", LOG_LEVEL_FATAL); SetCloseAndDelete(); } + void TcpSocket::InitializeContext(const std::string& context, SSL_METHOD *meth_in) { /* Create our context*/ @@ -1182,6 +1230,7 @@ void TcpSocket::InitializeContext(const std::string& context, SSL_METHOD *meth_i } } + void TcpSocket::InitializeContext(const std::string& context,const std::string& keyfile,const std::string& password,SSL_METHOD *meth_in) { /* Create our context*/ @@ -1201,11 +1250,13 @@ void TcpSocket::InitializeContext(const std::string& context,const std::string& { m_ssl_ctx = server_contexts[context]; } + /* Load our keys and certificates*/ if (!(SSL_CTX_use_certificate_file(m_ssl_ctx, keyfile.c_str(), SSL_FILETYPE_PEM))) { Handler().LogError(this, "TcpSocket InitializeContext", 0, "Couldn't read certificate file " + keyfile, LOG_LEVEL_FATAL); } + m_password = password; SSL_CTX_set_default_passwd_cb(m_ssl_ctx, SSL_password_cb); SSL_CTX_set_default_passwd_cb_userdata(m_ssl_ctx, this); @@ -1215,6 +1266,7 @@ void TcpSocket::InitializeContext(const std::string& context,const std::string& } } + void TcpSocket::InitializeContext(const std::string& context,const std::string& certfile,const std::string& keyfile,const std::string& password,SSL_METHOD *meth_in) { /* Create our context*/ @@ -1234,11 +1286,13 @@ void TcpSocket::InitializeContext(const std::string& context,const std::string& { m_ssl_ctx = server_contexts[context]; } + /* Load our keys and certificates*/ if (!(SSL_CTX_use_certificate_file(m_ssl_ctx, certfile.c_str(), SSL_FILETYPE_PEM))) { Handler().LogError(this, "TcpSocket InitializeContext", 0, "Couldn't read certificate file " + keyfile, LOG_LEVEL_FATAL); } + m_password = password; SSL_CTX_set_default_passwd_cb(m_ssl_ctx, SSL_password_cb); SSL_CTX_set_default_passwd_cb_userdata(m_ssl_ctx, this); @@ -1248,6 +1302,7 @@ void TcpSocket::InitializeContext(const std::string& context,const std::string& } } + int TcpSocket::SSL_password_cb(char *buf,int num,int rwflag,void *userdata) { Socket *p0 = static_cast<Socket *>(userdata); @@ -1262,6 +1317,7 @@ int TcpSocket::SSL_password_cb(char *buf,int num,int rwflag,void *userdata) } #endif // HAVE_OPENSSL + int TcpSocket::Close() { if (GetSocket() == INVALID_SOCKET) // this could happen @@ -1300,6 +1356,7 @@ int TcpSocket::Close() return Socket::Close(); } + #ifdef HAVE_OPENSSL SSL_CTX *TcpSocket::GetSslContext() { @@ -1307,6 +1364,7 @@ SSL_CTX *TcpSocket::GetSslContext() Handler().LogError(this, "GetSslContext", 0, "SSL Context is NULL; check InitSSLServer/InitSSLClient", LOG_LEVEL_WARNING); return m_ssl_ctx; } + SSL *TcpSocket::GetSsl() { if (!m_ssl) @@ -1315,6 +1373,7 @@ SSL *TcpSocket::GetSsl() } #endif + #ifdef ENABLE_RECONNECT void TcpSocket::SetReconnect(bool x) { @@ -1322,20 +1381,24 @@ void TcpSocket::SetReconnect(bool x) } #endif + void TcpSocket::OnRawData(const char *buf_in,size_t len) { } + size_t TcpSocket::GetInputLength() { return ibuf.GetLength(); } + size_t TcpSocket::GetOutputLength() { return m_output_length; } + uint64_t TcpSocket::GetBytesReceived(bool clear) { uint64_t z = m_bytes_received; @@ -1344,6 +1407,7 @@ uint64_t TcpSocket::GetBytesReceived(bool clear) return z; } + uint64_t TcpSocket::GetBytesSent(bool clear) { uint64_t z = m_bytes_sent; @@ -1352,23 +1416,27 @@ uint64_t TcpSocket::GetBytesSent(bool clear) return z; } + #ifdef ENABLE_RECONNECT bool TcpSocket::Reconnect() { return m_b_reconnect; } + void TcpSocket::SetIsReconnect(bool x) { m_b_is_reconnect = x; } + bool TcpSocket::IsReconnect() { return m_b_is_reconnect; } #endif + #ifdef HAVE_OPENSSL const std::string& TcpSocket::GetPassword() { @@ -1376,11 +1444,13 @@ const std::string& TcpSocket::GetPassword() } #endif + void TcpSocket::DisableInputBuffer(bool x) { m_b_input_buffer_disabled = x; } + void TcpSocket::OnOptions(int family,int type,int protocol,SOCKET s) { DEB( fprintf(stderr, "Socket::OnOptions()\n");) @@ -1391,12 +1461,14 @@ DEB( fprintf(stderr, "Socket::OnOptions()\n");) SetSoKeepalive(true); } + void TcpSocket::SetLineProtocol(bool x) { StreamSocket::SetLineProtocol(x); DisableInputBuffer(x); } + bool TcpSocket::SetTcpNodelay(bool x) { #ifdef TCP_NODELAY @@ -1413,6 +1485,7 @@ bool TcpSocket::SetTcpNodelay(bool x) #endif } + TcpSocket::CircularBuffer::CircularBuffer(size_t size) :buf(new char[2 * size]) ,m_max(size) @@ -1423,11 +1496,13 @@ TcpSocket::CircularBuffer::CircularBuffer(size_t size) { } + TcpSocket::CircularBuffer::~CircularBuffer() { delete[] buf; } + bool TcpSocket::CircularBuffer::Write(const char *s,size_t l) { if (m_q + l > m_max) @@ -1457,6 +1532,7 @@ bool TcpSocket::CircularBuffer::Write(const char *s,size_t l) return true; } + bool TcpSocket::CircularBuffer::Read(char *s,size_t l) { if (l > m_q) @@ -1491,6 +1567,7 @@ bool TcpSocket::CircularBuffer::Read(char *s,size_t l) } return true; } + bool TcpSocket::CircularBuffer::SoftRead(char *s, size_t l) { if (l > m_q) @@ -1515,31 +1592,37 @@ bool TcpSocket::CircularBuffer::SoftRead(char *s, size_t l) } return true; } + bool TcpSocket::CircularBuffer::Remove(size_t l) { return Read(NULL, l); } + size_t TcpSocket::CircularBuffer::GetLength() { return m_q; } + const char *TcpSocket::CircularBuffer::GetStart() { return buf + m_b; } + size_t TcpSocket::CircularBuffer::GetL() { return (m_b + m_q > m_max) ? m_max - m_b : m_q; } + size_t TcpSocket::CircularBuffer::Space() { return m_max - m_q; } + unsigned long TcpSocket::CircularBuffer::ByteCounter(bool clear) { if (clear) @@ -1551,6 +1634,7 @@ unsigned long TcpSocket::CircularBuffer::ByteCounter(bool clear) return m_count; } + std::string TcpSocket::CircularBuffer::ReadString(size_t l) { char *sz = new char[l + 1]; @@ -1565,6 +1649,7 @@ std::string TcpSocket::CircularBuffer::ReadString(size_t l) return tmp; } + void TcpSocket::OnConnectTimeout() { Handler().LogError(this, "connect", -1, "connect timeout", LOG_LEVEL_FATAL); @@ -1602,6 +1687,7 @@ void TcpSocket::OnConnectTimeout() SetConnecting(false); } + #ifdef _WIN32 void TcpSocket::OnException() { @@ -1637,21 +1723,26 @@ void TcpSocket::OnException() } #endif // _WIN32 + int TcpSocket::Protocol() { return IPPROTO_TCP; } + void TcpSocket::SetTransferLimit(size_t sz) { m_transfer_limit = sz; } + void TcpSocket::OnTransferLimit() { } + #ifdef SOCKETS_NAMESPACE } #endif + |