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