⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 opensslconnectorbase.cpp

📁 强大易用的邮件收发客户端
💻 CPP
字号:
#include "stdafx.h"
#include "OpenSSLConnectorBase.h"

#include <openssl/err.h>

///////////////////////////////////////////////////////////////////////////////
// COpenSSLConnectorBase
///////////////////////////////////////////////////////////////////////////////

COpenSSLConnectorBase::COpenSSLConnectorBase(
   SSL_CTX *pContext)
   :  m_readRequired(false),
      m_pConnection(SSL_new(pContext)),
      m_pIn(BIO_new(BIO_s_mem())),
      m_pOut(BIO_new(BIO_s_mem()))
{ 
   SSL_set_bio(m_pConnection, m_pIn, m_pOut);
}
      
COpenSSLConnectorBase::~COpenSSLConnectorBase()
{
   SSL_free(m_pConnection);
}

size_t COpenSSLConnectorBase::DataToWrite(
   BYTE *pData,
   size_t dataLength)
{
   size_t bytesUsed = 0;

   int result = SSL_write(m_pConnection, pData, dataLength);

   if (result < 0)
   {
      HandleError(result);
   }
   else
   {
      bytesUsed = result;
   }

   if (SSL_want_read(m_pConnection))
   {
      OutputDebugString(_T("SSL_want_read\n"));

      m_readRequired = true;
   }

   return bytesUsed;
}

size_t COpenSSLConnectorBase::DataToRead(
   BYTE *pData,
   size_t dataLength)
{
   m_readRequired = false;

   size_t bytesUsed = BIO_write(m_pIn, pData, dataLength);

   BYTE *pBuffer = 0;
   size_t bufferSize = 0;

   GetNextReadDataBuffer(&pBuffer, bufferSize);

   int bytesOut = 0;
   
   do
   {
      bytesOut = SSL_read(m_pConnection, (void*)pBuffer, bufferSize);

      if (bytesOut > 0)
      {
         OnDataToRead(pBuffer, bytesOut);
      }
      
      if (bytesOut < 0)
      {
         HandleError(bytesOut);    
      }
   }
   while(bytesOut > 0);

   return bytesUsed;
}

void COpenSSLConnectorBase::SendPendingData()
{
   int pending;

   OutputDebugString("Send pending data\n");

   while ((pending = BIO_ctrl_pending(m_pOut)) > 0)
   {
      // If we were using BIO pairs then we'd be able to use nread() and access
      // the data in place, rather than copying it out into a buffer...
      // It complicates the example though.

      BYTE *pBuffer = 0;
      size_t bufferSize = 0;

      GetNextWriteDataBuffer(&pBuffer, bufferSize);

      int bytesToSend = BIO_read(m_pOut, (void*)pBuffer, bufferSize);

      if (bytesToSend > 0)
      {
         OnDataToWrite(pBuffer, bytesToSend);

         TRACE(_T("Sent %d bytes\n"), bytesToSend);
      }

      if (bytesToSend <= 0)
      {
         if (!BIO_should_retry(m_pOut))
         {
            HandleError(bytesToSend);
         }
      }
   }
}

void COpenSSLConnectorBase::ExpectConnect()
{
   SSL_set_connect_state(m_pConnection);
}

void COpenSSLConnectorBase::ExpectAccept()
{
   SSL_set_accept_state(m_pConnection);
}

void COpenSSLConnectorBase::HandleError(int result)
{
   if (result <= 0)
   {
      int error = SSL_get_error(m_pConnection, result);

      switch(error)
      {
         case SSL_ERROR_ZERO_RETURN:
         case SSL_ERROR_NONE: 
         case SSL_ERROR_WANT_READ :

         break;

         default :
         {

            char buffer[256];

            while (error != 0)
            {
               ERR_error_string_n(error, buffer, sizeof(buffer));

               TRACE(_T("Error: %d - %s\n"), error, buffer);

               error = ERR_get_error();
            }

            // Handle errors better than this!
            //ASSERT(false);
         }
         break;
      }
   }
}

void COpenSSLConnectorBase::RunSSL()
{
   OutputDebugString(_T("RunSSL\n"));
   
   bool dataToWrite = false;
   bool dataToRead = false;

   GetPendingOperations(dataToRead, dataToWrite);

   while ((!m_readRequired && dataToWrite) || dataToRead)
   {
      if (SSL_in_init(m_pConnection))
      {
         OutputDebugString("Client waiting in connect: ");
         OutputDebugString(SSL_state_string_long(m_pConnection));
         OutputDebugString("\n");
      }

      if (dataToRead)
      {
         PerformRead();
      }

      if (!m_readRequired && dataToWrite)
      {
         PerformWrite();
      }

      if (BIO_ctrl_pending(m_pOut))
      {
         SendPendingData();
      }

      GetPendingOperations(dataToRead, dataToWrite);
   }
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -