socks4.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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 <array>
  13. #include <string>
  14. #include <boost/asio/buffer.hpp>
  15. #include <boost/asio/ip/tcp.hpp>
  16. namespace socks4 {
  17. const unsigned char version = 0x04;
  18. class request
  19. {
  20. public:
  21. enum command_type
  22. {
  23. connect = 0x01,
  24. bind = 0x02
  25. };
  26. request(command_type cmd, const boost::asio::ip::tcp::endpoint& endpoint,
  27. const std::string& user_id)
  28. : version_(version),
  29. command_(cmd),
  30. user_id_(user_id),
  31. null_byte_(0)
  32. {
  33. // Only IPv4 is supported by the SOCKS 4 protocol.
  34. if (endpoint.protocol() != boost::asio::ip::tcp::v4())
  35. {
  36. throw boost::system::system_error(
  37. boost::asio::error::address_family_not_supported);
  38. }
  39. // Convert port number to network byte order.
  40. unsigned short port = endpoint.port();
  41. port_high_byte_ = (port >> 8) & 0xff;
  42. port_low_byte_ = port & 0xff;
  43. // Save IP address in network byte order.
  44. address_ = endpoint.address().to_v4().to_bytes();
  45. }
  46. std::array<boost::asio::const_buffer, 7> buffers() const
  47. {
  48. return
  49. {
  50. {
  51. boost::asio::buffer(&version_, 1),
  52. boost::asio::buffer(&command_, 1),
  53. boost::asio::buffer(&port_high_byte_, 1),
  54. boost::asio::buffer(&port_low_byte_, 1),
  55. boost::asio::buffer(address_),
  56. boost::asio::buffer(user_id_),
  57. boost::asio::buffer(&null_byte_, 1)
  58. }
  59. };
  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. std::array<boost::asio::mutable_buffer, 5> buffers()
  86. {
  87. return
  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. }
  98. bool success() const
  99. {
  100. return null_byte_ == 0 && status_ == request_granted;
  101. }
  102. unsigned char status() const
  103. {
  104. return status_;
  105. }
  106. boost::asio::ip::tcp::endpoint endpoint() const
  107. {
  108. unsigned short port = port_high_byte_;
  109. port = (port << 8) & 0xff00;
  110. port = port | port_low_byte_;
  111. boost::asio::ip::address_v4 address(address_);
  112. return boost::asio::ip::tcp::endpoint(address, port);
  113. }
  114. private:
  115. unsigned char null_byte_;
  116. unsigned char status_;
  117. unsigned char port_high_byte_;
  118. unsigned char port_low_byte_;
  119. boost::asio::ip::address_v4::bytes_type address_;
  120. };
  121. } // namespace socks4
  122. #endif // SOCKS4_HPP