socks4.hpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. //
  2. // socks4.hpp
  3. // ~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef SOCKS4_HPP
  11. #define SOCKS4_HPP
  12. #include <string>
  13. #include <boost/asio.hpp>
  14. #include <boost/array.hpp>
  15. namespace socks4 {
  16. const unsigned char version = 0x04;
  17. class request
  18. {
  19. public:
  20. enum command_type
  21. {
  22. connect = 0x01,
  23. bind = 0x02
  24. };
  25. request(command_type cmd, const boost::asio::ip::tcp::endpoint& endpoint,
  26. const std::string& user_id)
  27. : version_(version),
  28. command_(cmd),
  29. user_id_(user_id),
  30. null_byte_(0)
  31. {
  32. // Only IPv4 is supported by the SOCKS 4 protocol.
  33. if (endpoint.protocol() != boost::asio::ip::tcp::v4())
  34. {
  35. throw boost::system::system_error(
  36. boost::asio::error::address_family_not_supported);
  37. }
  38. // Convert port number to network byte order.
  39. unsigned short port = endpoint.port();
  40. port_high_byte_ = (port >> 8) & 0xff;
  41. port_low_byte_ = port & 0xff;
  42. // Save IP address in network byte order.
  43. address_ = endpoint.address().to_v4().to_bytes();
  44. }
  45. boost::array<boost::asio::const_buffer, 7> buffers() const
  46. {
  47. boost::array<boost::asio::const_buffer, 7> bufs =
  48. {
  49. {
  50. boost::asio::buffer(&version_, 1),
  51. boost::asio::buffer(&command_, 1),
  52. boost::asio::buffer(&port_high_byte_, 1),
  53. boost::asio::buffer(&port_low_byte_, 1),
  54. boost::asio::buffer(address_),
  55. boost::asio::buffer(user_id_),
  56. boost::asio::buffer(&null_byte_, 1)
  57. }
  58. };
  59. return bufs;
  60. }
  61. private:
  62. unsigned char version_;
  63. unsigned char command_;
  64. unsigned char port_high_byte_;
  65. unsigned char port_low_byte_;
  66. boost::asio::ip::address_v4::bytes_type address_;
  67. std::string user_id_;
  68. unsigned char null_byte_;
  69. };
  70. class reply
  71. {
  72. public:
  73. enum status_type
  74. {
  75. request_granted = 0x5a,
  76. request_failed = 0x5b,
  77. request_failed_no_identd = 0x5c,
  78. request_failed_bad_user_id = 0x5d
  79. };
  80. reply()
  81. : null_byte_(0),
  82. status_()
  83. {
  84. }
  85. boost::array<boost::asio::mutable_buffer, 5> buffers()
  86. {
  87. boost::array<boost::asio::mutable_buffer, 5> bufs =
  88. {
  89. {
  90. boost::asio::buffer(&null_byte_, 1),
  91. boost::asio::buffer(&status_, 1),
  92. boost::asio::buffer(&port_high_byte_, 1),
  93. boost::asio::buffer(&port_low_byte_, 1),
  94. boost::asio::buffer(address_)
  95. }
  96. };
  97. return bufs;
  98. }
  99. bool success() const
  100. {
  101. return null_byte_ == 0 && status_ == request_granted;
  102. }
  103. unsigned char status() const
  104. {
  105. return status_;
  106. }
  107. boost::asio::ip::tcp::endpoint endpoint() const
  108. {
  109. unsigned short port = port_high_byte_;
  110. port = (port << 8) & 0xff00;
  111. port = port | port_low_byte_;
  112. boost::asio::ip::address_v4 address(address_);
  113. return boost::asio::ip::tcp::endpoint(address, port);
  114. }
  115. private:
  116. unsigned char null_byte_;
  117. unsigned char status_;
  118. unsigned char port_high_byte_;
  119. unsigned char port_low_byte_;
  120. boost::asio::ip::address_v4::bytes_type address_;
  121. };
  122. } // namespace socks4
  123. #endif // SOCKS4_HPP