aboutsummaryrefslogtreecommitdiff
path: root/dep/src/sockets/TcpSocket.cpp
diff options
context:
space:
mode:
authormaximius <none@none>2009-10-17 15:51:44 -0700
committermaximius <none@none>2009-10-17 15:51:44 -0700
commite585187b248f48b3c6e9247b49fa07c6565d65e5 (patch)
tree637c5b7ddacf41040bef4ea4f75a97da64c6a9bc /dep/src/sockets/TcpSocket.cpp
parent26b5e033ffde3d161382fc9addbfa99738379641 (diff)
*Backed out changeset 3be01fb200a5
--HG-- branch : trunk
Diffstat (limited to 'dep/src/sockets/TcpSocket.cpp')
-rw-r--r--dep/src/sockets/TcpSocket.cpp91
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
+