mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-22 21:37:17 +01:00
read correct reply length and handle reply codes
This commit is contained in:
parent
7691a5b4a9
commit
967627e58a
106
libi2pd/Socks5.h
106
libi2pd/Socks5.h
|
@ -29,7 +29,87 @@ namespace transport
|
|||
const size_t SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE = 10;
|
||||
const size_t SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE = 22;
|
||||
|
||||
const uint8_t SOCKS5_REPLY_SUCCESS = 0x00;
|
||||
const uint8_t SOCKS5_REPLY_SERVER_FAILURE = 0x01;
|
||||
const uint8_t SOCKS5_REPLY_CONNECTION_NOT_ALLOWED = 0x02;
|
||||
const uint8_t SOCKS5_REPLY_NETWORK_UNREACHABLE = 0x03;
|
||||
const uint8_t SOCKS5_REPLY_HOST_UNREACHABLE = 0x04;
|
||||
const uint8_t SOCKS5_REPLY_CONNECTION_REFUSED = 0x05;
|
||||
const uint8_t SOCKS5_REPLY_TTL_EXPIRED = 0x06;
|
||||
const uint8_t SOCKS5_REPLY_COMMAND_NOT_SUPPORTED = 0x07;
|
||||
const uint8_t SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED = 0x08;
|
||||
|
||||
// SOCKS5 handshake
|
||||
template<typename Socket, typename Handler>
|
||||
void Socks5ReadReply (Socket& s, Handler handler)
|
||||
{
|
||||
auto readbuff = std::make_shared<std::vector<int8_t> >(258); // max possible
|
||||
boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), 5), boost::asio::transfer_all(), // read 4 bytes of header + first byte of address
|
||||
[readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred)
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
if ((*readbuff)[1] == SOCKS5_REPLY_SUCCESS)
|
||||
{
|
||||
size_t len = 0;
|
||||
switch ((*readbuff)[3]) // ATYP
|
||||
{
|
||||
case SOCKS5_ATYP_IPV4: len = 3; break; // address length 4 bytes
|
||||
case SOCKS5_ATYP_IPV6: len = 15; break; // address length 16 bytes
|
||||
case SOCKS5_ATYP_NAME: len += (*readbuff)[4]; break; // first byte of address is length
|
||||
default: ;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
len += 2; // port
|
||||
boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), len), boost::asio::transfer_all(),
|
||||
[readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred)
|
||||
{
|
||||
if (!ec)
|
||||
handler (boost::system::error_code ()); // success
|
||||
else
|
||||
handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted));
|
||||
});
|
||||
}
|
||||
else
|
||||
handler (boost::asio::error::make_error_code (boost::asio::error::fault)); // unknown address type
|
||||
}
|
||||
else
|
||||
switch ((*readbuff)[1]) // REP
|
||||
{
|
||||
case SOCKS5_REPLY_SERVER_FAILURE:
|
||||
handler (boost::asio::error::make_error_code (boost::asio::error::access_denied ));
|
||||
break;
|
||||
case SOCKS5_REPLY_CONNECTION_NOT_ALLOWED:
|
||||
handler (boost::asio::error::make_error_code (boost::asio::error::no_permission));
|
||||
break;
|
||||
case SOCKS5_REPLY_HOST_UNREACHABLE:
|
||||
handler (boost::asio::error::make_error_code (boost::asio::error::host_unreachable));
|
||||
break;
|
||||
case SOCKS5_REPLY_NETWORK_UNREACHABLE:
|
||||
handler (boost::asio::error::make_error_code (boost::asio::error::network_unreachable));
|
||||
break;
|
||||
case SOCKS5_REPLY_CONNECTION_REFUSED:
|
||||
handler (boost::asio::error::make_error_code (boost::asio::error::connection_refused));
|
||||
break;
|
||||
case SOCKS5_REPLY_TTL_EXPIRED:
|
||||
handler (boost::asio::error::make_error_code (boost::asio::error::timed_out));
|
||||
break;
|
||||
case SOCKS5_REPLY_COMMAND_NOT_SUPPORTED:
|
||||
handler (boost::asio::error::make_error_code (boost::asio::error::operation_not_supported));
|
||||
break;
|
||||
case SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED:
|
||||
handler (boost::asio::error::make_error_code (boost::asio::error::no_protocol_option));
|
||||
break;
|
||||
default:
|
||||
handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted));
|
||||
}
|
||||
}
|
||||
else
|
||||
handler (ec);
|
||||
});
|
||||
}
|
||||
|
||||
template<typename Socket, typename Handler>
|
||||
void Socks5Connect (Socket& s, Handler handler, std::shared_ptr<std::vector<uint8_t> > buff, uint16_t port)
|
||||
{
|
||||
|
@ -44,31 +124,7 @@ namespace transport
|
|||
{
|
||||
(void) transferred;
|
||||
if (!ec)
|
||||
{
|
||||
auto readbuff = std::make_shared<std::vector<int8_t> >(262); // max possible
|
||||
boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), 7), boost::asio::transfer_all(), // read min reply size
|
||||
[readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred)
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
if (!(*readbuff)[1]) // succeeded
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
size_t moreBytes = s.available(ec);
|
||||
if (!ec && moreBytes) // read remaining portion of reply
|
||||
boost::asio::read (s, boost::asio::buffer(readbuff->data (), moreBytes), boost::asio::transfer_all (), ec);
|
||||
if (!ec)
|
||||
handler (boost::system::error_code ());
|
||||
else
|
||||
handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted));
|
||||
}
|
||||
else
|
||||
handler (boost::asio::error::make_error_code (boost::asio::error::connection_refused));
|
||||
}
|
||||
else
|
||||
handler (ec);
|
||||
});
|
||||
}
|
||||
Socks5ReadReply (s, handler);
|
||||
else
|
||||
handler (ec);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue