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_
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"
22 class ClientToServerMessage
;
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.
43 // CONNECTION_UNAVAILABLE is returned when InternetConnect() fails.
44 CONNECTION_UNAVAILABLE
,
46 // IO_ERROR is returned when reading/writing to a buffer has failed.
49 // SYNC_SERVER_ERROR is returned when the HTTP status code indicates that
50 // a non-auth error has occured.
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
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.
61 // SERVER_CONNECTION_OK is returned when request was handled correctly.
64 // RETRY is returned when a Commit request fails with a RETRY response from
67 // TODO(idana): the server no longer returns RETRY so we should remove this
72 // The HTTP Status code.
75 // The value of the Content-length header.
78 // The size of a download request's payload.
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
;
89 static const char* GetServerConnectionCodeString(
90 ServerConnectionCode code
);
92 static ServerConnectionCode
ServerConnectionCodeFromNetError(
96 struct ServerConnectionEvent
{
97 HttpResponse::ServerConnectionCode connection_code
;
98 explicit ServerConnectionEvent(HttpResponse::ServerConnectionCode code
) :
99 connection_code(code
) {}
102 class SYNC_EXPORT_PRIVATE ServerConnectionEventListener
{
104 virtual void OnServerConnectionEvent(const ServerConnectionEvent
& event
) = 0;
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,
113 class SYNC_EXPORT_PRIVATE ScopedServerStatusWatcher
114 : public base::NonThreadSafe
{
116 ScopedServerStatusWatcher(ServerConnectionManager
* conn_mgr
,
117 HttpResponse
* response
);
118 virtual ~ScopedServerStatusWatcher();
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
{
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
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
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
);
161 std::string
MakeConnectionURL(const std::string
& sync_server
,
162 const std::string
& path
,
165 void GetServerParams(std::string
* server
,
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_
;
176 ServerConnectionManager
* scm_
;
179 int ReadResponse(void* buffer
, int length
);
180 int ReadResponse(std::string
* buffer
, int length
);
183 ServerConnectionManager(const std::string
& server
,
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
,
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());
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
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.
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.
318 // A non-owning pointer to any active http connection, so that we can abort
320 Connection
* active_connection_
;
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
{
332 // |manager| must outlive this. Takes ownership of |connection|.
333 ScopedConnectionHelper(ServerConnectionManager
* manager
,
334 Connection
* connection
);
335 ~ScopedConnectionHelper();
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_