nghttpx: Add basic infrastructure for mruby support
This commit is contained in:
parent
dd0a72579f
commit
1508c50a45
|
@ -98,6 +98,7 @@ OPTIONS = [
|
||||||
"tls-ticket-key-memcached-interval",
|
"tls-ticket-key-memcached-interval",
|
||||||
"tls-ticket-key-memcached-max-retry",
|
"tls-ticket-key-memcached-max-retry",
|
||||||
"tls-ticket-key-memcached-max-fail",
|
"tls-ticket-key-memcached-max-fail",
|
||||||
|
"on-request-mruby-file",
|
||||||
"conf",
|
"conf",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,8 @@ NGHTTPX_SRCS = \
|
||||||
shrpx_memcached_connection.cc shrpx_memcached_connection.h \
|
shrpx_memcached_connection.cc shrpx_memcached_connection.h \
|
||||||
shrpx_memcached_request.h \
|
shrpx_memcached_request.h \
|
||||||
shrpx_memcached_result.h \
|
shrpx_memcached_result.h \
|
||||||
|
shrpx_mruby.cc shrpx_mruby.h \
|
||||||
|
shrpx_mruby_module.cc shrpx_mruby_module.h \
|
||||||
buffer.h memchunk.h template.h
|
buffer.h memchunk.h template.h
|
||||||
|
|
||||||
if HAVE_SPDYLAY
|
if HAVE_SPDYLAY
|
||||||
|
@ -134,7 +136,7 @@ noinst_LIBRARIES = libnghttpx.a
|
||||||
libnghttpx_a_SOURCES = ${NGHTTPX_SRCS}
|
libnghttpx_a_SOURCES = ${NGHTTPX_SRCS}
|
||||||
|
|
||||||
nghttpx_SOURCES = shrpx.cc shrpx.h
|
nghttpx_SOURCES = shrpx.cc shrpx.h
|
||||||
nghttpx_LDADD = libnghttpx.a ${LDADD}
|
nghttpx_LDADD = libnghttpx.a ${LDADD} -lmruby
|
||||||
|
|
||||||
if HAVE_CUNIT
|
if HAVE_CUNIT
|
||||||
check_PROGRAMS += nghttpx-unittest
|
check_PROGRAMS += nghttpx-unittest
|
||||||
|
@ -150,7 +152,7 @@ nghttpx_unittest_SOURCES = shrpx-unittest.cc \
|
||||||
memchunk_test.cc memchunk_test.h
|
memchunk_test.cc memchunk_test.h
|
||||||
nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS}\
|
nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS}\
|
||||||
-DNGHTTP2_TESTS_DIR=\"$(top_srcdir)/tests\"
|
-DNGHTTP2_TESTS_DIR=\"$(top_srcdir)/tests\"
|
||||||
nghttpx_unittest_LDADD = libnghttpx.a ${LDADD} @CUNIT_LIBS@ @TESTLDADD@
|
nghttpx_unittest_LDADD = libnghttpx.a ${LDADD} -lmruby @CUNIT_LIBS@ @TESTLDADD@
|
||||||
|
|
||||||
TESTS += nghttpx-unittest
|
TESTS += nghttpx-unittest
|
||||||
endif # HAVE_CUNIT
|
endif # HAVE_CUNIT
|
||||||
|
|
17
src/shrpx.cc
17
src/shrpx.cc
|
@ -926,9 +926,13 @@ int event_loop() {
|
||||||
#endif // !NOTHREADS
|
#endif // !NOTHREADS
|
||||||
|
|
||||||
if (get_config()->num_worker == 1) {
|
if (get_config()->num_worker == 1) {
|
||||||
conn_handler->create_single_worker();
|
rv = conn_handler->create_single_worker();
|
||||||
} else {
|
} else {
|
||||||
conn_handler->create_worker_thread(get_config()->num_worker);
|
rv = conn_handler->create_worker_thread(get_config()->num_worker);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rv != 0) {
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NOTHREADS
|
#ifndef NOTHREADS
|
||||||
|
@ -1899,6 +1903,7 @@ int main(int argc, char **argv) {
|
||||||
89},
|
89},
|
||||||
{SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL, required_argument, &flag,
|
{SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL, required_argument, &flag,
|
||||||
90},
|
90},
|
||||||
|
{SHRPX_OPT_ON_REQUEST_MRUBY_FILE, required_argument, &flag, 91},
|
||||||
{nullptr, 0, nullptr, 0}};
|
{nullptr, 0, nullptr, 0}};
|
||||||
|
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
|
@ -2296,6 +2301,10 @@ int main(int argc, char **argv) {
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL,
|
cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL,
|
||||||
optarg);
|
optarg);
|
||||||
break;
|
break;
|
||||||
|
case 91:
|
||||||
|
// --on-request-mruby-file
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_ON_REQUEST_MRUBY_FILE, optarg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2613,7 +2622,9 @@ int main(int argc, char **argv) {
|
||||||
act.sa_handler = SIG_IGN;
|
act.sa_handler = SIG_IGN;
|
||||||
sigaction(SIGPIPE, &act, nullptr);
|
sigaction(SIGPIPE, &act, nullptr);
|
||||||
|
|
||||||
event_loop();
|
if (event_loop() != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
LOG(NOTICE) << "Shutdown momentarily";
|
LOG(NOTICE) << "Shutdown momentarily";
|
||||||
|
|
||||||
|
|
|
@ -690,6 +690,7 @@ enum {
|
||||||
SHRPX_OPTID_NO_VIA,
|
SHRPX_OPTID_NO_VIA,
|
||||||
SHRPX_OPTID_NPN_LIST,
|
SHRPX_OPTID_NPN_LIST,
|
||||||
SHRPX_OPTID_OCSP_UPDATE_INTERVAL,
|
SHRPX_OPTID_OCSP_UPDATE_INTERVAL,
|
||||||
|
SHRPX_OPTID_ON_REQUEST_MRUBY_FILE,
|
||||||
SHRPX_OPTID_PADDING,
|
SHRPX_OPTID_PADDING,
|
||||||
SHRPX_OPTID_PID_FILE,
|
SHRPX_OPTID_PID_FILE,
|
||||||
SHRPX_OPTID_PRIVATE_KEY_FILE,
|
SHRPX_OPTID_PRIVATE_KEY_FILE,
|
||||||
|
@ -1089,6 +1090,11 @@ int option_lookup_token(const char *name, size_t namelen) {
|
||||||
return SHRPX_OPTID_BACKEND_TLS_SNI_FIELD;
|
return SHRPX_OPTID_BACKEND_TLS_SNI_FIELD;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'e':
|
||||||
|
if (util::strieq_l("on-request-mruby-fil", name, 20)) {
|
||||||
|
return SHRPX_OPTID_ON_REQUEST_MRUBY_FILE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
if (util::strieq_l("tls-ticket-key-ciphe", name, 20)) {
|
if (util::strieq_l("tls-ticket-key-ciphe", name, 20)) {
|
||||||
return SHRPX_OPTID_TLS_TICKET_KEY_CIPHER;
|
return SHRPX_OPTID_TLS_TICKET_KEY_CIPHER;
|
||||||
|
@ -1938,6 +1944,10 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL:
|
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL:
|
||||||
return parse_uint(&mod_config()->tls_ticket_key_memcached_max_fail, opt,
|
return parse_uint(&mod_config()->tls_ticket_key_memcached_max_fail, opt,
|
||||||
optarg);
|
optarg);
|
||||||
|
case SHRPX_OPTID_ON_REQUEST_MRUBY_FILE:
|
||||||
|
mod_config()->on_request_mruby_file = strcopy(optarg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
case SHRPX_OPTID_CONF:
|
case SHRPX_OPTID_CONF:
|
||||||
LOG(WARN) << "conf: ignored";
|
LOG(WARN) << "conf: ignored";
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,7 @@ constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY[] =
|
||||||
"tls-ticket-key-memcached-max-retry";
|
"tls-ticket-key-memcached-max-retry";
|
||||||
constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL[] =
|
constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL[] =
|
||||||
"tls-ticket-key-memcached-max-fail";
|
"tls-ticket-key-memcached-max-fail";
|
||||||
|
constexpr char SHRPX_OPT_ON_REQUEST_MRUBY_FILE[] = "on-request-mruby-file";
|
||||||
|
|
||||||
union sockaddr_union {
|
union sockaddr_union {
|
||||||
sockaddr_storage storage;
|
sockaddr_storage storage;
|
||||||
|
@ -314,6 +315,8 @@ struct Config {
|
||||||
std::unique_ptr<char[]> user;
|
std::unique_ptr<char[]> user;
|
||||||
std::unique_ptr<char[]> session_cache_memcached_host;
|
std::unique_ptr<char[]> session_cache_memcached_host;
|
||||||
std::unique_ptr<char[]> tls_ticket_key_memcached_host;
|
std::unique_ptr<char[]> tls_ticket_key_memcached_host;
|
||||||
|
std::unique_ptr<char[]> on_request_mruby_file;
|
||||||
|
std::unique_ptr<char[]> on_response_mruby_file;
|
||||||
FILE *http2_upstream_dump_request_header;
|
FILE *http2_upstream_dump_request_header;
|
||||||
FILE *http2_upstream_dump_response_header;
|
FILE *http2_upstream_dump_response_header;
|
||||||
nghttp2_session_callbacks *http2_upstream_callbacks;
|
nghttp2_session_callbacks *http2_upstream_callbacks;
|
||||||
|
|
|
@ -149,7 +149,7 @@ void ConnectionHandler::worker_reopen_log_files() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionHandler::create_single_worker() {
|
int ConnectionHandler::create_single_worker() {
|
||||||
auto cert_tree = ssl::create_cert_lookup_tree();
|
auto cert_tree = ssl::create_cert_lookup_tree();
|
||||||
auto sv_ssl_ctx = ssl::setup_server_ssl_context(all_ssl_ctx_, cert_tree);
|
auto sv_ssl_ctx = ssl::setup_server_ssl_context(all_ssl_ctx_, cert_tree);
|
||||||
auto cl_ssl_ctx = ssl::setup_client_ssl_context();
|
auto cl_ssl_ctx = ssl::setup_client_ssl_context();
|
||||||
|
@ -160,9 +160,14 @@ void ConnectionHandler::create_single_worker() {
|
||||||
|
|
||||||
single_worker_ = make_unique<Worker>(loop_, sv_ssl_ctx, cl_ssl_ctx, cert_tree,
|
single_worker_ = make_unique<Worker>(loop_, sv_ssl_ctx, cl_ssl_ctx, cert_tree,
|
||||||
ticket_keys_);
|
ticket_keys_);
|
||||||
|
if (single_worker_->create_mruby_context() != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionHandler::create_worker_thread(size_t num) {
|
int ConnectionHandler::create_worker_thread(size_t num) {
|
||||||
#ifndef NOTHREADS
|
#ifndef NOTHREADS
|
||||||
assert(workers_.size() == 0);
|
assert(workers_.size() == 0);
|
||||||
|
|
||||||
|
@ -179,14 +184,23 @@ void ConnectionHandler::create_worker_thread(size_t num) {
|
||||||
|
|
||||||
auto worker = make_unique<Worker>(loop, sv_ssl_ctx, cl_ssl_ctx, cert_tree,
|
auto worker = make_unique<Worker>(loop, sv_ssl_ctx, cl_ssl_ctx, cert_tree,
|
||||||
ticket_keys_);
|
ticket_keys_);
|
||||||
worker->run_async();
|
if (worker->create_mruby_context() != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
workers_.push_back(std::move(worker));
|
workers_.push_back(std::move(worker));
|
||||||
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
LLOG(INFO, this) << "Created thread #" << workers_.size() - 1;
|
LLOG(INFO, this) << "Created thread #" << workers_.size() - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto &worker : workers_) {
|
||||||
|
worker->run_async();
|
||||||
|
}
|
||||||
#endif // NOTHREADS
|
#endif // NOTHREADS
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionHandler::join_worker() {
|
void ConnectionHandler::join_worker() {
|
||||||
|
|
|
@ -73,10 +73,10 @@ public:
|
||||||
~ConnectionHandler();
|
~ConnectionHandler();
|
||||||
int handle_connection(int fd, sockaddr *addr, int addrlen);
|
int handle_connection(int fd, sockaddr *addr, int addrlen);
|
||||||
// Creates Worker object for single threaded configuration.
|
// Creates Worker object for single threaded configuration.
|
||||||
void create_single_worker();
|
int create_single_worker();
|
||||||
// Creates |num| Worker objects for multi threaded configuration.
|
// Creates |num| Worker objects for multi threaded configuration.
|
||||||
// The |num| must be strictly more than 1.
|
// The |num| must be strictly more than 1.
|
||||||
void create_worker_thread(size_t num);
|
int create_worker_thread(size_t num);
|
||||||
void
|
void
|
||||||
set_ticket_keys_to_worker(const std::shared_ptr<TicketKeys> &ticket_keys);
|
set_ticket_keys_to_worker(const std::shared_ptr<TicketKeys> &ticket_keys);
|
||||||
void worker_reopen_log_files();
|
void worker_reopen_log_files();
|
||||||
|
|
|
@ -127,7 +127,7 @@ Downstream::Downstream(Upstream *upstream, MemchunkPool *mcpool,
|
||||||
request_http2_expect_body_(false), chunked_response_(false),
|
request_http2_expect_body_(false), chunked_response_(false),
|
||||||
response_connection_close_(false), response_header_key_prev_(false),
|
response_connection_close_(false), response_header_key_prev_(false),
|
||||||
response_trailer_key_prev_(false), expect_final_response_(false),
|
response_trailer_key_prev_(false), expect_final_response_(false),
|
||||||
request_pending_(false) {
|
request_pending_(false), request_headers_dirty_(false) {
|
||||||
|
|
||||||
ev_timer_init(&upstream_rtimer_, &upstream_rtimeoutcb, 0.,
|
ev_timer_init(&upstream_rtimer_, &upstream_rtimeoutcb, 0.,
|
||||||
get_config()->stream_read_timeout);
|
get_config()->stream_read_timeout);
|
||||||
|
@ -240,6 +240,8 @@ const Headers &Downstream::get_request_headers() const {
|
||||||
return request_headers_;
|
return request_headers_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Headers &Downstream::get_request_headers() { return request_headers_; }
|
||||||
|
|
||||||
void Downstream::assemble_request_cookie() {
|
void Downstream::assemble_request_cookie() {
|
||||||
std::string &cookie = assembled_request_cookie_;
|
std::string &cookie = assembled_request_cookie_;
|
||||||
cookie = "";
|
cookie = "";
|
||||||
|
@ -336,6 +338,9 @@ void set_last_header_value(bool &key_prev, size_t &sum, Headers &headers,
|
||||||
namespace {
|
namespace {
|
||||||
int index_headers(http2::HeaderIndex &hdidx, Headers &headers,
|
int index_headers(http2::HeaderIndex &hdidx, Headers &headers,
|
||||||
int64_t &content_length) {
|
int64_t &content_length) {
|
||||||
|
http2::init_hdidx(hdidx);
|
||||||
|
content_length = -1;
|
||||||
|
|
||||||
for (size_t i = 0; i < headers.size(); ++i) {
|
for (size_t i = 0; i < headers.size(); ++i) {
|
||||||
auto &kv = headers[i];
|
auto &kv = headers[i];
|
||||||
util::inp_strlower(kv.name);
|
util::inp_strlower(kv.name);
|
||||||
|
@ -1213,4 +1218,12 @@ bool Downstream::can_detach_downstream_connection() const {
|
||||||
!response_connection_close_;
|
!response_connection_close_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Downstream::set_request_headers_dirty(bool f) {
|
||||||
|
request_headers_dirty_ = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Downstream::get_request_headers_dirty() const {
|
||||||
|
return request_headers_dirty_;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -96,6 +96,7 @@ public:
|
||||||
const std::string &get_http2_settings() const;
|
const std::string &get_http2_settings() const;
|
||||||
// downstream request API
|
// downstream request API
|
||||||
const Headers &get_request_headers() const;
|
const Headers &get_request_headers() const;
|
||||||
|
Headers &get_request_headers();
|
||||||
// Crumbles (split cookie by ";") in request_headers_ and returns
|
// Crumbles (split cookie by ";") in request_headers_ and returns
|
||||||
// them. Headers::no_index is inherited.
|
// them. Headers::no_index is inherited.
|
||||||
Headers crumble_request_cookie();
|
Headers crumble_request_cookie();
|
||||||
|
@ -126,6 +127,8 @@ public:
|
||||||
void append_last_request_header_value(const char *data, size_t len);
|
void append_last_request_header_value(const char *data, size_t len);
|
||||||
// Empties request headers.
|
// Empties request headers.
|
||||||
void clear_request_headers();
|
void clear_request_headers();
|
||||||
|
void set_request_headers_dirty(bool f);
|
||||||
|
bool get_request_headers_dirty() const;
|
||||||
|
|
||||||
size_t get_request_headers_sum() const;
|
size_t get_request_headers_sum() const;
|
||||||
|
|
||||||
|
@ -454,6 +457,8 @@ private:
|
||||||
// has not been established or should be checked before use;
|
// has not been established or should be checked before use;
|
||||||
// currently used only with HTTP/2 connection.
|
// currently used only with HTTP/2 connection.
|
||||||
bool request_pending_;
|
bool request_pending_;
|
||||||
|
// true if we need to execute index_request_headers()
|
||||||
|
bool request_headers_dirty_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "shrpx_http.h"
|
#include "shrpx_http.h"
|
||||||
#include "shrpx_worker.h"
|
#include "shrpx_worker.h"
|
||||||
#include "shrpx_http2_session.h"
|
#include "shrpx_http2_session.h"
|
||||||
|
#include "shrpx_mruby.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
@ -306,6 +307,13 @@ int Http2Upstream::on_request_headers(Downstream *downstream,
|
||||||
downstream->set_request_http2_expect_body(true);
|
downstream->set_request_http2_expect_body(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto upstream = downstream->get_upstream();
|
||||||
|
auto handler = upstream->get_client_handler();
|
||||||
|
auto worker = handler->get_worker();
|
||||||
|
auto mruby_ctx = worker->get_mruby_context();
|
||||||
|
|
||||||
|
mruby_ctx->run_on_request_proc(downstream);
|
||||||
|
|
||||||
downstream->inspect_http2_request();
|
downstream->inspect_http2_request();
|
||||||
|
|
||||||
downstream->set_request_state(Downstream::HEADER_COMPLETE);
|
downstream->set_request_state(Downstream::HEADER_COMPLETE);
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "shrpx_log_config.h"
|
#include "shrpx_log_config.h"
|
||||||
#include "shrpx_worker.h"
|
#include "shrpx_worker.h"
|
||||||
#include "shrpx_http2_session.h"
|
#include "shrpx_http2_session.h"
|
||||||
|
#include "shrpx_mruby.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "template.h"
|
#include "template.h"
|
||||||
|
@ -272,6 +273,12 @@ int htp_hdrs_completecb(http_parser *htp) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto handler = upstream->get_client_handler();
|
||||||
|
auto worker = handler->get_worker();
|
||||||
|
auto mruby_ctx = worker->get_mruby_context();
|
||||||
|
|
||||||
|
mruby_ctx->run_on_request_proc(downstream);
|
||||||
|
|
||||||
downstream->inspect_http1_request();
|
downstream->inspect_http1_request();
|
||||||
|
|
||||||
if (downstream->get_request_method() != HTTP_CONNECT) {
|
if (downstream->get_request_method() != HTTP_CONNECT) {
|
||||||
|
|
|
@ -0,0 +1,163 @@
|
||||||
|
/*
|
||||||
|
* nghttp2 - HTTP/2 C Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "shrpx_mruby.h"
|
||||||
|
|
||||||
|
#include <mruby/compile.h>
|
||||||
|
#include <mruby/string.h>
|
||||||
|
|
||||||
|
#include "shrpx_downstream.h"
|
||||||
|
#include "shrpx_config.h"
|
||||||
|
#include "shrpx_mruby_module.h"
|
||||||
|
#include "template.h"
|
||||||
|
|
||||||
|
namespace shrpx {
|
||||||
|
|
||||||
|
namespace mruby {
|
||||||
|
|
||||||
|
MRubyContext::MRubyContext(mrb_state *mrb, RProc *on_request_proc,
|
||||||
|
RProc *on_response_proc)
|
||||||
|
: mrb_(mrb), on_request_proc_(on_request_proc),
|
||||||
|
on_response_proc_(on_response_proc) {}
|
||||||
|
|
||||||
|
MRubyContext::~MRubyContext() { mrb_close(mrb_); }
|
||||||
|
|
||||||
|
int MRubyContext::run_on_request_proc(Downstream *downstream) {
|
||||||
|
if (!on_request_proc_) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mrb_->ud = downstream;
|
||||||
|
|
||||||
|
int rv = 0;
|
||||||
|
auto ai = mrb_gc_arena_save(mrb_);
|
||||||
|
|
||||||
|
auto res = mrb_run(mrb_, on_request_proc_, mrb_top_self(mrb_));
|
||||||
|
(void)res;
|
||||||
|
|
||||||
|
if (mrb_->exc) {
|
||||||
|
rv = -1;
|
||||||
|
auto error =
|
||||||
|
mrb_str_ptr(mrb_funcall(mrb_, mrb_obj_value(mrb_->exc), "inspect", 0));
|
||||||
|
|
||||||
|
LOG(ERROR) << "Exception caught while executing mruby code: "
|
||||||
|
<< error->as.heap.ptr;
|
||||||
|
mrb_->exc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mrb_->ud = nullptr;
|
||||||
|
|
||||||
|
mrb_gc_arena_restore(mrb_, ai);
|
||||||
|
|
||||||
|
if (downstream->get_request_headers_dirty()) {
|
||||||
|
downstream->set_request_headers_dirty(false);
|
||||||
|
downstream->index_request_headers();
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int run_on_response_proc(Downstream *downstream) {
|
||||||
|
// TODO not implemented yet
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Based on
|
||||||
|
// https://github.com/h2o/h2o/blob/master/lib/handler/mruby.c. It is
|
||||||
|
// very hard to write these kind of code because mruby has almost no
|
||||||
|
// documentation aobut compiling or generating code, at least at the
|
||||||
|
// time of this writing.
|
||||||
|
RProc *compile(mrb_state *mrb, const char *filename) {
|
||||||
|
if (filename == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto infile = fopen(filename, "rb");
|
||||||
|
if (infile == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto infile_d = defer(fclose, infile);
|
||||||
|
|
||||||
|
auto mrbc = mrbc_context_new(mrb);
|
||||||
|
if (mrbc == nullptr) {
|
||||||
|
LOG(ERROR) << "mrb_context_new failed";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto mrbc_d = defer(mrbc_context_free, mrb, mrbc);
|
||||||
|
|
||||||
|
auto parser = mrb_parse_file(mrb, infile, nullptr);
|
||||||
|
if (parser == nullptr) {
|
||||||
|
LOG(ERROR) << "mrb_parse_nstring failed";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto parser_d = defer(mrb_parser_free, parser);
|
||||||
|
|
||||||
|
if (parser->nerr != 0) {
|
||||||
|
LOG(ERROR) << "mruby parser detected parse error";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto proc = mrb_generate_code(mrb, parser);
|
||||||
|
if (proc == nullptr) {
|
||||||
|
LOG(ERROR) << "mrb_generate_code failed";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<MRubyContext> create_mruby_context() {
|
||||||
|
auto mrb = mrb_open();
|
||||||
|
if (mrb == nullptr) {
|
||||||
|
LOG(ERROR) << "mrb_open failed";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_module(mrb);
|
||||||
|
|
||||||
|
auto req_file = get_config()->on_request_mruby_file.get();
|
||||||
|
auto res_file = get_config()->on_response_mruby_file.get();
|
||||||
|
|
||||||
|
auto req_proc = compile(mrb, req_file);
|
||||||
|
|
||||||
|
if (req_file && !req_proc) {
|
||||||
|
LOG(ERROR) << "Could not compile mruby code " << req_file;
|
||||||
|
mrb_close(mrb);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto res_proc = compile(mrb, res_file);
|
||||||
|
|
||||||
|
if (res_file && !res_proc) {
|
||||||
|
LOG(ERROR) << "Could not compile mruby code " << res_file;
|
||||||
|
mrb_close(mrb);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return make_unique<MRubyContext>(mrb, req_proc, res_proc);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mruby
|
||||||
|
|
||||||
|
} // namespace shrpx
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* nghttp2 - HTTP/2 C Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef SHRPX_MRUBY_H
|
||||||
|
#define SHRPX_MRUBY_H
|
||||||
|
|
||||||
|
#include "shrpx.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <mruby.h>
|
||||||
|
#include <mruby/proc.h>
|
||||||
|
|
||||||
|
using namespace nghttp2;
|
||||||
|
|
||||||
|
namespace shrpx {
|
||||||
|
|
||||||
|
namespace mruby {
|
||||||
|
|
||||||
|
class MRubyContext {
|
||||||
|
public:
|
||||||
|
MRubyContext(mrb_state *mrb, RProc *on_request_proc, RProc *on_response_proc);
|
||||||
|
~MRubyContext();
|
||||||
|
|
||||||
|
int run_on_request_proc(Downstream *downstream);
|
||||||
|
int run_on_response_proc(Downstream *downstream);
|
||||||
|
|
||||||
|
private:
|
||||||
|
mrb_state *mrb_;
|
||||||
|
RProc *on_request_proc_;
|
||||||
|
RProc *on_response_proc_;
|
||||||
|
};
|
||||||
|
|
||||||
|
RProc *compile(mrb_state *mrb, const char *filename);
|
||||||
|
|
||||||
|
std::unique_ptr<MRubyContext> create_mruby_context();
|
||||||
|
|
||||||
|
} // namespace mruby
|
||||||
|
|
||||||
|
} // namespace shrpx
|
||||||
|
|
||||||
|
#endif // SHRPX_MRUBY_H
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* nghttp2 - HTTP/2 C Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "shrpx_mruby_module.h"
|
||||||
|
|
||||||
|
#include <mruby/variable.h>
|
||||||
|
#include <mruby/string.h>
|
||||||
|
|
||||||
|
#include "shrpx_downstream.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
namespace shrpx {
|
||||||
|
|
||||||
|
namespace mruby {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
mrb_value request_init(mrb_state *mrb, mrb_value self) { return self; }
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
mrb_value request_get_path(mrb_state *mrb, mrb_value self) {
|
||||||
|
auto downstream = static_cast<Downstream *>(mrb->ud);
|
||||||
|
auto &path = downstream->get_request_path();
|
||||||
|
|
||||||
|
return mrb_str_new_static(mrb, path.c_str(), path.size());
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
mrb_value request_set_path(mrb_state *mrb, mrb_value self) {
|
||||||
|
auto downstream = static_cast<Downstream *>(mrb->ud);
|
||||||
|
|
||||||
|
const char *path;
|
||||||
|
mrb_int pathlen;
|
||||||
|
mrb_get_args(mrb, "s", &path, &pathlen);
|
||||||
|
if (pathlen == 0) {
|
||||||
|
mrb_raise(mrb, E_RUNTIME_ERROR, "path must not be empty string");
|
||||||
|
}
|
||||||
|
|
||||||
|
downstream->set_request_path(std::string(path, pathlen));
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
mrb_value request_get_headers(mrb_state *mrb, mrb_value self) {
|
||||||
|
auto headers = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "RequestHeaders"));
|
||||||
|
if (mrb_nil_p(headers)) {
|
||||||
|
auto module = mrb_module_get(mrb, "Nghttpx");
|
||||||
|
auto headers_class = mrb_class_get_under(mrb, module, "RequestHeaders");
|
||||||
|
headers = mrb_obj_new(mrb, headers_class, 0, nullptr);
|
||||||
|
mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "RequestHeaders"), headers);
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
mrb_value headers_init(mrb_state *mrb, mrb_value self) { return self; }
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
mrb_value request_headers_get(mrb_state *mrb, mrb_value self) {
|
||||||
|
auto downstream = static_cast<Downstream *>(mrb->ud);
|
||||||
|
|
||||||
|
mrb_value key;
|
||||||
|
mrb_get_args(mrb, "o", &key);
|
||||||
|
|
||||||
|
key = mrb_funcall(mrb, key, "downcase", 0);
|
||||||
|
|
||||||
|
if (RSTRING_LEN(key) == 0) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto hd = downstream->get_request_header(
|
||||||
|
std::string(RSTRING_PTR(key), RSTRING_LEN(key)));
|
||||||
|
|
||||||
|
if (hd == nullptr) {
|
||||||
|
return mrb_nil_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mrb_str_new_static(mrb, hd->value.c_str(), hd->value.size());
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
mrb_value request_headers_set(mrb_state *mrb, mrb_value self, bool repl) {
|
||||||
|
auto downstream = static_cast<Downstream *>(mrb->ud);
|
||||||
|
|
||||||
|
mrb_value key, value;
|
||||||
|
mrb_get_args(mrb, "oo", &key, &value);
|
||||||
|
|
||||||
|
key = mrb_funcall(mrb, key, "downcase", 0);
|
||||||
|
|
||||||
|
if (RSTRING_LEN(key) == 0) {
|
||||||
|
mrb_raise(mrb, E_RUNTIME_ERROR, "empty key is not allowed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (repl) {
|
||||||
|
for (auto &hd : downstream->get_request_headers()) {
|
||||||
|
if (util::streq(std::begin(hd.name), hd.name.size(), RSTRING_PTR(key),
|
||||||
|
RSTRING_LEN(key))) {
|
||||||
|
hd.name = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
downstream->add_request_header(
|
||||||
|
std::string(RSTRING_PTR(key), RSTRING_LEN(key)),
|
||||||
|
std::string(RSTRING_PTR(value), RSTRING_LEN(value)));
|
||||||
|
|
||||||
|
downstream->set_request_headers_dirty(true);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
mrb_value request_headers_set(mrb_state *mrb, mrb_value self) {
|
||||||
|
return request_headers_set(mrb, self, true);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
mrb_value request_headers_add(mrb_state *mrb, mrb_value self) {
|
||||||
|
return request_headers_set(mrb, self, false);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void init_headers_class(mrb_state *mrb, RClass *module, const char *name,
|
||||||
|
mrb_func_t get, mrb_func_t set, mrb_func_t add) {
|
||||||
|
auto headers_class =
|
||||||
|
mrb_define_class_under(mrb, module, name, mrb->object_class);
|
||||||
|
|
||||||
|
mrb_define_method(mrb, headers_class, "initialize", headers_init,
|
||||||
|
MRB_ARGS_NONE());
|
||||||
|
mrb_define_method(mrb, headers_class, "get", get, MRB_ARGS_REQ(1));
|
||||||
|
mrb_define_method(mrb, headers_class, "set", set, MRB_ARGS_REQ(2));
|
||||||
|
mrb_define_method(mrb, headers_class, "add", set, MRB_ARGS_REQ(2));
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void init_request_class(mrb_state *mrb, RClass *module) {
|
||||||
|
auto request_class =
|
||||||
|
mrb_define_class_under(mrb, module, "Request", mrb->object_class);
|
||||||
|
|
||||||
|
mrb_define_method(mrb, request_class, "initialize", request_init,
|
||||||
|
MRB_ARGS_NONE());
|
||||||
|
mrb_define_method(mrb, request_class, "path", request_get_path,
|
||||||
|
MRB_ARGS_NONE());
|
||||||
|
mrb_define_method(mrb, request_class, "path=", request_set_path,
|
||||||
|
MRB_ARGS_REQ(1));
|
||||||
|
mrb_define_method(mrb, request_class, "headers", request_get_headers,
|
||||||
|
MRB_ARGS_NONE());
|
||||||
|
|
||||||
|
init_headers_class(mrb, module, "RequestHeaders", request_headers_get,
|
||||||
|
request_headers_set, request_headers_add);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void init_module(mrb_state *mrb) {
|
||||||
|
auto module = mrb_define_module(mrb, "Nghttpx");
|
||||||
|
|
||||||
|
init_request_class(mrb, module);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mruby
|
||||||
|
|
||||||
|
} // namespace shrpx
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* nghttp2 - HTTP/2 C Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef SHRPX_MRUBY_MODULE_H
|
||||||
|
#define SHRPX_MRUBY_MODULE_H
|
||||||
|
|
||||||
|
#include "shrpx.h"
|
||||||
|
|
||||||
|
#include <mruby.h>
|
||||||
|
|
||||||
|
using namespace nghttp2;
|
||||||
|
|
||||||
|
namespace shrpx {
|
||||||
|
|
||||||
|
namespace mruby {
|
||||||
|
|
||||||
|
void init_module(mrb_state *mrb);
|
||||||
|
|
||||||
|
} // namespace mruby
|
||||||
|
|
||||||
|
} // namespace shrpx
|
||||||
|
|
||||||
|
#endif // SHRPX_MRUBY_MODULE_H
|
|
@ -37,6 +37,7 @@
|
||||||
#include "shrpx_log_config.h"
|
#include "shrpx_log_config.h"
|
||||||
#include "shrpx_connect_blocker.h"
|
#include "shrpx_connect_blocker.h"
|
||||||
#include "shrpx_memcached_dispatcher.h"
|
#include "shrpx_memcached_dispatcher.h"
|
||||||
|
#include "shrpx_mruby.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "template.h"
|
#include "template.h"
|
||||||
|
|
||||||
|
@ -265,4 +266,17 @@ MemcachedDispatcher *Worker::get_session_cache_memcached_dispatcher() {
|
||||||
return session_cache_memcached_dispatcher_.get();
|
return session_cache_memcached_dispatcher_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Worker::create_mruby_context() {
|
||||||
|
mruby_ctx_ = mruby::create_mruby_context();
|
||||||
|
if (!mruby_ctx_) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mruby::MRubyContext *Worker::get_mruby_context() const {
|
||||||
|
return mruby_ctx_.get();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -51,6 +51,12 @@ class Http2Session;
|
||||||
class ConnectBlocker;
|
class ConnectBlocker;
|
||||||
class MemcachedDispatcher;
|
class MemcachedDispatcher;
|
||||||
|
|
||||||
|
namespace mruby {
|
||||||
|
|
||||||
|
class MRubyContext;
|
||||||
|
|
||||||
|
} // namespace mruby
|
||||||
|
|
||||||
namespace ssl {
|
namespace ssl {
|
||||||
class CertLookupTree;
|
class CertLookupTree;
|
||||||
} // namespace ssl
|
} // namespace ssl
|
||||||
|
@ -124,6 +130,10 @@ public:
|
||||||
|
|
||||||
MemcachedDispatcher *get_session_cache_memcached_dispatcher();
|
MemcachedDispatcher *get_session_cache_memcached_dispatcher();
|
||||||
|
|
||||||
|
int create_mruby_context();
|
||||||
|
|
||||||
|
mruby::MRubyContext *get_mruby_context() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifndef NOTHREADS
|
#ifndef NOTHREADS
|
||||||
std::future<void> fut_;
|
std::future<void> fut_;
|
||||||
|
@ -137,6 +147,7 @@ private:
|
||||||
WorkerStat worker_stat_;
|
WorkerStat worker_stat_;
|
||||||
std::vector<DownstreamGroup> dgrps_;
|
std::vector<DownstreamGroup> dgrps_;
|
||||||
std::unique_ptr<MemcachedDispatcher> session_cache_memcached_dispatcher_;
|
std::unique_ptr<MemcachedDispatcher> session_cache_memcached_dispatcher_;
|
||||||
|
std::unique_ptr<mruby::MRubyContext> mruby_ctx_;
|
||||||
struct ev_loop *loop_;
|
struct ev_loop *loop_;
|
||||||
|
|
||||||
// Following fields are shared across threads if
|
// Following fields are shared across threads if
|
||||||
|
|
Loading…
Reference in New Issue