From 7d709fa3ff0a08aa229628595f34b99810c5c326 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 24 Mar 2013 21:03:39 +0900 Subject: [PATCH] shrpx: Support non-TLS SPDY in frontend connection --- src/shrpx.cc | 29 +++++++++++++++++++++++++-- src/shrpx_client_handler.cc | 9 +++++++-- src/shrpx_config.cc | 39 ++++++++++++++++++++++++++++++------- src/shrpx_config.h | 4 ++++ 4 files changed, 70 insertions(+), 11 deletions(-) diff --git a/src/shrpx.cc b/src/shrpx.cc index 8d0ae219..749a5216 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -243,7 +243,8 @@ int event_loop() cl_ssl_ctx = get_config()->spdy_downstream_no_tls ? 0 : ssl::create_ssl_client_context(); } else { - sv_ssl_ctx = get_config()->default_ssl_ctx; + sv_ssl_ctx = get_config()->spdy_upstream_no_tls ? + 0 : get_config()->default_ssl_ctx; cl_ssl_ctx = get_config()->spdy_bridge && !get_config()->spdy_downstream_no_tls ? ssl::create_ssl_client_context() : 0; @@ -356,6 +357,8 @@ void fill_default_config() mod_config()->spdy_upstream_window_bits = 16; mod_config()->spdy_downstream_window_bits = 16; + mod_config()->spdy_upstream_no_tls = false; + mod_config()->spdy_upstream_version = 3; mod_config()->spdy_downstream_no_tls = false; mod_config()->spdy_downstream_version = 3; @@ -530,6 +533,16 @@ void print_help(std::ostream& out) << " frontend connection to 2**.\n" << " Default: " << get_config()->spdy_upstream_window_bits << "\n" + << " --frontend-spdy-no-tls\n" + << " Disable SSL/TLS on frontend SPDY\n" + << " connections. SPDY protocol must be specified\n" + << " using --frontend-spdy-proto. This option\n" + << " also disables frontend HTTP/1.1.\n" + << " --frontend-spdy-proto\n" + << " Specify SPDY protocol used in frontend\n" + << " connection if --frontend-spdy-no-tls is\n" + << " used. Default: spdy/" + << get_config()->spdy_upstream_version << "\n" << " --backend-spdy-window-bits=\n" << " Sets the initial window size of SPDY\n" << " backend connection to 2**.\n" @@ -644,6 +657,8 @@ int main(int argc, char **argv) {"backend-http-proxy-uri", required_argument, &flag, 26}, {"backend-spdy-no-tls", no_argument, &flag, 27}, {"backend-spdy-proto", required_argument, &flag, 28}, + {"frontend-spdy-no-tls", no_argument, &flag, 29}, + {"frontend-spdy-proto", required_argument, &flag, 30}, {0, 0, 0, 0 } }; int option_index = 0; @@ -813,6 +828,16 @@ int main(int argc, char **argv) cmdcfgs.push_back(std::make_pair(SHRPX_OPT_BACKEND_SPDY_PROTO, optarg)); break; + case 29: + // --frontend-spdy-no-tls + cmdcfgs.push_back(std::make_pair(SHRPX_OPT_FRONTEND_SPDY_NO_TLS, + "yes")); + break; + case 30: + // --frontend-spdy-proto + cmdcfgs.push_back(std::make_pair(SHRPX_OPT_FRONTEND_SPDY_PROTO, + optarg)); + break; default: break; } @@ -882,7 +907,7 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } - if(!get_config()->client_mode) { + if(!get_config()->client_mode && !get_config()->spdy_upstream_no_tls) { if(!get_config()->private_key_file || !get_config()->cert_file) { print_usage(std::cerr); LOG(FATAL) << "Too few arguments"; diff --git a/src/shrpx_client_handler.cc b/src/shrpx_client_handler.cc index 914a815d..e2074d99 100644 --- a/src/shrpx_client_handler.cc +++ b/src/shrpx_client_handler.cc @@ -135,8 +135,13 @@ ClientHandler::ClientHandler(bufferevent *bev, int fd, SSL *ssl, if(ssl_) { set_bev_cb(0, upstream_writecb, upstream_eventcb); } else { - // For client-mode - upstream_ = new HttpsUpstream(this); + if(get_config()->client_mode) { + // Client mode + upstream_ = new HttpsUpstream(this); + } else { + // no-TLS SPDY + upstream_ = new SpdyUpstream(get_config()->spdy_upstream_version, this); + } set_bev_cb(upstream_readcb, upstream_writecb, upstream_eventcb); } } diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 9061ef11..97efebb1 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -75,6 +75,8 @@ const char SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT[] = "backend-keep-alive-timeout"; const char SHRPX_OPT_FRONTEND_SPDY_WINDOW_BITS[] = "frontend-spdy-window-bits"; const char SHRPX_OPT_BACKEND_SPDY_WINDOW_BITS[] = "backend-spdy-window-bits"; +const char SHRPX_OPT_FRONTEND_SPDY_NO_TLS[] = "frontend-spdy-no-tls"; +const char SHRPX_OPT_FRONTEND_SPDY_PROTO[] = "frontend-spdy-proto"; const char SHRPX_OPT_BACKEND_SPDY_NO_TLS[] = "backend-spdy-no-tls"; const char SHRPX_OPT_BACKEND_SPDY_PROTO[] = "backend-spdy-proto"; const char SHRPX_OPT_PID_FILE[] = "pid-file"; @@ -184,6 +186,23 @@ void set_config_str(char **destp, const char *val) *destp = strdup(val); } +namespace { +// Parses |optarg| as SPDY NPN protocol string and returns SPDY +// protocol version number. This function returns -1 on error. +int parse_spdy_proto(const char *optarg) +{ + size_t len = strlen(optarg); + const unsigned char *proto; + proto = reinterpret_cast(optarg); + uint16_t version = spdylay_npn_get_version(proto, len); + if(!version) { + LOG(ERROR) << "Unsupported SPDY version: " << optarg; + return -1; + } + return version; +} +} // namespace + int parse_config(const char *opt, const char *optarg) { char host[NI_MAXHOST]; @@ -263,18 +282,24 @@ int parse_config(const char *opt, const char *optarg) << " specify the integer in the range [0, 30], inclusive"; return -1; } + } else if(util::strieq(opt, SHRPX_OPT_FRONTEND_SPDY_NO_TLS)) { + mod_config()->spdy_upstream_no_tls = util::strieq(optarg, "yes"); + } else if(util::strieq(opt, SHRPX_OPT_FRONTEND_SPDY_PROTO)) { + int version = parse_spdy_proto(optarg); + if(version == -1) { + return -1; + } else { + mod_config()->spdy_upstream_version = version; + } } else if(util::strieq(opt, SHRPX_OPT_BACKEND_SPDY_NO_TLS)) { mod_config()->spdy_downstream_no_tls = util::strieq(optarg, "yes"); } else if(util::strieq(opt, SHRPX_OPT_BACKEND_SPDY_PROTO)) { - size_t len = strlen(optarg); - const unsigned char *proto; - proto = reinterpret_cast(optarg); - uint16_t version = spdylay_npn_get_version(proto, len); - if(!version) { - LOG(ERROR) << "Unsupported SPDY version: " << optarg; + int version = parse_spdy_proto(optarg); + if(version == -1) { return -1; + } else { + mod_config()->spdy_downstream_version = version; } - mod_config()->spdy_downstream_version = version; } else if(util::strieq(opt, SHRPX_OPT_PID_FILE)) { set_config_str(&mod_config()->pid_file, optarg); } else if(util::strieq(opt, SHRPX_OPT_USER)) { diff --git a/src/shrpx_config.h b/src/shrpx_config.h index 7fd56da6..b63d6e0c 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -68,6 +68,8 @@ extern const char SHRPX_OPT_ACCESSLOG[]; extern const char SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT[]; extern const char SHRPX_OPT_FRONTEND_SPDY_WINDOW_BITS[]; extern const char SHRPX_OPT_BACKEND_SPDY_WINDOW_BITS[]; +extern const char SHRPX_OPT_FRONTEND_SPDY_NO_TLS[]; +extern const char SHRPX_OPT_FRONTEND_SPDY_PROTO[]; extern const char SHRPX_OPT_BACKEND_SPDY_NO_TLS[]; extern const char SHRPX_OPT_BACKEND_SPDY_PROTO[]; extern const char SHRPX_OPT_PID_FILE[]; @@ -128,6 +130,8 @@ struct Config { bool accesslog; size_t spdy_upstream_window_bits; size_t spdy_downstream_window_bits; + bool spdy_upstream_no_tls; + uint16_t spdy_upstream_version; bool spdy_downstream_no_tls; uint16_t spdy_downstream_version; char *pid_file;