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/internal_api/public/base/cancelation_observer.h"
20 #include "sync/syncable/syncable_id.h"
23 class ClientToServerMessage
;
28 class CancelationSignal
;
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.
46 // CONNECTION_UNAVAILABLE is returned when InternetConnect() fails.
47 CONNECTION_UNAVAILABLE
,
49 // IO_ERROR is returned when reading/writing to a buffer has failed.
52 // SYNC_SERVER_ERROR is returned when the HTTP status code indicates that
53 // a non-auth error has occured.
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
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.
64 // SERVER_CONNECTION_OK is returned when request was handled correctly.
67 // RETRY is returned when a Commit request fails with a RETRY response from
70 // TODO(idana): the server no longer returns RETRY so we should remove this
75 // The HTTP Status code.
78 // The value of the Content-length header.
81 // The size of a download request's payload.
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
: public CancelationObserver
{
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
,
167 bool* use_ssl
) const {
168 server
->assign(scm_
->sync_server_
);
169 *server_port
= scm_
->sync_server_port_
;
170 *use_ssl
= scm_
->use_ssl_
;
174 ServerConnectionManager
* scm_
;
177 int ReadResponse(void* buffer
, int length
);
178 int ReadResponse(std::string
* buffer
, int length
);
181 ServerConnectionManager(const std::string
& server
,
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
,
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());
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
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.
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.
304 // A non-owning pointer to any active http connection, so that we can abort
306 Connection
* active_connection_
;
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
{
318 // |manager| must outlive this. Takes ownership of |connection|.
319 ScopedConnectionHelper(ServerConnectionManager
* manager
,
320 Connection
* connection
);
321 ~ScopedConnectionHelper();
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_