12c593315Sopenharmony_ci/* 22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library 32c593315Sopenharmony_ci * 42c593315Sopenharmony_ci * Copyright (c) 2016 Tatsuhiro Tsujikawa 52c593315Sopenharmony_ci * 62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the 82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to 112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 122c593315Sopenharmony_ci * the following conditions: 132c593315Sopenharmony_ci * 142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be 152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software. 162c593315Sopenharmony_ci * 172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 242c593315Sopenharmony_ci */ 252c593315Sopenharmony_ci#include "shrpx_api_downstream_connection.h" 262c593315Sopenharmony_ci 272c593315Sopenharmony_ci#include <sys/mman.h> 282c593315Sopenharmony_ci#include <fcntl.h> 292c593315Sopenharmony_ci#include <unistd.h> 302c593315Sopenharmony_ci#include <cstdlib> 312c593315Sopenharmony_ci 322c593315Sopenharmony_ci#include "shrpx_client_handler.h" 332c593315Sopenharmony_ci#include "shrpx_upstream.h" 342c593315Sopenharmony_ci#include "shrpx_downstream.h" 352c593315Sopenharmony_ci#include "shrpx_worker.h" 362c593315Sopenharmony_ci#include "shrpx_connection_handler.h" 372c593315Sopenharmony_ci#include "shrpx_log.h" 382c593315Sopenharmony_ci 392c593315Sopenharmony_cinamespace shrpx { 402c593315Sopenharmony_ci 412c593315Sopenharmony_cinamespace { 422c593315Sopenharmony_ci// List of API endpoints 432c593315Sopenharmony_ciconst std::array<APIEndpoint, 2> &apis() { 442c593315Sopenharmony_ci static const auto apis = new std::array<APIEndpoint, 2>{ 452c593315Sopenharmony_ci APIEndpoint{ 462c593315Sopenharmony_ci StringRef::from_lit("/api/v1beta1/backendconfig"), 472c593315Sopenharmony_ci true, 482c593315Sopenharmony_ci (1 << API_METHOD_POST) | (1 << API_METHOD_PUT), 492c593315Sopenharmony_ci &APIDownstreamConnection::handle_backendconfig, 502c593315Sopenharmony_ci }, 512c593315Sopenharmony_ci APIEndpoint{ 522c593315Sopenharmony_ci StringRef::from_lit("/api/v1beta1/configrevision"), 532c593315Sopenharmony_ci true, 542c593315Sopenharmony_ci (1 << API_METHOD_GET), 552c593315Sopenharmony_ci &APIDownstreamConnection::handle_configrevision, 562c593315Sopenharmony_ci }, 572c593315Sopenharmony_ci }; 582c593315Sopenharmony_ci 592c593315Sopenharmony_ci return *apis; 602c593315Sopenharmony_ci} 612c593315Sopenharmony_ci} // namespace 622c593315Sopenharmony_ci 632c593315Sopenharmony_cinamespace { 642c593315Sopenharmony_ci// The method string. This must be same order of APIMethod. 652c593315Sopenharmony_ciconstexpr StringRef API_METHOD_STRING[] = { 662c593315Sopenharmony_ci StringRef::from_lit("GET"), 672c593315Sopenharmony_ci StringRef::from_lit("POST"), 682c593315Sopenharmony_ci StringRef::from_lit("PUT"), 692c593315Sopenharmony_ci}; 702c593315Sopenharmony_ci} // namespace 712c593315Sopenharmony_ci 722c593315Sopenharmony_ciAPIDownstreamConnection::APIDownstreamConnection(Worker *worker) 732c593315Sopenharmony_ci : worker_(worker), api_(nullptr), fd_(-1), shutdown_read_(false) {} 742c593315Sopenharmony_ci 752c593315Sopenharmony_ciAPIDownstreamConnection::~APIDownstreamConnection() { 762c593315Sopenharmony_ci if (fd_ != -1) { 772c593315Sopenharmony_ci close(fd_); 782c593315Sopenharmony_ci } 792c593315Sopenharmony_ci} 802c593315Sopenharmony_ci 812c593315Sopenharmony_ciint APIDownstreamConnection::attach_downstream(Downstream *downstream) { 822c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 832c593315Sopenharmony_ci DCLOG(INFO, this) << "Attaching to DOWNSTREAM:" << downstream; 842c593315Sopenharmony_ci } 852c593315Sopenharmony_ci 862c593315Sopenharmony_ci downstream_ = downstream; 872c593315Sopenharmony_ci 882c593315Sopenharmony_ci return 0; 892c593315Sopenharmony_ci} 902c593315Sopenharmony_ci 912c593315Sopenharmony_civoid APIDownstreamConnection::detach_downstream(Downstream *downstream) { 922c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 932c593315Sopenharmony_ci DCLOG(INFO, this) << "Detaching from DOWNSTREAM:" << downstream; 942c593315Sopenharmony_ci } 952c593315Sopenharmony_ci downstream_ = nullptr; 962c593315Sopenharmony_ci} 972c593315Sopenharmony_ci 982c593315Sopenharmony_ciint APIDownstreamConnection::send_reply(unsigned int http_status, 992c593315Sopenharmony_ci APIStatusCode api_status, 1002c593315Sopenharmony_ci const StringRef &data) { 1012c593315Sopenharmony_ci shutdown_read_ = true; 1022c593315Sopenharmony_ci 1032c593315Sopenharmony_ci auto upstream = downstream_->get_upstream(); 1042c593315Sopenharmony_ci 1052c593315Sopenharmony_ci auto &resp = downstream_->response(); 1062c593315Sopenharmony_ci 1072c593315Sopenharmony_ci resp.http_status = http_status; 1082c593315Sopenharmony_ci 1092c593315Sopenharmony_ci auto &balloc = downstream_->get_block_allocator(); 1102c593315Sopenharmony_ci 1112c593315Sopenharmony_ci StringRef api_status_str; 1122c593315Sopenharmony_ci 1132c593315Sopenharmony_ci switch (api_status) { 1142c593315Sopenharmony_ci case APIStatusCode::SUCCESS: 1152c593315Sopenharmony_ci api_status_str = StringRef::from_lit("Success"); 1162c593315Sopenharmony_ci break; 1172c593315Sopenharmony_ci case APIStatusCode::FAILURE: 1182c593315Sopenharmony_ci api_status_str = StringRef::from_lit("Failure"); 1192c593315Sopenharmony_ci break; 1202c593315Sopenharmony_ci default: 1212c593315Sopenharmony_ci assert(0); 1222c593315Sopenharmony_ci } 1232c593315Sopenharmony_ci 1242c593315Sopenharmony_ci constexpr auto M1 = StringRef::from_lit("{\"status\":\""); 1252c593315Sopenharmony_ci constexpr auto M2 = StringRef::from_lit("\",\"code\":"); 1262c593315Sopenharmony_ci constexpr auto M3 = StringRef::from_lit("}"); 1272c593315Sopenharmony_ci 1282c593315Sopenharmony_ci // 3 is the number of digits in http_status, assuming it is 3 digits 1292c593315Sopenharmony_ci // number. 1302c593315Sopenharmony_ci auto buflen = M1.size() + M2.size() + M3.size() + data.size() + 1312c593315Sopenharmony_ci api_status_str.size() + 3; 1322c593315Sopenharmony_ci 1332c593315Sopenharmony_ci auto buf = make_byte_ref(balloc, buflen); 1342c593315Sopenharmony_ci auto p = buf.base; 1352c593315Sopenharmony_ci 1362c593315Sopenharmony_ci p = std::copy(std::begin(M1), std::end(M1), p); 1372c593315Sopenharmony_ci p = std::copy(std::begin(api_status_str), std::end(api_status_str), p); 1382c593315Sopenharmony_ci p = std::copy(std::begin(M2), std::end(M2), p); 1392c593315Sopenharmony_ci p = util::utos(p, http_status); 1402c593315Sopenharmony_ci p = std::copy(std::begin(data), std::end(data), p); 1412c593315Sopenharmony_ci p = std::copy(std::begin(M3), std::end(M3), p); 1422c593315Sopenharmony_ci 1432c593315Sopenharmony_ci buf.len = p - buf.base; 1442c593315Sopenharmony_ci 1452c593315Sopenharmony_ci auto content_length = util::make_string_ref_uint(balloc, buf.len); 1462c593315Sopenharmony_ci 1472c593315Sopenharmony_ci resp.fs.add_header_token(StringRef::from_lit("content-length"), 1482c593315Sopenharmony_ci content_length, false, http2::HD_CONTENT_LENGTH); 1492c593315Sopenharmony_ci 1502c593315Sopenharmony_ci switch (http_status) { 1512c593315Sopenharmony_ci case 400: 1522c593315Sopenharmony_ci case 405: 1532c593315Sopenharmony_ci case 413: 1542c593315Sopenharmony_ci resp.fs.add_header_token(StringRef::from_lit("connection"), 1552c593315Sopenharmony_ci StringRef::from_lit("close"), false, 1562c593315Sopenharmony_ci http2::HD_CONNECTION); 1572c593315Sopenharmony_ci break; 1582c593315Sopenharmony_ci } 1592c593315Sopenharmony_ci 1602c593315Sopenharmony_ci if (upstream->send_reply(downstream_, buf.base, buf.len) != 0) { 1612c593315Sopenharmony_ci return -1; 1622c593315Sopenharmony_ci } 1632c593315Sopenharmony_ci 1642c593315Sopenharmony_ci return 0; 1652c593315Sopenharmony_ci} 1662c593315Sopenharmony_ci 1672c593315Sopenharmony_cinamespace { 1682c593315Sopenharmony_ciconst APIEndpoint *lookup_api(const StringRef &path) { 1692c593315Sopenharmony_ci switch (path.size()) { 1702c593315Sopenharmony_ci case 26: 1712c593315Sopenharmony_ci switch (path[25]) { 1722c593315Sopenharmony_ci case 'g': 1732c593315Sopenharmony_ci if (util::streq_l("/api/v1beta1/backendconfi", std::begin(path), 25)) { 1742c593315Sopenharmony_ci return &apis()[0]; 1752c593315Sopenharmony_ci } 1762c593315Sopenharmony_ci break; 1772c593315Sopenharmony_ci } 1782c593315Sopenharmony_ci break; 1792c593315Sopenharmony_ci case 27: 1802c593315Sopenharmony_ci switch (path[26]) { 1812c593315Sopenharmony_ci case 'n': 1822c593315Sopenharmony_ci if (util::streq_l("/api/v1beta1/configrevisio", std::begin(path), 26)) { 1832c593315Sopenharmony_ci return &apis()[1]; 1842c593315Sopenharmony_ci } 1852c593315Sopenharmony_ci break; 1862c593315Sopenharmony_ci } 1872c593315Sopenharmony_ci break; 1882c593315Sopenharmony_ci } 1892c593315Sopenharmony_ci return nullptr; 1902c593315Sopenharmony_ci} 1912c593315Sopenharmony_ci} // namespace 1922c593315Sopenharmony_ci 1932c593315Sopenharmony_ciint APIDownstreamConnection::push_request_headers() { 1942c593315Sopenharmony_ci auto &req = downstream_->request(); 1952c593315Sopenharmony_ci 1962c593315Sopenharmony_ci auto path = 1972c593315Sopenharmony_ci StringRef{std::begin(req.path), 1982c593315Sopenharmony_ci std::find(std::begin(req.path), std::end(req.path), '?')}; 1992c593315Sopenharmony_ci 2002c593315Sopenharmony_ci api_ = lookup_api(path); 2012c593315Sopenharmony_ci 2022c593315Sopenharmony_ci if (!api_) { 2032c593315Sopenharmony_ci send_reply(404, APIStatusCode::FAILURE); 2042c593315Sopenharmony_ci 2052c593315Sopenharmony_ci return 0; 2062c593315Sopenharmony_ci } 2072c593315Sopenharmony_ci 2082c593315Sopenharmony_ci switch (req.method) { 2092c593315Sopenharmony_ci case HTTP_GET: 2102c593315Sopenharmony_ci if (!(api_->allowed_methods & (1 << API_METHOD_GET))) { 2112c593315Sopenharmony_ci error_method_not_allowed(); 2122c593315Sopenharmony_ci return 0; 2132c593315Sopenharmony_ci } 2142c593315Sopenharmony_ci break; 2152c593315Sopenharmony_ci case HTTP_POST: 2162c593315Sopenharmony_ci if (!(api_->allowed_methods & (1 << API_METHOD_POST))) { 2172c593315Sopenharmony_ci error_method_not_allowed(); 2182c593315Sopenharmony_ci return 0; 2192c593315Sopenharmony_ci } 2202c593315Sopenharmony_ci break; 2212c593315Sopenharmony_ci case HTTP_PUT: 2222c593315Sopenharmony_ci if (!(api_->allowed_methods & (1 << API_METHOD_PUT))) { 2232c593315Sopenharmony_ci error_method_not_allowed(); 2242c593315Sopenharmony_ci return 0; 2252c593315Sopenharmony_ci } 2262c593315Sopenharmony_ci break; 2272c593315Sopenharmony_ci default: 2282c593315Sopenharmony_ci error_method_not_allowed(); 2292c593315Sopenharmony_ci return 0; 2302c593315Sopenharmony_ci } 2312c593315Sopenharmony_ci 2322c593315Sopenharmony_ci // This works with req.fs.content_length == -1 2332c593315Sopenharmony_ci if (req.fs.content_length > 2342c593315Sopenharmony_ci static_cast<int64_t>(get_config()->api.max_request_body)) { 2352c593315Sopenharmony_ci send_reply(413, APIStatusCode::FAILURE); 2362c593315Sopenharmony_ci 2372c593315Sopenharmony_ci return 0; 2382c593315Sopenharmony_ci } 2392c593315Sopenharmony_ci 2402c593315Sopenharmony_ci switch (req.method) { 2412c593315Sopenharmony_ci case HTTP_POST: 2422c593315Sopenharmony_ci case HTTP_PUT: { 2432c593315Sopenharmony_ci char tempname[] = "/tmp/nghttpx-api.XXXXXX"; 2442c593315Sopenharmony_ci#ifdef HAVE_MKOSTEMP 2452c593315Sopenharmony_ci fd_ = mkostemp(tempname, O_CLOEXEC); 2462c593315Sopenharmony_ci#else // !HAVE_MKOSTEMP 2472c593315Sopenharmony_ci fd_ = mkstemp(tempname); 2482c593315Sopenharmony_ci#endif // !HAVE_MKOSTEMP 2492c593315Sopenharmony_ci if (fd_ == -1) { 2502c593315Sopenharmony_ci send_reply(500, APIStatusCode::FAILURE); 2512c593315Sopenharmony_ci 2522c593315Sopenharmony_ci return 0; 2532c593315Sopenharmony_ci } 2542c593315Sopenharmony_ci#ifndef HAVE_MKOSTEMP 2552c593315Sopenharmony_ci util::make_socket_closeonexec(fd_); 2562c593315Sopenharmony_ci#endif // HAVE_MKOSTEMP 2572c593315Sopenharmony_ci unlink(tempname); 2582c593315Sopenharmony_ci break; 2592c593315Sopenharmony_ci } 2602c593315Sopenharmony_ci } 2612c593315Sopenharmony_ci 2622c593315Sopenharmony_ci downstream_->set_request_header_sent(true); 2632c593315Sopenharmony_ci auto src = downstream_->get_blocked_request_buf(); 2642c593315Sopenharmony_ci auto dest = downstream_->get_request_buf(); 2652c593315Sopenharmony_ci src->remove(*dest); 2662c593315Sopenharmony_ci 2672c593315Sopenharmony_ci return 0; 2682c593315Sopenharmony_ci} 2692c593315Sopenharmony_ci 2702c593315Sopenharmony_ciint APIDownstreamConnection::error_method_not_allowed() { 2712c593315Sopenharmony_ci auto &resp = downstream_->response(); 2722c593315Sopenharmony_ci 2732c593315Sopenharmony_ci size_t len = 0; 2742c593315Sopenharmony_ci for (uint8_t i = 0; i < API_METHOD_MAX; ++i) { 2752c593315Sopenharmony_ci if (api_->allowed_methods & (1 << i)) { 2762c593315Sopenharmony_ci // The length of method + ", " 2772c593315Sopenharmony_ci len += API_METHOD_STRING[i].size() + 2; 2782c593315Sopenharmony_ci } 2792c593315Sopenharmony_ci } 2802c593315Sopenharmony_ci 2812c593315Sopenharmony_ci assert(len > 0); 2822c593315Sopenharmony_ci 2832c593315Sopenharmony_ci auto &balloc = downstream_->get_block_allocator(); 2842c593315Sopenharmony_ci 2852c593315Sopenharmony_ci auto iov = make_byte_ref(balloc, len + 1); 2862c593315Sopenharmony_ci auto p = iov.base; 2872c593315Sopenharmony_ci for (uint8_t i = 0; i < API_METHOD_MAX; ++i) { 2882c593315Sopenharmony_ci if (api_->allowed_methods & (1 << i)) { 2892c593315Sopenharmony_ci auto &s = API_METHOD_STRING[i]; 2902c593315Sopenharmony_ci p = std::copy(std::begin(s), std::end(s), p); 2912c593315Sopenharmony_ci p = std::copy_n(", ", 2, p); 2922c593315Sopenharmony_ci } 2932c593315Sopenharmony_ci } 2942c593315Sopenharmony_ci 2952c593315Sopenharmony_ci p -= 2; 2962c593315Sopenharmony_ci *p = '\0'; 2972c593315Sopenharmony_ci 2982c593315Sopenharmony_ci resp.fs.add_header_token(StringRef::from_lit("allow"), StringRef{iov.base, p}, 2992c593315Sopenharmony_ci false, -1); 3002c593315Sopenharmony_ci return send_reply(405, APIStatusCode::FAILURE); 3012c593315Sopenharmony_ci} 3022c593315Sopenharmony_ci 3032c593315Sopenharmony_ciint APIDownstreamConnection::push_upload_data_chunk(const uint8_t *data, 3042c593315Sopenharmony_ci size_t datalen) { 3052c593315Sopenharmony_ci if (shutdown_read_ || !api_->require_body) { 3062c593315Sopenharmony_ci return 0; 3072c593315Sopenharmony_ci } 3082c593315Sopenharmony_ci 3092c593315Sopenharmony_ci auto &req = downstream_->request(); 3102c593315Sopenharmony_ci auto &apiconf = get_config()->api; 3112c593315Sopenharmony_ci 3122c593315Sopenharmony_ci if (static_cast<size_t>(req.recv_body_length) > apiconf.max_request_body) { 3132c593315Sopenharmony_ci send_reply(413, APIStatusCode::FAILURE); 3142c593315Sopenharmony_ci 3152c593315Sopenharmony_ci return 0; 3162c593315Sopenharmony_ci } 3172c593315Sopenharmony_ci 3182c593315Sopenharmony_ci ssize_t nwrite; 3192c593315Sopenharmony_ci while ((nwrite = write(fd_, data, datalen)) == -1 && errno == EINTR) 3202c593315Sopenharmony_ci ; 3212c593315Sopenharmony_ci if (nwrite == -1) { 3222c593315Sopenharmony_ci auto error = errno; 3232c593315Sopenharmony_ci LOG(ERROR) << "Could not write API request body: errno=" << error; 3242c593315Sopenharmony_ci send_reply(500, APIStatusCode::FAILURE); 3252c593315Sopenharmony_ci 3262c593315Sopenharmony_ci return 0; 3272c593315Sopenharmony_ci } 3282c593315Sopenharmony_ci 3292c593315Sopenharmony_ci // We don't have to call Upstream::resume_read() here, because 3302c593315Sopenharmony_ci // request buffer is effectively unlimited. Actually, we cannot 3312c593315Sopenharmony_ci // call it here since it could recursively call this function again. 3322c593315Sopenharmony_ci 3332c593315Sopenharmony_ci return 0; 3342c593315Sopenharmony_ci} 3352c593315Sopenharmony_ci 3362c593315Sopenharmony_ciint APIDownstreamConnection::end_upload_data() { 3372c593315Sopenharmony_ci if (shutdown_read_) { 3382c593315Sopenharmony_ci return 0; 3392c593315Sopenharmony_ci } 3402c593315Sopenharmony_ci 3412c593315Sopenharmony_ci return api_->handler(*this); 3422c593315Sopenharmony_ci} 3432c593315Sopenharmony_ci 3442c593315Sopenharmony_ciint APIDownstreamConnection::handle_backendconfig() { 3452c593315Sopenharmony_ci auto &req = downstream_->request(); 3462c593315Sopenharmony_ci 3472c593315Sopenharmony_ci if (req.recv_body_length == 0) { 3482c593315Sopenharmony_ci send_reply(200, APIStatusCode::SUCCESS); 3492c593315Sopenharmony_ci 3502c593315Sopenharmony_ci return 0; 3512c593315Sopenharmony_ci } 3522c593315Sopenharmony_ci 3532c593315Sopenharmony_ci auto rp = mmap(nullptr, req.recv_body_length, PROT_READ, MAP_SHARED, fd_, 0); 3542c593315Sopenharmony_ci if (rp == reinterpret_cast<void *>(-1)) { 3552c593315Sopenharmony_ci send_reply(500, APIStatusCode::FAILURE); 3562c593315Sopenharmony_ci return 0; 3572c593315Sopenharmony_ci } 3582c593315Sopenharmony_ci 3592c593315Sopenharmony_ci auto unmapper = defer(munmap, rp, req.recv_body_length); 3602c593315Sopenharmony_ci 3612c593315Sopenharmony_ci Config new_config{}; 3622c593315Sopenharmony_ci new_config.conn.downstream = std::make_shared<DownstreamConfig>(); 3632c593315Sopenharmony_ci const auto &downstreamconf = new_config.conn.downstream; 3642c593315Sopenharmony_ci 3652c593315Sopenharmony_ci auto config = get_config(); 3662c593315Sopenharmony_ci auto &src = config->conn.downstream; 3672c593315Sopenharmony_ci 3682c593315Sopenharmony_ci downstreamconf->timeout = src->timeout; 3692c593315Sopenharmony_ci downstreamconf->connections_per_host = src->connections_per_host; 3702c593315Sopenharmony_ci downstreamconf->connections_per_frontend = src->connections_per_frontend; 3712c593315Sopenharmony_ci downstreamconf->request_buffer_size = src->request_buffer_size; 3722c593315Sopenharmony_ci downstreamconf->response_buffer_size = src->response_buffer_size; 3732c593315Sopenharmony_ci downstreamconf->family = src->family; 3742c593315Sopenharmony_ci 3752c593315Sopenharmony_ci std::set<StringRef> include_set; 3762c593315Sopenharmony_ci std::map<StringRef, size_t> pattern_addr_indexer; 3772c593315Sopenharmony_ci 3782c593315Sopenharmony_ci for (auto first = reinterpret_cast<const uint8_t *>(rp), 3792c593315Sopenharmony_ci last = first + req.recv_body_length; 3802c593315Sopenharmony_ci first != last;) { 3812c593315Sopenharmony_ci auto eol = std::find(first, last, '\n'); 3822c593315Sopenharmony_ci if (eol == last) { 3832c593315Sopenharmony_ci break; 3842c593315Sopenharmony_ci } 3852c593315Sopenharmony_ci 3862c593315Sopenharmony_ci if (first == eol || *first == '#') { 3872c593315Sopenharmony_ci first = ++eol; 3882c593315Sopenharmony_ci continue; 3892c593315Sopenharmony_ci } 3902c593315Sopenharmony_ci 3912c593315Sopenharmony_ci auto eq = std::find(first, eol, '='); 3922c593315Sopenharmony_ci if (eq == eol) { 3932c593315Sopenharmony_ci send_reply(400, APIStatusCode::FAILURE); 3942c593315Sopenharmony_ci return 0; 3952c593315Sopenharmony_ci } 3962c593315Sopenharmony_ci 3972c593315Sopenharmony_ci auto opt = StringRef{first, eq}; 3982c593315Sopenharmony_ci auto optval = StringRef{eq + 1, eol}; 3992c593315Sopenharmony_ci 4002c593315Sopenharmony_ci auto optid = option_lookup_token(opt.c_str(), opt.size()); 4012c593315Sopenharmony_ci 4022c593315Sopenharmony_ci switch (optid) { 4032c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND: 4042c593315Sopenharmony_ci break; 4052c593315Sopenharmony_ci default: 4062c593315Sopenharmony_ci first = ++eol; 4072c593315Sopenharmony_ci continue; 4082c593315Sopenharmony_ci } 4092c593315Sopenharmony_ci 4102c593315Sopenharmony_ci if (parse_config(&new_config, optid, opt, optval, include_set, 4112c593315Sopenharmony_ci pattern_addr_indexer) != 0) { 4122c593315Sopenharmony_ci send_reply(400, APIStatusCode::FAILURE); 4132c593315Sopenharmony_ci return 0; 4142c593315Sopenharmony_ci } 4152c593315Sopenharmony_ci 4162c593315Sopenharmony_ci first = ++eol; 4172c593315Sopenharmony_ci } 4182c593315Sopenharmony_ci 4192c593315Sopenharmony_ci auto &tlsconf = config->tls; 4202c593315Sopenharmony_ci if (configure_downstream_group(&new_config, config->http2_proxy, true, 4212c593315Sopenharmony_ci tlsconf) != 0) { 4222c593315Sopenharmony_ci send_reply(400, APIStatusCode::FAILURE); 4232c593315Sopenharmony_ci return 0; 4242c593315Sopenharmony_ci } 4252c593315Sopenharmony_ci 4262c593315Sopenharmony_ci auto conn_handler = worker_->get_connection_handler(); 4272c593315Sopenharmony_ci 4282c593315Sopenharmony_ci conn_handler->send_replace_downstream(downstreamconf); 4292c593315Sopenharmony_ci 4302c593315Sopenharmony_ci send_reply(200, APIStatusCode::SUCCESS); 4312c593315Sopenharmony_ci 4322c593315Sopenharmony_ci return 0; 4332c593315Sopenharmony_ci} 4342c593315Sopenharmony_ci 4352c593315Sopenharmony_ciint APIDownstreamConnection::handle_configrevision() { 4362c593315Sopenharmony_ci auto config = get_config(); 4372c593315Sopenharmony_ci auto &balloc = downstream_->get_block_allocator(); 4382c593315Sopenharmony_ci 4392c593315Sopenharmony_ci // Construct the following string: 4402c593315Sopenharmony_ci // , 4412c593315Sopenharmony_ci // "data":{ 4422c593315Sopenharmony_ci // "configRevision": N 4432c593315Sopenharmony_ci // } 4442c593315Sopenharmony_ci auto data = concat_string_ref( 4452c593315Sopenharmony_ci balloc, StringRef::from_lit(R"(,"data":{"configRevision":)"), 4462c593315Sopenharmony_ci util::make_string_ref_uint(balloc, config->config_revision), 4472c593315Sopenharmony_ci StringRef::from_lit("}")); 4482c593315Sopenharmony_ci 4492c593315Sopenharmony_ci send_reply(200, APIStatusCode::SUCCESS, data); 4502c593315Sopenharmony_ci 4512c593315Sopenharmony_ci return 0; 4522c593315Sopenharmony_ci} 4532c593315Sopenharmony_ci 4542c593315Sopenharmony_civoid APIDownstreamConnection::pause_read(IOCtrlReason reason) {} 4552c593315Sopenharmony_ci 4562c593315Sopenharmony_ciint APIDownstreamConnection::resume_read(IOCtrlReason reason, size_t consumed) { 4572c593315Sopenharmony_ci return 0; 4582c593315Sopenharmony_ci} 4592c593315Sopenharmony_ci 4602c593315Sopenharmony_civoid APIDownstreamConnection::force_resume_read() {} 4612c593315Sopenharmony_ci 4622c593315Sopenharmony_ciint APIDownstreamConnection::on_read() { return 0; } 4632c593315Sopenharmony_ci 4642c593315Sopenharmony_ciint APIDownstreamConnection::on_write() { return 0; } 4652c593315Sopenharmony_ci 4662c593315Sopenharmony_civoid APIDownstreamConnection::on_upstream_change(Upstream *upstream) {} 4672c593315Sopenharmony_ci 4682c593315Sopenharmony_cibool APIDownstreamConnection::poolable() const { return false; } 4692c593315Sopenharmony_ci 4702c593315Sopenharmony_ciconst std::shared_ptr<DownstreamAddrGroup> & 4712c593315Sopenharmony_ciAPIDownstreamConnection::get_downstream_addr_group() const { 4722c593315Sopenharmony_ci static std::shared_ptr<DownstreamAddrGroup> s; 4732c593315Sopenharmony_ci return s; 4742c593315Sopenharmony_ci} 4752c593315Sopenharmony_ci 4762c593315Sopenharmony_ciDownstreamAddr *APIDownstreamConnection::get_addr() const { return nullptr; } 4772c593315Sopenharmony_ci 4782c593315Sopenharmony_ci} // namespace shrpx 479