Logo Search packages:      
Sourcecode: znc version File versions  Download package

bool Csock::Write ( const char *  data,
int  len 
) [virtual]

Write data to the socket if not all of the data is sent, it will be stored on an internal buffer, and tried again with next call to Write if the socket is blocking, it will send everything, its ok to check ernno after this (nothing else is processed)

Parameters:
data the data to send
len the length of data

Definition at line 1269 of file Csocket.cpp.

References ConnectionRefused(), ResetTimer(), SEL_OK, and WriteSelect().

Referenced by Write().

{
      m_sSend.append( data, len );

      if ( m_sSend.empty() )
            return( true );

      if ( m_eConState != CST_OK )
            return( true );

      if ( m_bBLOCK )
      {
            if ( WriteSelect() != SEL_OK )
                  return( false );

      }
      // rate shaping
      u_int iBytesToSend = 0;

      if ( ( m_iMaxBytes > 0 ) && ( m_iMaxMilliSeconds > 0 ) )
      {
            unsigned long long iNOW = millitime();
            // figure out the shaping here
            // if NOW - m_iLastSendTime > m_iMaxMilliSeconds then send a full length of ( iBytesToSend )
            if ( ( iNOW - m_iLastSendTime ) > m_iMaxMilliSeconds )
            {
                  m_iLastSendTime = iNOW;
                  iBytesToSend = m_iMaxBytes;
                  m_iLastSend = 0;

            } else // otherwise send m_iMaxBytes - m_iLastSend
                  iBytesToSend = m_iMaxBytes - m_iLastSend;

            // take which ever is lesser
            if ( m_sSend.length() < iBytesToSend )
                  iBytesToSend =    m_sSend.length();

            // add up the bytes sent
            m_iLastSend += iBytesToSend;

            // so, are we ready to send anything ?
            if ( iBytesToSend == 0 )
                  return( true );

      } else
            iBytesToSend = m_sSend.length();

#ifdef HAVE_LIBSSL
      if ( m_bssl )
      {

            if ( m_sSSLBuffer.empty() ) // on retrying to write data, ssl wants the data in the SAME spot and the SAME size
                  m_sSSLBuffer.append( m_sSend.data(), iBytesToSend );

            int iErr = SSL_write( m_ssl, m_sSSLBuffer.data(), m_sSSLBuffer.length() );

            if ( ( iErr < 0 ) && ( GetSockError() == ECONNREFUSED ) )
            {
                  // If ret == -1, the underlying BIO reported an I/O error (man SSL_get_error)
                  ConnectionRefused();
                  return( false );
            }

            switch( SSL_get_error( m_ssl, iErr ) )
            {
                  case SSL_ERROR_NONE:
                  m_bsslEstablished = true;
                  // all ok
                  break;

                  case SSL_ERROR_ZERO_RETURN:
                  {
                        // weird closer alert
                        return( false );
                  }

                  case SSL_ERROR_WANT_READ:
                  // retry
                  break;

                  case SSL_ERROR_WANT_WRITE:
                  // retry
                  break;

                  case SSL_ERROR_SSL:
                  {
                        SSLErrors( __FILE__, __LINE__ );
                        return( false );
                  }
            }

            if ( iErr > 0 )
            {
                  m_sSSLBuffer.clear();
                  m_sSend.erase( 0, iErr );
                  // reset the timer on successful write (we have to set it here because the write
                  // bit might not always be set, so need to trigger)
                  if ( TMO_WRITE & GetTimeoutType() )
                        ResetTimer();

                  m_iBytesWritten += (unsigned long long)iErr;
            }

            return( true );
      }
#endif /* HAVE_LIBSSL */
#ifdef _WIN32
      int bytes = send( m_iWriteSock, m_sSend.data(), iBytesToSend, 0 );
#else
      int bytes = write( m_iWriteSock, m_sSend.data(), iBytesToSend );
#endif /* _WIN32 */

      if ( ( bytes == -1 ) && ( GetSockError() == ECONNREFUSED ) )
      {
            ConnectionRefused();
            return( false );
      }

#ifdef _WIN32
      if ( ( bytes <= 0 ) && ( GetSockError() != WSAEWOULDBLOCK ) )
            return( false );
#else
      if ( ( bytes <= 0 ) && ( GetSockError() != EAGAIN ) )
            return( false );
#endif /* _WIN32 */

      // delete the bytes we sent
      if ( bytes > 0 )
      {
            m_sSend.erase( 0, bytes );
            if ( TMO_WRITE & GetTimeoutType() )
                  ResetTimer();     // reset the timer on successful write
            m_iBytesWritten += (unsigned long long)bytes;
      }

      return( true );
}


Generated by  Doxygen 1.6.0   Back to index