]>
Commit | Line | Data |
---|---|---|
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 |
14 | namespace dmc = rgw::dmclock; |
15 | ||
16 | RGWCivetWebFrontend::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 |
48 | static 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 | ||
54 | int 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 | ||
87 | int 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 */ |