| 131 | } |
| 132 | |
| 133 | void HttpThread() |
| 134 | { |
| 135 | CURL *curl = curl_easy_init(); |
| 136 | assert(curl != nullptr); |
| 137 | |
| 138 | for (;;) { |
| 139 | std::unique_lock<std::mutex> lock(_http_mutex); |
| 140 | |
| 141 | /* Wait for a new request. */ |
| 142 | while (_http_requests.empty() && !_http_thread_exit) { |
| 143 | _http_cv.wait(lock); |
| 144 | } |
| 145 | if (_http_thread_exit) break; |
| 146 | |
| 147 | std::unique_ptr<NetworkHTTPRequest> request = std::move(_http_requests.front()); |
| 148 | _http_requests.pop(); |
| 149 | |
| 150 | /* Release the lock, as we will take a while to process the request. */ |
| 151 | lock.unlock(); |
| 152 | |
| 153 | /* Reset to default settings. */ |
| 154 | curl_easy_reset(curl); |
| 155 | curl_slist *headers = nullptr; |
| 156 | |
| 157 | if (_debug_net_level >= 5) { |
| 158 | CurlSetOption(curl, CURLOPT_VERBOSE, 1L); |
| 159 | } |
| 160 | |
| 161 | /* Setup some default options. */ |
| 162 | std::string user_agent = fmt::format("OpenTTD/{}", GetNetworkRevisionString()); |
| 163 | CurlSetOption(curl, CURLOPT_USERAGENT, user_agent.c_str()); |
| 164 | CurlSetOption(curl, CURLOPT_FOLLOWLOCATION, 1L); |
| 165 | CurlSetOption(curl, CURLOPT_MAXREDIRS, 5L); |
| 166 | |
| 167 | /* Ensure we validate the certificate and hostname of the server. */ |
| 168 | #if defined(UNIX) |
| 169 | CurlSetOption(curl, CURLOPT_CAINFO, _http_ca_file.empty() ? nullptr : _http_ca_file.c_str()); |
| 170 | CurlSetOption(curl, CURLOPT_CAPATH, _http_ca_path.empty() ? nullptr : _http_ca_path.c_str()); |
| 171 | #endif /* UNIX */ |
| 172 | CurlSetOption(curl, CURLOPT_SSL_VERIFYHOST, 2); |
| 173 | CurlSetOption(curl, CURLOPT_SSL_VERIFYPEER, true); |
| 174 | |
| 175 | /* Give the connection about 10 seconds to complete. */ |
| 176 | CurlSetOption(curl, CURLOPT_CONNECTTIMEOUT, 10L); |
| 177 | |
| 178 | /* Set a buffer of 100KiB, as the default of 16KiB seems a bit small. */ |
| 179 | CurlSetOption(curl, CURLOPT_BUFFERSIZE, 100L * 1024L); |
| 180 | |
| 181 | /* Fail our call if we don't receive a 2XX return value. */ |
| 182 | CurlSetOption(curl, CURLOPT_FAILONERROR, 1L); |
| 183 | |
| 184 | /* Prepare POST body and URI. */ |
| 185 | if (!request->data.empty()) { |
| 186 | /* When the payload starts with a '{', it is a JSON payload. */ |
| 187 | if (request->data.starts_with("{")) { |
| 188 | headers = curl_slist_append(headers, "Content-Type: application/json"); |
| 189 | } else { |
| 190 | headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded"); |
nothing calls this directly
no test coverage detected