OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 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. |
| 4 |
| 5 #ifndef CHROME_BROWSER_SYNC_ENGINE_NET_SERVER_CONNECTION_MANAGER_H_ |
| 6 #define CHROME_BROWSER_SYNC_ENGINE_NET_SERVER_CONNECTION_MANAGER_H_ |
| 7 |
| 8 #include <iosfwd> |
| 9 #include <string> |
| 10 #include <vector> |
| 11 |
| 12 #include "base/atomicops.h" |
| 13 #include "base/logging.h" |
| 14 #include "base/scoped_ptr.h" |
| 15 #include "base/string_util.h" |
| 16 #include "chrome/browser/sync/engine/net/http_return.h" |
| 17 #include "chrome/browser/sync/syncable/syncable_id.h" |
| 18 #include "chrome/browser/sync/util/event_sys.h" |
| 19 #include "chrome/browser/sync/util/pthread_helpers.h" |
| 20 #include "chrome/browser/sync/util/signin.h" |
| 21 #include "chrome/browser/sync/util/sync_types.h" |
| 22 |
| 23 namespace syncable { |
| 24 class WriteTransaction; |
| 25 class DirectoryManager; |
| 26 } |
| 27 |
| 28 namespace sync_pb { |
| 29 class ClientToServerMessage; |
| 30 }; |
| 31 |
| 32 struct RequestTimingInfo; |
| 33 |
| 34 namespace browser_sync { |
| 35 |
| 36 class ClientToServerMessage; |
| 37 |
| 38 // How many connection errors are accepted before network handles are closed |
| 39 // and reopened. |
| 40 static const int32 kMaxConnectionErrorsBeforeReset = 10; |
| 41 |
| 42 // HttpResponse gathers the relevant output properties of an HTTP request. |
| 43 // Depending on the value of the server_status code, response_code, and |
| 44 // content_length may not be valid. |
| 45 struct HttpResponse { |
| 46 enum ServerConnectionCode { |
| 47 // For uninitialized state. |
| 48 NONE, |
| 49 |
| 50 // CONNECTION_UNAVAILABLE is returned when InternetConnect() fails. |
| 51 CONNECTION_UNAVAILABLE, |
| 52 |
| 53 // IO_ERROR is returned when reading/writing to a buffer has failed. |
| 54 IO_ERROR, |
| 55 |
| 56 // SYNC_SERVER_ERROR is returned when the HTTP status code indicates that |
| 57 // a non-auth error has occured. |
| 58 SYNC_SERVER_ERROR, |
| 59 |
| 60 // SYNC_AUTH_ERROR is returned when the HTTP status code indicates that an |
| 61 // auth error has occured (i.e. a 401) |
| 62 SYNC_AUTH_ERROR, |
| 63 |
| 64 // All the following connection codes are valid responses from the server. |
| 65 // Means the server is up. If you update this list, be sure to also update |
| 66 // IsGoodReplyFromServer(). |
| 67 |
| 68 // SERVER_CONNECTION_OK is returned when request was handled correctly. |
| 69 SERVER_CONNECTION_OK, |
| 70 |
| 71 // RETRY is returned when a Commit request fails with a RETRY response from |
| 72 // the server. |
| 73 // |
| 74 // TODO(idana): the server no longer returns RETRY so we should remove this |
| 75 // value. |
| 76 RETRY, |
| 77 }; |
| 78 |
| 79 // The HTTP Status code. |
| 80 int64 response_code; |
| 81 |
| 82 // The value of the Content-length header. |
| 83 int64 content_length; |
| 84 |
| 85 // The size of a download request's payload. |
| 86 int64 payload_length; |
| 87 |
| 88 // Identifies the type of failure, if any. |
| 89 ServerConnectionCode server_status; |
| 90 }; |
| 91 |
| 92 inline bool IsGoodReplyFromServer(HttpResponse::ServerConnectionCode code) { |
| 93 return code >= HttpResponse::SERVER_CONNECTION_OK; |
| 94 } |
| 95 |
| 96 struct ServerConnectionEvent { |
| 97 enum { SHUTDOWN, STATUS_CHANGED } what_happened; |
| 98 HttpResponse::ServerConnectionCode connection_code; |
| 99 bool server_reachable; |
| 100 |
| 101 // Traits. |
| 102 typedef ServerConnectionEvent EventType; |
| 103 static inline bool IsChannelShutdownEvent(const EventType& event) { |
| 104 return SHUTDOWN == event.what_happened; |
| 105 } |
| 106 }; |
| 107 |
| 108 struct WatchServerStatus; |
| 109 |
| 110 // Use this class to interact with the sync server. |
| 111 // The ServerConnectionManager currently supports POSTing protocol buffers. |
| 112 // |
| 113 // *** This class is thread safe. In fact, you should consider creating only |
| 114 // one instance for every server that you need to talk to. |
| 115 class ServerConnectionManager { |
| 116 friend class Post; |
| 117 friend struct WatchServerStatus; |
| 118 public: |
| 119 typedef EventChannel<ServerConnectionEvent, PThreadMutex> Channel; |
| 120 |
| 121 // The lifetime of the GaiaAuthenticator must be longer than the instance |
| 122 // of the ServerConnectionManager that you're creating. |
| 123 ServerConnectionManager(const std::string& server, int port, bool use_ssl, |
| 124 const std::string& user_agent, |
| 125 const std::string& client_id); |
| 126 |
| 127 virtual ~ServerConnectionManager(); |
| 128 |
| 129 // buffer_in - will be POSTed |
| 130 // buffer_out - string will be overwritten with response |
| 131 struct PostBufferParams { |
| 132 const std::string& buffer_in; |
| 133 std::string* buffer_out; |
| 134 HttpResponse* response; |
| 135 RequestTimingInfo* timing_info; |
| 136 }; |
| 137 |
| 138 // Abstract class providing network-layer functionality to the |
| 139 // ServerConnectionManager. Subclasses implement this using an HTTP stack of |
| 140 // their choice. |
| 141 class Post { |
| 142 public: |
| 143 explicit Post(ServerConnectionManager* scm) : scm_(scm), timing_info_(0) { |
| 144 } |
| 145 virtual ~Post() { } |
| 146 |
| 147 // Called to initialize and perform an HTTP POST. |
| 148 virtual bool Init(const char* path, const std::string& auth_token, |
| 149 const std::string& payload, |
| 150 HttpResponse* response) = 0; |
| 151 |
| 152 bool ReadBufferResponse(std::string* buffer_out, HttpResponse* response, |
| 153 bool require_response); |
| 154 bool ReadDownloadResponse(HttpResponse* response, std::string* buffer_out); |
| 155 |
| 156 void set_timing_info(RequestTimingInfo* timing_info) { |
| 157 timing_info_ = timing_info; |
| 158 } |
| 159 RequestTimingInfo* timing_info() { return timing_info_; } |
| 160 |
| 161 protected: |
| 162 std::string MakeConnectionURL(const std::string& sync_server, |
| 163 const std::string& path, bool use_ssl) const; |
| 164 |
| 165 void GetServerParams(std::string* server, int* server_port, |
| 166 bool* use_ssl) { |
| 167 ServerConnectionManager::ParametersLock lock( |
| 168 &scm_->server_parameters_mutex_); |
| 169 server->assign(scm_->sync_server_); |
| 170 *server_port = scm_->sync_server_port_; |
| 171 *use_ssl = scm_->use_ssl_; |
| 172 } |
| 173 |
| 174 std::string buffer_; |
| 175 ServerConnectionManager* scm_; |
| 176 |
| 177 private: |
| 178 int ReadResponse(void* buffer, int length); |
| 179 int ReadResponse(std::string* buffer, int length); |
| 180 RequestTimingInfo* timing_info_; |
| 181 }; |
| 182 |
| 183 // POSTS buffer_in and reads a response into buffer_out. Uses our currently |
| 184 // set auth token in our headers. |
| 185 // |
| 186 // Returns true if executed successfully. |
| 187 virtual bool PostBufferWithCachedAuth(const PostBufferParams* params); |
| 188 |
| 189 // POSTS buffer_in and reads a response into buffer_out. Add a specific auth |
| 190 // token to http headers. |
| 191 // |
| 192 // Returns true if executed successfully. |
| 193 virtual bool PostBufferWithAuth(const PostBufferParams* params, |
| 194 const std::string& auth_token); |
| 195 |
| 196 // Checks the time on the server. Returns false if the request failed. |time| |
| 197 // is an out parameter that stores the value returned from the server. |
| 198 virtual bool CheckTime(int32* out_time); |
| 199 |
| 200 // Returns true if sync_server_ is reachable. This method verifies that the |
| 201 // server is pingable and that traffic can be sent to and from it. |
| 202 virtual bool IsServerReachable(); |
| 203 |
| 204 // Returns true if user has been successfully authenticated. |
| 205 virtual bool IsUserAuthenticated(); |
| 206 |
| 207 // Updates status and broadcasts events on change. |
| 208 bool CheckServerReachable(); |
| 209 |
| 210 // Signal the shutdown event to notify listeners. |
| 211 virtual void kill(); |
| 212 |
| 213 inline Channel* channel() const { return channel_; } |
| 214 |
| 215 inline std::string user_agent() const { return user_agent_; } |
| 216 |
| 217 inline HttpResponse::ServerConnectionCode server_status() const { |
| 218 return server_status_; |
| 219 } |
| 220 |
| 221 inline bool server_reachable() const { return server_reachable_; } |
| 222 |
| 223 void ResetAuthStatus(); |
| 224 |
| 225 void ResetConnection(); |
| 226 |
| 227 void NotifyStatusChanged(); |
| 228 |
| 229 const std::string client_id() const { return client_id_; } |
| 230 |
| 231 void SetDomainFromSignIn(SignIn signin_type, const std::string& signin); |
| 232 |
| 233 // This changes the server info used by the connection manager. This allows |
| 234 // a single client instance to talk to different backing servers. This is |
| 235 // typically called during / after authentication so that the server url |
| 236 // can be a function of the user's login id. A side effect of this call is |
| 237 // that ResetConnection is called. |
| 238 void SetServerParameters(const std::string& server_url, int port, |
| 239 bool use_ssl); |
| 240 |
| 241 // Returns the current server parameters in server_url, port and use_ssl. |
| 242 void GetServerParameters(std::string* server_url, int* port, bool* use_ssl); |
| 243 |
| 244 bool terminate_all_io() const { |
| 245 PThreadScopedLock<PThreadMutex> lock(&terminate_all_io_mutex_); |
| 246 return terminate_all_io_; |
| 247 } |
| 248 |
| 249 // Factory method to create a Post object we can use for communication with |
| 250 // the server. |
| 251 virtual Post* MakePost() { |
| 252 return NULL; // For testing. |
| 253 }; |
| 254 |
| 255 void set_auth_token(const std::string& auth_token) { |
| 256 auth_token_.assign(auth_token); |
| 257 } |
| 258 |
| 259 protected: |
| 260 |
| 261 PThreadMutex shutdown_event_mutex_; |
| 262 PThreadCondVar shutdown_event_condition_; |
| 263 |
| 264 // Protects access to sync_server_, sync_server_port_ and use_ssl_: |
| 265 mutable PThreadMutex server_parameters_mutex_; |
| 266 typedef PThreadScopedLock<PThreadMutex> ParametersLock; |
| 267 |
| 268 // The sync_server_ is the server that requests will be made to. |
| 269 std::string sync_server_; |
| 270 |
| 271 // The sync_server_port_ is the port that HTTP requests will be made on. |
| 272 int sync_server_port_; |
| 273 |
| 274 // The unique id of the user's client. |
| 275 const std::string client_id_; |
| 276 |
| 277 // The user-agent string for HTTP. |
| 278 std::string user_agent_; |
| 279 |
| 280 // Indicates whether or not requests should be made using HTTPS. |
| 281 bool use_ssl_; |
| 282 |
| 283 // The paths we post to. |
| 284 mutable PThreadMutex path_mutex_; |
| 285 typedef PThreadScopedLock<PThreadMutex> ScopedPathLock; |
| 286 |
| 287 std::string proto_sync_path_; |
| 288 std::string get_time_path_; |
| 289 |
| 290 // The auth token to use in authenticated requests. Set by the AuthWatcher. |
| 291 std::string auth_token_; |
| 292 |
| 293 inline std::string proto_sync_path() const { |
| 294 ScopedPathLock lock(&path_mutex_); |
| 295 return proto_sync_path_; |
| 296 } |
| 297 std::string get_time_path() const { |
| 298 ScopedPathLock lock(&path_mutex_); |
| 299 return get_time_path_; |
| 300 } |
| 301 |
| 302 // Called wherever a failure should be taken as an indication that we may |
| 303 // be experiencing connection difficulties. |
| 304 virtual bool IncrementErrorCount(); |
| 305 mutable PThreadMutex error_count_mutex_; // Protects error_count_ |
| 306 int error_count_; // Tracks the number of connection errors. |
| 307 |
| 308 protected: |
| 309 Channel* const channel_; |
| 310 // Volatile so various threads can call server_status() without |
| 311 // synchronization. |
| 312 volatile HttpResponse::ServerConnectionCode server_status_; |
| 313 bool server_reachable_; |
| 314 |
| 315 struct PlatformMembers; // Contains platform specific member vars. |
| 316 PlatformMembers* const platform_; |
| 317 |
| 318 // A counter that is incremented everytime ResetAuthStatus() is called. |
| 319 volatile base::subtle::AtomicWord reset_count_; |
| 320 |
| 321 // NOTE: Tests rely on this protected function being virtual. |
| 322 // |
| 323 // Internal PostBuffer base function. |
| 324 virtual bool PostBufferToPath(const PostBufferParams*, |
| 325 const std::string& path, |
| 326 const std::string& auth_token); |
| 327 |
| 328 private: |
| 329 mutable PThreadMutex terminate_all_io_mutex_; |
| 330 bool terminate_all_io_; // when set to true, terminate all connections asap |
| 331 DISALLOW_COPY_AND_ASSIGN(ServerConnectionManager); |
| 332 }; |
| 333 |
| 334 // Fills a ClientToServerMessage with the appropriate share and birthday |
| 335 // settings. |
| 336 bool FillMessageWithShareDetails(sync_pb::ClientToServerMessage* csm, |
| 337 syncable::DirectoryManager* manager, |
| 338 const PathString &share); |
| 339 |
| 340 } // namespace browser_sync |
| 341 |
| 342 std::ostream& operator<<(std::ostream& s, |
| 343 const struct browser_sync::HttpResponse& hr); |
| 344 |
| 345 #endif // CHROME_BROWSER_SYNC_ENGINE_NET_SERVER_CONNECTION_MANAGER_H_ |
OLD | NEW |