summaryrefslogtreecommitdiff
path: root/brillo/http/http_transport_curl.h
blob: 0a95c635cff26117bbfd61fc9329ad4df1aa45cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// 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_