来看下tc_openssl, 其中的TC_OpenSSL是对开源openssl基本操作的封装, 可以看到:
#include <openssl/ssl.h>
#include <openssl/err.h>
可以将_ssl理解为一个广义socket, 如下是初始化和销毁的相关操作:
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;
}
然后握手:
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;
}
可以看到, 基本都是对广义socket _ssl进行操作。
在tars源码中, 处处可见类似的广义socket, 后面我们会涉及到communicator, 也是抽象物, 也可以理解为广义socket.