21#include <condition_variable>
30static constexpr std::initializer_list<std::string_view> _certificate_files = {
31 "/etc/ssl/certs/ca-certificates.crt"sv,
32 "/etc/pki/tls/certs/ca-bundle.crt"sv,
33 "/etc/ssl/ca-bundle.pem"sv,
34 "/etc/pki/tls/cacert.pem"sv,
35 "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"sv,
36 "/etc/ssl/cert.pem"sv,
39static constexpr std::initializer_list<std::string_view> _certificate_directories = {
41 "/etc/pki/tls/certs"sv,
42 "/system/etc/security/cacerts"sv,
77 const std::string
uri;
88static std::string _http_ca_file =
"";
89static std::string _http_ca_path =
"";
96 if (_http_ca_file.empty() && _http_ca_path.empty()) {
103 _http_requests.push(std::make_unique<NetworkHTTPRequest>(uri, callback, std::move(data)));
121 callback->HandleQueue();
133 CURLcode res = curl_easy_setopt(curl, option, value);
134 if (res != CURLE_OK) {
142 CURL *curl = curl_easy_init();
143 assert(curl !=
nullptr);
154 std::unique_ptr<NetworkHTTPRequest> request = std::move(
_http_requests.front());
161 curl_easy_reset(curl);
162 curl_slist *headers =
nullptr;
176 CurlSetOption(curl, CURLOPT_CAINFO, _http_ca_file.empty() ?
nullptr : _http_ca_file.c_str());
177 CurlSetOption(curl, CURLOPT_CAPATH, _http_ca_path.empty() ?
nullptr : _http_ca_path.c_str());
192 if (!request->data.empty()) {
194 if (request->data.starts_with(
"{")) {
195 headers = curl_slist_append(headers,
"Content-Type: application/json");
197 headers = curl_slist_append(headers,
"Content-Type: application/x-www-form-urlencoded");
201 CurlSetOption(curl, CURLOPT_POSTFIELDS, request->data.c_str());
207 CurlSetOption(curl, CURLOPT_WRITEFUNCTION, +[](
char *ptr,
size_t size,
size_t nmemb,
void *userdata) ->
size_t {
212 std::unique_ptr<char[]> buffer = std::make_unique<char[]>(size * nmemb);
213 std::copy_n(ptr, size * nmemb, buffer.get());
225 CurlSetOption(curl, CURLOPT_XFERINFOFUNCTION, +[](
void *userdata, curl_off_t , curl_off_t , curl_off_t , curl_off_t ) ->
int {
229 CurlSetOption(curl, CURLOPT_XFERINFODATA, &request->callback);
232 CURLcode res = curl_easy_perform(curl);
234 curl_slist_free_all(headers);
236 if (res == CURLE_OK) {
238 request->callback.OnReceiveData(
nullptr, 0);
240 long status_code = 0;
241 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status_code);
245 request->callback.OnFailure();
249 request->callback.WaitTillEmptyOrCondition([]() ->
bool {
254 curl_easy_cleanup(curl);
259 curl_global_init(CURL_GLOBAL_DEFAULT);
265 for (
auto &ca_file : _certificate_files) {
267 _http_ca_file = ca_file;
271 if (_http_ca_file.empty()) {
272 for (
auto &ca_path : _certificate_directories) {
274 _http_ca_path = ca_path;
283 if (_http_ca_file.empty() && _http_ca_path.empty()) {
309 curl_global_cleanup();
Converts a HTTPCallback to a Thread-Safe variant.
void OnReceiveData(std::unique_ptr< char[]> data, size_t length)
Similar to HTTPCallback::OnReceiveData, but thread-safe.
std::atomic< bool > cancelled
Whether this callback has been cancelled, or not.
const std::string data
Data to send, if any.
~NetworkHTTPRequest()
Remove ourselves from the callback list.
NetworkHTTPRequest(std::string_view uri, HTTPCallback *callback, std::string &&data)
Create a new HTTP request.
HTTPThreadSafeCallback callback
Callback to send data back on.
const std::string uri
URI to connect to.
static void Connect(std::string_view uri, HTTPCallback *callback, std::string &&data="")
Connect to the given URI.
static void HTTPReceive()
Do the receiving for all HTTP connections.
Functions related to debugging.
bool IsVisibleSeverity(Facility facility, Severity severity)
Test if debug severity is visible for the given facility.
#define Debug(facility, severity, format_string,...)
Output a line of debugging information.
@ Net
Net message facility.
@ Debug1
Debug #1 - High level debug messages.
@ Critical
Critical, user should know about this.
@ Debug2
Debug #2 - Low level debug messages.
@ Error
Error, but we are recovering.
bool FileExists(std::string_view filename)
Test whether the given filename exists.
Functions for standard in/out file operations.
Basic functions to send and receive HTTP packets.
constexpr int HTTP_429_TOO_MANY_REQUESTS
HTTP error code for when the client is doing too many requests.
static std::mutex _http_mutex
Mutex to prevent concurrent access _http_requests.
static std::queue< std::unique_ptr< NetworkHTTPRequest > > _http_requests
HTTP requests that are currently running.
void NetworkHTTPInitialize()
Initialize the HTTP socket handler.
static std::vector< HTTPThreadSafeCallback * > _new_http_callbacks
Callbacks for the request that should be started.
static std::thread _http_thread
The thread running the HTTP requests.
static std::condition_variable _http_cv
Conditional variable to wake up the HTTP request thread.
static std::atomic< bool > _http_thread_exit
Whether to ask the HTTP request thread to stop.
static std::mutex _http_callback_mutex
Mutex to prevent concurrent access to _http_callbacks.
void CurlSetOption(CURL *curl, auto option, auto value)
Set some specific option and emit debug information upon failure.
static std::mutex _new_http_callback_mutex
Mutex to prevent concurrent access to _new_http_callbacks.
void HttpThread()
Thread entry point for the HTTP request thread.
void NetworkHTTPUninitialize()
Uninitialize the HTTP socket handler.
static std::vector< HTTPThreadSafeCallback * > _http_callbacks
Callback for the current requests.
Shared functions for implementations of HTTP requests.
static std::vector< HTTPThreadSafeCallback * > _new_http_callbacks
Callbacks for the request that should be started.
static std::mutex _http_callback_mutex
Mutex to prevent concurrent access to _http_callbacks.
static std::mutex _new_http_callback_mutex
Mutex to prevent concurrent access to _new_http_callbacks.
static std::vector< HTTPThreadSafeCallback * > _http_callbacks
Callback for the current requests.
std::string_view GetNetworkRevisionString()
Get the network version string used by this build.
Variables and function used internally.
Declaration of OTTD revision dependent variables.
A number of safeguards to prevent using unsafe methods.
Definition of base types and functions in a cross-platform compatible way.
Callback for when the HTTP handler has something to tell us.
virtual void OnFailure()=0
An error has occurred and the connection has been closed.
bool StartNewThread(std::thread *thr, std::string_view name, TFn &&_Fx, TArgs &&... _Ax)
Start a new thread.
std::mutex lock
synchronization for playback status fields