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:
Tatsuhiro Tsujikawa 2012-08-02 00:06:41 +09:00
parent 28e477eb3a
commit 1dd61d5973
4 changed files with 349 additions and 121 deletions

View File

@ -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);

View File

@ -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

View File

@ -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

29
shrpx.conf.sample Normal file
View File

@ -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