Skip to content
This repository has been archived by the owner on Jan 2, 2025. It is now read-only.

Commit

Permalink
Allow to run NDT over Tor (#15)
Browse files Browse the repository at this point in the history
* Start adding support for NDT over Tor

* curlx_test.cpp: fix test I have broken

Now init() is idempotent in the proper sense, while before the
behavior was consistent but possibly not idempotent.

* Revert small, unnecessary change

* libndt.cpp: fix MSVC 32 bit build

* Repair build

* revamp socks5 code

* libndt.cpp: attempt to fix windows build

* Write tests to cover more curlx methods

* Add one more simple test

* libndt_test: use connect_tcp_maybe_socks5()

Of course, where it makes sense.

* Start adding more tests for socks5h

* Repair build error

* More tests for socks5 code

* Fix previous

* Add some more tests

* More socks5 tests

* more tests

* improve tests

* add two more tests

* Remove unused methods

* Final changes before merging
  • Loading branch information
bassosimone authored Jun 17, 2018
1 parent b8540dd commit eccd5e7
Show file tree
Hide file tree
Showing 7 changed files with 880 additions and 53 deletions.
26 changes: 25 additions & 1 deletion curlx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,25 @@ void CurlDeleter::operator()(CURL *handle) noexcept {

Curl::Curl() noexcept {}

bool Curl::method_get_maybe_socks5(const std::string &proxy_port,
const std::string &url, long timeout,
std::string *body,
std::string *err) noexcept {
if (!init()) {
*err = "cannot initialize cURL";
return false;
}
if (!proxy_port.empty()) {
std::stringstream ss;
ss << "socks5h://127.0.0.1:" << proxy_port;
if (setopt_proxy(ss.str()) != CURLE_OK) {
*err = "cannot set proxy";
return false;
}
}
return method_get(url, timeout, body, err);
}

bool Curl::method_get(const std::string &url, long timeout, std::string *body,
std::string *err) noexcept {
if (body == nullptr || err == nullptr) {
Expand Down Expand Up @@ -80,7 +99,7 @@ bool Curl::method_get(const std::string &url, long timeout, std::string *body,

bool Curl::init() noexcept {
if (!!handle_) {
return false;
return true; // make the method idempotent
}
auto handle = this->easy_init();
if (!handle) {
Expand All @@ -95,6 +114,11 @@ CURLcode Curl::setopt_url(const std::string &url) noexcept {
return ::curl_easy_setopt(handle_.get(), CURLOPT_URL, url.c_str());
}

CURLcode Curl::setopt_proxy(const std::string &url) noexcept {
assert(handle_);
return ::curl_easy_setopt(handle_.get(), CURLOPT_PROXY, url.c_str());
}

CURLcode Curl::setopt_writefunction(size_t (*callback)(
char *ptr, size_t size, size_t nmemb, void *userdata)) noexcept {
assert(handle_);
Expand Down
6 changes: 6 additions & 0 deletions curlx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ class Curl {

Curl() noexcept;

bool method_get_maybe_socks5(const std::string &proxy_port,
const std::string &url, long timeout,
std::string *body, std::string *err) noexcept;

bool method_get(const std::string &url, long timeout, std::string *body,
std::string *err) noexcept;

Expand All @@ -35,6 +39,8 @@ class Curl {

virtual CURLcode setopt_url(const std::string &url) noexcept;

virtual CURLcode setopt_proxy(const std::string &url) noexcept;

virtual CURLcode setopt_writefunction(size_t (*callback)(
char *ptr, size_t size, size_t nmemb, void *userdata)) noexcept;

Expand Down
51 changes: 44 additions & 7 deletions curlx_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,40 @@

using namespace measurement_kit;

// Curl::method_get_maybe_socks5() tests
// -------------------------------------

class FailInit : public libndt::Curl {
public:
using libndt::Curl::Curl;
virtual bool init() noexcept override { return false; }
};

TEST_CASE("Curl::method_get_maybe_socks5() deals with Curl::init() failure") {
FailInit curl;
std::string body;
std::string err;
REQUIRE(!curl.method_get_maybe_socks5("", "http://x.org", 1, &body, &err));
}

class FailSetoptProxy : public libndt::Curl {
public:
using libndt::Curl::Curl;
virtual CURLcode setopt_proxy(const std::string &) noexcept override {
return CURLE_UNSUPPORTED_PROTOCOL; // any error is okay here
}
};

TEST_CASE(
"Curl::method_get_maybe_socks5() deals with Curl::setopt_proxy() failure") {
FailSetoptProxy curl;
std::string body;
std::string err;
REQUIRE(
!curl.method_get_maybe_socks5("9050", "http://x.org", 1, &body, &err));
REQUIRE(err == "cannot set proxy");
}

// Curl::method_get() tests
// ------------------------

Expand All @@ -24,12 +58,6 @@ TEST_CASE("Curl::method_get() deals with null err") {
REQUIRE(curl.method_get("http://x.org", 1, &body, nullptr) == false);
}

class FailInit : public libndt::Curl {
public:
using libndt::Curl::Curl;
virtual bool init() noexcept override { return false; }
};

TEST_CASE("Curl::method_get() deals with Curl::init() failure") {
FailInit curl;
std::string body;
Expand Down Expand Up @@ -129,7 +157,16 @@ TEST_CASE("Curl::init() deals with curl_easy_init() failure") {
TEST_CASE("Curl::init() is idempotent") {
libndt::Curl curl;
REQUIRE(curl.init() == true);
REQUIRE(curl.init() == false);
REQUIRE(curl.init() == true);
}

// Curl::setopt_proxy() tests
// --------------------------

TEST_CASE("Curl::setopt_proxy() works") {
libndt::Curl curl;
REQUIRE(curl.init() == true);
REQUIRE(curl.setopt_proxy("socks5h://127.0.0.1:9050") == CURLE_OK);
}

#endif // HAVE_CURL
9 changes: 8 additions & 1 deletion libndt-client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ static void usage() {
std::clog << " --download-ext : run multi-stream download test\n";
std::clog << " --json : use the JSON protocol\n";
std::clog << " --port <port> : use the specified port\n";
std::clog
<< " --socks5h <port> : use socks5h proxy at 127.0.0.1:<port>\n";
std::clog << " --upload : run upload test\n";
std::clog << " --verbose : be verbose\n";
std::clog << "\n";
Expand All @@ -31,11 +33,12 @@ int main(int, char **argv) {
using namespace measurement_kit;
libndt::Settings settings;
settings.verbosity = libndt::verbosity::quiet;
settings.test_suite = 0; // you need to enable tests explicitly
settings.test_suite = 0; // you need to enable tests explicitly

{
argh::parser cmdline;
cmdline.add_param("port");
cmdline.add_param("socks5h");
cmdline.parse(argv);
for (auto &flag : cmdline.flags()) {
if (flag == "download") {
Expand Down Expand Up @@ -63,6 +66,10 @@ int main(int, char **argv) {
if (param.first == "port") {
settings.port = param.second;
std::clog << "will use port: " << param.second << std::endl;
} else if (param.first == "socks5h") {
settings.socks5h_port = param.second;
std::clog << "will use socks5h proxy at: 127.0.0.1:" << param.second
<< std::endl;
} else {
std::clog << "fatal: unrecognized param: " << param.first << std::endl;
usage();
Expand Down
Loading

0 comments on commit eccd5e7

Please sign in to comment.