| 6368 | } |
| 6369 | |
| 6370 | inline bool ClientImpl::send_(Request &req, Response &res, Error &error) { |
| 6371 | { |
| 6372 | std::lock_guard<std::mutex> guard(socket_mutex_); |
| 6373 | |
| 6374 | // Set this to false immediately - if it ever gets set to true by the end of |
| 6375 | // the request, we know another thread instructed us to close the socket. |
| 6376 | socket_should_be_closed_when_request_is_done_ = false; |
| 6377 | |
| 6378 | auto is_alive = false; |
| 6379 | if (socket_.is_open()) { |
| 6380 | is_alive = detail::is_socket_alive(socket_.sock); |
| 6381 | if (!is_alive) { |
| 6382 | // Attempt to avoid sigpipe by shutting down nongracefully if it seems |
| 6383 | // like the other side has already closed the connection Also, there |
| 6384 | // cannot be any requests in flight from other threads since we locked |
| 6385 | // request_mutex_, so safe to close everything immediately |
| 6386 | const bool shutdown_gracefully = false; |
| 6387 | shutdown_ssl(socket_, shutdown_gracefully); |
| 6388 | shutdown_socket(socket_); |
| 6389 | close_socket(socket_); |
| 6390 | } |
| 6391 | } |
| 6392 | |
| 6393 | if (!is_alive) { |
| 6394 | if (!create_and_connect_socket(socket_, error)) { return false; } |
| 6395 | |
| 6396 | #ifdef CPPHTTPLIB_OPENSSL_SUPPORT |
| 6397 | // TODO: refactoring |
| 6398 | if (is_ssl()) { |
| 6399 | auto &scli = static_cast<SSLClient &>(*this); |
| 6400 | if (!proxy_host_.empty() && proxy_port_ != -1) { |
| 6401 | auto success = false; |
| 6402 | if (!scli.connect_with_proxy(socket_, res, success, error)) { |
| 6403 | return success; |
| 6404 | } |
| 6405 | } |
| 6406 | |
| 6407 | if (!scli.initialize_ssl(socket_, error)) { return false; } |
| 6408 | } |
| 6409 | #endif |
| 6410 | } |
| 6411 | |
| 6412 | // Mark the current socket as being in use so that it cannot be closed by |
| 6413 | // anyone else while this request is ongoing, even though we will be |
| 6414 | // releasing the mutex. |
| 6415 | if (socket_requests_in_flight_ > 1) { |
| 6416 | assert(socket_requests_are_from_thread_ == std::this_thread::get_id()); |
| 6417 | } |
| 6418 | socket_requests_in_flight_ += 1; |
| 6419 | socket_requests_are_from_thread_ = std::this_thread::get_id(); |
| 6420 | } |
| 6421 | |
| 6422 | for (const auto &header : default_headers_) { |
| 6423 | if (req.headers.find(header.first) == req.headers.end()) { |
| 6424 | req.headers.insert(header); |
| 6425 | } |
| 6426 | } |
| 6427 |
nothing calls this directly
no test coverage detected