]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_civetweb_frontend.cc
buildsys: switch source download to quincy
[ceph.git] / ceph / src / rgw / rgw_civetweb_frontend.cc
CommitLineData
7c673cae 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
9f95a23c 2// vim: ts=8 sw=2 smarttab ft=cpp
7c673cae
FG
3
4#include <set>
5#include <string>
f67539c2 6#include <string_view>
7c673cae
FG
7
8#include "rgw_frontend.h"
9#include "rgw_client_io_filters.h"
11fdf7f2 10#include "rgw_dmclock_sync_scheduler.h"
7c673cae
FG
11
12#define dout_subsys ceph_subsys_rgw
13
11fdf7f2
TL
14namespace dmc = rgw::dmclock;
15
16RGWCivetWebFrontend::RGWCivetWebFrontend(RGWProcessEnv& env,
17 RGWFrontendConfig *conf,
18 dmc::SchedulerCtx& sched_ctx)
19 : conf(conf),
20 ctx(nullptr),
21 env(env)
22{
23
24 auto sched_t = dmc::get_scheduler_t(cct());
25 switch(sched_t){
26 case dmc::scheduler_t::none: [[fallthrough]];
27 case dmc::scheduler_t::throttler:
28 break;
29 case dmc::scheduler_t::dmclock:
30 // TODO: keep track of server ready state and use that here civetweb
31 // internally tracks in the ctx the threads used and free, while it is
32 // expected with the current implementation that the threads waiting on the
33 // queue would still show up in the "used" queue, it might be a useful thing
34 // to make decisions on in the future. Also while reconfiguring we should
35 // probably set this to false
36 auto server_ready_f = []() -> bool { return true; };
37
38 scheduler.reset(new dmc::SyncScheduler(cct(),
39 std::ref(sched_ctx.get_dmc_client_counters()),
40 *sched_ctx.get_dmc_client_config(),
41 server_ready_f,
42 std::ref(dmc::SyncScheduler::handle_request_cb),
43 dmc::AtLimit::Reject));
44 }
45
46}
47
7c673cae
FG
48static int civetweb_callback(struct mg_connection* conn)
49{
50 const struct mg_request_info* const req_info = mg_get_request_info(conn);
51 return static_cast<RGWCivetWebFrontend *>(req_info->user_data)->process(conn);
52}
53
54int RGWCivetWebFrontend::process(struct mg_connection* const conn)
55{
56 /* Hold a read lock over access to env.store for reconfiguration. */
9f95a23c 57 std::shared_lock lock{env.mutex};
7c673cae
FG
58
59 RGWCivetWeb cw_client(conn);
60 auto real_client_io = rgw::io::add_reordering(
181888fb 61 rgw::io::add_buffering(dout_context,
7c673cae
FG
62 rgw::io::add_chunking(
63 rgw::io::add_conlen_controlling(
64 &cw_client))));
181888fb 65 RGWRestfulIO client_io(dout_context, &real_client_io);
7c673cae 66
9f95a23c 67 RGWRequest req(env.store->getRados()->get_new_req_id());
94b18763 68 int http_ret = 0;
f67539c2 69 ceph::coarse_real_clock::duration latency{};
11fdf7f2 70 //assert (scheduler != nullptr);
7c673cae 71 int ret = process_request(env.store, env.rest, &req, env.uri_prefix,
11fdf7f2 72 *env.auth_registry, &client_io, env.olog,
f67539c2 73 null_yield, scheduler.get(), nullptr, &latency, &http_ret);
7c673cae
FG
74 if (ret < 0) {
75 /* We don't really care about return code. */
76 dout(20) << "process_request() returned " << ret << dendl;
77 }
78
94b18763
FG
79 if (http_ret <= 0) {
80 /* Mark as processed. */
81 return 1;
82 }
83
84 return http_ret;
7c673cae
FG
85}
86
87int RGWCivetWebFrontend::run()
88{
89 auto& conf_map = conf->get_config_map();
7c673cae
FG
90
91 set_conf_default(conf_map, "num_threads",
11fdf7f2 92 std::to_string(g_conf()->rgw_thread_pool_size));
7c673cae
FG
93 set_conf_default(conf_map, "decode_url", "no");
94 set_conf_default(conf_map, "enable_keep_alive", "yes");
95 set_conf_default(conf_map, "validate_http_method", "no");
96 set_conf_default(conf_map, "canonicalize_url_path", "no");
31f18b77 97 set_conf_default(conf_map, "enable_auth_domain_check", "no");
11fdf7f2 98 set_conf_default(conf_map, "allow_unicode_in_urls", "yes");
f67539c2 99 set_conf_default(conf_map, "request_timeout_ms", "65000");
28e407b8
AA
100
101 std::string listening_ports;
102 // support multiple port= entries
103 auto range = conf_map.equal_range("port");
104 for (auto p = range.first; p != range.second; ++p) {
105 std::string port_str = p->second;
106 // support port= entries with multiple values
107 std::replace(port_str.begin(), port_str.end(), '+', ',');
108 if (!listening_ports.empty()) {
109 listening_ports.append(1, ',');
110 }
111 listening_ports.append(port_str);
112 }
113 if (listening_ports.empty()) {
114 listening_ports = "80";
115 }
116 conf_map.emplace("listening_ports", std::move(listening_ports));
7c673cae
FG
117
118 /* Set run_as_user. This will cause civetweb to invoke setuid() and setgid()
119 * based on pw_uid and pw_gid obtained from pw_name. */
120 std::string uid_string = g_ceph_context->get_set_uid_string();
121 if (! uid_string.empty()) {
28e407b8 122 conf_map.emplace("run_as_user", std::move(uid_string));
7c673cae
FG
123 }
124
125 /* Prepare options for CivetWeb. */
f67539c2 126 const std::set<std::string_view> rgw_opts = { "port", "prefix" };
7c673cae
FG
127
128 std::vector<const char*> options;
129
130 for (const auto& pair : conf_map) {
131 if (! rgw_opts.count(pair.first)) {
132 /* CivetWeb doesn't understand configurables of the glue layer between
133 * it and RadosGW. We need to strip them out. Otherwise CivetWeb would
134 * signalise an error. */
135 options.push_back(pair.first.c_str());
136 options.push_back(pair.second.c_str());
137
138 dout(20) << "civetweb config: " << pair.first
139 << ": " << pair.second << dendl;
140 }
141 }
142
143 options.push_back(nullptr);
144 /* Initialize the CivetWeb right now. */
145 struct mg_callbacks cb;
92f5a8d4 146 // FIPS zeroization audit 20191115: this memset is not security related.
7c673cae
FG
147 memset((void *)&cb, 0, sizeof(cb));
148 cb.begin_request = civetweb_callback;
149 cb.log_message = rgw_civetweb_log_callback;
150 cb.log_access = rgw_civetweb_log_access_callback;
151 ctx = mg_start(&cb, this, options.data());
152
153 return ! ctx ? -EIO : 0;
154} /* RGWCivetWebFrontend::run */