// Copyright 2014 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef LIBBRILLO_BRILLO_HTTP_HTTP_TRANSPORT_CURL_H_ #define LIBBRILLO_BRILLO_HTTP_HTTP_TRANSPORT_CURL_H_ #include <map> #include <string> #include <utility> #include <base/memory/weak_ptr.h> #include <brillo/brillo_export.h> #include <brillo/http/curl_api.h> #include <brillo/http/http_transport.h> namespace brillo { namespace http { namespace curl { class Connection; /////////////////////////////////////////////////////////////////////////////// // An implementation of http::Transport that uses libcurl for // HTTP communications. This class (as http::Transport base) // is used by http::Request and http::Response classes to provide HTTP // functionality to the clients. // See http_transport.h for more details. /////////////////////////////////////////////////////////////////////////////// class BRILLO_EXPORT Transport : public http::Transport { public: // Constructs the transport using the current message loop for async // operations. explicit Transport(const std::shared_ptr<CurlInterface>& curl_interface); // Creates a transport object using a proxy. // |proxy| is of the form [protocol://][user:password@]host[:port]. // If not defined, protocol is assumed to be http://. Transport(const std::shared_ptr<CurlInterface>& curl_interface, const std::string& proxy); ~Transport() override; // Overrides from http::Transport. std::shared_ptr<http::Connection> CreateConnection( const std::string& url, const std::string& method, const HeaderList& headers, const std::string& user_agent, const std::string& referer, brillo::ErrorPtr* error) override; void RunCallbackAsync(const tracked_objects::Location& from_here, const base::Closure& callback) override; RequestID StartAsyncTransfer(http::Connection* connection, const SuccessCallback& success_callback, const ErrorCallback& error_callback) override; bool CancelRequest(RequestID request_id) override; void SetDefaultTimeout(base::TimeDelta timeout) override; // Helper methods to convert CURL error codes (CURLcode and CURLMcode) // into brillo::Error object. static void AddEasyCurlError(brillo::ErrorPtr* error, const tracked_objects::Location& location, CURLcode code, CurlInterface* curl_interface); static void AddMultiCurlError(brillo::ErrorPtr* error, const tracked_objects::Location& location, CURLMcode code, CurlInterface* curl_interface); private: // Forward-declaration of internal implementation structures. struct AsyncRequestData; class SocketPollData; // Initializes CURL for async operation. bool SetupAsyncCurl(brillo::ErrorPtr* error); // Stops CURL's async operations. void ShutDownAsyncCurl(); // Handles all pending async messages from CURL. void ProcessAsyncCurlMessages(); // Processes the transfer completion message (success or failure). void OnTransferComplete(http::curl::Connection* connection, CURLcode code); // Cleans up internal data for a completed/canceled asynchronous operation // on a connection. void CleanAsyncConnection(http::curl::Connection* connection); // Called after a timeout delay requested by CURL has elapsed. void OnTimer(); // Callback for CURL to handle curl_socket_callback() notifications. // The parameters correspond to those of curl_socket_callback(). static int MultiSocketCallback(CURL* easy, curl_socket_t s, int what, void* userp, void* socketp); // Callback for CURL to handle curl_multi_timer_callback() notifications. // The parameters correspond to those of curl_multi_timer_callback(). // CURL actually uses "long" types in callback signatures, so we must comply. static int MultiTimerCallback(CURLM* multi, long timeout_ms, // NOLINT(runtime/int) void* userp); std::shared_ptr<CurlInterface> curl_interface_; std::string proxy_; // CURL "multi"-handle for processing requests on multiple connections. CURLM* curl_multi_handle_{nullptr}; // A map to find a corresponding Connection* using a request ID. std::map<RequestID, Connection*> request_id_map_; // Stores the connection-specific asynchronous data (such as the success // and error callbacks that need to be called at the end of the async // operation). std::map<Connection*, std::unique_ptr<AsyncRequestData>> async_requests_; // Internal data associated with in-progress asynchronous operations. std::map<std::pair<CURL*, curl_socket_t>, SocketPollData*> poll_data_map_; // The last request ID used for asynchronous operations. RequestID last_request_id_{0}; // The connection timeout for the requests made. base::TimeDelta connection_timeout_; base::WeakPtrFactory<Transport> weak_ptr_factory_for_timer_{this}; base::WeakPtrFactory<Transport> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(Transport); }; } // namespace curl } // namespace http } // namespace brillo #endif // LIBBRILLO_BRILLO_HTTP_HTTP_TRANSPORT_CURL_H_