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

View File

@ -102,6 +102,7 @@ struct Config {
int log_fd; int log_fd;
uint16_t port; uint16_t port;
uint16_t default_port; uint16_t default_port;
uint16_t connect_to_port;
bool verbose; bool verbose;
bool timing_script; bool timing_script;
std::string base_uri; 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_decode_hex", shrpx::test_util_decode_hex) ||
!CU_add_test(pSuite, "util_extract_host", !CU_add_test(pSuite, "util_extract_host",
shrpx::test_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, "gzip_inflate", test_nghttp2_gzip_inflate) ||
!CU_add_test(pSuite, "buffer_write", nghttp2::test_buffer_write) || !CU_add_test(pSuite, "buffer_write", nghttp2::test_buffer_write) ||
!CU_add_test(pSuite, "pool_recycle", nghttp2::test_pool_recycle) || !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}; 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::mt19937 make_mt19937() {
std::random_device rd; std::random_device rd;
return std::mt19937(rd()); return std::mt19937(rd());

View File

@ -769,6 +769,13 @@ int sha1(uint8_t *buf, const StringRef &s);
// NULL-terminated. // NULL-terminated.
StringRef extract_host(const StringRef &hostport); 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. // Returns new std::mt19937 object.
std::mt19937 make_mt19937(); std::mt19937 make_mt19937();

View File

@ -628,4 +628,28 @@ void test_util_extract_host(void) {
CU_ASSERT(util::extract_host(StringRef{}).empty()); 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 } // namespace shrpx

View File

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