h2load: Allow port in --connect-to

This commit is contained in:
Tatsuhiro Tsujikawa 2019-12-21 11:38:27 +09:00
parent df575f968f
commit e0d7f7de5e
7 changed files with 89 additions and 6 deletions

View File

@ -94,6 +94,7 @@ Config::Config()
log_fd(-1),
port(0),
default_port(0),
connect_to_port(0),
verbose(false),
timing_script(false),
base_uri_unix(false),
@ -1565,9 +1566,11 @@ void resolve_host() {
const auto &resolve_host =
config.connect_to_host.empty() ? config.host : config.connect_to_host;
auto port =
config.connect_to_port == 0 ? config.port : config.connect_to_port;
rv = getaddrinfo(resolve_host.c_str(), util::utos(config.port).c_str(),
&hints, &res);
rv =
getaddrinfo(resolve_host.c_str(), util::utos(port).c_str(), &hints, &res);
if (rv != 0) {
std::cerr << "getaddrinfo() failed: " << gai_strerror(rv) << std::endl;
exit(EXIT_FAILURE);
@ -1982,8 +1985,9 @@ Options:
response time when using one worker thread, but may
appear slightly out of order with multiple threads due
to buffering. Status code is -1 for failed streams.
--connect-to=<HOST>
Host to connect instead of using the host in <URI>.
--connect-to=<HOST>[:<PORT>]
Host and port to connect instead of using the authority
in <URI>.
-v, --verbose
Output debug information.
--version Display version information and exit.
@ -2270,11 +2274,20 @@ int main(int argc, char **argv) {
// --log-file
logfile = optarg;
break;
case 11:
case 11: {
// --connect-to
config.connect_to_host = optarg;
auto p = util::split_hostport(StringRef{optarg});
int64_t port = 0;
if (p.first.empty() ||
(!p.second.empty() && (port = util::parse_uint(p.second)) == -1)) {
std::cerr << "--connect-to: Invalid value " << optarg << std::endl;
exit(EXIT_FAILURE);
}
config.connect_to_host = p.first.str();
config.connect_to_port = port;
break;
}
}
break;
default:
break;

View File

@ -102,6 +102,7 @@ struct Config {
int log_fd;
uint16_t port;
uint16_t default_port;
uint16_t connect_to_port;
bool verbose;
bool timing_script;
std::string base_uri;

View File

@ -195,6 +195,8 @@ int main(int argc, char *argv[]) {
!CU_add_test(pSuite, "util_decode_hex", shrpx::test_util_decode_hex) ||
!CU_add_test(pSuite, "util_extract_host",
shrpx::test_util_extract_host) ||
!CU_add_test(pSuite, "util_split_hostport",
shrpx::test_util_split_hostport) ||
!CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate) ||
!CU_add_test(pSuite, "buffer_write", nghttp2::test_buffer_write) ||
!CU_add_test(pSuite, "pool_recycle", nghttp2::test_pool_recycle) ||

View File

@ -1537,6 +1537,41 @@ StringRef extract_host(const StringRef &hostport) {
return StringRef{std::begin(hostport), p};
}
std::pair<StringRef, StringRef> split_hostport(const StringRef &hostport) {
if (hostport.empty()) {
return {};
}
if (hostport[0] == '[') {
// assume this is IPv6 numeric address
auto p = std::find(std::begin(hostport), std::end(hostport), ']');
if (p == std::end(hostport)) {
return {};
}
if (p + 1 == std::end(hostport)) {
return {StringRef{std::begin(hostport) + 1, p}, {}};
}
if (*(p + 1) != ':' || p + 2 == std::end(hostport)) {
return {};
}
return {StringRef{std::begin(hostport) + 1, p},
StringRef{p + 2, std::end(hostport)}};
}
auto p = std::find(std::begin(hostport), std::end(hostport), ':');
if (p == std::begin(hostport)) {
return {};
}
if (p == std::end(hostport)) {
return {StringRef{std::begin(hostport), p}, {}};
}
if (p + 1 == std::end(hostport)) {
return {};
}
return {StringRef{std::begin(hostport), p},
StringRef{p + 1, std::end(hostport)}};
}
std::mt19937 make_mt19937() {
std::random_device rd;
return std::mt19937(rd());

View File

@ -769,6 +769,13 @@ int sha1(uint8_t *buf, const StringRef &s);
// NULL-terminated.
StringRef extract_host(const StringRef &hostport);
// split_hostport splits host and port in |hostport|. Unlike
// extract_host, square brackets enclosing host name is stripped. If
// port is not available, it returns empty string in the second
// string. The returned string might not be NULL-terminated. On any
// error, it returns a pair which has empty strings.
std::pair<StringRef, StringRef> split_hostport(const StringRef &hostport);
// Returns new std::mt19937 object.
std::mt19937 make_mt19937();

View File

@ -628,4 +628,28 @@ void test_util_extract_host(void) {
CU_ASSERT(util::extract_host(StringRef{}).empty());
}
void test_util_split_hostport(void) {
CU_ASSERT(std::make_pair(StringRef::from_lit("foo"), StringRef{}) ==
util::split_hostport(StringRef::from_lit("foo")));
CU_ASSERT(
std::make_pair(StringRef::from_lit("foo"), StringRef::from_lit("80")) ==
util::split_hostport(StringRef::from_lit("foo:80")));
CU_ASSERT(
std::make_pair(StringRef::from_lit("::1"), StringRef::from_lit("80")) ==
util::split_hostport(StringRef::from_lit("[::1]:80")));
CU_ASSERT(std::make_pair(StringRef::from_lit("::1"), StringRef{}) ==
util::split_hostport(StringRef::from_lit("[::1]")));
CU_ASSERT(std::make_pair(StringRef{}, StringRef{}) ==
util::split_hostport(StringRef{}));
CU_ASSERT(std::make_pair(StringRef{}, StringRef{}) ==
util::split_hostport(StringRef::from_lit("[::1]:")));
CU_ASSERT(std::make_pair(StringRef{}, StringRef{}) ==
util::split_hostport(StringRef::from_lit("foo:")));
CU_ASSERT(std::make_pair(StringRef{}, StringRef{}) ==
util::split_hostport(StringRef::from_lit("[::1:")));
CU_ASSERT(std::make_pair(StringRef{}, StringRef{}) ==
util::split_hostport(StringRef::from_lit("[::1]80")));
}
} // namespace shrpx

View File

@ -67,6 +67,7 @@ void test_util_format_hex(void);
void test_util_is_hex_string(void);
void test_util_decode_hex(void);
void test_util_extract_host(void);
void test_util_split_hostport(void);
} // namespace shrpx