163 lines
3.4 KiB
C++
163 lines
3.4 KiB
C++
#include "VoidNet_LL/SecureSocket.hpp"
|
|
|
|
#include <cassert>
|
|
|
|
namespace inl::net::sockets
|
|
{
|
|
/*SecureSocket::SecureSocket()
|
|
: m_context(0), m_conn(0), m_eof(false)
|
|
{
|
|
m_socket = make_unique<Socket>(SocketType::Streaming);
|
|
|
|
// Intitialize the SSL client-side socket
|
|
SSL_library_init();
|
|
SSL_load_error_strings();
|
|
ERR_load_BIO_strings();
|
|
}
|
|
|
|
bool SecureSocket::Connect(const IPAddress & addrStr)
|
|
{
|
|
if (!m_context)
|
|
{
|
|
m_context = SSL_CTX_new(SSLv23_client_method());
|
|
assert(m_context);
|
|
}
|
|
if (!m_conn)
|
|
{
|
|
m_conn = SSL_new(m_context);
|
|
assert(m_conn);
|
|
|
|
m_in = BIO_new(BIO_s_mem());
|
|
m_out = BIO_new(BIO_s_mem());
|
|
SSL_set_bio(m_conn, m_in, m_out);
|
|
SSL_set_connect_state(m_conn);
|
|
}
|
|
|
|
return m_socket->Connect(addrStr);
|
|
}
|
|
|
|
bool SecureSocket::Close() const
|
|
{
|
|
return m_socket->Close();
|
|
}
|
|
|
|
bool SecureSocket::HasPendingData(uint32_t & pendingDataSize) const
|
|
{
|
|
return m_socket->HasPendingData(pendingDataSize);
|
|
}
|
|
|
|
bool SecureSocket::Send(byte* data, int32_t count, int32_t &sent, int flags)
|
|
{
|
|
sent = SSL_write(m_conn, data, count);
|
|
SendFromBio(); // Write data if available
|
|
if (sent < 0)
|
|
{
|
|
HandleReturn(sent);
|
|
return true;
|
|
}
|
|
return sent > 0;
|
|
}
|
|
|
|
bool SecureSocket::SendRaw(byte * buf, size_t len, int flags)
|
|
{
|
|
int32_t sent;
|
|
return m_socket->Send(buf, len, sent) && sent == len;
|
|
|
|
}
|
|
|
|
bool SecureSocket::SendFromBio(int flags)
|
|
{
|
|
byte buf[4096];
|
|
size_t pending = BIO_ctrl_pending(m_out);
|
|
if (!pending)
|
|
return true;
|
|
size_t bytes = BIO_read(m_out, buf, sizeof(buf));
|
|
if (bytes > 0)
|
|
return SendRaw(buf, bytes, flags);
|
|
else if (bytes == -1 || bytes == 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
bool SecureSocket::RecvToBio(int flags)
|
|
{
|
|
byte buf[4096];
|
|
size_t bytes = m_socket->Recv(buf, sizeof(buf), flags);
|
|
if (bytes > 0)
|
|
{
|
|
size_t written = BIO_write(m_in, buf, int(bytes));
|
|
assert(bytes == written);
|
|
return true;
|
|
}
|
|
else if (bytes == 0)
|
|
{
|
|
// No data
|
|
m_eof = true;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void SecureSocket::HandleReturn(size_t ret)
|
|
{
|
|
int32_t err = SSL_get_error(m_conn, ret);
|
|
if (SSL_ERROR_WANT_WRITE == err)
|
|
SendFromBio();
|
|
else if (SSL_ERROR_WANT_READ == err)
|
|
RecvToBio();
|
|
else if (SSL_ERROR_SSL == err)
|
|
throw inl::RuntimeException();
|
|
else
|
|
assert(!"unexpected error");
|
|
}
|
|
|
|
bool SecureSocket::Recv(byte* data, int32_t count, int32_t &read, int flags)
|
|
{
|
|
read = SSL_read(m_conn, data, count);
|
|
if (read < 0)
|
|
{
|
|
HandleReturn(read);
|
|
if (m_eof)
|
|
return false;
|
|
}
|
|
return read > 0;
|
|
}
|
|
|
|
bool SecureSocket::Wait(SocketWaitConditions cond, chrono::milliseconds t) const
|
|
{
|
|
return m_socket->Wait(cond, t);
|
|
}
|
|
|
|
SocketConnectionState SecureSocket::GetConnectionState() const
|
|
{
|
|
return m_socket->GetConnectionState();
|
|
}
|
|
|
|
void SecureSocket::GetAddress(IPAddress & outAddr) const
|
|
{
|
|
m_socket->GetAddress(outAddr);
|
|
}
|
|
|
|
int32_t SecureSocket::GetPort() const
|
|
{
|
|
return m_socket->GetPort();
|
|
}
|
|
|
|
void SecureSocket::UseCertificateFile(string const & path)
|
|
{
|
|
if (!m_context)
|
|
assert(!"not initialized yet");
|
|
if (SSL_CTX_use_certificate_file(m_context, path.c_str(), SSL_FILETYPE_PEM) <= 0)
|
|
throw inl::RuntimeException();
|
|
}
|
|
|
|
void SecureSocket::UsePrivateKeyFile(string const & path)
|
|
{
|
|
if (!m_context)
|
|
assert(!"not initialized yet");
|
|
if (SSL_CTX_use_PrivateKey_file(m_context, path.c_str(), SSL_FILETYPE_PEM) <= 0)
|
|
throw inl::RuntimeException();
|
|
if (!SSL_CTX_check_private_key(m_context))
|
|
throw inl::RuntimeException();
|
|
}*/
|
|
} |