nghttpx: Accept s or ms as unit for <T> argument
This commit is contained in:
parent
402ebb277f
commit
6a39de0ae5
|
@ -134,6 +134,8 @@ int main(int argc, char *argv[]) {
|
|||
!CU_add_test(pSuite, "util_parse_uint_with_unit",
|
||||
shrpx::test_util_parse_uint_with_unit) ||
|
||||
!CU_add_test(pSuite, "util_parse_uint", shrpx::test_util_parse_uint) ||
|
||||
!CU_add_test(pSuite, "util_parse_time_with_unit",
|
||||
shrpx::test_util_parse_time_with_unit) ||
|
||||
!CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate) ||
|
||||
!CU_add_test(pSuite, "ringbuf_write", nghttp2::test_ringbuf_write) ||
|
||||
!CU_add_test(pSuite, "ringbuf_iovec", nghttp2::test_ringbuf_iovec) ||
|
||||
|
|
59
src/shrpx.cc
59
src/shrpx.cc
|
@ -902,46 +902,55 @@ Performance:
|
|||
--num-accept=<N>
|
||||
The number of connections acceptor can accept at once.
|
||||
Default: )" << get_config()->num_accept << R"(
|
||||
--accept-delay=<MSEC>
|
||||
Acceptors get idle in <MSEC> milliseconds after they
|
||||
--accept-delay=<T>
|
||||
Acceptors get idle in <T> amount of time after they
|
||||
accepted at most N connections, where N is defined in
|
||||
--num-accept option.
|
||||
Default: )" << static_cast<int>(get_config()->accept_delay * 1000)
|
||||
Default: )" << util::duration_str(get_config()->accept_delay)
|
||||
<< R"(
|
||||
|
||||
Timeout:
|
||||
--frontend-http2-read-timeout=<SEC>
|
||||
--frontend-http2-read-timeout=<T>
|
||||
Specify read timeout for HTTP/2 and SPDY frontend
|
||||
connection.
|
||||
Default: )" << get_config()->http2_upstream_read_timeout << R"(
|
||||
--frontend-read-timeout=<SEC>
|
||||
Default: )"
|
||||
<< util::duration_str(get_config()->http2_upstream_read_timeout) << R"(
|
||||
--frontend-read-timeout=<T>
|
||||
Specify read timeout for HTTP/1.1 frontend connection.
|
||||
Default: )" << get_config()->upstream_read_timeout << R"(
|
||||
--frontend-write-timeout=<SEC>
|
||||
Default: )"
|
||||
<< util::duration_str(get_config()->upstream_read_timeout) << R"(
|
||||
--frontend-write-timeout=<T>
|
||||
Specify write timeout for all frontend connections.
|
||||
Default: )" << get_config()->upstream_write_timeout << R"(
|
||||
--stream-read-timeout=<SEC>
|
||||
Default: )"
|
||||
<< util::duration_str(get_config()->upstream_write_timeout) << R"(
|
||||
--stream-read-timeout=<T>
|
||||
Specify read timeout for HTTP/2 and SPDY streams. 0
|
||||
means no timeout.
|
||||
Default: )" << get_config()->stream_read_timeout << R"(
|
||||
--stream-write-timeout=<SEC>
|
||||
Default: )"
|
||||
<< util::duration_str(get_config()->stream_read_timeout) << R"(
|
||||
--stream-write-timeout=<T>
|
||||
Specify write timeout for HTTP/2 and SPDY streams. 0
|
||||
means no timeout.
|
||||
Default: )" << get_config()->stream_write_timeout << R"(
|
||||
--backend-read-timeout=<SEC>
|
||||
Default: )"
|
||||
<< util::duration_str(get_config()->stream_write_timeout) << R"(
|
||||
--backend-read-timeout=<T>
|
||||
Specify read timeout for backend connection.
|
||||
Default: )" << get_config()->downstream_read_timeout << R"(
|
||||
--backend-write-timeout=<SEC>
|
||||
Default: )"
|
||||
<< util::duration_str(get_config()->downstream_read_timeout) << R"(
|
||||
--backend-write-timeout=<T>
|
||||
Specify write timeout for backend connection.
|
||||
Default: )" << get_config()->downstream_write_timeout << R"(
|
||||
--backend-keep-alive-timeout=<SEC>
|
||||
Default: )"
|
||||
<< util::duration_str(get_config()->downstream_write_timeout) << R"(
|
||||
--backend-keep-alive-timeout=<T>
|
||||
Specify keep-alive timeout for backend connection.
|
||||
Default: )" << get_config()->downstream_idle_read_timeout << R"(
|
||||
--listener-disable-timeout=<SEC>
|
||||
Default: )"
|
||||
<< util::duration_str(get_config()->downstream_idle_read_timeout) << R"(
|
||||
--listener-disable-timeout=<T>
|
||||
After accepting connection failed, connection listener
|
||||
is disabled for a given time in seconds. Specifying 0
|
||||
is disabled for a given amount of time. Specifying 0
|
||||
disables this feature.
|
||||
Default: )" << get_config()->listener_disable_timeout << R"(
|
||||
Default: )"
|
||||
<< util::duration_str(get_config()->listener_disable_timeout) << R"(
|
||||
|
||||
SSL/TLS:
|
||||
--ciphers=<SUITE>
|
||||
|
@ -1203,7 +1212,11 @@ Misc:
|
|||
-h, --help Print this help and exit.
|
||||
|
||||
The <SIZE> argument is an integer and an optional unit (e.g., 10K is
|
||||
10 * 1024). Units are K, M and G (powers of 1024).)" << std::endl;
|
||||
10 * 1024). Units are K, M and G (powers of 1024).
|
||||
|
||||
The <T> argument is an integer and an optional unit (e.g., 1s is 1
|
||||
second and 500ms is 500 milliseconds). Units are s or ms. If a
|
||||
unit is omitted, a second is used as unit.)" << std::endl;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
|
|
@ -503,14 +503,14 @@ std::vector<LogFragment> parse_log_format(const char *optarg) {
|
|||
}
|
||||
|
||||
namespace {
|
||||
int parse_timeval(ev_tstamp *dest, const char *opt, const char *optarg) {
|
||||
time_t sec;
|
||||
|
||||
if (parse_uint(&sec, opt, optarg) != 0) {
|
||||
int parse_duration(ev_tstamp *dest, const char *opt, const char *optarg) {
|
||||
auto t = util::parse_time_with_unit(optarg);
|
||||
if (t == std::numeric_limits<double>::infinity()) {
|
||||
LOG(ERROR) << opt << ": bad value: '" << optarg << "'";
|
||||
return -1;
|
||||
}
|
||||
|
||||
*dest = sec;
|
||||
*dest = t;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -604,32 +604,32 @@ int parse_config(const char *opt, const char *optarg) {
|
|||
}
|
||||
|
||||
if (util::strieq(opt, SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT)) {
|
||||
return parse_timeval(&mod_config()->http2_upstream_read_timeout, opt,
|
||||
optarg);
|
||||
return parse_duration(&mod_config()->http2_upstream_read_timeout, opt,
|
||||
optarg);
|
||||
}
|
||||
|
||||
if (util::strieq(opt, SHRPX_OPT_FRONTEND_READ_TIMEOUT)) {
|
||||
return parse_timeval(&mod_config()->upstream_read_timeout, opt, optarg);
|
||||
return parse_duration(&mod_config()->upstream_read_timeout, opt, optarg);
|
||||
}
|
||||
|
||||
if (util::strieq(opt, SHRPX_OPT_FRONTEND_WRITE_TIMEOUT)) {
|
||||
return parse_timeval(&mod_config()->upstream_write_timeout, opt, optarg);
|
||||
return parse_duration(&mod_config()->upstream_write_timeout, opt, optarg);
|
||||
}
|
||||
|
||||
if (util::strieq(opt, SHRPX_OPT_BACKEND_READ_TIMEOUT)) {
|
||||
return parse_timeval(&mod_config()->downstream_read_timeout, opt, optarg);
|
||||
return parse_duration(&mod_config()->downstream_read_timeout, opt, optarg);
|
||||
}
|
||||
|
||||
if (util::strieq(opt, SHRPX_OPT_BACKEND_WRITE_TIMEOUT)) {
|
||||
return parse_timeval(&mod_config()->downstream_write_timeout, opt, optarg);
|
||||
return parse_duration(&mod_config()->downstream_write_timeout, opt, optarg);
|
||||
}
|
||||
|
||||
if (util::strieq(opt, SHRPX_OPT_STREAM_READ_TIMEOUT)) {
|
||||
return parse_timeval(&mod_config()->stream_read_timeout, opt, optarg);
|
||||
return parse_duration(&mod_config()->stream_read_timeout, opt, optarg);
|
||||
}
|
||||
|
||||
if (util::strieq(opt, SHRPX_OPT_STREAM_WRITE_TIMEOUT)) {
|
||||
return parse_timeval(&mod_config()->stream_write_timeout, opt, optarg);
|
||||
return parse_duration(&mod_config()->stream_write_timeout, opt, optarg);
|
||||
}
|
||||
|
||||
if (util::strieq(opt, SHRPX_OPT_ACCESSLOG_FILE)) {
|
||||
|
@ -663,8 +663,8 @@ int parse_config(const char *opt, const char *optarg) {
|
|||
}
|
||||
|
||||
if (util::strieq(opt, SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT)) {
|
||||
return parse_timeval(&mod_config()->downstream_idle_read_timeout, opt,
|
||||
optarg);
|
||||
return parse_duration(&mod_config()->downstream_idle_read_timeout, opt,
|
||||
optarg);
|
||||
}
|
||||
|
||||
if (util::strieq(opt, SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS) ||
|
||||
|
@ -1104,7 +1104,7 @@ int parse_config(const char *opt, const char *optarg) {
|
|||
}
|
||||
|
||||
if (util::strieq(opt, SHRPX_OPT_LISTENER_DISABLE_TIMEOUT)) {
|
||||
return parse_timeval(&mod_config()->listener_disable_timeout, opt, optarg);
|
||||
return parse_duration(&mod_config()->listener_disable_timeout, opt, optarg);
|
||||
}
|
||||
|
||||
if (util::strieq(opt, SHRPX_OPT_TLS_TICKET_KEY_FILE)) {
|
||||
|
@ -1170,14 +1170,7 @@ int parse_config(const char *opt, const char *optarg) {
|
|||
}
|
||||
|
||||
if (util::strieq(opt, SHRPX_OPT_ACCEPT_DELAY)) {
|
||||
size_t n;
|
||||
if (parse_uint(&n, opt, optarg) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mod_config()->accept_delay = n / 1000.;
|
||||
|
||||
return 0;
|
||||
return parse_duration(&mod_config()->accept_delay, opt, optarg);
|
||||
}
|
||||
|
||||
if (util::strieq(opt, "conf")) {
|
||||
|
|
88
src/util.cc
88
src/util.cc
|
@ -899,32 +899,48 @@ bool ipv6_numeric_addr(const char *host) {
|
|||
return inet_pton(AF_INET6, host, dst) == 1;
|
||||
}
|
||||
|
||||
int64_t parse_uint_with_unit(const char *s) {
|
||||
namespace {
|
||||
std::pair<int64_t, size_t> parse_uint_digits(const void *ss, size_t len) {
|
||||
const uint8_t *s = static_cast<const uint8_t *>(ss);
|
||||
int64_t n = 0;
|
||||
size_t i;
|
||||
auto len = strlen(s);
|
||||
if (len == 0) {
|
||||
return -1;
|
||||
return {-1, 0};
|
||||
}
|
||||
constexpr int64_t max = std::numeric_limits<int64_t>::max();
|
||||
for (i = 0; i < len; ++i) {
|
||||
if ('0' <= s[i] && s[i] <= '9') {
|
||||
if (n > max / 10) {
|
||||
return -1;
|
||||
return {-1, 0};
|
||||
}
|
||||
n *= 10;
|
||||
if (n > max - (s[i] - '0')) {
|
||||
return -1;
|
||||
return {-1, 0};
|
||||
}
|
||||
n += s[i] - '0';
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (i == 0) {
|
||||
return {-1, 0};
|
||||
}
|
||||
return {n, i};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int64_t parse_uint_with_unit(const char *s) {
|
||||
int64_t n;
|
||||
size_t i;
|
||||
auto len = strlen(s);
|
||||
std::tie(n, i) = parse_uint_digits(s, len);
|
||||
if (n == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (i == len) {
|
||||
return n;
|
||||
}
|
||||
if (i == 0 || i + 1 != len) {
|
||||
if (i + 1 != len) {
|
||||
return -1;
|
||||
}
|
||||
int mul = 1;
|
||||
|
@ -944,6 +960,7 @@ int64_t parse_uint_with_unit(const char *s) {
|
|||
default:
|
||||
return -1;
|
||||
}
|
||||
constexpr int64_t max = std::numeric_limits<int64_t>::max();
|
||||
if (n > max / mul) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -959,28 +976,53 @@ int64_t parse_uint(const std::string &s) {
|
|||
}
|
||||
|
||||
int64_t parse_uint(const uint8_t *s, size_t len) {
|
||||
if (len == 0) {
|
||||
return -1;
|
||||
}
|
||||
constexpr int64_t max = std::numeric_limits<int64_t>::max();
|
||||
int64_t n = 0;
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
if ('0' <= s[i] && s[i] <= '9') {
|
||||
if (n > max / 10) {
|
||||
return -1;
|
||||
}
|
||||
n *= 10;
|
||||
if (n > max - (s[i] - '0')) {
|
||||
return -1;
|
||||
}
|
||||
n += s[i] - '0';
|
||||
continue;
|
||||
}
|
||||
int64_t n;
|
||||
size_t i;
|
||||
std::tie(n, i) = parse_uint_digits(s, len);
|
||||
if (n == -1 || i != len) {
|
||||
return -1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
double parse_time_with_unit(const char *s) {
|
||||
int64_t n;
|
||||
size_t i;
|
||||
auto len = strlen(s);
|
||||
std::tie(n, i) = parse_uint_digits(s, len);
|
||||
if (n == -1) {
|
||||
goto fail;
|
||||
}
|
||||
if (i == len) {
|
||||
return static_cast<double>(n);
|
||||
}
|
||||
switch (s[i]) {
|
||||
case 'S':
|
||||
case 's':
|
||||
if (i + 1 != len) {
|
||||
goto fail;
|
||||
}
|
||||
return static_cast<double>(n);
|
||||
break;
|
||||
case 'M':
|
||||
case 'm':
|
||||
if (i + 2 != len || (s[i + 1] != 's' && s[i + 1] != 'S')) {
|
||||
goto fail;
|
||||
}
|
||||
return static_cast<double>(n) / 1000.;
|
||||
}
|
||||
fail:
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
std::string duration_str(double t) {
|
||||
auto frac = static_cast<int64_t>(t * 1000) % 1000;
|
||||
if (frac > 0) {
|
||||
return utos(static_cast<int64_t>(t * 1000)) + "ms";
|
||||
}
|
||||
return utos(static_cast<int64_t>(t)) + "s";
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
||||
} // namespace nghttp2
|
||||
|
|
14
src/util.h
14
src/util.h
|
@ -508,6 +508,20 @@ int64_t parse_uint(const char *s);
|
|||
int64_t parse_uint(const uint8_t *s, size_t len);
|
||||
int64_t parse_uint(const std::string &s);
|
||||
|
||||
// Parses NULL terminated string |s| as unsigned integer and returns
|
||||
// the parsed integer casted to double. If |s| ends with "s", the
|
||||
// parsed value's unit is a second. If |s| ends with "ms", the unit
|
||||
// is millisecond. If none of them are given, the unit is second.
|
||||
// This function returns std::numeric_limits<double>::infinity() if
|
||||
// error occurs.
|
||||
double parse_time_with_unit(const char *s);
|
||||
|
||||
// Returns string representation of time duration |t|. If t has
|
||||
// fractional part (at least more than or equal to 1e-3), |t| is
|
||||
// multiplied by 1000 and the unit "ms" is appended. Otherwise, |t|
|
||||
// is left as is and "s" is appended.
|
||||
std::string duration_str(double t);
|
||||
|
||||
} // namespace util
|
||||
|
||||
} // namespace nghttp2
|
||||
|
|
|
@ -223,4 +223,24 @@ void test_util_parse_uint(void) {
|
|||
CU_ASSERT(-1 == util::parse_uint(""));
|
||||
}
|
||||
|
||||
void test_util_parse_time_with_unit(void) {
|
||||
CU_ASSERT(0. == util::parse_time_with_unit("0"));
|
||||
CU_ASSERT(123. == util::parse_time_with_unit("123"));
|
||||
CU_ASSERT(123. == util::parse_time_with_unit("123s"));
|
||||
CU_ASSERT(0.500 == util::parse_time_with_unit("500ms"));
|
||||
CU_ASSERT(123. == util::parse_time_with_unit("123S"));
|
||||
CU_ASSERT(0.500 == util::parse_time_with_unit("500MS"));
|
||||
|
||||
auto err = std::numeric_limits<double>::infinity();
|
||||
// check overflow case
|
||||
CU_ASSERT(err == util::parse_time_with_unit("9223372036854775808"));
|
||||
// bad characters
|
||||
CU_ASSERT(err == util::parse_time_with_unit("0u"));
|
||||
CU_ASSERT(err == util::parse_time_with_unit("0xs"));
|
||||
CU_ASSERT(err == util::parse_time_with_unit("0mt"));
|
||||
CU_ASSERT(err == util::parse_time_with_unit("0mss"));
|
||||
CU_ASSERT(err == util::parse_time_with_unit("s"));
|
||||
CU_ASSERT(err == util::parse_time_with_unit("ms"));
|
||||
}
|
||||
|
||||
} // namespace shrpx
|
||||
|
|
|
@ -40,6 +40,7 @@ void test_util_ipv6_numeric_addr(void);
|
|||
void test_util_utos_with_unit(void);
|
||||
void test_util_parse_uint_with_unit(void);
|
||||
void test_util_parse_uint(void);
|
||||
void test_util_parse_time_with_unit(void);
|
||||
|
||||
} // namespace shrpx
|
||||
|
||||
|
|
Loading…
Reference in New Issue