Logo
~Sockets~
~Examples~
~Contact~


TcpSocket Class Reference
[Basic sockets]

Socket implementation for TCP. More...

#include <TcpSocket.h>

Inheritance diagram for TcpSocket:

Inheritance graph
[legend]
Collaboration diagram for TcpSocket:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 TcpSocket (ISocketHandler &)
 Constructor with standard values on input/output buffers.
 TcpSocket (ISocketHandler &h, size_t isize, size_t osize)
 Constructor with custom values for i/o buffer.
 ~TcpSocket ()
bool Open (ipaddr_t ip, port_t port, bool skip_socks=false)
 Open a connection to a remote server.
bool Open (SocketAddress &, bool skip_socks=false)
bool Open (SocketAddress &, SocketAddress &bind_address, bool skip_socks=false)
bool Open (const std::string &host, port_t port)
 Open connection.
int Close ()
 Close file descriptor - internal use only.
void Send (const std::string &s, int f=0)
 Send a string.
void Sendf (const char *format,...)
 Send string using printf formatting.
void SendBuf (const char *buf, size_t len, int f=0)
 Send buffer of bytes.
virtual void OnRawData (const char *buf, size_t len)
 This callback is executed after a successful read from the socket.
size_t GetInputLength ()
 Number of bytes in input buffer.
size_t GetOutputLength ()
 Number of bytes in output buffer.
void OnLine (const std::string &line)
 Callback fires when a socket in line protocol has read one full line.
uint64_t GetBytesReceived (bool clear=false)
 Get counter of number of bytes received.
uint64_t GetBytesSent (bool clear=false)
 Get counter of number of bytes sent.
void OnSocks4Connect ()
 Socks4 specific callback.
void OnSocks4ConnectFailed ()
 Socks4 specific callback.
bool OnSocks4Read ()
 Socks4 specific callback.
void OnResolved (int id, ipaddr_t a, port_t port)
 Callback executed when resolver thread has finished a resolve request.
void OnSSLConnect ()
 Callback for 'New' ssl support - replaces SSLSocket.
void OnSSLAccept ()
 Callback for 'New' ssl support - replaces SSLSocket.
virtual void InitSSLClient ()
 This method must be implemented to initialize the ssl context for an outgoing connection.
virtual void InitSSLServer ()
 This method must be implemented to initialize the ssl context for an incoming connection.
void SetReconnect (bool=true)
 Flag that says a broken connection will try to reconnect.
bool Reconnect ()
 Check reconnect on lost connection flag status.
void SetIsReconnect (bool x=true)
 Flag to determine if a reconnect is in progress.
bool IsReconnect ()
 Socket is reconnecting.
void DisableInputBuffer (bool=true)
void OnOptions (int, int, int, SOCKET)
 Called when a socket is created, to set socket options.
void SetLineProtocol (bool=true)
 Enable the OnLine callback.

Protected Member Functions

 TcpSocket (const TcpSocket &s)
void OnRead ()
 Called when there is something to be read from the file descriptor.
void OnWrite ()
 Called when there is room for another write on the file descriptor.
void InitializeContext (const std::string &context, SSL_METHOD *meth_in=NULL)
 SSL; Initialize ssl context for a client socket.
void InitializeContext (const std::string &context, const std::string &keyfile, const std::string &password, SSL_METHOD *meth_in=NULL)
 SSL; Initialize ssl context for a server socket.
virtual SSL_CTX * GetSslContext ()
 SSL; Get pointer to ssl context structure.
virtual SSL * GetSsl ()
 SSL; Get pointer to ssl structure.
bool SSLNegotiate ()
 ssl; still negotiating connection.
const std::string & GetPassword ()
 SSL; Get ssl password.

Static Protected Member Functions

static int SSL_password_cb (char *buf, int num, int rwflag, void *userdata)
 SSL; Password callback method.

Protected Attributes

CircularBuffer ibuf
 Circular input buffer.
CircularBuffer obuf
 Circular output buffer.

Private Types

typedef std::list< MES * > ucharp_v
 Dynamic output buffer list.

Private Member Functions

TcpSocketoperator= (const TcpSocket &)

Private Attributes

bool m_b_input_buffer_disabled
uint64_t m_bytes_sent
uint64_t m_bytes_received
bool m_skip_c
 Skip second char of CRLF or LFCR sequence in OnRead.
char m_c
 First char in CRLF or LFCR sequence.
std::string m_line
 Current line in line protocol mode.
ucharp_v m_mes
 overflow protection, dynamic output buffer
char * m_buf
 temporary read buffer
SSL_CTX * m_ssl_ctx
 ssl context
SSL * m_ssl
 ssl 'socket'
BIO * m_sbio
 ssl bio
std::string m_password
 ssl password
int m_socks4_state
 socks4 support
char m_socks4_vn
 socks4 support, temporary variable
char m_socks4_cd
 socks4 support, temporary variable
unsigned short m_socks4_dstport
 socks4 support
unsigned long m_socks4_dstip
 socks4 support
int m_resolver_id
 Resolver id (if any) for current Open call.
bool m_b_reconnect
 Reconnect on lost connection flag.
bool m_b_is_reconnect
 Trying to reconnect.

Static Private Attributes

static SSLInitializer m_ssl_init

Classes

struct  MES
 Dynamic output buffer storage struct. More...

Detailed Description

Socket implementation for TCP.

Definition at line 53 of file TcpSocket.h.


Member Typedef Documentation

typedef std::list<MES *> TcpSocket::ucharp_v [private]

Dynamic output buffer list.

Definition at line 73 of file TcpSocket.h.


Constructor & Destructor Documentation

TcpSocket::TcpSocket ( ISocketHandler  ) 

Constructor with standard values on input/output buffers.

Definition at line 75 of file TcpSocket.cpp.

00075                                       : Socket(h)
00076 ,ibuf(*this, TCP_BUFSIZE_READ)
00077 ,obuf(*this, 32768)
00078 ,m_b_input_buffer_disabled(false)
00079 ,m_bytes_sent(0)
00080 ,m_bytes_received(0)
00081 ,m_skip_c(false)
00082 #ifdef SOCKETS_DYNAMIC_TEMP
00083 ,m_buf(new char[TCP_BUFSIZE_READ + 1])
00084 #endif
00085 #ifdef HAVE_OPENSSL
00086 ,m_ssl_ctx(NULL)
00087 ,m_ssl(NULL)
00088 ,m_sbio(NULL)
00089 #endif
00090 #ifdef ENABLE_SOCKS4
00091 ,m_socks4_state(0)
00092 #endif
00093 #ifdef ENABLE_RESOLVER
00094 ,m_resolver_id(0)
00095 #endif
00096 #ifdef ENABLE_RECONNECT
00097 ,m_b_reconnect(false)
00098 ,m_b_is_reconnect(false)
00099 #endif
00100 {
00101 }

TcpSocket::TcpSocket ( ISocketHandler h,
size_t  isize,
size_t  osize 
)

Constructor with custom values for i/o buffer.

Parameters:
h ISocketHandler reference
isize Input buffer size
osize Output buffer size

Definition at line 110 of file TcpSocket.cpp.

00110                                                                 : Socket(h)
00111 ,ibuf(*this, isize)
00112 ,obuf(*this, osize)
00113 ,m_b_input_buffer_disabled(false)
00114 ,m_bytes_sent(0)
00115 ,m_bytes_received(0)
00116 ,m_skip_c(false)
00117 #ifdef SOCKETS_DYNAMIC_TEMP
00118 ,m_buf(new char[TCP_BUFSIZE_READ + 1])
00119 #endif
00120 #ifdef HAVE_OPENSSL
00121 ,m_ssl_ctx(NULL)
00122 ,m_ssl(NULL)
00123 ,m_sbio(NULL)
00124 #endif
00125 #ifdef ENABLE_SOCKS4
00126 ,m_socks4_state(0)
00127 #endif
00128 #ifdef ENABLE_RESOLVER
00129 ,m_resolver_id(0)
00130 #endif
00131 #ifdef ENABLE_RECONNECT
00132 ,m_b_reconnect(false)
00133 ,m_b_is_reconnect(false)
00134 #endif
00135 {
00136 }

TcpSocket::~TcpSocket (  ) 

Definition at line 142 of file TcpSocket.cpp.

References Socket::Handler(), LOG_LEVEL_WARNING, ISocketHandler::LogError(), m_buf, m_mes, and m_ssl.

00143 {
00144         if (m_mes.size())
00145         {
00146                 Handler().LogError(this, "TcpSocket destructor", 0, "Output buffer not empty", LOG_LEVEL_WARNING);
00147         }
00148         while (m_mes.size())
00149         {
00150                 ucharp_v::iterator it = m_mes.begin();
00151                 MES *p = *it;
00152                 delete p;
00153                 m_mes.erase(it);
00154         }
00155 #ifdef SOCKETS_DYNAMIC_TEMP
00156         delete[] m_buf;
00157 #endif
00158 #ifdef HAVE_OPENSSL
00159         if (m_ssl)
00160         {
00161                 SSL_free(m_ssl);
00162         }
00163 #endif
00164 }

TcpSocket::TcpSocket ( const TcpSocket s  )  [protected]

Definition at line 856 of file TcpSocket.cpp.

00857 :Socket(s)
00858 ,ibuf(*this,0)
00859 ,obuf(*this,0)
00860 {
00861 }


Member Function Documentation

bool TcpSocket::Open ( ipaddr_t  ip,
port_t  port,
bool  skip_socks = false 
)

Open a connection to a remote server.

If you want your socket to connect to a server, always call Open before Add'ing a socket to the sockethandler. If not, the connection attempt will not be monitored by the socket handler...

Parameters:
ip IP address
port Port number
skip_socks Do not use socks4 even if configured

Definition at line 167 of file TcpSocket.cpp.

Referenced by HttpGetSocket::HttpGetSocket(), MinderSocket::OnLine(), OnResolved(), Open(), HttpPutSocket::Open(), and HttpPostSocket::Open().

00168 {
00169         Ipv4Address ad(ip, port);
00170         Ipv4Address local;
00171         return Open(ad, local, skip_socks);
00172 }

bool TcpSocket::Open ( SocketAddress ,
bool  skip_socks = false 
)

Definition at line 186 of file TcpSocket.cpp.

References Open().

00187 {
00188         Ipv4Address bind_ad("0.0.0.0", 0);
00189         return Open(ad, bind_ad, skip_socks);
00190 }

bool TcpSocket::Open ( SocketAddress ,
SocketAddress bind_address,
bool  skip_socks = false 
)

Connecting();

Definition at line 193 of file TcpSocket.cpp.

References Socket::Attach(), closesocket, Socket::CopyConnection(), Socket::CreateSocket(), Errno, ISocketHandler::FindConnection(), SocketAddress::GetFamily(), SocketAddress::GetPort(), Socket::GetSocks4Host(), Socket::GetSocks4Port(), Socket::Handler(), INVALID_SOCKET, SocketAddress::IsValid(), Utility::l2ip(), Utility::l2string(), LOG_LEVEL_FATAL, LOG_LEVEL_INFO, ISocketHandler::LogError(), Open(), Reconnect(), Socket::SetCallOnConnect(), Socket::SetClientRemoteAddress(), Socket::SetCloseAndDelete(), Socket::SetConnecting(), Socket::SetIsClient(), Socket::SetNonblocking(), Socket::SetRemoteAddress(), Socket::SetSocks4(), Socket::Socks4(), and StrError.

00194 {
00195         if (!ad.IsValid())
00196         {
00197                 Handler().LogError(this, "Open", 0, "Invalid SocketAddress", LOG_LEVEL_FATAL);
00198                 SetCloseAndDelete();
00199                 return false;
00200         }
00201         if (Handler().GetCount() >= FD_SETSIZE)
00202         {
00203                 Handler().LogError(this, "Open", 0, "no space left in fd_set", LOG_LEVEL_FATAL);
00204                 SetCloseAndDelete();
00205                 return false;
00206         }
00207         SetConnecting(false);
00208 #ifdef ENABLE_SOCKS4
00209         SetSocks4(false);
00210 #endif
00211         // check for pooling
00212 #ifdef ENABLE_POOL
00213         if (Handler().PoolEnabled())
00214         {
00215                 ISocketHandler::PoolSocket *pools = Handler().FindConnection(SOCK_STREAM, "tcp", ad);
00216                 if (pools)
00217                 {
00218                         CopyConnection( pools );
00219                         delete pools;
00220 
00221                         SetIsClient();
00222                         SetCallOnConnect(); // ISocketHandler must call OnConnect
00223                         Handler().LogError(this, "SetCallOnConnect", 0, "Found pooled connection", LOG_LEVEL_INFO);
00224                         return true;
00225                 }
00226         }
00227 #endif
00228         // if not, create new connection
00229         SOCKET s = CreateSocket(ad.GetFamily(), SOCK_STREAM, "tcp");
00230         if (s == INVALID_SOCKET)
00231         {
00232                 return false;
00233         }
00234         // socket must be nonblocking for async connect
00235         if (!SetNonblocking(true, s))
00236         {
00237                 SetCloseAndDelete();
00238                 closesocket(s);
00239                 return false;
00240         }
00241 #ifdef ENABLE_POOL
00242         SetIsClient(); // client because we connect
00243 #endif
00244         SetClientRemoteAddress(ad);
00245         int n = 0;
00246         if (bind_ad.GetPort() != 0)
00247         {
00248                 bind(s, bind_ad, bind_ad);
00249         }
00250 #ifdef ENABLE_SOCKS4
00251         if (!skip_socks && GetSocks4Host() && GetSocks4Port())
00252         {
00253                 Ipv4Address sa(GetSocks4Host(), GetSocks4Port());
00254                 {
00255                         std::string sockshost;
00256                         Utility::l2ip(GetSocks4Host(), sockshost);
00257                         Handler().LogError(this, "Open", 0, "Connecting to socks4 server @ " + sockshost + ":" +
00258                                 Utility::l2string(GetSocks4Port()), LOG_LEVEL_INFO);
00259                 }
00260                 SetSocks4();
00261                 n = connect(s, sa, sa);
00262                 SetRemoteAddress(sa);
00263         }
00264         else
00265 #endif
00266         {
00267                 n = connect(s, ad, ad);
00268                 SetRemoteAddress(ad);
00269         }
00270         if (n == -1)
00271         {
00272                 // check error code that means a connect is in progress
00273 #ifdef _WIN32
00274                 if (Errno == WSAEWOULDBLOCK)
00275 #else
00276                 if (Errno == EINPROGRESS)
00277 #endif
00278                 {
00279                         Attach(s);
00280                         SetConnecting( true ); // this flag will control fd_set's
00281                 }
00282                 else
00283 #ifdef ENABLE_SOCKS4
00284                 if (Socks4() && Handler().Socks4TryDirect() ) // retry
00285                 {
00286                         closesocket(s);
00287                         return Open(ad, true);
00288                 }
00289                 else
00290 #endif
00291 #ifdef ENABLE_RECONNECT
00292                 if (Reconnect())
00293                 {
00294                         Handler().LogError(this, "connect: failed, reconnect pending", Errno, StrError(Errno), LOG_LEVEL_INFO);
00295                         Attach(s);
00296                         SetConnecting( true ); // this flag will control fd_set's
00297                 }
00298                 else
00299 #endif
00300                 {
00301                         Handler().LogError(this, "connect: failed", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00302                         SetCloseAndDelete();
00303                         closesocket(s);
00304                         return false;
00305                 }
00306         }
00307         else
00308         {
00309                 Attach(s);
00310                 SetCallOnConnect(); // ISocketHandler must call OnConnect
00311         }
00312 
00313         // 'true' means connected or connecting(not yet connected)
00314         // 'false' means something failed
00315         return true; 
00316 }

bool TcpSocket::Open ( const std::string &  host,
port_t  port 
)

Open connection.

Parameters:
host Hostname
port Port number

Definition at line 319 of file TcpSocket.cpp.

References Socket::Handler(), Utility::isipv4(), m_resolver_id, Open(), Socket::Resolve(), Socket::SetCloseAndDelete(), and Utility::u2ip().

00320 {
00321 #ifdef ENABLE_IPV6
00322 #ifdef IPPROTO_IPV6
00323         if (IsIpv6())
00324         {
00325 #ifdef ENABLE_RESOLVER
00326                 if (!Handler().ResolvedEnabled() || Utility::isipv4(host) )
00327                 {
00328 #endif
00329                         in6_addr a;
00330                         if (!Utility::u2ip(host, a))
00331                         {
00332                                 SetCloseAndDelete();
00333                                 return false;
00334                         }
00335                         Ipv6Address ad(a, port);
00336                         Ipv6Address local;
00337                         return Open(ad, local);
00338 #ifdef ENABLE_RESOLVER
00339                 }
00340                 m_resolver_id = Resolve6(host, port);
00341                 return true;
00342 #endif
00343         }
00344 #endif
00345 #endif
00346 #ifdef ENABLE_RESOLVER
00347         if (!Handler().ResolverEnabled() || Utility::isipv4(host) )
00348         {
00349 #endif
00350                 ipaddr_t l;
00351                 if (!Utility::u2ip(host,l))
00352                 {
00353                         SetCloseAndDelete();
00354                         return false;
00355                 }
00356                 Ipv4Address ad(l, port);
00357                 Ipv4Address local;
00358                 return Open(ad, local);
00359 #ifdef ENABLE_RESOLVER
00360         }
00361         // resolve using async resolver thread
00362         m_resolver_id = Resolve(host, port);
00363         return true;
00364 #endif
00365 }

int TcpSocket::Close (  )  [virtual]

Close file descriptor - internal use only.

See also:
SetCloseAndDelete

Reimplemented from Socket.

Definition at line 1254 of file TcpSocket.cpp.

References Socket::Close(), Socket::IsSSL(), and m_ssl.

01255 {
01256 #ifdef HAVE_OPENSSL
01257         if (IsSSL() && m_ssl)
01258                 SSL_shutdown(m_ssl);
01259         if (m_ssl)
01260         {
01261                 SSL_free(m_ssl);
01262                 m_ssl = NULL;
01263         }
01264 #endif
01265         return Socket::Close();
01266 }

void TcpSocket::Send ( const std::string &  s,
int  f = 0 
) [virtual]

void TcpSocket::Sendf ( const char *  format,
  ... 
)

Send string using printf formatting.

Definition at line 978 of file TcpSocket.cpp.

References Send().

00979 {
00980         va_list ap;
00981         va_start(ap, format);
00982         char slask[5000]; // vsprintf / vsnprintf temporary
00983 #ifdef _WIN32
00984         vsprintf(slask, format, ap);
00985 #else
00986         vsnprintf(slask, 5000, format, ap);
00987 #endif
00988         va_end(ap);
00989         Send( slask );
00990 }

void TcpSocket::SendBuf ( const char *  buf,
size_t  len,
int  f = 0 
) [virtual]

Send buffer of bytes.

Parameters:
buf Buffer pointer
len Length of data
f Dummy flags -- not used

Todo:
check good value for max blocksize

Reimplemented from Socket.

Definition at line 797 of file TcpSocket.cpp.

References Socket::CloseAndDelete(), Socket::Connecting(), CircularBuffer::GetLength(), Socket::GetSocket(), Socket::Handler(), INVALID_SOCKET, Socket::IsConnected(), LOG_LEVEL_INFO, ISocketHandler::LogError(), m_mes, MAX_BLOCKSIZE, obuf, OnWrite(), Socket::Ready(), CircularBuffer::Space(), and CircularBuffer::Write().

Referenced by HttpPostSocket::DoMultipartPost(), HttpPutSocket::OnConnect(), HttpDebugSocket::OnData(), OnSocks4Connect(), Send(), and HttpdSocket::Send64().

00798 {
00799         size_t n = obuf.GetLength();
00800         if (!Ready() && !Connecting())
00801         {
00802                 Handler().LogError(this, "SendBuf", -1, "Attempt to write to a non-ready socket" ); // warning
00803                 if (GetSocket() == INVALID_SOCKET)
00804                         Handler().LogError(this, "SendBuf", 0, " * GetSocket() == INVALID_SOCKET", LOG_LEVEL_INFO);
00805                 if (Connecting())
00806                         Handler().LogError(this, "SendBuf", 0, " * Connecting()", LOG_LEVEL_INFO);
00807                 if (CloseAndDelete())
00808                         Handler().LogError(this, "SendBuf", 0, " * CloseAndDelete()", LOG_LEVEL_INFO);
00809                 return;
00810         }
00811         if (!IsConnected())
00812         {
00813                 Handler().LogError(this, "SendBuf", -1, "Attempt to write to a non-connected socket, will be sent on connect" ); // warning
00814         }
00815         //
00816         size_t ptr = 0;
00817         if (!m_mes.size() && obuf.Space())
00818         {
00819                 if (len <= obuf.Space()) // entire block of data fits
00820                 {
00821                         ptr = len;
00822                         obuf.Write(buf, len);
00823                 }
00824                 else // a part of the block fits
00825                 {
00826                         ptr = obuf.Space();
00827                         obuf.Write(buf, ptr);
00828                 }
00829         }
00831 #define MAX_BLOCKSIZE 1024000
00832         while (ptr < len) // data still left to buffer
00833         {
00834                 size_t sz = len - ptr; // size of data block that has not been buffered
00835                 if (sz > MAX_BLOCKSIZE)
00836                         sz = MAX_BLOCKSIZE;
00837                 m_mes.push_back(new MES(buf + ptr, sz));
00838                 ptr += sz;
00839         }
00840         // kick a real write
00841         if (!n && IsConnected())
00842         {
00843                 OnWrite();
00844         }
00845 }

void TcpSocket::OnRawData ( const char *  buf,
size_t  len 
) [virtual]

This callback is executed after a successful read from the socket.

Parameters:
buf Pointer to the data
len Length of the data

Reimplemented in HTTPSocket.

Definition at line 1294 of file TcpSocket.cpp.

Referenced by OnRead().

01295 {
01296 }

size_t TcpSocket::GetInputLength (  ) 

Number of bytes in input buffer.

Definition at line 1299 of file TcpSocket.cpp.

References CircularBuffer::GetLength(), and ibuf.

Referenced by OnRead(), and OnSocks4Read().

01300 {
01301         return ibuf.GetLength();
01302 }

size_t TcpSocket::GetOutputLength (  ) 

Number of bytes in output buffer.

Definition at line 1305 of file TcpSocket.cpp.

References CircularBuffer::GetLength(), and obuf.

Referenced by SSLNegotiate().

01306 {
01307         return obuf.GetLength();
01308 }

void TcpSocket::OnLine ( const std::string &  line  )  [virtual]

Callback fires when a socket in line protocol has read one full line.

Parameters:
line Line read

Reimplemented from Socket.

Reimplemented in HTTPSocket, MinderSocket, MinionSocket, ResolvSocket, and SmtpdSocket.

Definition at line 848 of file TcpSocket.cpp.

Referenced by OnRead().

00849 {
00850 }

uint64_t TcpSocket::GetBytesReceived ( bool  clear = false  )  [virtual]

Get counter of number of bytes received.

Reimplemented from Socket.

Definition at line 1311 of file TcpSocket.cpp.

References m_bytes_received.

01312 {
01313         uint64_t z = m_bytes_received;
01314         if (clear)
01315                 m_bytes_received = 0;
01316         return z;
01317 }

uint64_t TcpSocket::GetBytesSent ( bool  clear = false  )  [virtual]

Get counter of number of bytes sent.

Reimplemented from Socket.

Definition at line 1320 of file TcpSocket.cpp.

References m_bytes_sent.

01321 {
01322         uint64_t z = m_bytes_sent;
01323         if (clear)
01324                 m_bytes_sent = 0;
01325         return z;
01326 }

void TcpSocket::OnSocks4Connect (  )  [virtual]

Socks4 specific callback.

Todo:
warn

Todo:
warn

Reimplemented from Socket.

Definition at line 868 of file TcpSocket.cpp.

References Socket::GetClientRemoteAddress(), Socket::GetSocks4Userid(), m_socks4_state, and SendBuf().

00869 {
00870         char request[1000];
00871         memset(request, 0, sizeof(request));
00872         request[0] = 4; // socks v4
00873         request[1] = 1; // command code: CONNECT
00874         {
00875                 std::auto_ptr<SocketAddress> ad = GetClientRemoteAddress();
00876                 if (ad.get())
00877                 {
00878                         struct sockaddr *p0 = (struct sockaddr *)*ad;
00879                         struct sockaddr_in *p = (struct sockaddr_in *)p0;
00880                         if (p -> sin_family == AF_INET)
00881                         {
00882                                 memcpy(request + 2, &p -> sin_port, 2); // nwbo is ok here
00883                                 memcpy(request + 4, &p -> sin_addr, sizeof(struct in_addr));
00884                         }
00885                         else
00886                         {
00888                         }
00889                 }
00890                 else
00891                 {
00893                 }
00894         }
00895         strcpy(request + 8, GetSocks4Userid().c_str());
00896         size_t length = GetSocks4Userid().size() + 8 + 1;
00897         SendBuf(request, length);
00898         m_socks4_state = 0;
00899 }

void TcpSocket::OnSocks4ConnectFailed (  )  [virtual]

Socks4 specific callback.

Reimplemented from Socket.

Definition at line 902 of file TcpSocket.cpp.

References Socket::Handler(), LOG_LEVEL_WARNING, ISocketHandler::LogError(), Socket::OnConnectFailed(), Socket::SetCloseAndDelete(), Socket::SetConnecting(), and Socket::SetRetryClientConnect().

Referenced by OnWrite().

00903 {
00904         Handler().LogError(this,"OnSocks4ConnectFailed",0,"connection to socks4 server failed, trying direct connection",LOG_LEVEL_WARNING);
00905         if (!Handler().Socks4TryDirect())
00906         {
00907                 SetConnecting(false);
00908                 SetCloseAndDelete();
00909                 OnConnectFailed(); // just in case
00910         }
00911         else
00912         {
00913                 SetRetryClientConnect();
00914         }
00915 }

bool TcpSocket::OnSocks4Read (  )  [virtual]

Socks4 specific callback.

Returns:
'need_more'

Reimplemented from Socket.

Definition at line 918 of file TcpSocket.cpp.

References GetInputLength(), Socket::Handler(), ibuf, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, ISocketHandler::LogError(), m_socks4_cd, m_socks4_dstip, m_socks4_dstport, m_socks4_state, m_socks4_vn, Socket::OnConnect(), Socket::OnConnectFailed(), CircularBuffer::Read(), Socket::SetCloseAndDelete(), Socket::SetConnecting(), and Socket::SetSocks4().

Referenced by OnRead().

00919 {
00920         switch (m_socks4_state)
00921         {
00922         case 0:
00923                 ibuf.Read(&m_socks4_vn, 1);
00924                 m_socks4_state = 1;
00925                 break;
00926         case 1:
00927                 ibuf.Read(&m_socks4_cd, 1);
00928                 m_socks4_state = 2;
00929                 break;
00930         case 2:
00931                 if (GetInputLength() > 1)
00932                 {
00933                         ibuf.Read( (char *)&m_socks4_dstport, 2);
00934                         m_socks4_state = 3;
00935                 }
00936                 else
00937                 {
00938                         return true;
00939                 }
00940                 break;
00941         case 3:
00942                 if (GetInputLength() > 3)
00943                 {
00944                         ibuf.Read( (char *)&m_socks4_dstip, 4);
00945                         SetSocks4(false);
00946                         
00947                         switch (m_socks4_cd)
00948                         {
00949                         case 90:
00950                                 OnConnect();
00951                                 Handler().LogError(this, "OnSocks4Read", 0, "Connection established", LOG_LEVEL_INFO);
00952                                 break;
00953                         case 91:
00954                         case 92:
00955                         case 93:
00956                                 Handler().LogError(this,"OnSocks4Read",m_socks4_cd,"socks4 server reports connect failed",LOG_LEVEL_FATAL);
00957                                 SetConnecting(false);
00958                                 SetCloseAndDelete();
00959                                 OnConnectFailed();
00960                                 break;
00961                         default:
00962                                 Handler().LogError(this,"OnSocks4Read",m_socks4_cd,"socks4 server unrecognized response",LOG_LEVEL_FATAL);
00963                                 SetCloseAndDelete();
00964                                 break;
00965                         }
00966                 }
00967                 else
00968                 {
00969                         return true;
00970                 }
00971                 break;
00972         }
00973         return false;
00974 }

void TcpSocket::OnResolved ( int  id,
ipaddr_t  a,
port_t  port 
) [virtual]

Callback executed when resolver thread has finished a resolve request.

Reimplemented from Socket.

Definition at line 369 of file TcpSocket.cpp.

References ISocketHandler::Add(), Socket::Handler(), LOG_LEVEL_FATAL, ISocketHandler::LogError(), m_resolver_id, Open(), and Socket::SetCloseAndDelete().

Referenced by ResolvSocket::OnLine().

00370 {
00371         if (id == m_resolver_id)
00372         {
00373                 if (a && port)
00374                 {
00375                         Ipv4Address ad(a, port);
00376                         Ipv4Address local;
00377                         if (Open(ad, local))
00378                         {
00379                                 if (!Handler().Valid(this))
00380                                 {
00381                                         Handler().Add(this);
00382                                 }
00383                         }
00384                 }
00385                 else
00386                 {
00387                         Handler().LogError(this, "OnResolved", 0, "Resolver failed", LOG_LEVEL_FATAL);
00388                         SetCloseAndDelete();
00389                 }
00390         }
00391         else
00392         {
00393                 Handler().LogError(this, "OnResolved", id, "Resolver returned wrong job id", LOG_LEVEL_FATAL);
00394                 SetCloseAndDelete();
00395         }
00396 }

void TcpSocket::OnSSLConnect (  )  [virtual]

Callback for 'New' ssl support - replaces SSLSocket.

Internal use.

Reimplemented from Socket.

Definition at line 994 of file TcpSocket.cpp.

References DEB, Socket::GetSocket(), InitSSLClient(), m_sbio, m_ssl, m_ssl_ctx, Socket::SetCloseAndDelete(), Socket::SetNonblocking(), and Socket::SetSSLNegotiate().

00995 {
00996         SetNonblocking(true);
00997         {
00998                 if (m_ssl_ctx)
00999                 {
01000 DEB(                    fprintf(stderr, "SSL Context already initialized - closing socket\n");)
01001                         SetCloseAndDelete(true);
01002                         return;
01003                 }
01004                 InitSSLClient();
01005         }
01006         if (m_ssl_ctx)
01007         {
01008                 /* Connect the SSL socket */
01009                 m_ssl = SSL_new(m_ssl_ctx);
01010                 if (!m_ssl)
01011                 {
01012 DEB(                    fprintf(stderr, " m_ssl is NULL\n");)
01013                         SetCloseAndDelete(true);
01014                         return;
01015                 }
01016                 SSL_set_mode(m_ssl, SSL_MODE_AUTO_RETRY);
01017                 m_sbio = BIO_new_socket((int)GetSocket(), BIO_NOCLOSE);
01018                 if (!m_sbio)
01019                 {
01020 DEB(                    fprintf(stderr, " m_sbio is NULL\n");)
01021                         SetCloseAndDelete(true);
01022                         return;
01023                 }
01024                 SSL_set_bio(m_ssl, m_sbio, m_sbio);
01025 //              if (!SSLNegotiate())
01026                 {
01027                         SetSSLNegotiate();
01028                 }
01029         }
01030         else
01031         {
01032                 SetCloseAndDelete();
01033         }
01034 }

void TcpSocket::OnSSLAccept (  )  [virtual]

Callback for 'New' ssl support - replaces SSLSocket.

Internal use.

Reimplemented from Socket.

Definition at line 1037 of file TcpSocket.cpp.

References DEB, Socket::GetSocket(), InitSSLServer(), m_sbio, m_ssl, m_ssl_ctx, Socket::SetCloseAndDelete(), Socket::SetNonblocking(), Socket::SetSSLNegotiate(), and Socket::SetSSLServer().

01038 {
01039         SetNonblocking(true);
01040         {
01041                 if (m_ssl_ctx)
01042                 {
01043 DEB(                    fprintf(stderr, "SSL Context already initialized - closing socket\n");)
01044                         SetCloseAndDelete(true);
01045                         return;
01046                 }
01047                 InitSSLServer();
01048                 SetSSLServer();
01049         }
01050         if (m_ssl_ctx)
01051         {
01052                 m_ssl = SSL_new(m_ssl_ctx);
01053                 if (!m_ssl)
01054                 {
01055 DEB(                    fprintf(stderr, " m_ssl is NULL\n");)
01056                         SetCloseAndDelete(true);
01057                         return;
01058                 }
01059                 SSL_set_mode(m_ssl, SSL_MODE_AUTO_RETRY);
01060                 m_sbio = BIO_new_socket((int)GetSocket(), BIO_NOCLOSE);
01061                 if (!m_sbio)
01062                 {
01063 DEB(                    fprintf(stderr, " m_sbio is NULL\n");)
01064                         SetCloseAndDelete(true);
01065                         return;
01066                 }
01067                 SSL_set_bio(m_ssl, m_sbio, m_sbio);
01068 //              if (!SSLNegotiate())
01069                 {
01070                         SetSSLNegotiate();
01071                 }
01072         }
01073 }

void TcpSocket::InitSSLClient (  )  [virtual]

This method must be implemented to initialize the ssl context for an outgoing connection.

Definition at line 1173 of file TcpSocket.cpp.

References InitializeContext().

Referenced by OnSSLConnect().

01174 {
01175         InitializeContext("", SSLv23_method());
01176 }

void TcpSocket::InitSSLServer (  )  [virtual]

This method must be implemented to initialize the ssl context for an incoming connection.

Definition at line 1179 of file TcpSocket.cpp.

References Socket::Handler(), LOG_LEVEL_FATAL, ISocketHandler::LogError(), and Socket::SetCloseAndDelete().

Referenced by OnSSLAccept().

01180 {
01181         Handler().LogError(this, "InitSSLServer", 0, "You MUST implement your own InitSSLServer method", LOG_LEVEL_FATAL);
01182         SetCloseAndDelete();
01183 }

void TcpSocket::SetReconnect ( bool  = true  ) 

Flag that says a broken connection will try to reconnect.

Definition at line 1287 of file TcpSocket.cpp.

References m_b_reconnect.

01288 {
01289         m_b_reconnect = x;
01290 }

bool TcpSocket::Reconnect (  ) 

Check reconnect on lost connection flag status.

Definition at line 1330 of file TcpSocket.cpp.

References m_b_reconnect.

Referenced by Open().

01331 {
01332         return m_b_reconnect;
01333 }

void TcpSocket::SetIsReconnect ( bool  x = true  ) 

Flag to determine if a reconnect is in progress.

Definition at line 1336 of file TcpSocket.cpp.

References m_b_is_reconnect.

01337 {
01338         m_b_is_reconnect = x;
01339 }

bool TcpSocket::IsReconnect (  ) 

Socket is reconnecting.

Definition at line 1342 of file TcpSocket.cpp.

References m_b_is_reconnect.

Referenced by SSLNegotiate().

01343 {
01344         return m_b_is_reconnect;
01345 }

void TcpSocket::DisableInputBuffer ( bool  = true  ) 

Definition at line 1357 of file TcpSocket.cpp.

References m_b_input_buffer_disabled.

Referenced by HTTPSocket::HTTPSocket(), and SetLineProtocol().

01358 {
01359         m_b_input_buffer_disabled = x;
01360 }

void TcpSocket::OnOptions ( int  family,
int  type,
int  protocol,
SOCKET   
) [virtual]

Called when a socket is created, to set socket options.

Implements Socket.

Definition at line 1363 of file TcpSocket.cpp.

References DEB, Socket::SetKeepalive(), and Socket::SetReuse().

01364 {
01365 DEB(    fprintf(stderr, "Socket::OnOptions()\n");)
01366 /*
01367         Handler().LogError(this, "OnOptions", family, "Address Family", LOG_LEVEL_INFO);
01368         Handler().LogError(this, "OnOptions", type, "Type", LOG_LEVEL_INFO);
01369         Handler().LogError(this, "OnOptions", protocol, "Protocol", LOG_LEVEL_INFO);
01370 */
01371         SetReuse(true);
01372         SetKeepalive(true);
01373 }

void TcpSocket::SetLineProtocol ( bool  = true  )  [virtual]

Enable the OnLine callback.

Do not create your own OnRead callback when using this.

Reimplemented from Socket.

Definition at line 1376 of file TcpSocket.cpp.

References DisableInputBuffer(), and Socket::SetLineProtocol().

Referenced by HTTPSocket::HTTPSocket(), MinderSocket::MinderSocket(), MinionSocket::MinionSocket(), HTTPSocket::OnLine(), HTTPSocket::Reset(), ResolvSocket::ResolvSocket(), and SmtpdSocket::SmtpdSocket().

01377 {
01378         Socket::SetLineProtocol(x);
01379         DisableInputBuffer(x);
01380 }

void TcpSocket::OnRead (  )  [protected, virtual]

Called when there is something to be read from the file descriptor.

Reimplemented from Socket.

Definition at line 427 of file TcpSocket.cpp.

References Socket::CloseAndDelete(), DEB, Errno, GetInputLength(), Socket::GetSocket(), Socket::GetTrafficMonitor(), Socket::Handler(), ibuf, Socket::IsSSL(), Socket::LineProtocol(), LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_WARNING, ISocketHandler::LogError(), m_b_input_buffer_disabled, m_buf, m_bytes_received, m_c, m_line, m_skip_c, m_ssl, OnLine(), OnRawData(), OnSocks4Read(), Socket::Ready(), Socket::SetCloseAndDelete(), Socket::SetFlushBeforeClose(), Socket::SetLost(), Socket::SetShutdown(), Socket::Socks4(), StrError, TCP_BUFSIZE_READ, and CircularBuffer::Write().

00428 {
00429         int n = 0;
00430 #ifdef SOCKETS_DYNAMIC_TEMP
00431         char *buf = m_buf;
00432 #else
00433         char buf[TCP_BUFSIZE_READ];
00434 #endif
00435 #ifdef HAVE_OPENSSL
00436         if (IsSSL())
00437         {
00438                 if (!Ready())
00439                         return;
00440                 n = SSL_read(m_ssl, buf, TCP_BUFSIZE_READ);
00441                 if (n == -1)
00442                 {
00443                         n = SSL_get_error(m_ssl, n);
00444                         switch (n)
00445                         {
00446                         case SSL_ERROR_NONE:
00447                         case SSL_ERROR_WANT_READ:
00448                         case SSL_ERROR_WANT_WRITE:
00449                                 break;
00450                         case SSL_ERROR_ZERO_RETURN:
00451 DEB(                            fprintf(stderr, "SSL_read() returns zero - closing socket\n");)
00452                                 SetCloseAndDelete(true);
00453                                 SetFlushBeforeClose(false);
00454 #ifdef ENABLE_POOL
00455                                 SetLost();
00456 #endif
00457                                 break;
00458                         default:
00459 DEB(                            fprintf(stderr, "SSL read problem, errcode = %d\n",n);)
00460                                 SetCloseAndDelete(true);
00461                                 SetFlushBeforeClose(false);
00462 #ifdef ENABLE_POOL
00463                                 SetLost();
00464 #endif
00465                         }
00466                         return;
00467                 }
00468                 else
00469                 if (!n)
00470                 {
00471                         Handler().LogError(this, "SSL_read", 0, "read returns 0", LOG_LEVEL_FATAL);
00472                         SetCloseAndDelete(true);
00473                         SetFlushBeforeClose(false);
00474 #ifdef ENABLE_POOL
00475                         SetLost();
00476 #endif
00477                         SetShutdown(SHUT_WR);
00478                         return;
00479                 }
00480                 else
00481                 if (n > 0 && n <= TCP_BUFSIZE_READ)
00482                 {
00483                         m_bytes_received += n;
00484                         if (GetTrafficMonitor())
00485                         {
00486                                 GetTrafficMonitor() -> fwrite(buf, 1, n);
00487                         }
00488                         if (!m_b_input_buffer_disabled && !ibuf.Write(buf,n))
00489                         {
00490                                 Handler().LogError(this, "OnRead(ssl)", 0, "ibuf overflow", LOG_LEVEL_WARNING);
00491                         }
00492                 }
00493                 else
00494                 {
00495                         Handler().LogError(this, "OnRead(ssl)", n, "abnormal value from SSL_read", LOG_LEVEL_ERROR);
00496                 }
00497         }
00498         else
00499 #endif // HAVE_OPENSSL
00500         {
00501                 n = recv(GetSocket(), buf, TCP_BUFSIZE_READ, MSG_NOSIGNAL);
00502                 if (n == -1)
00503                 {
00504                         Handler().LogError(this, "read", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00505                         SetCloseAndDelete(true);
00506                         SetFlushBeforeClose(false);
00507 #ifdef ENABLE_POOL
00508                         SetLost();
00509 #endif
00510                         return;
00511                 }
00512                 else
00513                 if (!n)
00514                 {
00515                         SetCloseAndDelete(true);
00516                         SetFlushBeforeClose(false);
00517 #ifdef ENABLE_POOL
00518                         SetLost();
00519 #endif
00520                         SetShutdown(SHUT_WR);
00521                         return;
00522                 }
00523                 else
00524                 if (n > 0 && n <= TCP_BUFSIZE_READ)
00525                 {
00526                         m_bytes_received += n;
00527                         if (GetTrafficMonitor())
00528                         {
00529                                 GetTrafficMonitor() -> fwrite(buf, 1, n);
00530                         }
00531                         if (!m_b_input_buffer_disabled && !ibuf.Write(buf,n))
00532                         {
00533                                 Handler().LogError(this, "OnRead", 0, "ibuf overflow", LOG_LEVEL_WARNING);
00534                         }
00535                 }
00536                 else
00537                 {
00538                         Handler().LogError(this, "OnRead", n, "abnormal value from recv", LOG_LEVEL_ERROR);
00539                 }
00540         }
00541         // unbuffered
00542         if (n > 0 && n <= TCP_BUFSIZE_READ)
00543         {
00544                 if (LineProtocol())
00545                 {
00546                         size_t x = 0;
00547 
00548                         buf[n] = 0;
00549                         int i = 0;
00550                         if (m_skip_c && (buf[i] == 13 || buf[i] == 10) && buf[i] != m_c)
00551                         {
00552                                 m_skip_c = false;
00553                                 i++;
00554                         }
00555                         for (; i < n && LineProtocol(); i++)
00556                         {
00557                                 while ((buf[i] == 13 || buf[i] == 10) && LineProtocol())
00558                                 {
00559                                         char c = buf[i];
00560                                         buf[i] = 0;
00561                                         if (buf[x])
00562                                         {
00563                                                 m_line += (buf + x);
00564                                         }
00565                                         OnLine( m_line );
00566                                         i++;
00567                                         m_skip_c = true;
00568                                         m_c = c;
00569                                         if (i < n && (buf[i] == 13 || buf[i] == 10) && buf[i] != c)
00570                                         {
00571                                                 m_skip_c = false;
00572                                                 i++;
00573                                         }
00574                                         x = i;
00575                                         m_line = "";
00576                                 }
00577                                 if (!LineProtocol())
00578                                 {
00579                                         break;
00580                                 }
00581                         }
00582                         if (!LineProtocol())
00583                         {
00584                                 if (i < n)
00585                                 {
00586                                         OnRawData(buf + i, n - i);
00587                                 }
00588                         }
00589                         else
00590                         if (buf[x])
00591                         {
00592                                 m_line += (buf + x);
00593                         }
00594                 }
00595                 else
00596                 {
00597                         OnRawData(buf, n);
00598                 }
00599         }
00600         if (m_b_input_buffer_disabled)
00601         {
00602                 return;
00603         }
00604         // further processing: socks4
00605 #ifdef ENABLE_SOCKS4
00606         if (Socks4())
00607         {
00608                 bool need_more = false;
00609                 while (GetInputLength() && !need_more && !CloseAndDelete())
00610                 {
00611                         need_more = OnSocks4Read();
00612                 }
00613         }
00614 #endif
00615 }

void TcpSocket::OnWrite (  )  [protected, virtual]

Called when there is room for another write on the file descriptor.

Reimplemented from Socket.

Definition at line 618 of file TcpSocket.cpp.

References Socket::CheckConnect(), Socket::Connecting(), DEB, Errno, ISocketHandler::Get(), Socket::GetConnectionRetries(), Socket::GetConnectionRetry(), CircularBuffer::GetLength(), Socket::GetSocket(), CircularBuffer::GetStart(), Socket::GetTrafficMonitor(), Socket::Handler(), Socket::IsSSL(), LOG_LEVEL_FATAL, ISocketHandler::LogError(), m_bytes_sent, m_mes, m_ssl, obuf, Socket::OnConnectFailed(), OnSocks4ConnectFailed(), CircularBuffer::Remove(), Socket::Set(), Socket::SetCallOnConnect(), Socket::SetCloseAndDelete(), Socket::SetConnecting(), Socket::SetFlushBeforeClose(), Socket::SetLost(), Socket::Socks4(), CircularBuffer::Space(), StrError, and CircularBuffer::Write().

Referenced by SendBuf(), and SSLNegotiate().

00619 {
00620         if (Connecting())
00621         {
00622                 if (CheckConnect())
00623                 {
00624                         SetCallOnConnect();
00625                         return;
00626                 }
00627                 // failed
00628 #ifdef ENABLE_SOCKS4
00629                 if (Socks4())
00630                 {
00631                         OnSocks4ConnectFailed();
00632                         return;
00633                 }
00634 #endif
00635                 if (GetConnectionRetry() == -1 ||
00636                         (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
00637                 {
00638                         // even though the connection failed at once, only retry after
00639                         // the connection timeout.
00640                         // should we even try to connect again, when CheckConnect returns
00641                         // false it's because of a connection error - not a timeout...
00642                         return;
00643                 }
00644                 SetConnecting(false);
00645                 SetCloseAndDelete( true );
00647                 OnConnectFailed();
00648                 return;
00649         }
00650 #ifdef HAVE_OPENSSL
00651         if (IsSSL())
00652         {
00653                 int n = SSL_write(m_ssl,obuf.GetStart(),(int)obuf.GetLength());
00654                 int errnr = n < 1 ? SSL_get_error(m_ssl, n) : 0;
00655                 if (n == -1)
00656                 {
00657                         if ( errnr != SSL_ERROR_WANT_READ && errnr != SSL_ERROR_WANT_WRITE )
00658                         {
00659                                 SetCloseAndDelete(true);
00660                                 SetFlushBeforeClose(false);
00661 #ifdef ENABLE_POOL
00662                                 SetLost();
00663 #endif
00664                                 const char *errbuf = ERR_error_string(errnr, NULL);
00665                                 Handler().LogError(this, "OnWrite/SSL_write", errnr, errbuf, LOG_LEVEL_FATAL);
00666                         }
00667                 }
00668                 else
00669                 if (!n)
00670                 {
00671                         SetCloseAndDelete(true);
00672                         SetFlushBeforeClose(false);
00673 #ifdef ENABLE_POOL
00674                         SetLost();
00675 #endif
00676 DEB(                    const char *errbuf = ERR_error_string(errnr, NULL);
00677                         fprintf(stderr, "SSL_write() returns 0: %d : %s\n",errnr, errbuf);)
00678                 }
00679                 else
00680                 {
00681                         m_bytes_sent += n;
00682                         if (GetTrafficMonitor())
00683                         {
00684                                 GetTrafficMonitor() -> fwrite(obuf.GetStart(), 1, n);
00685                         }
00686                         obuf.Remove(n);
00687                         // move data from m_mes to immediate output buffer
00688                         while (obuf.Space() && m_mes.size())
00689                         {
00690                                 ucharp_v::iterator it = m_mes.begin();
00691                                 MES *p = *it;
00692                                 if (obuf.Space() > p -> left())
00693                                 {
00694                                         obuf.Write(p -> curbuf(),p -> left());
00695                                         delete p;
00696                                         m_mes.erase(it);
00697                                 }
00698                                 else
00699                                 {
00700                                         size_t sz = obuf.Space();
00701                                         obuf.Write(p -> curbuf(),sz);
00702                                         p -> ptr += sz;
00703                                 }
00704                         }
00705                 }
00706                 //
00707                 {
00708                         bool br;
00709                         bool bw;
00710                         bool bx;
00711                         Handler().Get(GetSocket(), br, bw, bx);
00712                         if (obuf.GetLength() || m_mes.size())
00713                                 Set(br, true);
00714                         else
00715                                 Set(br, false);
00716                 }
00717                 return;
00718         }
00719 #endif // HAVE_OPENSSL
00720         int n = send(GetSocket(),obuf.GetStart(),(int)obuf.GetLength(),MSG_NOSIGNAL);
00721 /*
00722 When writing onto a connection-oriented socket that has been shut down (by the  local
00723 or the remote end) SIGPIPE is sent to the writing process and EPIPE is returned.  The
00724 signal is not sent when the write call specified the MSG_NOSIGNAL flag.
00725 */
00726         if (n == -1)
00727         {
00728         // normal error codes:
00729         // WSAEWOULDBLOCK
00730         //       EAGAIN or EWOULDBLOCK
00731 #ifdef _WIN32
00732                 if (Errno != WSAEWOULDBLOCK)
00733 #else
00734                 if (Errno != EWOULDBLOCK)
00735 #endif
00736                 {       
00737                         Handler().LogError(this, "send", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00738                         SetCloseAndDelete(true);
00739                         SetFlushBeforeClose(false);
00740 #ifdef ENABLE_POOL
00741                         SetLost();
00742 #endif
00743                 }
00744         }
00745         else
00746         if (!n)
00747         {
00748 //              SetCloseAndDelete(true);
00749         }
00750         else
00751         {
00752                 m_bytes_sent += n;
00753                 if (GetTrafficMonitor())
00754                 {
00755                         GetTrafficMonitor() -> fwrite(obuf.GetStart(), 1, n);
00756                 }
00757                 obuf.Remove(n);
00758                 // move data from m_mes to immediate output buffer
00759                 while (obuf.Space() && m_mes.size())
00760                 {
00761                         ucharp_v::iterator it = m_mes.begin();
00762                         MES *p = *it;
00763                         if (obuf.Space() > p -> left())
00764                         {
00765                                 obuf.Write(p -> curbuf(),p -> left());
00766                                 delete p;
00767                                 m_mes.erase(it);
00768                         }
00769                         else
00770                         {
00771                                 size_t sz = obuf.Space();
00772                                 obuf.Write(p -> curbuf(),sz);
00773                                 p -> ptr += sz;
00774                         }
00775                 }
00776         }
00777         // set write flag if data still left to write
00778         {
00779                 bool br;
00780                 bool bw;
00781                 bool bx;
00782                 Handler().Get(GetSocket(), br, bw, bx);
00783                 if (obuf.GetLength() || m_mes.size())
00784                         Set(br, true);
00785                 else
00786                         Set(br, false);
00787         }
00788 }

void TcpSocket::InitializeContext ( const std::string &  context,
SSL_METHOD *  meth_in = NULL 
) [protected]

SSL; Initialize ssl context for a client socket.

Parameters:
meth_in SSL method

Definition at line 1186 of file TcpSocket.cpp.

References m_ssl_ctx.

Referenced by InitSSLClient().

01187 {
01188         /* Create our context*/
01189         static std::map<std::string, SSL_CTX *> client_contexts;
01190         if (client_contexts.find(context) == client_contexts.end())
01191         {
01192                 SSL_METHOD *meth = meth_in ? meth_in : SSLv3_method();
01193                 m_ssl_ctx = client_contexts[context] = SSL_CTX_new(meth);
01194                 SSL_CTX_set_mode(m_ssl_ctx, SSL_MODE_AUTO_RETRY);
01195         }
01196         else
01197         {
01198                 m_ssl_ctx = client_contexts[context];
01199         }
01200 }

void TcpSocket::InitializeContext ( const std::string &  context,
const std::string &  keyfile,
const std::string &  password,
SSL_METHOD *  meth_in = NULL 
) [protected]

SSL; Initialize ssl context for a server socket.

Parameters:
keyfile Combined private key/certificate file
password Password for private key
meth_in SSL method

Definition at line 1203 of file TcpSocket.cpp.

References Socket::Handler(), LOG_LEVEL_FATAL, ISocketHandler::LogError(), m_password, m_ssl_ctx, and SSL_password_cb().

01204 {
01205         /* Create our context*/
01206         static std::map<std::string, SSL_CTX *> server_contexts;
01207         if (server_contexts.find(context) == server_contexts.end())
01208         {
01209                 SSL_METHOD *meth = meth_in ? meth_in : SSLv3_method();
01210                 m_ssl_ctx = server_contexts[context] = SSL_CTX_new(meth);
01211                 SSL_CTX_set_mode(m_ssl_ctx, SSL_MODE_AUTO_RETRY);
01212                 // session id
01213                 if (context.size())
01214                         SSL_CTX_set_session_id_context(m_ssl_ctx, (const unsigned char *)context.c_str(), (unsigned int)context.size());
01215                 else
01216                         SSL_CTX_set_session_id_context(m_ssl_ctx, (const unsigned char *)"--empty--", 9);
01217         }
01218         else
01219         {
01220                 m_ssl_ctx = server_contexts[context];
01221         }
01222 
01223         /* Load our keys and certificates*/
01224         if (!(SSL_CTX_use_certificate_file(m_ssl_ctx, keyfile.c_str(), SSL_FILETYPE_PEM)))
01225         {
01226                 Handler().LogError(this, "TcpSocket InitializeContext", 0, "Couldn't read certificate file " + keyfile, LOG_LEVEL_FATAL);
01227         }
01228 
01229         m_password = password;
01230         SSL_CTX_set_default_passwd_cb(m_ssl_ctx, SSL_password_cb);
01231         SSL_CTX_set_default_passwd_cb_userdata(m_ssl_ctx, this);
01232         if (!(SSL_CTX_use_PrivateKey_file(m_ssl_ctx, keyfile.c_str(), SSL_FILETYPE_PEM)))
01233         {
01234                 Handler().LogError(this, "TcpSocket InitializeContext", 0, "Couldn't read private key file " + keyfile, LOG_LEVEL_FATAL);
01235         }
01236 }

int TcpSocket::SSL_password_cb ( char *  buf,
int  num,
int  rwflag,
void *  userdata 
) [static, protected]

SSL; Password callback method.

Definition at line 1239 of file TcpSocket.cpp.

References GetPassword().

Referenced by InitializeContext().

01240 {
01241         Socket *p0 = static_cast<Socket *>(userdata);
01242         TcpSocket *p = dynamic_cast<TcpSocket *>(p0);
01243         std::string pw = p ? p -> GetPassword() : "";
01244         if ( (size_t)num < pw.size() + 1)
01245         {
01246                 return 0;
01247         }
01248         strcpy(buf,pw.c_str());
01249         return (int)pw.size();
01250 }

SSL_CTX * TcpSocket::GetSslContext (  )  [protected, virtual]

SSL; Get pointer to ssl context structure.

Reimplemented from Socket.

Definition at line 1270 of file TcpSocket.cpp.

References Socket::Handler(), LOG_LEVEL_WARNING, ISocketHandler::LogError(), and m_ssl_ctx.

01271 {
01272         if (!m_ssl_ctx)
01273                 Handler().LogError(this, "GetSslContext", 0, "SSL Context is NULL; check InitSSLServer/InitSSLClient", LOG_LEVEL_WARNING);
01274         return m_ssl_ctx;
01275 }

SSL * TcpSocket::GetSsl (  )  [protected, virtual]

SSL; Get pointer to ssl structure.

Reimplemented from Socket.

Definition at line 1277 of file TcpSocket.cpp.

References Socket::Handler(), LOG_LEVEL_WARNING, ISocketHandler::LogError(), and m_ssl.

01278 {
01279         if (!m_ssl)
01280                 Handler().LogError(this, "GetSsl", 0, "SSL is NULL; check InitSSLServer/InitSSLClient", LOG_LEVEL_WARNING);
01281         return m_ssl;
01282 }

bool TcpSocket::SSLNegotiate (  )  [protected, virtual]

ssl; still negotiating connection.

Todo:
: resurrect certificate check... client

Todo:
: resurrect certificate check... server

Reimplemented from Socket.

Definition at line 1076 of file TcpSocket.cpp.

References DEB, GetOutputLength(), Socket::Handler(), IsReconnect(), Socket::IsSSLServer(), LOG_LEVEL_INFO, ISocketHandler::LogError(), m_ssl, Socket::OnAccept(), Socket::OnConnect(), Socket::OnReconnect(), Socket::OnSSLAcceptFailed(), Socket::OnSSLConnectFailed(), OnWrite(), Socket::SetCloseAndDelete(), Socket::SetConnected(), Socket::SetNonblocking(), and Socket::SetSSLNegotiate().

01077 {
01078         if (!IsSSLServer()) // client
01079         {
01080                 int r = SSL_connect(m_ssl);
01081                 if (r > 0)
01082                 {
01083                         SetSSLNegotiate(false);
01085 //                      CheckCertificateChain( "");//ServerHOST);
01086                         SetNonblocking(false);
01087                         //
01088                         {
01089                                 SetConnected();
01090                                 if (GetOutputLength())
01091                                 {
01092                                         OnWrite();
01093                                 }
01094                         }
01095 #ifdef ENABLE_RECONNECT
01096                         if (IsReconnect())
01097                                 OnReconnect();
01098                         else
01099 #endif
01100                         {
01101                                 OnConnect();
01102                         }
01103                         Handler().LogError(this, "SSLNegotiate/SSL_connect", 0, "Connection established", LOG_LEVEL_INFO);
01104                         return true;
01105                 }
01106                 else
01107                 if (!r)
01108                 {
01109                         Handler().LogError(this, "SSLNegotiate/SSL_connect", 0, "Connection failed", LOG_LEVEL_INFO);
01110                         SetSSLNegotiate(false);
01111                         SetCloseAndDelete();
01112                         OnSSLConnectFailed();
01113                 }
01114                 else
01115                 {
01116                         r = SSL_get_error(m_ssl, r);
01117                         if (r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
01118                         {
01119                                 Handler().LogError(this, "SSLNegotiate/SSL_connect", -1, "Connection failed", LOG_LEVEL_INFO);
01120 DEB(                            fprintf(stderr, "SSL_connect() failed - closing socket, return code: %d\n",r);)
01121                                 SetSSLNegotiate(false);
01122                                 SetCloseAndDelete(true);
01123                                 OnSSLConnectFailed();
01124                         }
01125                 }
01126         }
01127         else // server
01128         {
01129                 int r = SSL_accept(m_ssl);
01130                 if (r > 0)
01131                 {
01132                         SetSSLNegotiate(false);
01134 //                      CheckCertificateChain( "");//ClientHOST);
01135                         SetNonblocking(false);
01136                         //
01137                         {
01138                                 SetConnected();
01139                                 if (GetOutputLength())
01140                                 {
01141                                         OnWrite();
01142                                 }
01143                         }
01144                         OnAccept();
01145                         Handler().LogError(this, "SSLNegotiate/SSL_accept", 0, "Connection established", LOG_LEVEL_INFO);
01146                         return true;
01147                 }
01148                 else
01149                 if (!r)
01150                 {
01151                         Handler().LogError(this, "SSLNegotiate/SSL_accept", 0, "Connection failed", LOG_LEVEL_INFO);
01152                         SetSSLNegotiate(false);
01153                         SetCloseAndDelete();
01154                         OnSSLAcceptFailed();
01155                 }
01156                 else
01157                 {
01158                         r = SSL_get_error(m_ssl, r);
01159                         if (r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
01160                         {
01161                                 Handler().LogError(this, "SSLNegotiate/SSL_accept", -1, "Connection failed", LOG_LEVEL_INFO);
01162 DEB(                            fprintf(stderr, "SSL_accept() failed - closing socket, return code: %d\n",r);)
01163                                 SetSSLNegotiate(false);
01164                                 SetCloseAndDelete(true);
01165                                 OnSSLAcceptFailed();
01166                         }
01167                 }
01168         }
01169         return false;
01170 }

const std::string & TcpSocket::GetPassword (  )  [protected]

SSL; Get ssl password.

Definition at line 1350 of file TcpSocket.cpp.

References m_password.

Referenced by SSL_password_cb().

01351 {
01352         return m_password;
01353 }

TcpSocket& TcpSocket::operator= ( const TcpSocket  )  [inline, private]

Definition at line 215 of file TcpSocket.h.

00215 { return *this; }


Member Data Documentation

Circular input buffer.

Definition at line 211 of file TcpSocket.h.

Referenced by GetInputLength(), OnRead(), and OnSocks4Read().

Circular output buffer.

Definition at line 212 of file TcpSocket.h.

Referenced by GetOutputLength(), OnWrite(), and SendBuf().

Definition at line 216 of file TcpSocket.h.

Referenced by DisableInputBuffer(), and OnRead().

uint64_t TcpSocket::m_bytes_sent [private]

Definition at line 217 of file TcpSocket.h.

Referenced by GetBytesSent(), and OnWrite().

uint64_t TcpSocket::m_bytes_received [private]

Definition at line 218 of file TcpSocket.h.

Referenced by GetBytesReceived(), and OnRead().

bool TcpSocket::m_skip_c [private]

Skip second char of CRLF or LFCR sequence in OnRead.

Definition at line 219 of file TcpSocket.h.

Referenced by OnRead().

char TcpSocket::m_c [private]

First char in CRLF or LFCR sequence.

Definition at line 220 of file TcpSocket.h.

Referenced by OnRead().

std::string TcpSocket::m_line [private]

Current line in line protocol mode.

Reimplemented in HTTPSocket.

Definition at line 221 of file TcpSocket.h.

Referenced by OnRead().

overflow protection, dynamic output buffer

Definition at line 222 of file TcpSocket.h.

Referenced by OnWrite(), SendBuf(), and ~TcpSocket().

char* TcpSocket::m_buf [private]

temporary read buffer

Definition at line 224 of file TcpSocket.h.

Referenced by OnRead(), and ~TcpSocket().

Definition at line 228 of file TcpSocket.h.

SSL_CTX* TcpSocket::m_ssl_ctx [private]

ssl context

Definition at line 229 of file TcpSocket.h.

Referenced by GetSslContext(), InitializeContext(), OnSSLAccept(), and OnSSLConnect().

SSL* TcpSocket::m_ssl [private]

ssl 'socket'

Definition at line 230 of file TcpSocket.h.

Referenced by Close(), GetSsl(), OnRead(), OnSSLAccept(), OnSSLConnect(), OnWrite(), SSLNegotiate(), and ~TcpSocket().

BIO* TcpSocket::m_sbio [private]

ssl bio

Definition at line 231 of file TcpSocket.h.

Referenced by OnSSLAccept(), and OnSSLConnect().

std::string TcpSocket::m_password [private]

ssl password

Definition at line 232 of file TcpSocket.h.

Referenced by GetPassword(), and InitializeContext().

socks4 support

Definition at line 236 of file TcpSocket.h.

Referenced by OnSocks4Connect(), and OnSocks4Read().

char TcpSocket::m_socks4_vn [private]

socks4 support, temporary variable

Definition at line 237 of file TcpSocket.h.

Referenced by OnSocks4Read().

char TcpSocket::m_socks4_cd [private]

socks4 support, temporary variable

Definition at line 238 of file TcpSocket.h.

Referenced by OnSocks4Read().

unsigned short TcpSocket::m_socks4_dstport [private]

socks4 support

Definition at line 239 of file TcpSocket.h.

Referenced by OnSocks4Read().

unsigned long TcpSocket::m_socks4_dstip [private]

socks4 support

Definition at line 240 of file TcpSocket.h.

Referenced by OnSocks4Read().

int TcpSocket::m_resolver_id [private]

Resolver id (if any) for current Open call.

Definition at line 244 of file TcpSocket.h.

Referenced by OnResolved(), and Open().

bool TcpSocket::m_b_reconnect [private]

Reconnect on lost connection flag.

Definition at line 248 of file TcpSocket.h.

Referenced by Reconnect(), and SetReconnect().

Trying to reconnect.

Definition at line 249 of file TcpSocket.h.

Referenced by IsReconnect(), and SetIsReconnect().


The documentation for this class was generated from the following files:
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4