上周启动了C ++,其任务是将SSL实现到代理中。 这段代码在下面工作但看起来真的很臃肿恕我直言唯一的区别只是一个小的改动,以指示使用哪个套接字:
typedef ip::tcp::socket socket_type;
typedef boost::shared_ptr<Bridge> ptr_type;
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
...
ssl_socket downstream_socket_; // (SSL socket connected to client)
...
if (sslEnabled)
{
downstream_socket_.async_read_some(
boost::asio::buffer(downstream_data_, max_data_length),
boost::bind(&Bridge::handle_downstream_read,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
downstream_socket_.next_layer().async_read_some(
boost::asio::buffer(downstream_data_, max_data_length),
boost::bind(&Bridge::handle_downstream_read,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
我想知道是否可以将上述代码减少到此:
downstream_socket().async_read_some(
boost::asio::buffer(downstream_data_, max_data_length),
boost::bind(&Bridge::handle_downstream_read,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
其中新函数 downstream_socket()定义为:
socket_type &Bridge::downstream_socket()
{
if (sslEnabled)
{
return downstream_socket_;
}
else
{
return downstream_socket_.next_layer();
}
}
我试过这个重载的函数概念,如果我可以定义一个模板变量&#34; sslEnabled&#34;要么在启用SSL时为int,要么在非SSL时为double,那么我可以这样写:
socket_type& socket(double sslEnabled)
{
return downstream_socket_->next_layer();
}
ssl_socket& socket(int sslEnabled)
{
return downstream_socket_;
}
让编译器找出要调用的重载函数以返回正确的套接字:
downstream_socket(sslEnabled).async_read_some(
boost::asio::buffer(downstream_data_, max_data_length),
boost::bind(&Bridge::handle_downstream_read,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
但是遇到了定义模板变量的问题&#34; sslEnabled&#34;根据SSL或启用非SSL而成为 int 或 double 。
要确定是否启用了SSL,请调用此代码:
// Used to detect the start of an SSL handshake.
#pragma pack(push, 1)
typedef struct
{
BYTE Handshake; // SSL handshake: 0x16
BYTE TLS; // Newest major version: 0x03
BYTE Version; // Version: 0x00 (SSL v3), 0x01 (TLS v1.0), 0x02 (TLS v1.1), 0x03 (TLS v1.2)
} TLSHeader;
#pragma pack(pop)
...
...
...
TLSHeader *TLS_header = new TLSHeader;
// Peek at incoming client data (3 bytes) to see if it might be a TLSv1.x handshake
// and without removing it from the input queue.
session->downstream_socket_.next_layer().async_receive(
boost::asio::buffer(TLS_header, sizeof(TLSHeader)),
ip::tcp::socket::message_peek,
boost::bind(&Acceptor::handle_TLS_header,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
session,
TLS_header));
调用下面的函数来确定TLS握手:
void Bridge::Acceptor::handle_TLS_header(const boost::system::error_code &error, const size_t &bytes_transferred, ptr_type session, TLSHeader *TLS_header)
{
if (!error)
{
// Detect the start of an SSL handshake.
if (TLS_header->Handshake == 0x16 && TLS_header->TLS == 0x03 && TLS_header->Version)
{
switch (TLS_header->Version)
{
case 0x01:
DBOUT("TLS v1.0 Handshake Detected.");
break;
case 0x02:
DBOUT("TLS v1.1 Handshake Detected.");
break;
case 0x03:
DBOUT("TLS v1.2 Handshake Detected.");
break;
default:
DBOUT("TLS v1.x Handshake Detected.");
break;
}
DBOUT("Starting an SSL session.");
session->sslEnabled = true;
session->downstream_socket_.async_handshake(
boost::asio::ssl::stream_base::server,
boost::bind(&Acceptor::handle_accept,
this,
boost::asio::placeholders::error,
session));
}
else
{
DBOUT("Starting a non-SSL session.");
session->sslEnabled = false;
boost::system::error_code error = boost::system::errc::make_error_code(boost::system::errc::success);
handle_accept(error, session);
}
}
else
{
DBOUT("handle_TLS_header: " << error.message());
session->close();
delete this;
}
delete TLS_header;
}
有什么想法吗?感谢。