nghttpx: Use std::unique_ptr<char[]> instead of raw char pointer
This commit is contained in:
parent
ca3444c34c
commit
dd8ce1e9d2
|
@ -261,35 +261,37 @@ std::string read_passwd_from_file(const char *filename) {
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<char *> parse_config_str_list(const char *s, char delim) {
|
std::vector<Range<const char *>> split_config_str_list(const char *s,
|
||||||
|
char delim) {
|
||||||
size_t len = 1;
|
size_t len = 1;
|
||||||
for (const char *first = s, *p = nullptr; (p = strchr(first, delim));
|
auto last = s + strlen(s);
|
||||||
++len, first = p + 1)
|
for (const char *first = s, *d = nullptr;
|
||||||
|
(d = std::find(first, last, delim)) != last; ++len, first = d + 1)
|
||||||
;
|
;
|
||||||
auto list = std::vector<char *>(len);
|
|
||||||
auto first = strdup(s);
|
auto list = std::vector<Range<const char *>>(len);
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
for (;;) {
|
for (auto first = s;; ++len) {
|
||||||
auto p = strchr(first, delim);
|
auto stop = std::find(first, last, delim);
|
||||||
if (p == nullptr) {
|
list[len] = {first, stop};
|
||||||
|
if (stop == last) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
list[len++] = first;
|
first = stop + 1;
|
||||||
*p = '\0';
|
|
||||||
first = p + 1;
|
|
||||||
}
|
}
|
||||||
list[len++] = first;
|
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_config_str_list(std::vector<char *> &list) {
|
std::vector<std::unique_ptr<char[]>> parse_config_str_list(const char *s,
|
||||||
if (list.empty()) {
|
char delim) {
|
||||||
return;
|
auto ranges = split_config_str_list(s, delim);
|
||||||
|
auto res = std::vector<std::unique_ptr<char[]>>();
|
||||||
|
res.reserve(ranges.size());
|
||||||
|
for (const auto &range : ranges) {
|
||||||
|
res.push_back(strcopy(range.first, range.second));
|
||||||
}
|
}
|
||||||
|
return res;
|
||||||
free(list[0]);
|
|
||||||
list.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<std::string, std::string> parse_header(const char *optarg) {
|
std::pair<std::string, std::string> parse_header(const char *optarg) {
|
||||||
|
@ -590,22 +592,21 @@ namespace {
|
||||||
void parse_mapping(const DownstreamAddr &addr, const char *src) {
|
void parse_mapping(const DownstreamAddr &addr, const char *src) {
|
||||||
// This returns at least 1 element (it could be empty string). We
|
// This returns at least 1 element (it could be empty string). We
|
||||||
// will append '/' to all patterns, so it becomes catch-all pattern.
|
// will append '/' to all patterns, so it becomes catch-all pattern.
|
||||||
auto mapping = parse_config_str_list(src, ':');
|
auto mapping = split_config_str_list(src, ':');
|
||||||
assert(!mapping.empty());
|
assert(!mapping.empty());
|
||||||
for (auto raw_pattern : mapping) {
|
for (const auto &raw_pattern : mapping) {
|
||||||
auto done = false;
|
auto done = false;
|
||||||
std::string pattern;
|
std::string pattern;
|
||||||
auto slash = strchr(raw_pattern, '/');
|
auto slash = std::find(raw_pattern.first, raw_pattern.second, '/');
|
||||||
if (slash == nullptr) {
|
if (slash == raw_pattern.second) {
|
||||||
// This effectively makes empty pattern to "/".
|
// This effectively makes empty pattern to "/".
|
||||||
pattern = raw_pattern;
|
pattern.assign(raw_pattern.first, raw_pattern.second);
|
||||||
util::inp_strlower(pattern);
|
util::inp_strlower(pattern);
|
||||||
pattern += "/";
|
pattern += "/";
|
||||||
} else {
|
} else {
|
||||||
pattern.assign(raw_pattern, slash);
|
pattern.assign(raw_pattern.first, slash);
|
||||||
util::inp_strlower(pattern);
|
util::inp_strlower(pattern);
|
||||||
pattern +=
|
pattern += http2::normalize_path(slash, raw_pattern.second);
|
||||||
http2::normalize_path(slash, raw_pattern + strlen(raw_pattern));
|
|
||||||
}
|
}
|
||||||
for (auto &g : mod_config()->downstream_addr_groups) {
|
for (auto &g : mod_config()->downstream_addr_groups) {
|
||||||
if (g.pattern == pattern) {
|
if (g.pattern == pattern) {
|
||||||
|
@ -621,7 +622,6 @@ void parse_mapping(const DownstreamAddr &addr, const char *src) {
|
||||||
g.addrs.push_back(addr);
|
g.addrs.push_back(addr);
|
||||||
mod_config()->downstream_addr_groups.push_back(std::move(g));
|
mod_config()->downstream_addr_groups.push_back(std::move(g));
|
||||||
}
|
}
|
||||||
clear_config_str_list(mapping);
|
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -1629,12 +1629,10 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
LOG(WARN) << opt << ": not implemented yet";
|
LOG(WARN) << opt << ": not implemented yet";
|
||||||
return parse_uint_with_unit(&mod_config()->worker_write_burst, opt, optarg);
|
return parse_uint_with_unit(&mod_config()->worker_write_burst, opt, optarg);
|
||||||
case SHRPX_OPTID_NPN_LIST:
|
case SHRPX_OPTID_NPN_LIST:
|
||||||
clear_config_str_list(mod_config()->npn_list);
|
|
||||||
mod_config()->npn_list = parse_config_str_list(optarg);
|
mod_config()->npn_list = parse_config_str_list(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_TLS_PROTO_LIST:
|
case SHRPX_OPTID_TLS_PROTO_LIST:
|
||||||
clear_config_str_list(mod_config()->tls_proto_list);
|
|
||||||
mod_config()->tls_proto_list = parse_config_str_list(optarg);
|
mod_config()->tls_proto_list = parse_config_str_list(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1689,13 +1687,13 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
|
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
if (parse_uint(&port, opt, tokens[1]) != 0) {
|
if (parse_uint(&port, opt, tokens[1].get()) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port < 1 ||
|
if (port < 1 ||
|
||||||
port > static_cast<int>(std::numeric_limits<uint16_t>::max())) {
|
port > static_cast<int>(std::numeric_limits<uint16_t>::max())) {
|
||||||
LOG(ERROR) << opt << ": port is invalid: " << tokens[1];
|
LOG(ERROR) << opt << ": port is invalid: " << tokens[1].get();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1703,16 +1701,16 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
|
|
||||||
altsvc.port = port;
|
altsvc.port = port;
|
||||||
|
|
||||||
altsvc.protocol_id = tokens[0];
|
altsvc.protocol_id = std::move(tokens[0]);
|
||||||
altsvc.protocol_id_len = strlen(altsvc.protocol_id);
|
altsvc.protocol_id_len = strlen(altsvc.protocol_id.get());
|
||||||
|
|
||||||
if (tokens.size() > 2) {
|
if (tokens.size() > 2) {
|
||||||
altsvc.host = tokens[2];
|
altsvc.host = std::move(tokens[2]);
|
||||||
altsvc.host_len = strlen(altsvc.host);
|
altsvc.host_len = strlen(altsvc.host.get());
|
||||||
|
|
||||||
if (tokens.size() > 3) {
|
if (tokens.size() > 3) {
|
||||||
altsvc.origin = tokens[3];
|
altsvc.origin = std::move(tokens[3]);
|
||||||
altsvc.origin_len = strlen(altsvc.origin);
|
altsvc.origin_len = strlen(altsvc.origin.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -184,13 +184,11 @@ union sockaddr_union {
|
||||||
enum shrpx_proto { PROTO_HTTP2, PROTO_HTTP };
|
enum shrpx_proto { PROTO_HTTP2, PROTO_HTTP };
|
||||||
|
|
||||||
struct AltSvc {
|
struct AltSvc {
|
||||||
AltSvc()
|
AltSvc() : protocol_id_len(0), host_len(0), origin_len(0), port(0) {}
|
||||||
: protocol_id(nullptr), host(nullptr), origin(nullptr),
|
|
||||||
protocol_id_len(0), host_len(0), origin_len(0), port(0) {}
|
|
||||||
|
|
||||||
char *protocol_id;
|
std::unique_ptr<char[]> protocol_id;
|
||||||
char *host;
|
std::unique_ptr<char[]> host;
|
||||||
char *origin;
|
std::unique_ptr<char[]> origin;
|
||||||
|
|
||||||
size_t protocol_id_len;
|
size_t protocol_id_len;
|
||||||
size_t host_len;
|
size_t host_len;
|
||||||
|
@ -291,10 +289,10 @@ struct Config {
|
||||||
// list of supported NPN/ALPN protocol strings in the order of
|
// list of supported NPN/ALPN protocol strings in the order of
|
||||||
// preference. The each element of this list is a NULL-terminated
|
// preference. The each element of this list is a NULL-terminated
|
||||||
// string.
|
// string.
|
||||||
std::vector<char *> npn_list;
|
std::vector<std::unique_ptr<char[]>> npn_list;
|
||||||
// list of supported SSL/TLS protocol strings. The each element of
|
// list of supported SSL/TLS protocol strings. The each element of
|
||||||
// this list is a NULL-terminated string.
|
// this list is a NULL-terminated string.
|
||||||
std::vector<char *> tls_proto_list;
|
std::vector<std::unique_ptr<char[]>> tls_proto_list;
|
||||||
// Path to file containing CA certificate solely used for client
|
// Path to file containing CA certificate solely used for client
|
||||||
// certificate validation
|
// certificate validation
|
||||||
std::unique_ptr<char[]> verify_client_cacert;
|
std::unique_ptr<char[]> verify_client_cacert;
|
||||||
|
@ -410,19 +408,20 @@ int load_config(const char *filename, std::set<std::string> &include_set);
|
||||||
// Read passwd from |filename|
|
// Read passwd from |filename|
|
||||||
std::string read_passwd_from_file(const char *filename);
|
std::string read_passwd_from_file(const char *filename);
|
||||||
|
|
||||||
// Parses delimited strings in |s| and returns the array of pointers,
|
template <typename T> using Range = std::pair<T, T>;
|
||||||
// each element points to the each substring in |s|. The delimiter is
|
|
||||||
// given by |delim. The |s| must be comma delimited list of strings.
|
|
||||||
// The strings must be delimited by a single comma and any white
|
|
||||||
// spaces around it are treated as a part of protocol strings. This
|
|
||||||
// function copies |s| and first element in the return value points to
|
|
||||||
// it. It is caller's responsibility to deallocate its memory.
|
|
||||||
std::vector<char *> parse_config_str_list(const char *s, char delim = ',');
|
|
||||||
|
|
||||||
// Clears all elements of |list|, which is returned by
|
// Parses delimited strings in |s| and returns the array of substring,
|
||||||
// parse_config_str_list(). If list is not empty, list[0] is freed by
|
// delimited by |delim|. The any white spaces around substring are
|
||||||
// free(2). After this call, list.empty() must be true.
|
// treated as a part of substring.
|
||||||
void clear_config_str_list(std::vector<char *> &list);
|
std::vector<std::unique_ptr<char[]>> parse_config_str_list(const char *s,
|
||||||
|
char delim = ',');
|
||||||
|
|
||||||
|
// Parses delimited strings in |s| and returns the array of pointers,
|
||||||
|
// each element points to the beginning and one beyond last of
|
||||||
|
// substring in |s|. The delimiter is given by |delim|. The any
|
||||||
|
// white spaces around substring are treated as a part of substring.
|
||||||
|
std::vector<Range<const char *>> split_config_str_list(const char *s,
|
||||||
|
char delim);
|
||||||
|
|
||||||
// Parses header field in |optarg|. We expect header field is formed
|
// Parses header field in |optarg|. We expect header field is formed
|
||||||
// like "NAME: VALUE". We require that NAME is non empty string. ":"
|
// like "NAME: VALUE". We require that NAME is non empty string. ":"
|
||||||
|
|
|
@ -39,34 +39,29 @@ namespace shrpx {
|
||||||
void test_shrpx_config_parse_config_str_list(void) {
|
void test_shrpx_config_parse_config_str_list(void) {
|
||||||
auto res = parse_config_str_list("a");
|
auto res = parse_config_str_list("a");
|
||||||
CU_ASSERT(1 == res.size());
|
CU_ASSERT(1 == res.size());
|
||||||
CU_ASSERT(0 == strcmp("a", res[0]));
|
CU_ASSERT(0 == strcmp("a", res[0].get()));
|
||||||
clear_config_str_list(res);
|
|
||||||
|
|
||||||
res = parse_config_str_list("a,");
|
res = parse_config_str_list("a,");
|
||||||
CU_ASSERT(2 == res.size());
|
CU_ASSERT(2 == res.size());
|
||||||
CU_ASSERT(0 == strcmp("a", res[0]));
|
CU_ASSERT(0 == strcmp("a", res[0].get()));
|
||||||
CU_ASSERT(0 == strcmp("", res[1]));
|
CU_ASSERT(0 == strcmp("", res[1].get()));
|
||||||
clear_config_str_list(res);
|
|
||||||
|
|
||||||
res = parse_config_str_list(":a::", ':');
|
res = parse_config_str_list(":a::", ':');
|
||||||
CU_ASSERT(4 == res.size());
|
CU_ASSERT(4 == res.size());
|
||||||
CU_ASSERT(0 == strcmp("", res[0]));
|
CU_ASSERT(0 == strcmp("", res[0].get()));
|
||||||
CU_ASSERT(0 == strcmp("a", res[1]));
|
CU_ASSERT(0 == strcmp("a", res[1].get()));
|
||||||
CU_ASSERT(0 == strcmp("", res[2]));
|
CU_ASSERT(0 == strcmp("", res[2].get()));
|
||||||
CU_ASSERT(0 == strcmp("", res[3]));
|
CU_ASSERT(0 == strcmp("", res[3].get()));
|
||||||
clear_config_str_list(res);
|
|
||||||
|
|
||||||
res = parse_config_str_list("");
|
res = parse_config_str_list("");
|
||||||
CU_ASSERT(1 == res.size());
|
CU_ASSERT(1 == res.size());
|
||||||
CU_ASSERT(0 == strcmp("", res[0]));
|
CU_ASSERT(0 == strcmp("", res[0].get()));
|
||||||
clear_config_str_list(res);
|
|
||||||
|
|
||||||
res = parse_config_str_list("alpha,bravo,charlie");
|
res = parse_config_str_list("alpha,bravo,charlie");
|
||||||
CU_ASSERT(3 == res.size());
|
CU_ASSERT(3 == res.size());
|
||||||
CU_ASSERT(0 == strcmp("alpha", res[0]));
|
CU_ASSERT(0 == strcmp("alpha", res[0].get()));
|
||||||
CU_ASSERT(0 == strcmp("bravo", res[1]));
|
CU_ASSERT(0 == strcmp("bravo", res[1].get()));
|
||||||
CU_ASSERT(0 == strcmp("charlie", res[2]));
|
CU_ASSERT(0 == strcmp("charlie", res[2].get()));
|
||||||
clear_config_str_list(res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_shrpx_config_parse_header(void) {
|
void test_shrpx_config_parse_header(void) {
|
||||||
|
|
|
@ -845,9 +845,10 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
hdrs += "Alt-Svc: ";
|
hdrs += "Alt-Svc: ";
|
||||||
|
|
||||||
for (auto &altsvc : get_config()->altsvcs) {
|
for (auto &altsvc : get_config()->altsvcs) {
|
||||||
hdrs += util::percent_encode_token(altsvc.protocol_id);
|
hdrs += util::percent_encode_token(altsvc.protocol_id.get());
|
||||||
hdrs += "=\"";
|
hdrs += "=\"";
|
||||||
hdrs += util::quote_string(std::string(altsvc.host, altsvc.host_len));
|
hdrs +=
|
||||||
|
util::quote_string(std::string(altsvc.host.get(), altsvc.host_len));
|
||||||
hdrs += ":";
|
hdrs += ":";
|
||||||
hdrs += util::utos(altsvc.port);
|
hdrs += util::utos(altsvc.port);
|
||||||
hdrs += "\", ";
|
hdrs += "\", ";
|
||||||
|
|
|
@ -86,11 +86,12 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::vector<unsigned char> set_alpn_prefs(const std::vector<char *> &protos) {
|
std::vector<unsigned char>
|
||||||
|
set_alpn_prefs(const std::vector<std::unique_ptr<char[]>> &protos) {
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
for (auto proto : protos) {
|
for (auto &proto : protos) {
|
||||||
auto n = strlen(proto);
|
auto n = strlen(proto.get());
|
||||||
|
|
||||||
if (n > 255) {
|
if (n > 255) {
|
||||||
LOG(FATAL) << "Too long ALPN identifier: " << n;
|
LOG(FATAL) << "Too long ALPN identifier: " << n;
|
||||||
|
@ -108,11 +109,11 @@ std::vector<unsigned char> set_alpn_prefs(const std::vector<char *> &protos) {
|
||||||
auto out = std::vector<unsigned char>(len);
|
auto out = std::vector<unsigned char>(len);
|
||||||
auto ptr = out.data();
|
auto ptr = out.data();
|
||||||
|
|
||||||
for (auto proto : protos) {
|
for (auto &proto : protos) {
|
||||||
auto proto_len = strlen(proto);
|
auto proto_len = strlen(proto.get());
|
||||||
|
|
||||||
*ptr++ = proto_len;
|
*ptr++ = proto_len;
|
||||||
memcpy(ptr, proto, proto_len);
|
memcpy(ptr, proto.get(), proto_len);
|
||||||
ptr += proto_len;
|
ptr += proto_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,16 +282,15 @@ int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
||||||
// We assume that get_config()->npn_list contains ALPN protocol
|
// We assume that get_config()->npn_list contains ALPN protocol
|
||||||
// identifier sorted by preference order. So we just break when we
|
// identifier sorted by preference order. So we just break when we
|
||||||
// found the first overlap.
|
// found the first overlap.
|
||||||
for (auto target_proto_id : get_config()->npn_list) {
|
for (auto &target_proto_id : get_config()->npn_list) {
|
||||||
auto target_proto_len =
|
auto target_proto_len = strlen(target_proto_id.get());
|
||||||
strlen(reinterpret_cast<const char *>(target_proto_id));
|
|
||||||
|
|
||||||
for (auto p = in, end = in + inlen; p < end;) {
|
for (auto p = in, end = in + inlen; p < end;) {
|
||||||
auto proto_id = p + 1;
|
auto proto_id = p + 1;
|
||||||
auto proto_len = *p;
|
auto proto_len = *p;
|
||||||
|
|
||||||
if (proto_id + proto_len <= end && target_proto_len == proto_len &&
|
if (proto_id + proto_len <= end && target_proto_len == proto_len &&
|
||||||
memcmp(target_proto_id, proto_id, proto_len) == 0) {
|
memcmp(target_proto_id.get(), proto_id, proto_len) == 0) {
|
||||||
|
|
||||||
*out = reinterpret_cast<const unsigned char *>(proto_id);
|
*out = reinterpret_cast<const unsigned char *>(proto_id);
|
||||||
*outlen = proto_len;
|
*outlen = proto_len;
|
||||||
|
@ -314,13 +314,14 @@ constexpr long int tls_masks[] = {SSL_OP_NO_TLSv1_2, SSL_OP_NO_TLSv1_1,
|
||||||
SSL_OP_NO_TLSv1};
|
SSL_OP_NO_TLSv1};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
long int create_tls_proto_mask(const std::vector<char *> &tls_proto_list) {
|
long int create_tls_proto_mask(
|
||||||
|
const std::vector<std::unique_ptr<char[]>> &tls_proto_list) {
|
||||||
long int res = 0;
|
long int res = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < tls_namelen; ++i) {
|
for (size_t i = 0; i < tls_namelen; ++i) {
|
||||||
size_t j;
|
size_t j;
|
||||||
for (j = 0; j < tls_proto_list.size(); ++j) {
|
for (j = 0; j < tls_proto_list.size(); ++j) {
|
||||||
if (util::strieq(tls_names[i], tls_proto_list[j])) {
|
if (util::strieq(tls_names[i], tls_proto_list[j].get())) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -949,10 +950,10 @@ int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool in_proto_list(const std::vector<char *> &protos,
|
bool in_proto_list(const std::vector<std::unique_ptr<char[]>> &protos,
|
||||||
const unsigned char *needle, size_t len) {
|
const unsigned char *needle, size_t len) {
|
||||||
for (auto proto : protos) {
|
for (auto &proto : protos) {
|
||||||
if (strlen(proto) == len && memcmp(proto, needle, len) == 0) {
|
if (strlen(proto.get()) == len && memcmp(proto.get(), needle, len) == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,7 @@ int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx,
|
||||||
|
|
||||||
// Returns true if |needle| which has |len| bytes is included in the
|
// Returns true if |needle| which has |len| bytes is included in the
|
||||||
// protocol list |protos|.
|
// protocol list |protos|.
|
||||||
bool in_proto_list(const std::vector<char *> &protos,
|
bool in_proto_list(const std::vector<std::unique_ptr<char[]>> &protos,
|
||||||
const unsigned char *needle, size_t len);
|
const unsigned char *needle, size_t len);
|
||||||
|
|
||||||
// Returns true if security requirement for HTTP/2 is fulfilled.
|
// Returns true if security requirement for HTTP/2 is fulfilled.
|
||||||
|
@ -149,9 +149,11 @@ bool check_http2_requirement(SSL *ssl);
|
||||||
// Returns SSL/TLS option mask to disable SSL/TLS protocol version not
|
// Returns SSL/TLS option mask to disable SSL/TLS protocol version not
|
||||||
// included in |tls_proto_list|. The returned mask can be directly
|
// included in |tls_proto_list|. The returned mask can be directly
|
||||||
// passed to SSL_CTX_set_options().
|
// passed to SSL_CTX_set_options().
|
||||||
long int create_tls_proto_mask(const std::vector<char *> &tls_proto_list);
|
long int create_tls_proto_mask(
|
||||||
|
const std::vector<std::unique_ptr<char[]>> &tls_proto_list);
|
||||||
|
|
||||||
std::vector<unsigned char> set_alpn_prefs(const std::vector<char *> &protos);
|
std::vector<unsigned char>
|
||||||
|
set_alpn_prefs(const std::vector<std::unique_ptr<char[]>> &protos);
|
||||||
|
|
||||||
// Setups server side SSL_CTX. This function inspects get_config()
|
// Setups server side SSL_CTX. This function inspects get_config()
|
||||||
// and if upstream_no_tls is true, returns nullptr. Otherwise
|
// and if upstream_no_tls is true, returns nullptr. Otherwise
|
||||||
|
|
Loading…
Reference in New Issue