Commit 516a2f0e authored by Brian Card's avatar Brian Card

Adding an address parameter that allows nghttpd to bind to a non-default...

Adding an address parameter that allows nghttpd to bind to a non-default address.  Both IPv4 and IPv6 addresses are supported.  In addition with verbose mode enable the address that the webserver binds to is now printed in addition to the port.
parent 682db00b
......@@ -31,6 +31,7 @@
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <cassert>
#include <set>
......@@ -1459,12 +1460,34 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
}
} // namespace
namespace {
// finds a readable address and adds stores it in the given string
char *get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen) {
switch (sa->sa_family) {
case AF_INET:
inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), s, maxlen);
break;
case AF_INET6:
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), s, maxlen);
break;
default:
strncpy(s, "Unknown AF", maxlen);
return NULL;
}
return s;
}
} // namespace
namespace {
int start_listen(struct ev_loop *loop, Sessions *sessions,
const Config *config) {
addrinfo hints;
int r;
bool ok = false;
const char *addr = nullptr;
auto acceptor = std::make_shared<AcceptHandler>(sessions, config);
auto service = util::utos(config->port);
......@@ -1477,12 +1500,17 @@ int start_listen(struct ev_loop *loop, Sessions *sessions,
hints.ai_flags |= AI_ADDRCONFIG;
#endif // AI_ADDRCONFIG
if (!config->address.empty()) {
addr = config->address.c_str();
}
addrinfo *res, *rp;
r = getaddrinfo(nullptr, service.c_str(), &hints, &res);
r = getaddrinfo(addr, service.c_str(), &hints, &res);
if (r != 0) {
std::cerr << "getaddrinfo() failed: " << gai_strerror(r) << std::endl;
return -1;
}
for (rp = res; rp; rp = rp->ai_next) {
int fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (fd == -1) {
......@@ -1508,8 +1536,10 @@ int start_listen(struct ev_loop *loop, Sessions *sessions,
new ListenEventHandler(sessions, fd, acceptor);
if (config->verbose) {
std::cout << (rp->ai_family == AF_INET ? "IPv4" : "IPv6")
<< ": listen on port " << config->port << std::endl;
char s[INET6_ADDRSTRLEN];
get_ip_str((struct sockaddr *)rp->ai_addr, s, sizeof s);
std::cout << (rp->ai_family == AF_INET ? "IPv4" : "IPv6") << ": listen "
<< s << ":" << config->port << std::endl;
}
ok = true;
continue;
......
......@@ -55,6 +55,7 @@ struct Config {
std::string private_key_file;
std::string cert_file;
std::string dh_param_file;
std::string address;
ev_tstamp stream_read_timeout;
ev_tstamp stream_write_timeout;
nghttp2_option *session_option;
......
......@@ -97,6 +97,9 @@ void print_help(std::ostream &out) {
<CERT> Set path to server's certificate. Required unless
--no-tls is specified.
Options:
-a --address
The address to bind to. If not specified the default IP
address determined by getaddrinfo is used.
-D, --daemon
Run in a background. If -D is used, the current working
directory is changed to '/'. Therefore if this option
......@@ -151,30 +154,35 @@ int main(int argc, char **argv) {
while (1) {
static int flag = 0;
static option long_options[] = {
{"daemon", no_argument, nullptr, 'D'},
{"htdocs", required_argument, nullptr, 'd'},
{"help", no_argument, nullptr, 'h'},
{"verbose", no_argument, nullptr, 'v'},
{"verify-client", no_argument, nullptr, 'V'},
{"header-table-size", required_argument, nullptr, 'c'},
{"push", required_argument, nullptr, 'p'},
{"padding", required_argument, nullptr, 'b'},
{"workers", required_argument, nullptr, 'n'},
{"error-gzip", no_argument, nullptr, 'e'},
{"no-tls", no_argument, &flag, 1},
{"color", no_argument, &flag, 2},
{"version", no_argument, &flag, 3},
{"dh-param-file", required_argument, &flag, 4},
{"early-response", no_argument, &flag, 5},
{nullptr, 0, nullptr, 0}};
{ "address", required_argument, nullptr, 'a' },
{ "daemon", no_argument, nullptr, 'D' },
{ "htdocs", required_argument, nullptr, 'd' },
{ "help", no_argument, nullptr, 'h' },
{ "verbose", no_argument, nullptr, 'v' },
{ "verify-client", no_argument, nullptr, 'V' },
{ "header-table-size", required_argument, nullptr, 'c' },
{ "push", required_argument, nullptr, 'p' },
{ "padding", required_argument, nullptr, 'b' },
{ "workers", required_argument, nullptr, 'n' },
{ "error-gzip", no_argument, nullptr, 'e' },
{ "no-tls", no_argument, &flag, 1 },
{ "color", no_argument, &flag, 2 },
{ "version", no_argument, &flag, 3 },
{ "dh-param-file", required_argument, &flag, 4 },
{ "early-response", no_argument, &flag, 5 },
{ nullptr, 0, nullptr, 0 }
};
int option_index = 0;
int c =
getopt_long(argc, argv, "DVb:c:d:ehn:p:v", long_options, &option_index);
int c = getopt_long(argc, argv, "DVb:c:d:ehn:p:va:", long_options,
&option_index);
char *end;
if (c == -1) {
break;
}
switch (c) {
case 'a':
config.address = optarg;
break;
case 'D':
config.daemon = true;
break;
......
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