tars源码分析之27

openssl的read,write, handshake:

#if TARS_SSL

#include <openssl/ssl.h>
#include <openssl/err.h>

#include "util/tc_openssl.h"
#include "util/tc_buffer.h"


namespace tars
{

TC_OpenSSL::~TC_OpenSSL()
{
    Release();
}

void TC_OpenSSL::Release()
{
    if (_ssl)
    {
        SSL_free(_ssl);
        _ssl = NULL;
    }
    _bHandshaked = false;
    _err = 0;
}

void TC_OpenSSL::Init(SSL* ssl, bool isServer)
{
    assert (_ssl == NULL);
    _ssl = ssl;
    _bHandshaked = false;
    _isServer = isServer;
    _err = 0;
}

bool TC_OpenSSL::IsHandshaked() const
{
    return _bHandshaked;
}

bool TC_OpenSSL::HasError() const
{
    return _err != 0;
}
    
string* TC_OpenSSL::RecvBuffer()
{
    return &_plainBuf;
}

std::string TC_OpenSSL::DoHandshake(const void* data, size_t size)
{
    assert (!_bHandshaked);
    assert (_ssl);

    if (data && size)
    {
        // 写入ssl内存缓冲区
        BIO_write(SSL_get_rbio(_ssl), data, size);
    }

    ERR_clear_error(); 
    int ret = _isServer ? SSL_accept(_ssl) : SSL_connect(_ssl);

    if (ret <= 0)
    {
        _err = SSL_get_error(_ssl, ret);
        if (_err != SSL_ERROR_WANT_READ)
        {
            return std::string();
        }
    }

    _err = 0;

    if (ret == 1)
    {
        _bHandshaked = true;
    }

    // the encrypted data from write buffer
    std::string out;
    TC_Buffer outdata; 
    GetMemData(SSL_get_wbio(_ssl), outdata);
    if (!outdata.IsEmpty()) 
    {
        out.assign(outdata.ReadAddr(), outdata.ReadableSize());
    }

    return out;
}

std::string TC_OpenSSL::Write(const void* data, size_t size)
{
    if (!_bHandshaked)
        return std::string((const char*)data, size); //握手数据不用加密
 
    // 会话数据需加密
    ERR_clear_error(); 
    int ret = SSL_write(_ssl, data, size); 
    if (ret <= 0) 
    {
        _err = SSL_get_error(_ssl, ret);
        return std::string();
    }

    _err = 0;

    TC_Buffer toSend; 
    GetMemData(SSL_get_wbio(_ssl), toSend);
    return std::string(toSend.ReadAddr(), toSend.ReadableSize());
}

bool TC_OpenSSL::Read(const void* data, size_t size, std::string& out)
{
    bool usedData = false;
    if (!_bHandshaked)
    {
        usedData = true;
        _plainBuf.clear();
        std::string out2 = DoHandshake(data, size);
        out.swap(out2);

        if (_err != 0)
            return false;

        if (_bHandshaked)
            ; // TODO onHandshake
    }

    // 不要用else,因为数据可能紧跟着最后的握手而来
    if (_bHandshaked)
    {
        if (!usedData)
        {
            // 写入ssl内存缓冲区
            BIO_write(SSL_get_rbio(_ssl), data, size);
        }

        string data;
        if (DoSSLRead(_ssl, data))
        {
            _plainBuf.append(data.begin(), data.end());
        }
        else
        {
            _err = SSL_ERROR_SSL;
            return false;
        }
    }

    return true;
}

} // end namespace tars

#endif

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值