Resize destination bus to the actual number of decoded frames.
[chromium-blink-merge.git] / sync / engine / net / server_connection_manager.h
blob3bd533e78fdd07d555e54d296e9b70465fd5bbf6
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/syncable/syncable_id.h"
21 namespace sync_pb {
22 class ClientToServerMessage;
25 namespace syncer {
27 namespace syncable {
28 class Directory;
31 static const int32 kUnsetResponseCode = -1;
32 static const int32 kUnsetContentLength = -1;
33 static const int32 kUnsetPayloadLength = -1;
35 // HttpResponse gathers the relevant output properties of an HTTP request.
36 // Depending on the value of the server_status code, response_code, and
37 // content_length may not be valid.
38 struct SYNC_EXPORT_PRIVATE HttpResponse {
39 enum ServerConnectionCode {
40 // For uninitialized state.
41 NONE,
43 // CONNECTION_UNAVAILABLE is returned when InternetConnect() fails.
44 CONNECTION_UNAVAILABLE,
46 // IO_ERROR is returned when reading/writing to a buffer has failed.
47 IO_ERROR,
49 // SYNC_SERVER_ERROR is returned when the HTTP status code indicates that
50 // a non-auth error has occured.
51 SYNC_SERVER_ERROR,
53 // SYNC_AUTH_ERROR is returned when the HTTP status code indicates that an
54 // auth error has occured (i.e. a 401 or sync-specific AUTH_INVALID
55 // response)
56 // TODO(tim): Caring about AUTH_INVALID is a layering violation. But
57 // this app-specific logic is being added as a stable branch hotfix so
58 // minimal changes prevail for the moment. Fix this! Bug 35060.
59 SYNC_AUTH_ERROR,
61 // SERVER_CONNECTION_OK is returned when request was handled correctly.
62 SERVER_CONNECTION_OK,
64 // RETRY is returned when a Commit request fails with a RETRY response from
65 // the server.
67 // TODO(idana): the server no longer returns RETRY so we should remove this
68 // value.
69 RETRY,
72 // The HTTP Status code.
73 int64 response_code;
75 // The value of the Content-length header.
76 int64 content_length;
78 // The size of a download request's payload.
79 int64 payload_length;
81 // Value of the Update-Client-Auth header.
82 std::string update_client_auth_header;
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 {
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,
168 bool* use_oauth2_token) const {
169 server->assign(scm_->sync_server_);
170 *server_port = scm_->sync_server_port_;
171 *use_ssl = scm_->use_ssl_;
172 *use_oauth2_token = scm_->use_oauth2_token_;
175 std::string buffer_;
176 ServerConnectionManager* scm_;
178 private:
179 int ReadResponse(void* buffer, int length);
180 int ReadResponse(std::string* buffer, int length);
183 ServerConnectionManager(const std::string& server,
184 int port,
185 bool use_ssl,
186 bool use_oauth2_token);
188 virtual ~ServerConnectionManager();
190 // POSTS buffer_in and reads a response into buffer_out. Uses our currently
191 // set auth token in our headers.
193 // Returns true if executed successfully.
194 virtual bool PostBufferWithCachedAuth(PostBufferParams* params,
195 ScopedServerStatusWatcher* watcher);
197 void AddListener(ServerConnectionEventListener* listener);
198 void RemoveListener(ServerConnectionEventListener* listener);
200 inline HttpResponse::ServerConnectionCode server_status() const {
201 DCHECK(thread_checker_.CalledOnValidThread());
202 return server_status_;
205 const std::string client_id() const { return client_id_; }
207 // Returns the current server parameters in server_url, port and use_ssl.
208 void GetServerParameters(std::string* server_url,
209 int* port,
210 bool* use_ssl) const;
212 std::string GetServerHost() const;
214 // Factory method to create an Connection object we can use for
215 // communication with the server.
216 virtual Connection* MakeConnection();
218 // Aborts any active HTTP POST request.
219 // We expect this to get called on a different thread than the valid
220 // ThreadChecker thread, as we want to kill any pending http traffic without
221 // having to wait for the request to complete.
222 void TerminateAllIO();
224 void set_client_id(const std::string& client_id) {
225 DCHECK(thread_checker_.CalledOnValidThread());
226 DCHECK(client_id_.empty());
227 client_id_.assign(client_id);
230 // Sets a new auth token and time.
231 bool SetAuthToken(const std::string& auth_token);
233 // Our out-of-band invalidations channel can encounter auth errors,
234 // and when it does so it tells us via this method to prevent making more
235 // requests with known-bad tokens. This will put the
236 // ServerConnectionManager in an auth error state as if it received an
237 // HTTP 401 from sync servers.
238 void OnInvalidationCredentialsRejected();
240 bool HasInvalidAuthToken() {
241 return auth_token_.empty();
244 const std::string auth_token() const {
245 DCHECK(thread_checker_.CalledOnValidThread());
246 return auth_token_;
249 protected:
250 inline std::string proto_sync_path() const {
251 return proto_sync_path_;
254 // Updates server_status_ and notifies listeners if server_status_ changed
255 void SetServerStatus(HttpResponse::ServerConnectionCode server_status);
257 // NOTE: Tests rely on this protected function being virtual.
259 // Internal PostBuffer base function.
260 virtual bool PostBufferToPath(PostBufferParams*,
261 const std::string& path,
262 const std::string& auth_token,
263 ScopedServerStatusWatcher* watcher);
265 // An internal helper to clear our auth_token_ and cache the old version
266 // in |previously_invalidated_token_| to shelter us from retrying with a
267 // known bad token.
268 void InvalidateAndClearAuthToken();
270 // Helper to check terminated flags and build a Connection object, installing
271 // it as the |active_connection_|. If this ServerConnectionManager has been
272 // terminated, this will return NULL.
273 Connection* MakeActiveConnection();
275 // Called by Connection objects as they are destroyed to allow the
276 // ServerConnectionManager to cleanup active connections.
277 void OnConnectionDestroyed(Connection* connection);
279 // The sync_server_ is the server that requests will be made to.
280 std::string sync_server_;
282 // The sync_server_port_ is the port that HTTP requests will be made on.
283 int sync_server_port_;
285 // The unique id of the user's client.
286 std::string client_id_;
288 // Indicates whether or not requests should be made using HTTPS.
289 bool use_ssl_;
291 // Indicates if token should be handled as OAuth2 token. Connection should set
292 // auth header appropriately.
293 // TODO(pavely): Remove once sync on android switches to oauth2 tokens.
294 bool use_oauth2_token_;
296 // The paths we post to.
297 std::string proto_sync_path_;
299 // The auth token to use in authenticated requests.
300 std::string auth_token_;
302 // The previous auth token that is invalid now.
303 std::string previously_invalidated_token;
305 ObserverList<ServerConnectionEventListener> listeners_;
307 HttpResponse::ServerConnectionCode server_status_;
309 base::ThreadChecker thread_checker_;
311 // Protects all variables below to allow bailing out of active connections.
312 base::Lock terminate_connection_lock_;
314 // If true, we've been told to terminate IO and expect to be destroyed
315 // shortly. No future network requests will be made.
316 bool terminated_;
318 // A non-owning pointer to any active http connection, so that we can abort
319 // it if necessary.
320 Connection* active_connection_;
322 private:
323 friend class Connection;
324 friend class ScopedServerStatusWatcher;
326 // A class to help deal with cleaning up active Connection objects when (for
327 // ex) multiple early-exits are present in some scope. ScopedConnectionHelper
328 // informs the ServerConnectionManager before the Connection object it takes
329 // ownership of is destroyed.
330 class ScopedConnectionHelper {
331 public:
332 // |manager| must outlive this. Takes ownership of |connection|.
333 ScopedConnectionHelper(ServerConnectionManager* manager,
334 Connection* connection);
335 ~ScopedConnectionHelper();
336 Connection* get();
337 private:
338 ServerConnectionManager* manager_;
339 scoped_ptr<Connection> connection_;
340 DISALLOW_COPY_AND_ASSIGN(ScopedConnectionHelper);
343 void NotifyStatusChanged();
345 DISALLOW_COPY_AND_ASSIGN(ServerConnectionManager);
348 std::ostream& operator<<(std::ostream& s, const struct HttpResponse& hr);
350 } // namespace syncer
352 #endif // SYNC_ENGINE_NET_SERVER_CONNECTION_MANAGER_H_