summaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm16/lib/Debuginfod/HTTPClient.cpp
diff options
context:
space:
mode:
authorvvvv <[email protected]>2024-02-06 20:01:22 +0300
committervvvv <[email protected]>2024-02-06 20:22:16 +0300
commit0203b7a9a40828bb2bd4c32029b79ff0ea3d1f8f (patch)
treee630d0d5bd0bd29fc8c2d2842ed2cfde781b993a /contrib/libs/llvm16/lib/Debuginfod/HTTPClient.cpp
parentba27db76d99d12a4f1c06960b5449423218614c4 (diff)
llvm16 targets
Diffstat (limited to 'contrib/libs/llvm16/lib/Debuginfod/HTTPClient.cpp')
-rw-r--r--contrib/libs/llvm16/lib/Debuginfod/HTTPClient.cpp160
1 files changed, 160 insertions, 0 deletions
diff --git a/contrib/libs/llvm16/lib/Debuginfod/HTTPClient.cpp b/contrib/libs/llvm16/lib/Debuginfod/HTTPClient.cpp
new file mode 100644
index 00000000000..ab92c351dc0
--- /dev/null
+++ b/contrib/libs/llvm16/lib/Debuginfod/HTTPClient.cpp
@@ -0,0 +1,160 @@
+//===-- llvm/Debuginfod/HTTPClient.cpp - HTTP client library ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file defines the implementation of the HTTPClient library for issuing
+/// HTTP requests and handling the responses.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Debuginfod/HTTPClient.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+#ifdef LLVM_ENABLE_CURL
+#error #include <curl/curl.h>
+#endif
+
+using namespace llvm;
+
+HTTPRequest::HTTPRequest(StringRef Url) { this->Url = Url.str(); }
+
+bool operator==(const HTTPRequest &A, const HTTPRequest &B) {
+ return A.Url == B.Url && A.Method == B.Method &&
+ A.FollowRedirects == B.FollowRedirects;
+}
+
+HTTPResponseHandler::~HTTPResponseHandler() = default;
+
+bool HTTPClient::IsInitialized = false;
+
+class HTTPClientCleanup {
+public:
+ ~HTTPClientCleanup() { HTTPClient::cleanup(); }
+};
+static const HTTPClientCleanup Cleanup;
+
+#ifdef LLVM_ENABLE_CURL
+
+bool HTTPClient::isAvailable() { return true; }
+
+void HTTPClient::initialize() {
+ if (!IsInitialized) {
+ curl_global_init(CURL_GLOBAL_ALL);
+ IsInitialized = true;
+ }
+}
+
+void HTTPClient::cleanup() {
+ if (IsInitialized) {
+ curl_global_cleanup();
+ IsInitialized = false;
+ }
+}
+
+void HTTPClient::setTimeout(std::chrono::milliseconds Timeout) {
+ if (Timeout < std::chrono::milliseconds(0))
+ Timeout = std::chrono::milliseconds(0);
+ curl_easy_setopt(Curl, CURLOPT_TIMEOUT_MS, Timeout.count());
+}
+
+/// CurlHTTPRequest and the curl{Header,Write}Function are implementation
+/// details used to work with Curl. Curl makes callbacks with a single
+/// customizable pointer parameter.
+struct CurlHTTPRequest {
+ CurlHTTPRequest(HTTPResponseHandler &Handler) : Handler(Handler) {}
+ void storeError(Error Err) {
+ ErrorState = joinErrors(std::move(Err), std::move(ErrorState));
+ }
+ HTTPResponseHandler &Handler;
+ llvm::Error ErrorState = Error::success();
+};
+
+static size_t curlWriteFunction(char *Contents, size_t Size, size_t NMemb,
+ CurlHTTPRequest *CurlRequest) {
+ Size *= NMemb;
+ if (Error Err =
+ CurlRequest->Handler.handleBodyChunk(StringRef(Contents, Size))) {
+ CurlRequest->storeError(std::move(Err));
+ return 0;
+ }
+ return Size;
+}
+
+HTTPClient::HTTPClient() {
+ assert(IsInitialized &&
+ "Must call HTTPClient::initialize() at the beginning of main().");
+ if (Curl)
+ return;
+ Curl = curl_easy_init();
+ assert(Curl && "Curl could not be initialized");
+ // Set the callback hooks.
+ curl_easy_setopt(Curl, CURLOPT_WRITEFUNCTION, curlWriteFunction);
+}
+
+HTTPClient::~HTTPClient() { curl_easy_cleanup(Curl); }
+
+Error HTTPClient::perform(const HTTPRequest &Request,
+ HTTPResponseHandler &Handler) {
+ if (Request.Method != HTTPMethod::GET)
+ return createStringError(errc::invalid_argument,
+ "Unsupported CURL request method.");
+
+ SmallString<128> Url = Request.Url;
+ curl_easy_setopt(Curl, CURLOPT_URL, Url.c_str());
+ curl_easy_setopt(Curl, CURLOPT_FOLLOWLOCATION, Request.FollowRedirects);
+
+ curl_slist *Headers = nullptr;
+ for (const std::string &Header : Request.Headers)
+ Headers = curl_slist_append(Headers, Header.c_str());
+ curl_easy_setopt(Curl, CURLOPT_HTTPHEADER, Headers);
+
+ CurlHTTPRequest CurlRequest(Handler);
+ curl_easy_setopt(Curl, CURLOPT_WRITEDATA, &CurlRequest);
+ CURLcode CurlRes = curl_easy_perform(Curl);
+ curl_slist_free_all(Headers);
+ if (CurlRes != CURLE_OK)
+ return joinErrors(std::move(CurlRequest.ErrorState),
+ createStringError(errc::io_error,
+ "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(CurlRes)));
+ return std::move(CurlRequest.ErrorState);
+}
+
+unsigned HTTPClient::responseCode() {
+ long Code = 0;
+ curl_easy_getinfo(Curl, CURLINFO_RESPONSE_CODE, &Code);
+ return Code;
+}
+
+#else
+
+HTTPClient::HTTPClient() = default;
+
+HTTPClient::~HTTPClient() = default;
+
+bool HTTPClient::isAvailable() { return false; }
+
+void HTTPClient::initialize() {}
+
+void HTTPClient::cleanup() {}
+
+void HTTPClient::setTimeout(std::chrono::milliseconds Timeout) {}
+
+Error HTTPClient::perform(const HTTPRequest &Request,
+ HTTPResponseHandler &Handler) {
+ llvm_unreachable("No HTTP Client implementation available.");
+}
+
+unsigned HTTPClient::responseCode() {
+ llvm_unreachable("No HTTP Client implementation available.");
+}
+
+#endif