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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)