WIP: proxy_support #3
4 changed files with 53 additions and 54 deletions
|
@ -38,7 +38,7 @@ fi
|
|||
# Manual cmd command: for FILE in "$(git diff --cached --name-only --diff-filter=d | grep -E -i "\.(sh)$") .githooks/pre-commit"; do shellcheck -S warning $FILE; done
|
||||
#
|
||||
SHELLCHECK_RES=0
|
||||
# for FILE in $GIT_SCRIPT_FILES; do shellcheck -S warning $FILE; RET_CODE=$?; SHELLCHECK_RES=$(( RET_CODE + SHELLCHECK_RES )); done
|
||||
for FILE in $GIT_SCRIPT_FILES; do shellcheck -S warning $FILE; RET_CODE=$?; SHELLCHECK_RES=$(( RET_CODE + SHELLCHECK_RES )); done
|
||||
|
||||
if [[ $SHELLCHECK_RES != 0 ]]; then
|
||||
printf "\n\t ${RED}[ERROR] shell scripts check FAILED!${NC} Fix above errors before commiting your changes. (check .githooks/pre-commit for additional info)\n"
|
||||
|
@ -62,7 +62,7 @@ printf "\n\tBuild GTests to check (takes up to 30 seconds)"
|
|||
cmake --build ${GTEST_FOLDER} --target larra_xmpp_tests --parallel "$(nproc)"
|
||||
|
||||
printf "\n\tLaunch GTests to check\n"
|
||||
# ./larra_xmpp_tests --gtest_brief=1
|
||||
./larra_xmpp_tests --gtest_brief=1
|
||||
|
||||
GTEST_RES=$?
|
||||
cd ${PROJECT_FOLDER} && rm -rf ${GTEST_FOLDER?}
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -40,7 +40,6 @@ temp*
|
|||
#/.idea/codeStyles/Project.xml
|
||||
#/.idea/vcs.xml
|
||||
/.idea/
|
||||
.githooks/
|
||||
|
||||
sha512sum marked this conversation as resolved
|
||||
|
||||
|
||||
|
|
|
@ -171,25 +171,25 @@ auto ConnectViaProxy(Socket& socket, const HttpProxy& param_proxy, std::string_v
|
|||
|
||||
// ответ от прокси-сервера
|
||||
boost::asio::streambuf response;
|
||||
std::size_t bytes_transferred = co_await boost::asio::async_read_until(socket, response, kEndOfHeaders, boost::asio::use_awaitable);
|
||||
std::size_t bytesTransferred = co_await boost::asio::async_read_until(socket, response, kEndOfHeaders, boost::asio::use_awaitable);
|
||||
|
||||
// статус ответа
|
||||
sha512sum
commented
Meaningless comments, variable names reflect what they contain. No need to duplicate. And use English for comments in code Meaningless comments, variable names reflect what they contain. No need to duplicate. And use English for comments in code
|
||||
std::istream response_stream(&response);
|
||||
std::string http_version;
|
||||
unsigned int status_code = 0;
|
||||
std::string status_message;
|
||||
std::istream responseStream(&response);
|
||||
std::string httpVersion;
|
||||
unsigned int statusCode = 0;
|
||||
std::string statusMessage;
|
||||
|
||||
response_stream >> http_version >> status_code;
|
||||
std::getline(response_stream, status_message);
|
||||
responseStream >> httpVersion >> statusCode;
|
||||
std::getline(responseStream, statusMessage);
|
||||
|
||||
if(!response_stream || http_version.substr(0, kEndOfHttpSubstring) != "HTTP/") {
|
||||
if(!responseStream || httpVersion.substr(0, kEndOfHttpSubstring) != "HTTP/") {
|
||||
throw std::runtime_error("Invalid HTTP response from proxy");
|
||||
}
|
||||
|
||||
if(status_code != kSuccessStatusCode) {
|
||||
std::ostringstream error_stream;
|
||||
error_stream << http_version << " " << status_code << " " << status_message;
|
||||
throw std::runtime_error("HTTP proxy CONNECT failed: " + error_stream.str());
|
||||
if(statusCode != kSuccessStatusCode) {
|
||||
std::ostringstream errorStream;
|
||||
errorStream << httpVersion << " " << statusCode << " " << statusMessage;
|
||||
throw std::runtime_error("HTTP proxy CONNECT failed: " + errorStream.str());
|
||||
}
|
||||
|
||||
co_return;
|
||||
|
|
|
@ -18,36 +18,36 @@ class ProxyTest : public ::testing::Test {
|
|||
TEST_F(ProxyTest, ConnectViaHttpProxy_SuccessfulResponse) {
|
||||
HttpProxy proxy{"proxy_host", 8080};
|
||||
|
||||
std::string target_host = "target_host";
|
||||
uint16_t target_port = 80;
|
||||
std::string targetHost = "target_host";
|
||||
uint16_t targetPort = 80;
|
||||
|
||||
std::string expected_request =
|
||||
std::format("CONNECT {}:{} HTTP/1.1\r\nHost: {}:{}\r\n\r\n", target_host, target_port, target_host, target_port);
|
||||
std::string expectedRequest =
|
||||
std::format("CONNECT {}:{} HTTP/1.1\r\nHost: {}:{}\r\n\r\n", targetHost, targetPort, targetHost, targetPort);
|
||||
|
||||
std::string proxy_response = "HTTP/1.1 200 Connection established\r\n\r\n";
|
||||
std::string proxyResponse = "HTTP/1.1 200 Connection established\r\n\r\n";
|
||||
|
||||
mock_socket.AddReceivedData(proxy_response);
|
||||
mock_socket.AddReceivedData(proxyResponse);
|
||||
|
||||
bool connect_successful = false;
|
||||
bool connectSuccessful = false;
|
||||
|
||||
asio::co_spawn(
|
||||
io_context,
|
||||
[&]() -> asio::awaitable<void> {
|
||||
try {
|
||||
co_await client::impl::ConnectViaProxy(mock_socket, proxy, target_host, target_port);
|
||||
connect_successful = true;
|
||||
co_await client::impl::ConnectViaProxy(mock_socket, proxy, targetHost, targetPort);
|
||||
connectSuccessful = true;
|
||||
} catch(...) {
|
||||
connect_successful = false;
|
||||
connectSuccessful = false;
|
||||
}
|
||||
},
|
||||
asio::detached);
|
||||
|
||||
io_context.run();
|
||||
|
||||
std::string sent_data = mock_socket.GetSentData();
|
||||
std::string sentData = mock_socket.GetSentData();
|
||||
|
||||
EXPECT_EQ(sent_data, expected_request);
|
||||
EXPECT_TRUE(connect_successful);
|
||||
EXPECT_EQ(sentData, expectedRequest);
|
||||
EXPECT_TRUE(connectSuccessful);
|
||||
}
|
||||
|
||||
// Test 2: Connect via SOCKS proxy
|
||||
|
@ -58,53 +58,53 @@ TEST(Socks5ProxyTest, ConnectViaProxy) {
|
|||
larra::xmpp::impl::MockSocket socket{executor};
|
||||
|
||||
// expected server responses
|
||||
std::string server_response;
|
||||
server_response += "\x05\x00"; // VER, METHOD
|
||||
server_response += "\x05\x00\x00\x01"; // VER, REP, RSV, ATYP (IPv4)
|
||||
server_response += "\x7F\x00\x00\x01"; // BND.ADDR (127.0.0.1)
|
||||
server_response += "\x1F\x90"; // BND.PORT (8080)
|
||||
std::string serverResponse;
|
||||
serverResponse += "\x05\x00"; // VER, METHOD
|
||||
serverResponse += "\x05\x00\x00\x01"; // VER, REP, RSV, ATYP (IPv4)
|
||||
serverResponse += "\x7F\x00\x00\x01"; // BND.ADDR (127.0.0.1)
|
||||
serverResponse += "\x1F\x90"; // BND.PORT (8080)
|
||||
|
||||
socket.AddReceivedData(server_response);
|
||||
socket.AddReceivedData(serverResponse);
|
||||
|
||||
Socks5Proxy proxy{"proxy.example.com", 1080};
|
||||
std::string target_hostname = "target.example.com";
|
||||
std::uint16_t target_port = 80;
|
||||
std::string targetHostname = "target.example.com";
|
||||
std::uint16_t targetPort = 80;
|
||||
|
||||
boost::asio::co_spawn(
|
||||
executor,
|
||||
[&]() -> boost::asio::awaitable<void> {
|
||||
co_await client::impl::ConnectViaProxy(socket, proxy, target_hostname, target_port);
|
||||
co_await client::impl::ConnectViaProxy(socket, proxy, targetHostname, targetPort);
|
||||
|
||||
auto sent_data = socket.GetSentData();
|
||||
auto sentData = socket.GetSentData();
|
||||
|
||||
// Expected client greeting
|
||||
std::string expected_greeting = "\x05\x01\x00";
|
||||
std::string expectedGreeting = "\x05\x01\x00";
|
||||
|
||||
// Expected CONNECT request
|
||||
std::array<std::uint8_t, 262> expected_request{};
|
||||
std::array<std::uint8_t, 262> expectedRequest{};
|
||||
std::size_t req_len = 0;
|
||||
|
||||
expected_request[req_len++] = 0x05; // VER
|
||||
expected_request[req_len++] = 0x01; // CMD: CONNECT
|
||||
expected_request[req_len++] = 0x00; // RSV
|
||||
expected_request[req_len++] = 0x03; // ATYP: DOMAINNAME
|
||||
expectedRequest[req_len++] = 0x05; // VER
|
||||
expectedRequest[req_len++] = 0x01; // CMD: CONNECT
|
||||
expectedRequest[req_len++] = 0x00; // RSV
|
||||
expectedRequest[req_len++] = 0x03; // ATYP: DOMAINNAME
|
||||
|
||||
expected_request[req_len++] = static_cast<std::uint8_t>(target_hostname.size()); // domain length
|
||||
expectedRequest[req_len++] = static_cast<std::uint8_t>(targetHostname.size()); // domain length
|
||||
|
||||
std::memcpy(&expected_request[req_len], target_hostname.data(), target_hostname.size());
|
||||
req_len += target_hostname.size();
|
||||
std::memcpy(&expectedRequest[req_len], targetHostname.data(), targetHostname.size());
|
||||
req_len += targetHostname.size();
|
||||
|
||||
std::uint16_t network_order_port = htons(target_port);
|
||||
expected_request[req_len++] = static_cast<std::uint8_t>((network_order_port >> 8) & 0xFF);
|
||||
expected_request[req_len++] = static_cast<std::uint8_t>(network_order_port & 0xFF);
|
||||
std::uint16_t networkOrderPort = htons(targetPort);
|
||||
expectedRequest[req_len++] = static_cast<std::uint8_t>((networkOrderPort >> 8) & 0xFF);
|
||||
expectedRequest[req_len++] = static_cast<std::uint8_t>(networkOrderPort & 0xFF);
|
||||
|
||||
std::string expected_data = expected_greeting;
|
||||
auto transformed_view = expected_request | std::views::take(req_len) | std::views::transform([](std::uint8_t byte) {
|
||||
std::string expectedData = expectedGreeting;
|
||||
auto transformed_view = expectedRequest | std::views::take(req_len) | std::views::transform([](std::uint8_t byte) {
|
||||
return static_cast<char>(byte);
|
||||
});
|
||||
|
||||
expected_data.append(std::ranges::to<std::string>(transformed_view));
|
||||
EXPECT_EQ(sent_data, expected_data);
|
||||
expectedData.append(std::ranges::to<std::string>(transformed_view));
|
||||
EXPECT_EQ(sentData, expectedData);
|
||||
|
||||
co_return;
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue
Why .githooks ???