Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / sync / engine / net / server_connection_manager.h
blob6514290c9e943a4f128cf7f1c008dc797faee157
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef SYNC_ENGINE_NET_SERVER_CONNECTION_MANAGER_H_
6 #define SYNC_ENGINE_NET_SERVER_CONNECTION_MANAGER_H_
8 #include <iosfwd>
9 #include <string>
11 #include "base/atomicops.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/observer_list.h"
14 #include "base/strings/string_util.h"
15 #include "base/synchronization/lock.h"
16 #include "base/threading/non_thread_safe.h"
17 #include "base/threading/thread_checker.h"
18 #include "sync/base/sync_export.h"
19 #include "sync/internal_api/public/base/cancelation_observer.h"
20 #include "sync/syncable/syncable_id.h"
22 namespace sync_pb {
23 class ClientToServerMessage;
26 namespace syncer {
28 class CancelationSignal;
30 namespace syncable {
31 class Directory;
34 static const int32 kUnsetResponseCode = -1;
35 static const int32 kUnsetContentLength = -1;
36 static const int32 kUnsetPayloadLength = -1;
38 // HttpResponse gathers the relevant output properties of an HTTP request.
39 // Depending on the value of the server_status code, response_code, and
40 // content_length may not be valid.
41 struct SYNC_EXPORT_PRIVATE HttpResponse {
42 enum ServerConnectionCode {
43 // For uninitialized state.
44 NONE,
46 // CONNECTION_UNAVAILABLE is returned when InternetConnect() fails.
47 CONNECTION_UNAVAILABLE,
49 // IO_ERROR is returned when reading/writing to a buffer has failed.
50 IO_ERROR,
52 // SYNC_SERVER_ERROR is returned when the HTTP status code indicates that
53 // a non-auth error has occured.
54 SYNC_SERVER_ERROR,
56 // SYNC_AUTH_ERROR is returned when the HTTP status code indicates that an
57 // auth error has occured (i.e. a 401 or sync-specific AUTH_INVALID
58 // response)
59 // TODO(tim): Caring about AUTH_INVALID is a layering violation. But
60 // this app-specific logic is being added as a stable branch hotfix so
61 // minimal changes prevail for the moment. Fix this! Bug 35060.
62 SYNC_AUTH_ERROR,
64 // SERVER_CONNECTION_OK is returned when request was handled correctly.
65 SERVER_CONNECTION_OK,
67 // RETRY is returned when a Commit request fails with a RETRY response from
68 // the server.
70 // TODO(idana): the server no longer returns RETRY so we should remove this
71 // value.
72 RETRY,
75 // The HTTP Status code.
76 int64 response_code;
78 // The value of the Content-length header.
79 int64 content_length;
81 // The size of a download request's payload.
82 int64 payload_length;
84 // Identifies the type of failure, if any.
85 ServerConnectionCode server_status;
87 HttpResponse();
89 static const char* GetServerConnectionCodeString(
90 ServerConnectionCode code);
92 static ServerConnectionCode ServerConnectionCodeFromNetError(
93 int error_code);
96 struct ServerConnectionEvent {
97 HttpResponse::ServerConnectionCode connection_code;
98 explicit ServerConnectionEvent(HttpResponse::ServerConnectionCode code) :
99 connection_code(code) {}
102 class SYNC_EXPORT_PRIVATE ServerConnectionEventListener {
103 public:
104 virtual void OnServerConnectionEvent(const ServerConnectionEvent& event) = 0;
105 protected:
106 virtual ~ServerConnectionEventListener() {}
109 class ServerConnectionManager;
110 // A helper class that automatically notifies when the status changes.
111 // TODO(tim): This class shouldn't be exposed outside of the implementation,
112 // bug 35060.
113 class SYNC_EXPORT_PRIVATE ScopedServerStatusWatcher
114 : public base::NonThreadSafe {
115 public:
116 ScopedServerStatusWatcher(ServerConnectionManager* conn_mgr,
117 HttpResponse* response);
118 virtual ~ScopedServerStatusWatcher();
119 private:
120 ServerConnectionManager* const conn_mgr_;
121 HttpResponse* const response_;
122 DISALLOW_COPY_AND_ASSIGN(ScopedServerStatusWatcher);
125 // Use this class to interact with the sync server.
126 // The ServerConnectionManager currently supports POSTing protocol buffers.
128 class SYNC_EXPORT_PRIVATE ServerConnectionManager : public CancelationObserver {
129 public:
130 // buffer_in - will be POSTed
131 // buffer_out - string will be overwritten with response
132 struct PostBufferParams {
133 std::string buffer_in;
134 std::string buffer_out;
135 HttpResponse response;
138 // Abstract class providing network-layer functionality to the
139 // ServerConnectionManager. Subclasses implement this using an HTTP stack of
140 // their choice.
141 class Connection {
142 public:
143 explicit Connection(ServerConnectionManager* scm);
144 virtual ~Connection();
146 // Called to initialize and perform an HTTP POST.
147 virtual bool Init(const char* path,
148 const std::string& auth_token,
149 const std::string& payload,
150 HttpResponse* response) = 0;
152 // Immediately abandons a pending HTTP POST request and unblocks caller
153 // in Init.
154 virtual void Abort() = 0;
156 bool ReadBufferResponse(std::string* buffer_out, HttpResponse* response,
157 bool require_response);
158 bool ReadDownloadResponse(HttpResponse* response, std::string* buffer_out);
160 protected:
161 std::string MakeConnectionURL(const std::string& sync_server,
162 const std::string& path,
163 bool use_ssl) const;
165 void GetServerParams(std::string* server,
166 int* server_port,
167 bool* use_ssl) const {
168 server->assign(scm_->sync_server_);
169 *server_port = scm_->sync_server_port_;
170 *use_ssl = scm_->use_ssl_;
173 std::string buffer_;
174 ServerConnectionManager* scm_;
176 private:
177 int ReadResponse(void* buffer, int length);
178 int ReadResponse(std::string* buffer, int length);
181 ServerConnectionManager(const std::string& server,
182 int port,
183 bool use_ssl,
184 CancelationSignal* cancelation_signal);
186 ~ServerConnectionManager() override;
188 // POSTS buffer_in and reads a response into buffer_out. Uses our currently
189 // set auth token in our headers.
191 // Returns true if executed successfully.
192 virtual bool PostBufferWithCachedAuth(PostBufferParams* params,
193 ScopedServerStatusWatcher* watcher);
195 void AddListener(ServerConnectionEventListener* listener);
196 void RemoveListener(ServerConnectionEventListener* listener);
198 inline HttpResponse::ServerConnectionCode server_status() const {
199 DCHECK(thread_checker_.CalledOnValidThread());
200 return server_status_;
203 const std::string client_id() const { return client_id_; }
205 // Returns the current server parameters in server_url, port and use_ssl.
206 void GetServerParameters(std::string* server_url,
207 int* port,
208 bool* use_ssl) const;
210 std::string GetServerHost() const;
212 // Factory method to create an Connection object we can use for
213 // communication with the server.
214 virtual Connection* MakeConnection();
216 // Closes any active network connections to the sync server.
217 // We expect this to get called on a different thread than the valid
218 // ThreadChecker thread, as we want to kill any pending http traffic without
219 // having to wait for the request to complete.
220 void OnSignalReceived() final;
222 void set_client_id(const std::string& client_id) {
223 DCHECK(thread_checker_.CalledOnValidThread());
224 DCHECK(client_id_.empty());
225 client_id_.assign(client_id);
228 // Sets a new auth token and time.
229 bool SetAuthToken(const std::string& auth_token);
231 bool HasInvalidAuthToken() {
232 return auth_token_.empty();
235 const std::string auth_token() const {
236 DCHECK(thread_checker_.CalledOnValidThread());
237 return auth_token_;
240 protected:
241 inline std::string proto_sync_path() const {
242 return proto_sync_path_;
245 // Updates server_status_ and notifies listeners if server_status_ changed
246 void SetServerStatus(HttpResponse::ServerConnectionCode server_status);
248 // NOTE: Tests rely on this protected function being virtual.
250 // Internal PostBuffer base function.
251 virtual bool PostBufferToPath(PostBufferParams*,
252 const std::string& path,
253 const std::string& auth_token,
254 ScopedServerStatusWatcher* watcher);
256 // An internal helper to clear our auth_token_ and cache the old version
257 // in |previously_invalidated_token_| to shelter us from retrying with a
258 // known bad token.
259 void InvalidateAndClearAuthToken();
261 // Helper to check terminated flags and build a Connection object, installing
262 // it as the |active_connection_|. If this ServerConnectionManager has been
263 // terminated, this will return NULL.
264 Connection* MakeActiveConnection();
266 // Called by Connection objects as they are destroyed to allow the
267 // ServerConnectionManager to cleanup active connections.
268 void OnConnectionDestroyed(Connection* connection);
270 // The sync_server_ is the server that requests will be made to.
271 std::string sync_server_;
273 // The sync_server_port_ is the port that HTTP requests will be made on.
274 int sync_server_port_;
276 // The unique id of the user's client.
277 std::string client_id_;
279 // Indicates whether or not requests should be made using HTTPS.
280 bool use_ssl_;
282 // The paths we post to.
283 std::string proto_sync_path_;
285 // The auth token to use in authenticated requests.
286 std::string auth_token_;
288 // The previous auth token that is invalid now.
289 std::string previously_invalidated_token;
291 base::ObserverList<ServerConnectionEventListener> listeners_;
293 HttpResponse::ServerConnectionCode server_status_;
295 base::ThreadChecker thread_checker_;
297 // Protects all variables below to allow bailing out of active connections.
298 base::Lock terminate_connection_lock_;
300 // If true, we've been told to terminate IO and expect to be destroyed
301 // shortly. No future network requests will be made.
302 bool terminated_;
304 // A non-owning pointer to any active http connection, so that we can abort
305 // it if necessary.
306 Connection* active_connection_;
308 private:
309 friend class Connection;
310 friend class ScopedServerStatusWatcher;
312 // A class to help deal with cleaning up active Connection objects when (for
313 // ex) multiple early-exits are present in some scope. ScopedConnectionHelper
314 // informs the ServerConnectionManager before the Connection object it takes
315 // ownership of is destroyed.
316 class ScopedConnectionHelper {
317 public:
318 // |manager| must outlive this. Takes ownership of |connection|.
319 ScopedConnectionHelper(ServerConnectionManager* manager,
320 Connection* connection);
321 ~ScopedConnectionHelper();
322 Connection* get();
323 private:
324 ServerConnectionManager* manager_;
325 scoped_ptr<Connection> connection_;
326 DISALLOW_COPY_AND_ASSIGN(ScopedConnectionHelper);
329 void NotifyStatusChanged();
331 CancelationSignal* const cancelation_signal_;
332 bool signal_handler_registered_;
334 DISALLOW_COPY_AND_ASSIGN(ServerConnectionManager);
337 std::ostream& operator<<(std::ostream& s, const struct HttpResponse& hr);
339 } // namespace syncer
341 #endif // SYNC_ENGINE_NET_SERVER_CONNECTION_MANAGER_H_