shrpx: Support configuration file
By default, configuration file is /etc/shrpx/shrpx.conf. It can be overridden using --conf option. See shrpx.conf.sample to know how to write shrpx.conf. The configurations given in shrpx.conf will be overridden by the options specified in cmmand-line.
This commit is contained in:
parent
28e477eb3a
commit
1dd61d5973
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
@ -33,12 +34,12 @@
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <pwd.h>
|
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
|
@ -248,13 +249,23 @@ void save_pid()
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// Returns true if regular file or symbolic link |path| exists.
|
||||||
|
bool conf_exists(const char *path)
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
int rv = stat(path, &buf);
|
||||||
|
return rv == 0 && (buf.st_mode & (S_IFREG | S_IFLNK));
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void fill_default_config()
|
void fill_default_config()
|
||||||
{
|
{
|
||||||
mod_config()->daemon = false;
|
mod_config()->daemon = false;
|
||||||
|
|
||||||
mod_config()->server_name = "shrpx spdylay/"SPDYLAY_VERSION;
|
mod_config()->server_name = "shrpx spdylay/"SPDYLAY_VERSION;
|
||||||
mod_config()->host = "localhost";
|
set_config_str(&mod_config()->host, "localhost");
|
||||||
mod_config()->port = 3000;
|
mod_config()->port = 3000;
|
||||||
mod_config()->private_key_file = 0;
|
mod_config()->private_key_file = 0;
|
||||||
mod_config()->cert_file = 0;
|
mod_config()->cert_file = 0;
|
||||||
|
@ -284,43 +295,15 @@ void fill_default_config()
|
||||||
// 2**16 = 64KiB, which is SPDY/3 default.
|
// 2**16 = 64KiB, which is SPDY/3 default.
|
||||||
mod_config()->spdy_upstream_window_bits = 16;
|
mod_config()->spdy_upstream_window_bits = 16;
|
||||||
|
|
||||||
mod_config()->downstream_host = "localhost";
|
set_config_str(&mod_config()->downstream_host, "localhost");
|
||||||
mod_config()->downstream_port = 80;
|
mod_config()->downstream_port = 80;
|
||||||
|
|
||||||
mod_config()->num_worker = 1;
|
mod_config()->num_worker = 1;
|
||||||
|
|
||||||
mod_config()->spdy_max_concurrent_streams =
|
mod_config()->spdy_max_concurrent_streams =
|
||||||
SPDYLAY_INITIAL_MAX_CONCURRENT_STREAMS;
|
SPDYLAY_INITIAL_MAX_CONCURRENT_STREAMS;
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace {
|
set_config_str(&mod_config()->conf_path, "/etc/shrpx/shrpx.conf");
|
||||||
int split_host_port(char *host, size_t hostlen, uint16_t *port_ptr,
|
|
||||||
const char *hostport)
|
|
||||||
{
|
|
||||||
// host and port in |hostport| is separated by single ','.
|
|
||||||
const char *p = strchr(hostport, ',');
|
|
||||||
if(!p) {
|
|
||||||
std::cerr << "Invalid host, port: " << hostport << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
size_t len = p-hostport;
|
|
||||||
if(hostlen < len+1) {
|
|
||||||
std::cerr << "Hostname too long: " << hostport << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memcpy(host, hostport, len);
|
|
||||||
host[len] = '\0';
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
unsigned long d = strtoul(p+1, 0, 10);
|
|
||||||
if(errno == 0 && 1 <= d && d <= std::numeric_limits<uint16_t>::max()) {
|
|
||||||
*port_ptr = d;
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
std::cerr << "Port is invalid: " << p+1 << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -339,7 +322,6 @@ void print_usage(std::ostream& out)
|
||||||
namespace {
|
namespace {
|
||||||
void print_help(std::ostream& out)
|
void print_help(std::ostream& out)
|
||||||
{
|
{
|
||||||
fill_default_config();
|
|
||||||
print_usage(out);
|
print_usage(out);
|
||||||
out << "\n"
|
out << "\n"
|
||||||
<< "OPTIONS:\n"
|
<< "OPTIONS:\n"
|
||||||
|
@ -405,6 +387,9 @@ void print_help(std::ostream& out)
|
||||||
<< " --pid-file=<PATH> Set path to save PID of this program.\n"
|
<< " --pid-file=<PATH> Set path to save PID of this program.\n"
|
||||||
<< " --user=<USER> Run this program as USER. This option is\n"
|
<< " --user=<USER> Run this program as USER. This option is\n"
|
||||||
<< " intended to be used to drop root privileges.\n"
|
<< " intended to be used to drop root privileges.\n"
|
||||||
|
<< " --conf=<PATH> Load configuration from PATH.\n"
|
||||||
|
<< " Default: "
|
||||||
|
<< get_config()->conf_path << "\n"
|
||||||
<< " -h, --help Print this help.\n"
|
<< " -h, --help Print this help.\n"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
@ -416,11 +401,7 @@ int main(int argc, char **argv)
|
||||||
create_config();
|
create_config();
|
||||||
fill_default_config();
|
fill_default_config();
|
||||||
|
|
||||||
char frontend_host[NI_MAXHOST];
|
std::vector<std::pair<const char*, const char*> > cmdcfgs;
|
||||||
uint16_t frontend_port;
|
|
||||||
char backend_host[NI_MAXHOST];
|
|
||||||
uint16_t backend_port;
|
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
int flag;
|
int flag;
|
||||||
static option long_options[] = {
|
static option long_options[] = {
|
||||||
|
@ -442,6 +423,7 @@ int main(int argc, char **argv)
|
||||||
{"frontend-spdy-window-bits", required_argument, &flag, 9 },
|
{"frontend-spdy-window-bits", required_argument, &flag, 9 },
|
||||||
{"pid-file", required_argument, &flag, 10 },
|
{"pid-file", required_argument, &flag, 10 },
|
||||||
{"user", required_argument, &flag, 11 },
|
{"user", required_argument, &flag, 11 },
|
||||||
|
{"conf", required_argument, &flag, 12 },
|
||||||
{"help", no_argument, 0, 'h' },
|
{"help", no_argument, 0, 'h' },
|
||||||
{0, 0, 0, 0 }
|
{0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
@ -453,43 +435,29 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'D':
|
case 'D':
|
||||||
mod_config()->daemon = true;
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_DAEMON, "yes"));
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
print_help(std::cout);
|
print_help(std::cout);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
case 'L':
|
case 'L':
|
||||||
if(Log::set_severity_level_by_name(optarg) == -1) {
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_LOG_LEVEL, optarg));
|
||||||
std::cerr << "Invalid severity level: " << optarg << std::endl;
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
if(split_host_port(backend_host, sizeof(backend_host),
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_BACKEND, optarg));
|
||||||
&backend_port, optarg) == -1) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
} else {
|
|
||||||
mod_config()->downstream_host = backend_host;
|
|
||||||
mod_config()->downstream_port = backend_port;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
if(split_host_port(frontend_host, sizeof(frontend_host),
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_FRONTEND, optarg));
|
||||||
&frontend_port, optarg) == -1) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
} else {
|
|
||||||
mod_config()->host = frontend_host;
|
|
||||||
mod_config()->port = frontend_port;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
mod_config()->num_worker = strtol(optarg, 0, 10);
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_WORKERS, optarg));
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
mod_config()->spdy_max_concurrent_streams = strtol(optarg, 0, 10);
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_SPDY_MAX_CONCURRENT_STREAMS,
|
||||||
|
optarg));
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
mod_config()->spdy_proxy = true;
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_SPDY_PROXY, "yes"));
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -497,74 +465,57 @@ int main(int argc, char **argv)
|
||||||
switch(flag) {
|
switch(flag) {
|
||||||
case 1:
|
case 1:
|
||||||
// --add-x-forwarded-for
|
// --add-x-forwarded-for
|
||||||
mod_config()->add_x_forwarded_for = true;
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_ADD_X_FORWARDED_FOR,
|
||||||
|
"yes"));
|
||||||
break;
|
break;
|
||||||
case 2: {
|
case 2:
|
||||||
// --frontend-spdy-read-timeout
|
// --frontend-spdy-read-timeout
|
||||||
timeval tv = {strtol(optarg, 0, 10), 0};
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_FRONTEND_SPDY_READ_TIMEOUT,
|
||||||
mod_config()->spdy_upstream_read_timeout = tv;
|
optarg));
|
||||||
break;
|
break;
|
||||||
}
|
case 3:
|
||||||
case 3: {
|
|
||||||
// --frontend-read-timeout
|
// --frontend-read-timeout
|
||||||
timeval tv = {strtol(optarg, 0, 10), 0};
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_FRONTEND_READ_TIMEOUT,
|
||||||
mod_config()->upstream_read_timeout = tv;
|
optarg));
|
||||||
break;
|
break;
|
||||||
}
|
case 4:
|
||||||
case 4: {
|
|
||||||
// --frontend-write-timeout
|
// --frontend-write-timeout
|
||||||
timeval tv = {strtol(optarg, 0, 10), 0};
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_FRONTEND_WRITE_TIMEOUT,
|
||||||
mod_config()->upstream_write_timeout = tv;
|
optarg));
|
||||||
break;
|
break;
|
||||||
}
|
case 5:
|
||||||
case 5: {
|
|
||||||
// --backend-read-timeout
|
// --backend-read-timeout
|
||||||
timeval tv = {strtol(optarg, 0, 10), 0};
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_BACKEND_READ_TIMEOUT,
|
||||||
mod_config()->downstream_read_timeout = tv;
|
optarg));
|
||||||
break;
|
break;
|
||||||
}
|
case 6:
|
||||||
case 6: {
|
|
||||||
// --backend-write-timeout
|
// --backend-write-timeout
|
||||||
timeval tv = {strtol(optarg, 0, 10), 0};
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_BACKEND_WRITE_TIMEOUT,
|
||||||
mod_config()->downstream_write_timeout = tv;
|
optarg));
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case 7:
|
case 7:
|
||||||
mod_config()->accesslog = true;
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_ACCESSLOG, "yes"));
|
||||||
break;
|
break;
|
||||||
case 8: {
|
case 8:
|
||||||
// --backend-keep-alive-timeout
|
// --backend-keep-alive-timeout
|
||||||
timeval tv = {strtol(optarg, 0, 10), 0};
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT,
|
||||||
mod_config()->downstream_idle_read_timeout = tv;
|
optarg));
|
||||||
break;
|
break;
|
||||||
}
|
case 9:
|
||||||
case 9: {
|
|
||||||
// --frontend-spdy-window-bits
|
// --frontend-spdy-window-bits
|
||||||
errno = 0;
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_FRONTEND_SPDY_WINDOW_BITS,
|
||||||
unsigned long int n = strtoul(optarg, 0, 10);
|
optarg));
|
||||||
if(errno == 0 && n < 31) {
|
|
||||||
mod_config()->spdy_upstream_window_bits = n;
|
|
||||||
} else {
|
|
||||||
std::cerr << "-w: specify the integer in the range [0, 30], inclusive"
|
|
||||||
<< std::endl;
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case 10:
|
case 10:
|
||||||
mod_config()->pid_file = optarg;
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_PID_FILE, optarg));
|
||||||
break;
|
break;
|
||||||
case 11: {
|
case 11:
|
||||||
passwd *pwd = getpwnam(optarg);
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_USER, optarg));
|
||||||
if(pwd == 0) {
|
break;
|
||||||
std::cerr << "--user: failed to get uid from " << optarg
|
case 12:
|
||||||
<< ": " << strerror(errno) << std::endl;
|
// --conf
|
||||||
exit(EXIT_FAILURE);
|
set_config_str(&mod_config()->conf_path, optarg);
|
||||||
}
|
|
||||||
mod_config()->uid = pwd->pw_uid;
|
|
||||||
mod_config()->gid = pwd->pw_gid;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -574,14 +525,33 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(argc-optind < 2) {
|
if(conf_exists(get_config()->conf_path)) {
|
||||||
|
if(load_config(get_config()->conf_path) == -1) {
|
||||||
|
std::cerr << "Failed to load configuration from "
|
||||||
|
<< get_config()->conf_path << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((!get_config()->private_key_file || !get_config()->cert_file) &&
|
||||||
|
argc - optind < 2) {
|
||||||
print_usage(std::cerr);
|
print_usage(std::cerr);
|
||||||
std::cerr << "Too few arguments" << std::endl;
|
std::cerr << "Too few arguments" << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
if(argc - optind >= 2) {
|
||||||
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_PRIVATE_KEY_FILE,
|
||||||
|
argv[optind++]));
|
||||||
|
cmdcfgs.push_back(std::make_pair(SHRPX_OPT_CERTIFICATE_FILE,
|
||||||
|
argv[optind++]));
|
||||||
|
}
|
||||||
|
|
||||||
mod_config()->private_key_file = argv[optind++];
|
for(size_t i = 0, len = cmdcfgs.size(); i < len; ++i) {
|
||||||
mod_config()->cert_file = argv[optind++];
|
if(parse_config(cmdcfgs[i].first, cmdcfgs[i].second) == -1) {
|
||||||
|
std::cerr << "Failed to parse command-line argument." << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char hostport[NI_MAXHOST+16];
|
char hostport[NI_MAXHOST+16];
|
||||||
bool downstream_ipv6_addr =
|
bool downstream_ipv6_addr =
|
||||||
|
@ -598,7 +568,7 @@ int main(int argc, char **argv)
|
||||||
downstream_ipv6_addr ? "]" : "",
|
downstream_ipv6_addr ? "]" : "",
|
||||||
get_config()->downstream_port);
|
get_config()->downstream_port);
|
||||||
}
|
}
|
||||||
mod_config()->downstream_hostport = hostport;
|
set_config_str(&mod_config()->downstream_hostport, hostport);
|
||||||
|
|
||||||
if(cache_downstream_host_address() == -1) {
|
if(cache_downstream_host_address() == -1) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
|
@ -24,8 +24,46 @@
|
||||||
*/
|
*/
|
||||||
#include "shrpx_config.h"
|
#include "shrpx_config.h"
|
||||||
|
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <limits>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
using namespace spdylay;
|
||||||
|
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
|
const char SHRPX_OPT_PRIVATE_KEY_FILE[] = "private-key-file";
|
||||||
|
const char SHRPX_OPT_CERTIFICATE_FILE[] = "certificate-file";
|
||||||
|
|
||||||
|
const char SHRPX_OPT_BACKEND[] = "backend";
|
||||||
|
const char SHRPX_OPT_FRONTEND[] = "frontend";
|
||||||
|
const char SHRPX_OPT_WORKERS[] = "workers";
|
||||||
|
const char
|
||||||
|
SHRPX_OPT_SPDY_MAX_CONCURRENT_STREAMS[] = "spdy-max-concurrent-streams";
|
||||||
|
const char SHRPX_OPT_LOG_LEVEL[] = "log-level";
|
||||||
|
const char SHRPX_OPT_DAEMON[] = "daemon";
|
||||||
|
const char SHRPX_OPT_SPDY_PROXY[] = "spdy-proxy";
|
||||||
|
const char SHRPX_OPT_ADD_X_FORWARDED_FOR[] = "add-x-forwarded-for";
|
||||||
|
const char
|
||||||
|
SHRPX_OPT_FRONTEND_SPDY_READ_TIMEOUT[] = "frontend-spdy-read-timeout";
|
||||||
|
const char SHRPX_OPT_FRONTEND_READ_TIMEOUT[] = "frontend-read-timeout";
|
||||||
|
const char SHRPX_OPT_FRONTEND_WRITE_TIMEOUT[] = "frontend-write-timeout";
|
||||||
|
const char SHRPX_OPT_BACKEND_READ_TIMEOUT[] = "backend-read-timeout";
|
||||||
|
const char SHRPX_OPT_BACKEND_WRITE_TIMEOUT[] = "backend-write-timeout";
|
||||||
|
const char SHRPX_OPT_ACCESSLOG[] = "accesslog";
|
||||||
|
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_PID_FILE[] = "pid-file";
|
||||||
|
const char SHRPX_OPT_USER[] = "user";
|
||||||
|
|
||||||
Config::Config()
|
Config::Config()
|
||||||
: verbose(false),
|
: verbose(false),
|
||||||
daemon(false),
|
daemon(false),
|
||||||
|
@ -47,7 +85,8 @@ Config::Config()
|
||||||
spdy_upstream_window_bits(0),
|
spdy_upstream_window_bits(0),
|
||||||
pid_file(0),
|
pid_file(0),
|
||||||
uid(0),
|
uid(0),
|
||||||
gid(0)
|
gid(0),
|
||||||
|
conf_path(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -69,4 +108,159 @@ void create_config()
|
||||||
config = new Config();
|
config = new Config();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int split_host_port(char *host, size_t hostlen, uint16_t *port_ptr,
|
||||||
|
const char *hostport)
|
||||||
|
{
|
||||||
|
// host and port in |hostport| is separated by single ','.
|
||||||
|
const char *p = strchr(hostport, ',');
|
||||||
|
if(!p) {
|
||||||
|
std::cerr << "Invalid host, port: " << hostport << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
size_t len = p-hostport;
|
||||||
|
if(hostlen < len+1) {
|
||||||
|
std::cerr << "Hostname too long: " << hostport << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(host, hostport, len);
|
||||||
|
host[len] = '\0';
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
unsigned long d = strtoul(p+1, 0, 10);
|
||||||
|
if(errno == 0 && 1 <= d && d <= std::numeric_limits<uint16_t>::max()) {
|
||||||
|
*port_ptr = d;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Port is invalid: " << p+1 << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void set_config_str(char **destp, const char *val)
|
||||||
|
{
|
||||||
|
if(*destp) {
|
||||||
|
free(*destp);
|
||||||
|
}
|
||||||
|
*destp = strdup(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_config(const char *opt, const char *optarg)
|
||||||
|
{
|
||||||
|
char host[NI_MAXHOST];
|
||||||
|
uint16_t port;
|
||||||
|
if(util::strieq(opt, SHRPX_OPT_BACKEND)) {
|
||||||
|
if(split_host_port(host, sizeof(host), &port, optarg) == -1) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
set_config_str(&mod_config()->downstream_host, host);
|
||||||
|
mod_config()->downstream_port = port;
|
||||||
|
}
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_FRONTEND)) {
|
||||||
|
if(split_host_port(host, sizeof(host), &port, optarg) == -1) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
set_config_str(&mod_config()->host, host);
|
||||||
|
mod_config()->port = port;
|
||||||
|
}
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_WORKERS)) {
|
||||||
|
mod_config()->num_worker = strtol(optarg, 0, 10);
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_SPDY_MAX_CONCURRENT_STREAMS)) {
|
||||||
|
mod_config()->spdy_max_concurrent_streams = strtol(optarg, 0, 10);
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_LOG_LEVEL)) {
|
||||||
|
if(Log::set_severity_level_by_name(optarg) == -1) {
|
||||||
|
std::cerr << "Invalid severity level: " << optarg << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_DAEMON)) {
|
||||||
|
mod_config()->daemon = util::strieq(optarg, "yes");
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_SPDY_PROXY)) {
|
||||||
|
mod_config()->spdy_proxy = util::strieq(optarg, "yes");
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_ADD_X_FORWARDED_FOR)) {
|
||||||
|
mod_config()->add_x_forwarded_for = util::strieq(optarg, "yes");
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_FRONTEND_SPDY_READ_TIMEOUT)) {
|
||||||
|
timeval tv = {strtol(optarg, 0, 10), 0};
|
||||||
|
mod_config()->spdy_upstream_read_timeout = tv;
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_FRONTEND_READ_TIMEOUT)) {
|
||||||
|
timeval tv = {strtol(optarg, 0, 10), 0};
|
||||||
|
mod_config()->upstream_read_timeout = tv;
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_FRONTEND_WRITE_TIMEOUT)) {
|
||||||
|
timeval tv = {strtol(optarg, 0, 10), 0};
|
||||||
|
mod_config()->upstream_write_timeout = tv;
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_BACKEND_READ_TIMEOUT)) {
|
||||||
|
timeval tv = {strtol(optarg, 0, 10), 0};
|
||||||
|
mod_config()->downstream_read_timeout = tv;
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_BACKEND_WRITE_TIMEOUT)) {
|
||||||
|
timeval tv = {strtol(optarg, 0, 10), 0};
|
||||||
|
mod_config()->downstream_write_timeout = tv;
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_ACCESSLOG)) {
|
||||||
|
mod_config()->accesslog = util::strieq(optarg, "yes");
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT)) {
|
||||||
|
timeval tv = {strtol(optarg, 0, 10), 0};
|
||||||
|
mod_config()->downstream_idle_read_timeout = tv;
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_FRONTEND_SPDY_WINDOW_BITS)) {
|
||||||
|
errno = 0;
|
||||||
|
unsigned long int n = strtoul(optarg, 0, 10);
|
||||||
|
if(errno == 0 && n < 31) {
|
||||||
|
mod_config()->spdy_upstream_window_bits = n;
|
||||||
|
} else {
|
||||||
|
std::cerr << "-w: specify the integer in the range [0, 30], inclusive"
|
||||||
|
<< std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} 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)) {
|
||||||
|
passwd *pwd = getpwnam(optarg);
|
||||||
|
if(pwd == 0) {
|
||||||
|
std::cerr << "--user: failed to get uid from " << optarg
|
||||||
|
<< ": " << strerror(errno) << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mod_config()->uid = pwd->pw_uid;
|
||||||
|
mod_config()->gid = pwd->pw_gid;
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_PRIVATE_KEY_FILE)) {
|
||||||
|
set_config_str(&mod_config()->private_key_file, optarg);
|
||||||
|
} else if(util::strieq(opt, SHRPX_OPT_CERTIFICATE_FILE)) {
|
||||||
|
set_config_str(&mod_config()->cert_file, optarg);
|
||||||
|
} else if(util::strieq(opt, "conf")) {
|
||||||
|
std::cerr << "conf is ignored" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Unknown option: " << opt << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int load_config(const char *filename)
|
||||||
|
{
|
||||||
|
std::ifstream in(filename, std::ios::binary);
|
||||||
|
if(!in) {
|
||||||
|
std::cerr << "Could not open config file " << filename << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
std::string line;
|
||||||
|
int linenum = 0;
|
||||||
|
while(std::getline(in, line)) {
|
||||||
|
++linenum;
|
||||||
|
if(line.empty() || line[0] == '#') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
size_t i;
|
||||||
|
size_t size = line.size();
|
||||||
|
for(i = 0; i < size && line[i] != '='; ++i);
|
||||||
|
if(i == size) {
|
||||||
|
std::cerr << "Bad configuration format at line " << linenum << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
line[i] = '\0';
|
||||||
|
const char *s = line.c_str();
|
||||||
|
if(parse_config(s, s+i+1) == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -33,10 +33,30 @@
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
|
extern const char SHRPX_OPT_PRIVATE_KEY_FILE[];
|
||||||
|
extern const char SHRPX_OPT_CERTIFICATE_FILE[];
|
||||||
|
|
||||||
|
extern const char SHRPX_OPT_BACKEND[];
|
||||||
|
extern const char SHRPX_OPT_FRONTEND[];
|
||||||
|
extern const char SHRPX_OPT_WORKERS[];
|
||||||
|
extern const char SHRPX_OPT_SPDY_MAX_CONCURRENT_STREAMS[];
|
||||||
|
extern const char SHRPX_OPT_LOG_LEVEL[];
|
||||||
|
extern const char SHRPX_OPT_DAEMON[];
|
||||||
|
extern const char SHRPX_OPT_SPDY_PROXY[];
|
||||||
|
extern const char SHRPX_OPT_ADD_X_FORWARDED_FOR[];
|
||||||
|
extern const char SHRPX_OPT_FRONTEND_SPDY_READ_TIMEOUT[];
|
||||||
|
extern const char SHRPX_OPT_FRONTEND_READ_TIMEOUT[];
|
||||||
|
extern const char SHRPX_OPT_FRONTEND_WRITE_TIMEOUT[];
|
||||||
|
extern const char SHRPX_OPT_BACKEND_READ_TIMEOUT[];
|
||||||
|
extern const char SHRPX_OPT_BACKEND_WRITE_TIMEOUT[];
|
||||||
|
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_PID_FILE[];
|
||||||
|
extern const char SHRPX_OPT_USER[];
|
||||||
|
|
||||||
union sockaddr_union {
|
union sockaddr_union {
|
||||||
sockaddr sa;
|
sockaddr sa;
|
||||||
sockaddr_storage storage;
|
sockaddr_storage storage;
|
||||||
|
@ -47,15 +67,15 @@ union sockaddr_union {
|
||||||
struct Config {
|
struct Config {
|
||||||
bool verbose;
|
bool verbose;
|
||||||
bool daemon;
|
bool daemon;
|
||||||
const char *host;
|
char *host;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
const char *private_key_file;
|
char *private_key_file;
|
||||||
const char *cert_file;
|
char *cert_file;
|
||||||
bool verify_client;
|
bool verify_client;
|
||||||
const char *server_name;
|
const char *server_name;
|
||||||
const char *downstream_host;
|
char *downstream_host;
|
||||||
uint16_t downstream_port;
|
uint16_t downstream_port;
|
||||||
const char *downstream_hostport;
|
char *downstream_hostport;
|
||||||
sockaddr_union downstream_addr;
|
sockaddr_union downstream_addr;
|
||||||
size_t downstream_addrlen;
|
size_t downstream_addrlen;
|
||||||
timeval spdy_upstream_read_timeout;
|
timeval spdy_upstream_read_timeout;
|
||||||
|
@ -70,9 +90,10 @@ struct Config {
|
||||||
bool add_x_forwarded_for;
|
bool add_x_forwarded_for;
|
||||||
bool accesslog;
|
bool accesslog;
|
||||||
size_t spdy_upstream_window_bits;
|
size_t spdy_upstream_window_bits;
|
||||||
const char* pid_file;
|
char *pid_file;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
|
char *conf_path;
|
||||||
Config();
|
Config();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,6 +101,20 @@ const Config* get_config();
|
||||||
Config* mod_config();
|
Config* mod_config();
|
||||||
void create_config();
|
void create_config();
|
||||||
|
|
||||||
|
// Parses option name |opt| and value |optarg|. The results are
|
||||||
|
// stored into statically allocated Config object. This function
|
||||||
|
// returns 0 if it succeeds, or -1.
|
||||||
|
int parse_config(const char *opt, const char *optarg);
|
||||||
|
|
||||||
|
// Loads configurations from |filename| and stores them in statically
|
||||||
|
// allocated Config object. This function returns 0 if it succeeds, or
|
||||||
|
// -1.
|
||||||
|
int load_config(const char *filename);
|
||||||
|
|
||||||
|
// Copies NULL-terminated string |val| to |*destp|. If |*destp| is not
|
||||||
|
// NULL, it is freed before copying.
|
||||||
|
void set_config_str(char **destp, const char *val);
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
||||||
#endif // SHRPX_CONFIG_H
|
#endif // SHRPX_CONFIG_H
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#
|
||||||
|
# Sample configuration file for Shrpx.
|
||||||
|
#
|
||||||
|
# * Line staring '#' is treated as comment.
|
||||||
|
#
|
||||||
|
# * The option name in the configuration file is the long command-line
|
||||||
|
# option name, stripped leading '--' (e.g., frontend). Put '='
|
||||||
|
# between option name and value. Don't put extra leading or trailing
|
||||||
|
# spaces.
|
||||||
|
#
|
||||||
|
# * The options which do not take argument in the command-line *take*
|
||||||
|
# argument in the configuration file. Specify 'yes' as argument
|
||||||
|
# (e.g., spdy-proxy=yes). If other string is given, it disables the
|
||||||
|
# option.
|
||||||
|
#
|
||||||
|
# * To specify private key and certificate file, use private-key-file
|
||||||
|
# and certificate-file. See the examples below.
|
||||||
|
#
|
||||||
|
# * conf option cannot be used in the configuration file. It will be
|
||||||
|
# ignored.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
#
|
||||||
|
# frontend=localhost,3000
|
||||||
|
# backend=localhost,80
|
||||||
|
# private-key-file=/path/to/server.key
|
||||||
|
# certificate-file=/path/to/server.crt
|
||||||
|
# spdy-proxy=no
|
||||||
|
# workers=1
|
Loading…
Reference in New Issue