Commit 3e1aad60 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

nghttp: Remove --no-tls option and detect TLS requirement using URI scheme

parent 4fac4eb9
...@@ -79,7 +79,6 @@ struct Config { ...@@ -79,7 +79,6 @@ struct Config {
bool verbose; bool verbose;
bool get_assets; bool get_assets;
bool stat; bool stat;
bool no_tls;
bool no_connection_flow_control; bool no_connection_flow_control;
bool no_stream_flow_control; bool no_stream_flow_control;
bool upgrade; bool upgrade;
...@@ -99,7 +98,6 @@ struct Config { ...@@ -99,7 +98,6 @@ struct Config {
verbose(false), verbose(false),
get_assets(false), get_assets(false),
stat(false), stat(false),
no_tls(false),
no_connection_flow_control(false), no_connection_flow_control(false),
no_stream_flow_control(false), no_stream_flow_control(false),
upgrade(false), upgrade(false),
...@@ -400,6 +398,7 @@ struct HttpClient { ...@@ -400,6 +398,7 @@ struct HttpClient {
std::set<std::string> path_cache; std::set<std::string> path_cache;
// The number of completed requests, including failed ones. // The number of completed requests, including failed ones.
size_t complete; size_t complete;
std::string scheme;
std::string hostport; std::string hostport;
SessionStat stat; SessionStat stat;
// Used for parse the HTTP upgrade response from server // Used for parse the HTTP upgrade response from server
...@@ -436,6 +435,11 @@ struct HttpClient { ...@@ -436,6 +435,11 @@ struct HttpClient {
delete htp; delete htp;
} }
bool need_upgrade() const
{
return config.upgrade && scheme == "http";
}
int initiate_connection(const std::string& host, uint16_t port) int initiate_connection(const std::string& host, uint16_t port)
{ {
int rv; int rv;
...@@ -475,7 +479,7 @@ struct HttpClient { ...@@ -475,7 +479,7 @@ struct HttpClient {
return -1; return -1;
} }
bufferevent_enable(bev, EV_READ); bufferevent_enable(bev, EV_READ);
if(config.upgrade) { if(need_upgrade()) {
htp = new http_parser(); htp = new http_parser();
http_parser_init(htp, HTTP_RESPONSE); http_parser_init(htp, HTTP_RESPONSE);
htp->data = this; htp->data = this;
...@@ -610,14 +614,14 @@ struct HttpClient { ...@@ -610,14 +614,14 @@ struct HttpClient {
int on_connect() int on_connect()
{ {
int rv; int rv;
if(!config.upgrade) { if(!need_upgrade()) {
record_handshake_time(); record_handshake_time();
} }
rv = nghttp2_session_client_new(&session, callbacks, this); rv = nghttp2_session_client_new(&session, callbacks, this);
if(rv != 0) { if(rv != 0) {
return -1; return -1;
} }
if(config.upgrade) { if(need_upgrade()) {
// Adjust stream user-data depending on the existence of upload // Adjust stream user-data depending on the existence of upload
// data // data
Request *stream_user_data = nullptr; Request *stream_user_data = nullptr;
...@@ -641,7 +645,7 @@ struct HttpClient { ...@@ -641,7 +645,7 @@ struct HttpClient {
// If upgrade succeeds, the SETTINGS value sent with // If upgrade succeeds, the SETTINGS value sent with
// HTTP2-Settings header field has already been submitted to // HTTP2-Settings header field has already been submitted to
// session object. // session object.
if(!config.upgrade) { if(!need_upgrade()) {
nghttp2_settings_entry iv[16]; nghttp2_settings_entry iv[16];
auto niv = populate_settings(iv); auto niv = populate_settings(iv);
rv = nghttp2_submit_settings(session, iv, niv); rv = nghttp2_submit_settings(session, iv, niv);
...@@ -658,7 +662,7 @@ struct HttpClient { ...@@ -658,7 +662,7 @@ struct HttpClient {
} }
// Adjust first request depending on the existence of the upload // Adjust first request depending on the existence of the upload
// data // data
for(auto i = std::begin(reqvec)+(config.upgrade && !reqvec[0]->data_prd); for(auto i = std::begin(reqvec)+(need_upgrade() && !reqvec[0]->data_prd);
i != std::end(reqvec); ++i) { i != std::end(reqvec); ++i) {
submit_request(this, config.headers, (*i).get()); submit_request(this, config.headers, (*i).get());
} }
...@@ -744,6 +748,7 @@ struct HttpClient { ...@@ -744,6 +748,7 @@ struct HttpClient {
if(reqvec.empty()) { if(reqvec.empty()) {
return; return;
} }
scheme = get_uri_field(reqvec[0]->uri.c_str(), reqvec[0]->u, UF_SCHEMA);
std::stringstream ss; std::stringstream ss;
if(reqvec[0]->is_ipv6_literal_addr()) { if(reqvec[0]->is_ipv6_literal_addr()) {
ss << "["; ss << "[";
...@@ -1187,7 +1192,7 @@ void eventcb(bufferevent *bev, short events, void *ptr) ...@@ -1187,7 +1192,7 @@ void eventcb(bufferevent *bev, short events, void *ptr)
std::cerr << "Setting option TCP_NODELAY failed: errno=" std::cerr << "Setting option TCP_NODELAY failed: errno="
<< errno << std::endl; << errno << std::endl;
} }
if(config.upgrade) { if(client->need_upgrade()) {
rv = client->on_upgrade_connect(); rv = client->on_upgrade_connect();
} else { } else {
// TODO Check NPN result and fail fast? // TODO Check NPN result and fail fast?
...@@ -1239,7 +1244,8 @@ ssize_t client_recv_callback(nghttp2_session *session, ...@@ -1239,7 +1244,8 @@ ssize_t client_recv_callback(nghttp2_session *session,
} }
} // namespace } // namespace
int communicate(const std::string& host, uint16_t port, int communicate(const std::string& scheme, const std::string& host,
uint16_t port,
std::vector<std::tuple<std::string, std::vector<std::tuple<std::string,
nghttp2_data_provider*, nghttp2_data_provider*,
int64_t>> requests, int64_t>> requests,
...@@ -1248,7 +1254,7 @@ int communicate(const std::string& host, uint16_t port, ...@@ -1248,7 +1254,7 @@ int communicate(const std::string& host, uint16_t port,
int result = 0; int result = 0;
auto evbase = event_base_new(); auto evbase = event_base_new();
SSL_CTX *ssl_ctx = nullptr; SSL_CTX *ssl_ctx = nullptr;
if(!config.no_tls) { if(scheme == "https") {
ssl_ctx = SSL_CTX_new(SSLv23_client_method()); ssl_ctx = SSL_CTX_new(SSLv23_client_method());
if(!ssl_ctx) { if(!ssl_ctx) {
std::cerr << "Failed to create SSL_CTX: " std::cerr << "Failed to create SSL_CTX: "
...@@ -1355,6 +1361,7 @@ int run(char **uris, int n) ...@@ -1355,6 +1361,7 @@ int run(char **uris, int n)
callbacks.on_unknown_frame_recv_callback = on_unknown_frame_recv_callback; callbacks.on_unknown_frame_recv_callback = on_unknown_frame_recv_callback;
} }
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback; callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
std::string prev_scheme;
std::string prev_host; std::string prev_host;
uint16_t prev_port = 0; uint16_t prev_port = 0;
int failures = 0; int failures = 0;
...@@ -1385,15 +1392,17 @@ int run(char **uris, int n) ...@@ -1385,15 +1392,17 @@ int run(char **uris, int n)
has_uri_field(u, UF_SCHEMA)) { has_uri_field(u, UF_SCHEMA)) {
uint16_t port = has_uri_field(u, UF_PORT) ? uint16_t port = has_uri_field(u, UF_PORT) ?
u.port : get_default_port(uri.c_str(), u); u.port : get_default_port(uri.c_str(), u);
if(!fieldeq(uri.c_str(), u, UF_HOST, prev_host.c_str()) || if(!fieldeq(uri.c_str(), u, UF_SCHEMA, prev_scheme.c_str()) ||
!fieldeq(uri.c_str(), u, UF_HOST, prev_host.c_str()) ||
u.port != prev_port) { u.port != prev_port) {
if(!requests.empty()) { if(!requests.empty()) {
if (communicate(prev_host, prev_port, std::move(requests), if (communicate(prev_scheme, prev_host, prev_port,
&callbacks) != 0) { std::move(requests), &callbacks) != 0) {
++failures; ++failures;
} }
requests.clear(); requests.clear();
} }
prev_scheme = get_uri_field(uri.c_str(), u, UF_SCHEMA);
prev_host = get_uri_field(uri.c_str(), u, UF_HOST); prev_host = get_uri_field(uri.c_str(), u, UF_HOST);
prev_port = port; prev_port = port;
} }
...@@ -1402,7 +1411,7 @@ int run(char **uris, int n) ...@@ -1402,7 +1411,7 @@ int run(char **uris, int n)
} }
} }
if(!requests.empty()) { if(!requests.empty()) {
if (communicate(prev_host, prev_port, std::move(requests), if (communicate(prev_scheme, prev_host, prev_port, std::move(requests),
&callbacks) != 0) { &callbacks) != 0) {
++failures; ++failures;
} }
...@@ -1413,7 +1422,7 @@ int run(char **uris, int n) ...@@ -1413,7 +1422,7 @@ int run(char **uris, int n)
void print_usage(std::ostream& out) void print_usage(std::ostream& out)
{ {
out << "Usage: nghttp [-FOafnsuv] [-t <SECONDS>] [-w <WINDOW_BITS>] [--cert=<CERT>]\n" out << "Usage: nghttp [-FOafnsuv] [-t <SECONDS>] [-w <WINDOW_BITS>] [--cert=<CERT>]\n"
<< " [--key=<KEY>] [--no-tls] [-d <FILE>] [-m <N>] [-p <PRIORITY>]\n" << " [--key=<KEY>] [-d <FILE>] [-m <N>] [-p <PRIORITY>]\n"
<< " <URI>..." << " <URI>..."
<< std::endl; << std::endl;
} }
...@@ -1444,7 +1453,6 @@ void print_help(std::ostream& out) ...@@ -1444,7 +1453,6 @@ void print_help(std::ostream& out)
<< " The file must be in PEM format.\n" << " The file must be in PEM format.\n"
<< " --key=<KEY> Use the client private key file. The file\n" << " --key=<KEY> Use the client private key file. The file\n"
<< " must be in PEM format.\n" << " must be in PEM format.\n"
<< " --no-tls Disable SSL/TLS.\n"
<< " -d, --data=<FILE> Post FILE to server. If - is given, data\n" << " -d, --data=<FILE> Post FILE to server. If - is given, data\n"
<< " will be read from stdin.\n" << " will be read from stdin.\n"
<< " -m, --multiply=<N> Request each URI <N> times. By default, same\n" << " -m, --multiply=<N> Request each URI <N> times. By default, same\n"
...@@ -1455,7 +1463,8 @@ void print_help(std::ostream& out) ...@@ -1455,7 +1463,8 @@ void print_help(std::ostream& out)
<< " -f, --no-stream-flow-control\n" << " -f, --no-stream-flow-control\n"
<< " Disables stream level flow control.\n" << " Disables stream level flow control.\n"
<< " -u, --upgrade Perform HTTP Upgrade for HTTP/2.0. This\n" << " -u, --upgrade Perform HTTP Upgrade for HTTP/2.0. This\n"
<< " option is ignored if --no-tls is not given.\n" << " option is ignored if the request URI has\n"
<< " https scheme.\n"
<< " If -d is used, the HTTP upgrade request is\n" << " If -d is used, the HTTP upgrade request is\n"
<< " performed with OPTIONS method.\n" << " performed with OPTIONS method.\n"
<< " -p, --pri=<PRIORITY>\n" << " -p, --pri=<PRIORITY>\n"
...@@ -1480,7 +1489,6 @@ int main(int argc, char **argv) ...@@ -1480,7 +1489,6 @@ int main(int argc, char **argv)
{"key", required_argument, &flag, 2 }, {"key", required_argument, &flag, 2 },
{"help", no_argument, 0, 'h' }, {"help", no_argument, 0, 'h' },
{"header", required_argument, 0, 'H' }, {"header", required_argument, 0, 'H' },
{"no-tls", no_argument, &flag, 3 },
{"data", required_argument, 0, 'd' }, {"data", required_argument, 0, 'd' },
{"multiply", required_argument, 0, 'm' }, {"multiply", required_argument, 0, 'm' },
{"no-connection-flow-control", no_argument, 0, 'F'}, {"no-connection-flow-control", no_argument, 0, 'F'},
...@@ -1597,10 +1605,6 @@ int main(int argc, char **argv) ...@@ -1597,10 +1605,6 @@ int main(int argc, char **argv)
// key option // key option
config.keyfile = optarg; config.keyfile = optarg;
break; break;
case 3:
// no-tls option
config.no_tls = true;
break;
} }
break; break;
default: default:
...@@ -1610,12 +1614,6 @@ int main(int argc, char **argv) ...@@ -1610,12 +1614,6 @@ int main(int argc, char **argv)
set_color_output(isatty(fileno(stdout))); set_color_output(isatty(fileno(stdout)));
if(!config.no_tls && config.upgrade) {
std::cerr << "Warning: -u is ignored because --no-tls is not given."
<< std::endl;
config.upgrade = false;
}
struct sigaction act; struct sigaction act;
memset(&act, 0, sizeof(struct sigaction)); memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = SIG_IGN; act.sa_handler = SIG_IGN;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment