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.
void OnConnectTimeout ()
 Connect timeout callback.
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.
virtual void OnWriteComplete ()
 Called when output buffer has been sent.
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 client socket is created, to set socket options.
void SetLineProtocol (bool=true)
 Enable the OnLine callback.
bool SetTcpNodelay (bool=true)
virtual int Protocol ()
 Returns IPPROTO_TCP or IPPROTO_SCTP.
void SetTransferLimit (size_t sz)
 Trigger limit for callback OnTransferLimit.
virtual void OnTransferLimit ()
 This callback fires when the output buffer drops below the value set by SetTransferLimit.

Protected Types

typedef std::list< OUTPUT * > output_l

Protected Member Functions

 TcpSocket (const TcpSocket &)
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.

Private Member Functions

TcpSocketoperator= (const TcpSocket &)
int TryWrite (const char *buf, size_t len)
 the actual send()
void Buffer (const char *buf, size_t len)
 add data to output buffer top

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.
char * m_buf
 temporary read buffer
output_l m_obuf
 output buffer
OUTPUTm_obuf_top
 output buffer on top
size_t m_transfer_limit
size_t m_output_length
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

class  CircularBuffer
 Buffer class containing one read/write circular buffer. More...
struct  OUTPUT
 Output buffer struct. More...

Detailed Description

Socket implementation for TCP.

Definition at line 53 of file TcpSocket.h.


Member Typedef Documentation

typedef std::list<OUTPUT *> TcpSocket::output_l [protected]

Definition at line 127 of file TcpSocket.h.


Constructor & Destructor Documentation

TcpSocket::TcpSocket ( ISocketHandler  ) 

Constructor with standard values on input/output buffers.

Definition at line 74 of file TcpSocket.cpp.

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

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 111 of file TcpSocket.cpp.

00111                                                                 : StreamSocket(h)
00112 ,ibuf(isize)
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 ,m_obuf_top(NULL)
00121 ,m_transfer_limit(0)
00122 ,m_output_length(0)
00123 #ifdef HAVE_OPENSSL
00124 ,m_ssl_ctx(NULL)
00125 ,m_ssl(NULL)
00126 ,m_sbio(NULL)
00127 #endif
00128 #ifdef ENABLE_SOCKS4
00129 ,m_socks4_state(0)
00130 #endif
00131 #ifdef ENABLE_RESOLVER
00132 ,m_resolver_id(0)
00133 #endif
00134 #ifdef ENABLE_RECONNECT
00135 ,m_b_reconnect(false)
00136 ,m_b_is_reconnect(false)
00137 #endif
00138 {
00139 }

TcpSocket::~TcpSocket (  ) 

Definition at line 145 of file TcpSocket.cpp.

References m_buf, and m_ssl.

00146 {
00147 #ifdef SOCKETS_DYNAMIC_TEMP
00148         delete[] m_buf;
00149 #endif
00150         // %! empty m_obuf
00151 #ifdef HAVE_OPENSSL
00152         if (m_ssl)
00153         {
00154                 SSL_free(m_ssl);
00155         }
00156 #endif
00157 }

TcpSocket::TcpSocket ( const TcpSocket  )  [protected]

Definition at line 876 of file TcpSocket.cpp.

00877 :StreamSocket(s)
00878 ,ibuf(0)
00879 {
00880 }


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 160 of file TcpSocket.cpp.

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

00161 {
00162         Ipv4Address ad(ip, port);
00163         Ipv4Address local;
00164         return Open(ad, local, skip_socks);
00165 }

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

Definition at line 179 of file TcpSocket.cpp.

References Open().

00180 {
00181         Ipv4Address bind_ad("0.0.0.0", 0);
00182         return Open(ad, bind_ad, skip_socks);
00183 }

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

Connecting();

Definition at line 186 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(), StreamSocket::SetCallOnConnect(), Socket::SetClientRemoteAddress(), Socket::SetCloseAndDelete(), StreamSocket::SetConnecting(), Socket::SetIsClient(), Socket::SetNonblocking(), Socket::SetRemoteAddress(), Socket::SetSocks4(), Socket::Socks4(), and StrError.

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

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

Open connection.

Parameters:
host Hostname
port Port number

Definition at line 312 of file TcpSocket.cpp.

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

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

void TcpSocket::OnConnectTimeout (  )  [virtual]

Connect timeout callback.

Todo:
state reason why connect failed

Todo:
state reason why connect failed

Reimplemented from Socket.

Definition at line 1587 of file TcpSocket.cpp.

References StreamSocket::GetConnectionRetries(), StreamSocket::GetConnectionRetry(), Socket::Handler(), StreamSocket::IncreaseConnectionRetries(), LOG_LEVEL_FATAL, ISocketHandler::LogError(), Socket::OnConnectFailed(), Socket::OnConnectRetry(), OnSocks4ConnectFailed(), Socket::SetCloseAndDelete(), StreamSocket::SetConnecting(), StreamSocket::SetRetryClientConnect(), and Socket::Socks4().

01588 {
01589         Handler().LogError(this, "connect", -1, "connect timeout", LOG_LEVEL_FATAL);
01590 #ifdef ENABLE_SOCKS4
01591         if (Socks4())
01592         {
01593                 OnSocks4ConnectFailed();
01594                 // retry direct connection
01595         }
01596         else
01597 #endif
01598         if (GetConnectionRetry() == -1 ||
01599                 (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
01600         {
01601                 IncreaseConnectionRetries();
01602                 // ask socket via OnConnectRetry callback if we should continue trying
01603                 if (OnConnectRetry())
01604                 {
01605                         SetRetryClientConnect();
01606                 }
01607                 else
01608                 {
01609                         SetCloseAndDelete( true );
01611                         OnConnectFailed();
01612                 }
01613         }
01614         else
01615         {
01616                 SetCloseAndDelete(true);
01618                 OnConnectFailed();
01619         }
01620         //
01621         SetConnecting(false);
01622 }

int TcpSocket::Close (  )  [virtual]

Close file descriptor - internal use only.

See also:
SetCloseAndDelete

Reimplemented from Socket.

Definition at line 1273 of file TcpSocket.cpp.

References Socket::Close(), Errno, StreamSocket::GetShutdown(), Socket::GetSocket(), Socket::Handler(), INVALID_SOCKET, Socket::IsConnected(), Socket::IsSSL(), LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, ISocketHandler::LogError(), m_ssl, Socket::SetNonblocking(), and StrError.

01274 {
01275         if (GetSocket() == INVALID_SOCKET) // this could happen
01276         {
01277                 Handler().LogError(this, "Socket::Close", 0, "file descriptor invalid", LOG_LEVEL_WARNING);
01278                 return 0;
01279         }
01280         int n;
01281         SetNonblocking(true);
01282         if (IsConnected() && !(GetShutdown() & SHUT_WR))
01283         {
01284                 if (shutdown(GetSocket(), SHUT_WR) == -1)
01285                 {
01286                         // failed...
01287                         Handler().LogError(this, "shutdown", Errno, StrError(Errno), LOG_LEVEL_ERROR);
01288                 }
01289         }
01290         //
01291         char tmp[1000];
01292         if ((n = recv(GetSocket(),tmp,1000,0)) >= 0)
01293         {
01294                 if (n)
01295                 {
01296                         Handler().LogError(this, "read() after shutdown", n, "bytes read", LOG_LEVEL_WARNING);
01297                 }
01298         }
01299 #ifdef HAVE_OPENSSL
01300         if (IsSSL() && m_ssl)
01301                 SSL_shutdown(m_ssl);
01302         if (m_ssl)
01303         {
01304                 SSL_free(m_ssl);
01305                 m_ssl = NULL;
01306         }
01307 #endif
01308         return Socket::Close();
01309 }

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 997 of file TcpSocket.cpp.

References Send().

00998 {
00999         va_list ap;
01000         va_start(ap, format);
01001         char slask[5000]; // vsprintf / vsnprintf temporary
01002 #ifdef _WIN32
01003         vsprintf(slask, format, ap);
01004 #else
01005         vsnprintf(slask, 5000, format, ap);
01006 #endif
01007         va_end(ap);
01008         Send( slask );
01009 }

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

Reimplemented from Socket.

Definition at line 817 of file TcpSocket.cpp.

References Buffer(), Socket::CloseAndDelete(), StreamSocket::Connecting(), ISocketHandler::Get(), Socket::GetSocket(), Socket::Handler(), INVALID_SOCKET, Socket::IsConnected(), LOG_LEVEL_INFO, ISocketHandler::LogError(), m_obuf, m_obuf_top, StreamSocket::Ready(), Socket::Set(), and TryWrite().

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

00818 {
00819         if (!Ready() && !Connecting())
00820         {
00821                 Handler().LogError(this, "SendBuf", -1, "Attempt to write to a non-ready socket" ); // warning
00822                 if (GetSocket() == INVALID_SOCKET)
00823                         Handler().LogError(this, "SendBuf", 0, " * GetSocket() == INVALID_SOCKET", LOG_LEVEL_INFO);
00824                 if (Connecting())
00825                         Handler().LogError(this, "SendBuf", 0, " * Connecting()", LOG_LEVEL_INFO);
00826                 if (CloseAndDelete())
00827                         Handler().LogError(this, "SendBuf", 0, " * CloseAndDelete()", LOG_LEVEL_INFO);
00828                 return;
00829         }
00830         if (!IsConnected())
00831         {
00832                 Handler().LogError(this, "SendBuf", -1, "Attempt to write to a non-connected socket, will be sent on connect" ); // warning
00833                 Buffer(buf, len);
00834                 return;
00835         }
00836         if (m_obuf_top)
00837         {
00838                 Buffer(buf, len);
00839                 return;
00840         }
00841         int n = TryWrite(buf, len);
00842         if (n > 0 && n < (int)len)
00843         {
00844                 Buffer(buf + n, len - n);
00845         }
00846         // if ( data in buffer || !IsConnected )
00847         // {
00848         //   add to buffer
00849         // }
00850         // else
00851         // try_send
00852         // if any data is unsent, buffer it and set m_wfds
00853 
00854         // check output buffer set, set/reset m_wfds accordingly
00855         {
00856                 bool br;
00857                 bool bw;
00858                 bool bx;
00859                 Handler().Get(GetSocket(), br, bw, bx);
00860                 if (m_obuf.size())
00861                         Set(br, true);
00862                 else
00863                         Set(br, false);
00864         }
00865 }

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 1337 of file TcpSocket.cpp.

Referenced by OnRead().

01338 {
01339 }

void TcpSocket::OnWriteComplete (  )  [virtual]

Called when output buffer has been sent.

Definition at line 611 of file TcpSocket.cpp.

Referenced by OnWrite().

00612 {
00613 }

size_t TcpSocket::GetInputLength (  ) 

Number of bytes in input buffer.

Definition at line 1342 of file TcpSocket.cpp.

References TcpSocket::CircularBuffer::GetLength(), and ibuf.

Referenced by OnRead(), and OnSocks4Read().

01343 {
01344         return ibuf.GetLength();
01345 }

size_t TcpSocket::GetOutputLength (  ) 

Number of bytes in output buffer.

Definition at line 1348 of file TcpSocket.cpp.

References m_output_length.

Referenced by OnWrite(), and SSLNegotiate().

01349 {
01350         return m_output_length;
01351 /*
01352         size_t len = 0;
01353         for (output_l::iterator it = m_obuf.begin(); it != m_obuf.end(); it++)
01354                 len += (*it) -> Len();
01355         return len;
01356 */
01357 }

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, ResolvSocket, and SmtpdSocket.

Definition at line 868 of file TcpSocket.cpp.

Referenced by OnRead().

00869 {
00870 }

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

Get counter of number of bytes received.

Reimplemented from Socket.

Definition at line 1360 of file TcpSocket.cpp.

References m_bytes_received.

01361 {
01362         uint64_t z = m_bytes_received;
01363         if (clear)
01364                 m_bytes_received = 0;
01365         return z;
01366 }

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

Get counter of number of bytes sent.

Reimplemented from Socket.

Definition at line 1369 of file TcpSocket.cpp.

References m_bytes_sent.

01370 {
01371         uint64_t z = m_bytes_sent;
01372         if (clear)
01373                 m_bytes_sent = 0;
01374         return z;
01375 }

void TcpSocket::OnSocks4Connect (  )  [virtual]

Socks4 specific callback.

Todo:
warn

Todo:
warn

Reimplemented from Socket.

Definition at line 887 of file TcpSocket.cpp.

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

00888 {
00889         char request[1000];
00890         memset(request, 0, sizeof(request));
00891         request[0] = 4; // socks v4
00892         request[1] = 1; // command code: CONNECT
00893         {
00894                 std::auto_ptr<SocketAddress> ad = GetClientRemoteAddress();
00895                 if (ad.get())
00896                 {
00897                         struct sockaddr *p0 = (struct sockaddr *)*ad;
00898                         struct sockaddr_in *p = (struct sockaddr_in *)p0;
00899                         if (p -> sin_family == AF_INET)
00900                         {
00901                                 memcpy(request + 2, &p -> sin_port, 2); // nwbo is ok here
00902                                 memcpy(request + 4, &p -> sin_addr, sizeof(struct in_addr));
00903                         }
00904                         else
00905                         {
00907                         }
00908                 }
00909                 else
00910                 {
00912                 }
00913         }
00914         strcpy(request + 8, GetSocks4Userid().c_str());
00915         size_t length = GetSocks4Userid().size() + 8 + 1;
00916         SendBuf(request, length);
00917         m_socks4_state = 0;
00918 }

void TcpSocket::OnSocks4ConnectFailed (  )  [virtual]

Socks4 specific callback.

Reimplemented from Socket.

Definition at line 921 of file TcpSocket.cpp.

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

Referenced by OnConnectTimeout(), and OnWrite().

00922 {
00923         Handler().LogError(this,"OnSocks4ConnectFailed",0,"connection to socks4 server failed, trying direct connection",LOG_LEVEL_WARNING);
00924         if (!Handler().Socks4TryDirect())
00925         {
00926                 SetConnecting(false);
00927                 SetCloseAndDelete();
00928                 OnConnectFailed(); // just in case
00929         }
00930         else
00931         {
00932                 SetRetryClientConnect();
00933         }
00934 }

bool TcpSocket::OnSocks4Read (  )  [virtual]

Socks4 specific callback.

Returns:
'need_more'

Reimplemented from Socket.

Definition at line 937 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(), TcpSocket::CircularBuffer::Read(), Socket::SetCloseAndDelete(), StreamSocket::SetConnecting(), and Socket::SetSocks4().

Referenced by OnRead().

00938 {
00939         switch (m_socks4_state)
00940         {
00941         case 0:
00942                 ibuf.Read(&m_socks4_vn, 1);
00943                 m_socks4_state = 1;
00944                 break;
00945         case 1:
00946                 ibuf.Read(&m_socks4_cd, 1);
00947                 m_socks4_state = 2;
00948                 break;
00949         case 2:
00950                 if (GetInputLength() > 1)
00951                 {
00952                         ibuf.Read( (char *)&m_socks4_dstport, 2);
00953                         m_socks4_state = 3;
00954                 }
00955                 else
00956                 {
00957                         return true;
00958                 }
00959                 break;
00960         case 3:
00961                 if (GetInputLength() > 3)
00962                 {
00963                         ibuf.Read( (char *)&m_socks4_dstip, 4);
00964                         SetSocks4(false);
00965                         
00966                         switch (m_socks4_cd)
00967                         {
00968                         case 90:
00969                                 OnConnect();
00970                                 Handler().LogError(this, "OnSocks4Read", 0, "Connection established", LOG_LEVEL_INFO);
00971                                 break;
00972                         case 91:
00973                         case 92:
00974                         case 93:
00975                                 Handler().LogError(this,"OnSocks4Read",m_socks4_cd,"socks4 server reports connect failed",LOG_LEVEL_FATAL);
00976                                 SetConnecting(false);
00977                                 SetCloseAndDelete();
00978                                 OnConnectFailed();
00979                                 break;
00980                         default:
00981                                 Handler().LogError(this,"OnSocks4Read",m_socks4_cd,"socks4 server unrecognized response",LOG_LEVEL_FATAL);
00982                                 SetCloseAndDelete();
00983                                 break;
00984                         }
00985                 }
00986                 else
00987                 {
00988                         return true;
00989                 }
00990                 break;
00991         }
00992         return false;
00993 }

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 362 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().

00363 {
00364         if (id == m_resolver_id)
00365         {
00366                 if (a && port)
00367                 {
00368                         Ipv4Address ad(a, port);
00369                         Ipv4Address local;
00370                         if (Open(ad, local))
00371                         {
00372                                 if (!Handler().Valid(this))
00373                                 {
00374                                         Handler().Add(this);
00375                                 }
00376                         }
00377                 }
00378                 else
00379                 {
00380                         Handler().LogError(this, "OnResolved", 0, "Resolver failed", LOG_LEVEL_FATAL);
00381                         SetCloseAndDelete();
00382                 }
00383         }
00384         else
00385         {
00386                 Handler().LogError(this, "OnResolved", id, "Resolver returned wrong job id", LOG_LEVEL_FATAL);
00387                 SetCloseAndDelete();
00388         }
00389 }

void TcpSocket::OnSSLConnect (  )  [virtual]

Callback for 'New' ssl support - replaces SSLSocket.

Internal use.

Reimplemented from Socket.

Definition at line 1013 of file TcpSocket.cpp.

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

01014 {
01015         SetNonblocking(true);
01016         {
01017                 if (m_ssl_ctx)
01018                 {
01019 DEB(                    fprintf(stderr, "SSL Context already initialized - closing socket\n");)
01020                         SetCloseAndDelete(true);
01021                         return;
01022                 }
01023                 InitSSLClient();
01024         }
01025         if (m_ssl_ctx)
01026         {
01027                 /* Connect the SSL socket */
01028                 m_ssl = SSL_new(m_ssl_ctx);
01029                 if (!m_ssl)
01030                 {
01031 DEB(                    fprintf(stderr, " m_ssl is NULL\n");)
01032                         SetCloseAndDelete(true);
01033                         return;
01034                 }
01035                 SSL_set_mode(m_ssl, SSL_MODE_AUTO_RETRY);
01036                 m_sbio = BIO_new_socket((int)GetSocket(), BIO_NOCLOSE);
01037                 if (!m_sbio)
01038                 {
01039 DEB(                    fprintf(stderr, " m_sbio is NULL\n");)
01040                         SetCloseAndDelete(true);
01041                         return;
01042                 }
01043                 SSL_set_bio(m_ssl, m_sbio, m_sbio);
01044 //              if (!SSLNegotiate())
01045                 {
01046                         SetSSLNegotiate();
01047                 }
01048         }
01049         else
01050         {
01051                 SetCloseAndDelete();
01052         }
01053 }

void TcpSocket::OnSSLAccept (  )  [virtual]

Callback for 'New' ssl support - replaces SSLSocket.

Internal use.

Reimplemented from Socket.

Definition at line 1056 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().

01057 {
01058         SetNonblocking(true);
01059         {
01060                 if (m_ssl_ctx)
01061                 {
01062 DEB(                    fprintf(stderr, "SSL Context already initialized - closing socket\n");)
01063                         SetCloseAndDelete(true);
01064                         return;
01065                 }
01066                 InitSSLServer();
01067                 SetSSLServer();
01068         }
01069         if (m_ssl_ctx)
01070         {
01071                 m_ssl = SSL_new(m_ssl_ctx);
01072                 if (!m_ssl)
01073                 {
01074 DEB(                    fprintf(stderr, " m_ssl is NULL\n");)
01075                         SetCloseAndDelete(true);
01076                         return;
01077                 }
01078                 SSL_set_mode(m_ssl, SSL_MODE_AUTO_RETRY);
01079                 m_sbio = BIO_new_socket((int)GetSocket(), BIO_NOCLOSE);
01080                 if (!m_sbio)
01081                 {
01082 DEB(                    fprintf(stderr, " m_sbio is NULL\n");)
01083                         SetCloseAndDelete(true);
01084                         return;
01085                 }
01086                 SSL_set_bio(m_ssl, m_sbio, m_sbio);
01087 //              if (!SSLNegotiate())
01088                 {
01089                         SetSSLNegotiate();
01090                 }
01091         }
01092 }

void TcpSocket::InitSSLClient (  )  [virtual]

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

Definition at line 1192 of file TcpSocket.cpp.

References InitializeContext().

Referenced by OnSSLConnect().

01193 {
01194         InitializeContext("", SSLv23_method());
01195 }

void TcpSocket::InitSSLServer (  )  [virtual]

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

Definition at line 1198 of file TcpSocket.cpp.

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

Referenced by OnSSLAccept().

01199 {
01200         Handler().LogError(this, "InitSSLServer", 0, "You MUST implement your own InitSSLServer method", LOG_LEVEL_FATAL);
01201         SetCloseAndDelete();
01202 }

void TcpSocket::SetReconnect ( bool  = true  ) 

Flag that says a broken connection will try to reconnect.

Definition at line 1330 of file TcpSocket.cpp.

References m_b_reconnect.

01331 {
01332         m_b_reconnect = x;
01333 }

bool TcpSocket::Reconnect (  ) 

Check reconnect on lost connection flag status.

Definition at line 1379 of file TcpSocket.cpp.

References m_b_reconnect.

Referenced by Open().

01380 {
01381         return m_b_reconnect;
01382 }

void TcpSocket::SetIsReconnect ( bool  x = true  ) 

Flag to determine if a reconnect is in progress.

Definition at line 1385 of file TcpSocket.cpp.

References m_b_is_reconnect.

01386 {
01387         m_b_is_reconnect = x;
01388 }

bool TcpSocket::IsReconnect (  ) 

Socket is reconnecting.

Definition at line 1391 of file TcpSocket.cpp.

References m_b_is_reconnect.

Referenced by SSLNegotiate().

01392 {
01393         return m_b_is_reconnect;
01394 }

void TcpSocket::DisableInputBuffer ( bool  = true  ) 

Definition at line 1406 of file TcpSocket.cpp.

References m_b_input_buffer_disabled.

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

01407 {
01408         m_b_input_buffer_disabled = x;
01409 }

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

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

Parameters:
family AF_INET, AF_INET6, etc
type SOCK_STREAM, SOCK_DGRAM, etc
protocol Protocol number (tcp, udp, sctp, etc)
s Socket file descriptor

Implements Socket.

Definition at line 1412 of file TcpSocket.cpp.

References DEB, Socket::SetSoKeepalive(), and Socket::SetSoReuseaddr().

01413 {
01414 DEB(    fprintf(stderr, "Socket::OnOptions()\n");)
01415 #ifdef SO_NOSIGPIPE
01416         SetSoNosigpipe(true);
01417 #endif
01418         SetSoReuseaddr(true);
01419         SetSoKeepalive(true);
01420 }

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

Enable the OnLine callback.

Do not create your own OnRead callback when using this.

Reimplemented from StreamSocket.

Definition at line 1423 of file TcpSocket.cpp.

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

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

01424 {
01425         StreamSocket::SetLineProtocol(x);
01426         DisableInputBuffer(x);
01427 }

bool TcpSocket::SetTcpNodelay ( bool  = true  ) 

Definition at line 1430 of file TcpSocket.cpp.

References Errno, Socket::GetSocket(), Socket::Handler(), LOG_LEVEL_FATAL, LOG_LEVEL_INFO, ISocketHandler::LogError(), and StrError.

01431 {
01432 #ifdef TCP_NODELAY
01433         int optval = x ? 1 : 0;
01434         if (setsockopt(GetSocket(), IPPROTO_TCP, TCP_NODELAY, (char *)&optval, sizeof(optval)) == -1)
01435         {
01436                 Handler().LogError(this, "setsockopt(IPPROTO_TCP, TCP_NODELAY)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
01437                 return false;
01438         }
01439         return true;
01440 #else
01441         Handler().LogError(this, "socket option not available", 0, "TCP_NODELAY", LOG_LEVEL_INFO);
01442         return false;
01443 #endif
01444 }

int TcpSocket::Protocol (  )  [virtual]

Returns IPPROTO_TCP or IPPROTO_SCTP.

Implements StreamSocket.

Definition at line 1661 of file TcpSocket.cpp.

01662 {
01663         return IPPROTO_TCP;
01664 }

void TcpSocket::SetTransferLimit ( size_t  sz  ) 

Trigger limit for callback OnTransferLimit.

Definition at line 1667 of file TcpSocket.cpp.

References m_transfer_limit.

01668 {
01669         m_transfer_limit = sz;
01670 }

void TcpSocket::OnTransferLimit (  )  [virtual]

This callback fires when the output buffer drops below the value set by SetTransferLimit.

Default: 0 (disabled).

Definition at line 1673 of file TcpSocket.cpp.

Referenced by OnWrite().

01674 {
01675 }

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

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

Reimplemented from Socket.

Definition at line 420 of file TcpSocket.cpp.

References Socket::CloseAndDelete(), DEB, Errno, GetInputLength(), Socket::GetSocket(), Socket::GetTrafficMonitor(), Socket::Handler(), ibuf, Socket::IsSSL(), StreamSocket::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, Socket::OnDisconnect(), OnLine(), OnRawData(), OnSocks4Read(), StreamSocket::Ready(), Socket::SetCloseAndDelete(), StreamSocket::SetFlushBeforeClose(), Socket::SetLost(), StreamSocket::SetShutdown(), Socket::Socks4(), StrError, TCP_BUFSIZE_READ, and TcpSocket::CircularBuffer::Write().

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

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

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

Reimplemented from Socket.

Definition at line 616 of file TcpSocket.cpp.

References StreamSocket::Connecting(), ISocketHandler::Get(), StreamSocket::GetConnectionRetries(), StreamSocket::GetConnectionRetry(), GetOutputLength(), Socket::GetSocket(), Socket::Handler(), Socket::IsDisableRead(), LOG_LEVEL_FATAL, ISocketHandler::LogError(), m_obuf, m_obuf_top, m_output_length, m_transfer_limit, Socket::OnConnectFailed(), OnSocks4ConnectFailed(), OnTransferLimit(), OnWriteComplete(), Socket::Set(), StreamSocket::SetCallOnConnect(), Socket::SetCloseAndDelete(), StreamSocket::SetConnecting(), Socket::Socks4(), Socket::SoError(), StrError, and TryWrite().

Referenced by SSLNegotiate().

00617 {
00618         if (Connecting())
00619         {
00620                 int err = SoError();
00621 
00622                 // don't reset connecting flag on error here, we want the OnConnectFailed timeout later on
00623                 if (!err) // ok
00624                 {
00625                         Set(!IsDisableRead(), false);
00626                         SetConnecting(false);
00627                         SetCallOnConnect();
00628                         return;
00629                 }
00630                 Handler().LogError(this, "tcp: connect failed", err, StrError(err), LOG_LEVEL_FATAL);
00631                 Set(false, false); // no more monitoring because connection failed
00632 
00633                 // failed
00634 #ifdef ENABLE_SOCKS4
00635                 if (Socks4())
00636                 {
00637                         // %! leave 'Connecting' flag set?
00638                         OnSocks4ConnectFailed();
00639                         return;
00640                 }
00641 #endif
00642                 if (GetConnectionRetry() == -1 ||
00643                         (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
00644                 {
00645                         // even though the connection failed at once, only retry after
00646                         // the connection timeout.
00647                         // should we even try to connect again, when CheckConnect returns
00648                         // false it's because of a connection error - not a timeout...
00649                         return;
00650                 }
00651                 SetConnecting(false);
00652                 SetCloseAndDelete( true );
00654                 OnConnectFailed();
00655                 return;
00656         }
00657         // try send next block in buffer
00658         // if full block is sent, repeat
00659         // if all blocks are sent, reset m_wfds
00660 
00661         bool repeat = false;
00662         size_t sz = m_transfer_limit ? GetOutputLength() : 0;
00663         do
00664         {
00665                 output_l::iterator it = m_obuf.begin();
00666                 OUTPUT *p = *it;
00667                 repeat = false;
00668                 int n = TryWrite(p -> Buf(), p -> Len());
00669                 if (n > 0)
00670                 {
00671                         size_t left = p -> Remove(n);
00672                         m_output_length -= n;
00673                         if (!left)
00674                         {
00675                                 delete p;
00676                                 m_obuf.erase(it);
00677                                 if (!m_obuf.size())
00678                                 {
00679                                         m_obuf_top = NULL;
00680                                         OnWriteComplete();
00681                                 }
00682                                 else
00683                                 {
00684                                         repeat = true;
00685                                 }
00686                         }
00687                 }
00688         } while (repeat);
00689 
00690         if (m_transfer_limit && sz > m_transfer_limit && GetOutputLength() < m_transfer_limit)
00691         {
00692                 OnTransferLimit();
00693         }
00694 
00695         // check output buffer set, set/reset m_wfds accordingly
00696         {
00697                 bool br;
00698                 bool bw;
00699                 bool bx;
00700                 Handler().Get(GetSocket(), br, bw, bx);
00701                 if (m_obuf.size())
00702                         Set(br, true);
00703                 else
00704                         Set(br, false);
00705         }
00706 }

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 1205 of file TcpSocket.cpp.

References m_ssl_ctx.

Referenced by InitSSLClient().

01206 {
01207         /* Create our context*/
01208         static std::map<std::string, SSL_CTX *> client_contexts;
01209         if (client_contexts.find(context) == client_contexts.end())
01210         {
01211                 SSL_METHOD *meth = meth_in ? meth_in : SSLv3_method();
01212                 m_ssl_ctx = client_contexts[context] = SSL_CTX_new(meth);
01213                 SSL_CTX_set_mode(m_ssl_ctx, SSL_MODE_AUTO_RETRY);
01214         }
01215         else
01216         {
01217                 m_ssl_ctx = client_contexts[context];
01218         }
01219 }

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 1222 of file TcpSocket.cpp.

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

01223 {
01224         /* Create our context*/
01225         static std::map<std::string, SSL_CTX *> server_contexts;
01226         if (server_contexts.find(context) == server_contexts.end())
01227         {
01228                 SSL_METHOD *meth = meth_in ? meth_in : SSLv3_method();
01229                 m_ssl_ctx = server_contexts[context] = SSL_CTX_new(meth);
01230                 SSL_CTX_set_mode(m_ssl_ctx, SSL_MODE_AUTO_RETRY);
01231                 // session id
01232                 if (context.size())
01233                         SSL_CTX_set_session_id_context(m_ssl_ctx, (const unsigned char *)context.c_str(), (unsigned int)context.size());
01234                 else
01235                         SSL_CTX_set_session_id_context(m_ssl_ctx, (const unsigned char *)"--empty--", 9);
01236         }
01237         else
01238         {
01239                 m_ssl_ctx = server_contexts[context];
01240         }
01241 
01242         /* Load our keys and certificates*/
01243         if (!(SSL_CTX_use_certificate_file(m_ssl_ctx, keyfile.c_str(), SSL_FILETYPE_PEM)))
01244         {
01245                 Handler().LogError(this, "TcpSocket InitializeContext", 0, "Couldn't read certificate file " + keyfile, LOG_LEVEL_FATAL);
01246         }
01247 
01248         m_password = password;
01249         SSL_CTX_set_default_passwd_cb(m_ssl_ctx, SSL_password_cb);
01250         SSL_CTX_set_default_passwd_cb_userdata(m_ssl_ctx, this);
01251         if (!(SSL_CTX_use_PrivateKey_file(m_ssl_ctx, keyfile.c_str(), SSL_FILETYPE_PEM)))
01252         {
01253                 Handler().LogError(this, "TcpSocket InitializeContext", 0, "Couldn't read private key file " + keyfile, LOG_LEVEL_FATAL);
01254         }
01255 }

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

SSL; Password callback method.

Definition at line 1258 of file TcpSocket.cpp.

References GetPassword().

Referenced by InitializeContext().

01259 {
01260         Socket *p0 = static_cast<Socket *>(userdata);
01261         TcpSocket *p = dynamic_cast<TcpSocket *>(p0);
01262         std::string pw = p ? p -> GetPassword() : "";
01263         if ( (size_t)num < pw.size() + 1)
01264         {
01265                 return 0;
01266         }
01267         strcpy(buf,pw.c_str());
01268         return (int)pw.size();
01269 }

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

SSL; Get pointer to ssl context structure.

Reimplemented from Socket.

Definition at line 1313 of file TcpSocket.cpp.

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

01314 {
01315         if (!m_ssl_ctx)
01316                 Handler().LogError(this, "GetSslContext", 0, "SSL Context is NULL; check InitSSLServer/InitSSLClient", LOG_LEVEL_WARNING);
01317         return m_ssl_ctx;
01318 }

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

SSL; Get pointer to ssl structure.

Reimplemented from Socket.

Definition at line 1320 of file TcpSocket.cpp.

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

01321 {
01322         if (!m_ssl)
01323                 Handler().LogError(this, "GetSsl", 0, "SSL is NULL; check InitSSLServer/InitSSLClient", LOG_LEVEL_WARNING);
01324         return m_ssl;
01325 }

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 1095 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().

01096 {
01097         if (!IsSSLServer()) // client
01098         {
01099                 int r = SSL_connect(m_ssl);
01100                 if (r > 0)
01101                 {
01102                         SetSSLNegotiate(false);
01104 //                      CheckCertificateChain( "");//ServerHOST);
01105                         SetNonblocking(false);
01106                         //
01107                         {
01108                                 SetConnected();
01109                                 if (GetOutputLength())
01110                                 {
01111                                         OnWrite();
01112                                 }
01113                         }
01114 #ifdef ENABLE_RECONNECT
01115                         if (IsReconnect())
01116                                 OnReconnect();
01117                         else
01118 #endif
01119                         {
01120                                 OnConnect();
01121                         }
01122                         Handler().LogError(this, "SSLNegotiate/SSL_connect", 0, "Connection established", LOG_LEVEL_INFO);
01123                         return true;
01124                 }
01125                 else
01126                 if (!r)
01127                 {
01128                         Handler().LogError(this, "SSLNegotiate/SSL_connect", 0, "Connection failed", LOG_LEVEL_INFO);
01129                         SetSSLNegotiate(false);
01130                         SetCloseAndDelete();
01131                         OnSSLConnectFailed();
01132                 }
01133                 else
01134                 {
01135                         r = SSL_get_error(m_ssl, r);
01136                         if (r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
01137                         {
01138                                 Handler().LogError(this, "SSLNegotiate/SSL_connect", -1, "Connection failed", LOG_LEVEL_INFO);
01139 DEB(                            fprintf(stderr, "SSL_connect() failed - closing socket, return code: %d\n",r);)
01140                                 SetSSLNegotiate(false);
01141                                 SetCloseAndDelete(true);
01142                                 OnSSLConnectFailed();
01143                         }
01144                 }
01145         }
01146         else // server
01147         {
01148                 int r = SSL_accept(m_ssl);
01149                 if (r > 0)
01150                 {
01151                         SetSSLNegotiate(false);
01153 //                      CheckCertificateChain( "");//ClientHOST);
01154                         SetNonblocking(false);
01155                         //
01156                         {
01157                                 SetConnected();
01158                                 if (GetOutputLength())
01159                                 {
01160                                         OnWrite();
01161                                 }
01162                         }
01163                         OnAccept();
01164                         Handler().LogError(this, "SSLNegotiate/SSL_accept", 0, "Connection established", LOG_LEVEL_INFO);
01165                         return true;
01166                 }
01167                 else
01168                 if (!r)
01169                 {
01170                         Handler().LogError(this, "SSLNegotiate/SSL_accept", 0, "Connection failed", LOG_LEVEL_INFO);
01171                         SetSSLNegotiate(false);
01172                         SetCloseAndDelete();
01173                         OnSSLAcceptFailed();
01174                 }
01175                 else
01176                 {
01177                         r = SSL_get_error(m_ssl, r);
01178                         if (r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
01179                         {
01180                                 Handler().LogError(this, "SSLNegotiate/SSL_accept", -1, "Connection failed", LOG_LEVEL_INFO);
01181 DEB(                            fprintf(stderr, "SSL_accept() failed - closing socket, return code: %d\n",r);)
01182                                 SetSSLNegotiate(false);
01183                                 SetCloseAndDelete(true);
01184                                 OnSSLAcceptFailed();
01185                         }
01186                 }
01187         }
01188         return false;
01189 }

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

SSL; Get ssl password.

Definition at line 1399 of file TcpSocket.cpp.

References m_password.

Referenced by SSL_password_cb().

01400 {
01401         return m_password;
01402 }

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

Definition at line 290 of file TcpSocket.h.

00290 { return *this; }

int TcpSocket::TryWrite ( const char *  buf,
size_t  len 
) [private]

the actual send()

Definition at line 709 of file TcpSocket.cpp.

References DEB, Errno, Socket::GetSocket(), Socket::GetTrafficMonitor(), Socket::Handler(), Socket::IsSSL(), LOG_LEVEL_FATAL, ISocketHandler::LogError(), m_bytes_sent, m_ssl, Socket::SetCloseAndDelete(), StreamSocket::SetFlushBeforeClose(), Socket::SetLost(), and StrError.

Referenced by OnWrite(), and SendBuf().

00710 {
00711         int n = 0;
00712 #ifdef HAVE_OPENSSL
00713         if (IsSSL())
00714         {
00715                 n = SSL_write(m_ssl, buf, len);
00716                 if (n == -1)
00717                 {
00718                         int errnr = SSL_get_error(m_ssl, n);
00719                         if ( errnr != SSL_ERROR_WANT_READ && errnr != SSL_ERROR_WANT_WRITE )
00720                         {
00721                                 SetCloseAndDelete(true);
00722                                 SetFlushBeforeClose(false);
00723 #ifdef ENABLE_POOL
00724                                 SetLost();
00725 #endif
00726                                 const char *errbuf = ERR_error_string(errnr, NULL);
00727                                 Handler().LogError(this, "OnWrite/SSL_write", errnr, errbuf, LOG_LEVEL_FATAL);
00728                         }
00729                 }
00730                 else
00731                 if (!n)
00732                 {
00733                         SetCloseAndDelete(true);
00734                         SetFlushBeforeClose(false);
00735 #ifdef ENABLE_POOL
00736                         SetLost();
00737 #endif
00738 DEB(                    int errnr = SSL_get_error(m_ssl, n);
00739                         const char *errbuf = ERR_error_string(errnr, NULL);
00740                         fprintf(stderr, "SSL_write() returns 0: %d : %s\n",errnr, errbuf);)
00741                 }
00742         }
00743         else
00744 #endif // HAVE_OPENSSL
00745         {
00746                 n = send(GetSocket(), buf, len, MSG_NOSIGNAL);
00747                 if (n == -1)
00748                 {
00749                 // normal error codes:
00750                 // WSAEWOULDBLOCK
00751                 //       EAGAIN or EWOULDBLOCK
00752 #ifdef _WIN32
00753                         if (Errno != WSAEWOULDBLOCK)
00754 #else
00755                         if (Errno != EWOULDBLOCK)
00756 #endif
00757                         {       
00758                                 Handler().LogError(this, "send", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00759                                 SetCloseAndDelete(true);
00760                                 SetFlushBeforeClose(false);
00761 #ifdef ENABLE_POOL
00762                                 SetLost();
00763 #endif
00764                         }
00765                 }
00766         }
00767         if (n > 0)
00768         {
00769                 m_bytes_sent += n;
00770                 if (GetTrafficMonitor())
00771                 {
00772                         GetTrafficMonitor() -> fwrite(buf, 1, n);
00773                 }
00774         }
00775         return n;
00776 }

void TcpSocket::Buffer ( const char *  buf,
size_t  len 
) [private]

add data to output buffer top

Definition at line 779 of file TcpSocket.cpp.

References m_obuf, m_obuf_top, and m_output_length.

Referenced by SendBuf().

00780 {
00781         size_t ptr = 0;
00782         m_output_length += len;
00783         while (ptr < len)
00784         {
00785                 // buf/len => pbuf/sz
00786                 size_t space = 0;
00787                 if (m_obuf_top && (space = m_obuf_top -> Space()) > 0)
00788                 {
00789                         const char *pbuf = buf + ptr;
00790                         size_t sz = len - ptr;
00791                         if (space >= sz)
00792                         {
00793                                 m_obuf_top -> Add(pbuf, sz);
00794                                 ptr += sz;
00795                         }
00796                         else
00797                         {
00798                                 m_obuf_top -> Add(pbuf, space);
00799                                 ptr += space;
00800                         }
00801                 }
00802                 else
00803                 {
00804                         m_obuf_top = new OUTPUT;
00805                         m_obuf.push_back( m_obuf_top );
00806                 }
00807         }
00808 }


Member Data Documentation

Circular input buffer.

Definition at line 287 of file TcpSocket.h.

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

Definition at line 298 of file TcpSocket.h.

Referenced by DisableInputBuffer(), and OnRead().

uint64_t TcpSocket::m_bytes_sent [private]

Definition at line 299 of file TcpSocket.h.

Referenced by GetBytesSent(), and TryWrite().

uint64_t TcpSocket::m_bytes_received [private]

Definition at line 300 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 301 of file TcpSocket.h.

Referenced by OnRead().

char TcpSocket::m_c [private]

First char in CRLF or LFCR sequence.

Definition at line 302 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 303 of file TcpSocket.h.

Referenced by OnRead().

char* TcpSocket::m_buf [private]

temporary read buffer

Definition at line 305 of file TcpSocket.h.

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

output buffer

Definition at line 307 of file TcpSocket.h.

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

output buffer on top

Definition at line 308 of file TcpSocket.h.

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

size_t TcpSocket::m_transfer_limit [private]

Definition at line 309 of file TcpSocket.h.

Referenced by OnWrite(), and SetTransferLimit().

size_t TcpSocket::m_output_length [private]

Definition at line 310 of file TcpSocket.h.

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

Definition at line 313 of file TcpSocket.h.

SSL_CTX* TcpSocket::m_ssl_ctx [private]

ssl context

Definition at line 314 of file TcpSocket.h.

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

SSL* TcpSocket::m_ssl [private]

ssl 'socket'

Definition at line 315 of file TcpSocket.h.

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

BIO* TcpSocket::m_sbio [private]

ssl bio

Definition at line 316 of file TcpSocket.h.

Referenced by OnSSLAccept(), and OnSSLConnect().

std::string TcpSocket::m_password [private]

ssl password

Definition at line 317 of file TcpSocket.h.

Referenced by GetPassword(), and InitializeContext().

socks4 support

Definition at line 321 of file TcpSocket.h.

Referenced by OnSocks4Connect(), and OnSocks4Read().

char TcpSocket::m_socks4_vn [private]

socks4 support, temporary variable

Definition at line 322 of file TcpSocket.h.

Referenced by OnSocks4Read().

char TcpSocket::m_socks4_cd [private]

socks4 support, temporary variable

Definition at line 323 of file TcpSocket.h.

Referenced by OnSocks4Read().

unsigned short TcpSocket::m_socks4_dstport [private]

socks4 support

Definition at line 324 of file TcpSocket.h.

Referenced by OnSocks4Read().

unsigned long TcpSocket::m_socks4_dstip [private]

socks4 support

Definition at line 325 of file TcpSocket.h.

Referenced by OnSocks4Read().

int TcpSocket::m_resolver_id [private]

Resolver id (if any) for current Open call.

Definition at line 329 of file TcpSocket.h.

Referenced by OnResolved(), and Open().

bool TcpSocket::m_b_reconnect [private]

Reconnect on lost connection flag.

Definition at line 333 of file TcpSocket.h.

Referenced by Reconnect(), and SetReconnect().

Trying to reconnect.

Definition at line 334 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