OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "sync/engine/net/server_connection_manager.h" | 5 #include "sync/engine/net/server_connection_manager.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 | 8 |
9 #include <ostream> | 9 #include <ostream> |
10 #include <string> | 10 #include <string> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
14 #include "build/build_config.h" | 14 #include "build/build_config.h" |
15 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" |
16 #include "net/http/http_status_code.h" | 16 #include "net/http/http_status_code.h" |
17 #include "sync/engine/net/url_translator.h" | 17 #include "sync/engine/net/url_translator.h" |
18 #include "sync/engine/syncer.h" | 18 #include "sync/engine/syncer.h" |
19 #include "sync/internal_api/public/base/cancelation_signal.h" | |
20 #include "sync/protocol/sync.pb.h" | 19 #include "sync/protocol/sync.pb.h" |
21 #include "sync/syncable/directory.h" | 20 #include "sync/syncable/directory.h" |
22 #include "url/gurl.h" | 21 #include "url/gurl.h" |
23 | 22 |
24 namespace syncer { | 23 namespace syncer { |
25 | 24 |
26 using std::ostream; | 25 using std::ostream; |
27 using std::string; | 26 using std::string; |
28 using std::vector; | 27 using std::vector; |
29 | 28 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 if (bytes_read != response->content_length) { | 107 if (bytes_read != response->content_length) { |
109 LOG(ERROR) << "Mismatched content lengths, server claimed " << | 108 LOG(ERROR) << "Mismatched content lengths, server claimed " << |
110 response->content_length << ", but sent " << bytes_read; | 109 response->content_length << ", but sent " << bytes_read; |
111 response->server_status = HttpResponse::IO_ERROR; | 110 response->server_status = HttpResponse::IO_ERROR; |
112 return false; | 111 return false; |
113 } | 112 } |
114 return true; | 113 return true; |
115 } | 114 } |
116 | 115 |
117 ServerConnectionManager::ScopedConnectionHelper::ScopedConnectionHelper( | 116 ServerConnectionManager::ScopedConnectionHelper::ScopedConnectionHelper( |
118 CancelationSignal* signaller, scoped_ptr<Connection> connection) | 117 ServerConnectionManager* manager, Connection* connection) |
119 : cancelation_signal_(signaller), connection_(connection.Pass()) { | 118 : manager_(manager), connection_(connection) {} |
120 // Special early return for tests. | |
121 if (!connection_.get()) | |
122 return; | |
123 | |
124 if (!cancelation_signal_->TryRegisterHandler(this)) { | |
125 connection_.reset(); | |
126 } | |
127 } | |
128 | |
129 // This function may be called from another thread. | |
130 void ServerConnectionManager::ScopedConnectionHelper::OnStopRequested() { | |
131 DCHECK(connection_); | |
132 connection_->Abort(); | |
133 } | |
134 | 119 |
135 ServerConnectionManager::ScopedConnectionHelper::~ScopedConnectionHelper() { | 120 ServerConnectionManager::ScopedConnectionHelper::~ScopedConnectionHelper() { |
136 // We should be registered iff connection_.get() != NULL. | 121 if (connection_) |
137 if (connection_.get()) { | 122 manager_->OnConnectionDestroyed(connection_.get()); |
138 // It is important that this be called before this destructor completes. | 123 connection_.reset(); |
139 // Until the unregistration is complete, it's possible that the virtual | |
140 // OnStopRequested() function may be called from a different thread. We | |
141 // need to unregister it before destruction modifies our vptr. | |
142 cancelation_signal_->UnregisterHandler(this); | |
143 } | |
144 } | 124 } |
145 | 125 |
146 ServerConnectionManager::Connection* | 126 ServerConnectionManager::Connection* |
147 ServerConnectionManager::ScopedConnectionHelper::get() { | 127 ServerConnectionManager::ScopedConnectionHelper::get() { |
148 return connection_.get(); | 128 return connection_.get(); |
149 } | 129 } |
150 | 130 |
151 namespace { | 131 namespace { |
152 | 132 |
153 string StripTrailingSlash(const string& s) { | 133 string StripTrailingSlash(const string& s) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 } | 170 } |
191 | 171 |
192 ScopedServerStatusWatcher::~ScopedServerStatusWatcher() { | 172 ScopedServerStatusWatcher::~ScopedServerStatusWatcher() { |
193 conn_mgr_->SetServerStatus(response_->server_status); | 173 conn_mgr_->SetServerStatus(response_->server_status); |
194 } | 174 } |
195 | 175 |
196 ServerConnectionManager::ServerConnectionManager( | 176 ServerConnectionManager::ServerConnectionManager( |
197 const string& server, | 177 const string& server, |
198 int port, | 178 int port, |
199 bool use_ssl, | 179 bool use_ssl, |
200 bool use_oauth2_token, | 180 bool use_oauth2_token) |
201 CancelationSignal* cancelation_signal) | |
202 : sync_server_(server), | 181 : sync_server_(server), |
203 sync_server_port_(port), | 182 sync_server_port_(port), |
204 use_ssl_(use_ssl), | 183 use_ssl_(use_ssl), |
205 use_oauth2_token_(use_oauth2_token), | 184 use_oauth2_token_(use_oauth2_token), |
206 proto_sync_path_(kSyncServerSyncPath), | 185 proto_sync_path_(kSyncServerSyncPath), |
207 server_status_(HttpResponse::NONE), | 186 server_status_(HttpResponse::NONE), |
208 cancelation_signal_(cancelation_signal) { | 187 terminated_(false), |
| 188 active_connection_(NULL) { |
209 } | 189 } |
210 | 190 |
211 ServerConnectionManager::~ServerConnectionManager() { | 191 ServerConnectionManager::~ServerConnectionManager() { |
212 } | 192 } |
213 | 193 |
| 194 ServerConnectionManager::Connection* |
| 195 ServerConnectionManager::MakeActiveConnection() { |
| 196 base::AutoLock lock(terminate_connection_lock_); |
| 197 DCHECK(!active_connection_); |
| 198 if (terminated_) |
| 199 return NULL; |
| 200 |
| 201 active_connection_ = MakeConnection(); |
| 202 return active_connection_; |
| 203 } |
| 204 |
| 205 void ServerConnectionManager::OnConnectionDestroyed(Connection* connection) { |
| 206 DCHECK(connection); |
| 207 base::AutoLock lock(terminate_connection_lock_); |
| 208 // |active_connection_| can be NULL already if it was aborted. Also, |
| 209 // it can legitimately be a different Connection object if a new Connection |
| 210 // was created after a previous one was Aborted and destroyed. |
| 211 if (active_connection_ != connection) |
| 212 return; |
| 213 |
| 214 active_connection_ = NULL; |
| 215 } |
| 216 |
214 bool ServerConnectionManager::SetAuthToken(const std::string& auth_token) { | 217 bool ServerConnectionManager::SetAuthToken(const std::string& auth_token) { |
215 DCHECK(thread_checker_.CalledOnValidThread()); | 218 DCHECK(thread_checker_.CalledOnValidThread()); |
216 if (previously_invalidated_token != auth_token) { | 219 if (previously_invalidated_token != auth_token) { |
217 auth_token_.assign(auth_token); | 220 auth_token_.assign(auth_token); |
218 previously_invalidated_token = std::string(); | 221 previously_invalidated_token = std::string(); |
219 return true; | 222 return true; |
220 } | 223 } |
221 return false; | 224 return false; |
222 } | 225 } |
223 | 226 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 // workaround for M29 blocker to avoid sending RPC to sync with known invalid | 271 // workaround for M29 blocker to avoid sending RPC to sync with known invalid |
269 // token but instead to trigger refreshing token in ProfileSyncService. Need | 272 // token but instead to trigger refreshing token in ProfileSyncService. Need |
270 // to clean it. | 273 // to clean it. |
271 if (auth_token.empty() || auth_token == "credentials_lost") { | 274 if (auth_token.empty() || auth_token == "credentials_lost") { |
272 params->response.server_status = HttpResponse::SYNC_AUTH_ERROR; | 275 params->response.server_status = HttpResponse::SYNC_AUTH_ERROR; |
273 return false; | 276 return false; |
274 } | 277 } |
275 | 278 |
276 // When our connection object falls out of scope, it clears itself from | 279 // When our connection object falls out of scope, it clears itself from |
277 // active_connection_. | 280 // active_connection_. |
278 ScopedConnectionHelper post(cancelation_signal_, MakeConnection()); | 281 ScopedConnectionHelper post(this, MakeActiveConnection()); |
279 if (!post.get()) { | 282 if (!post.get()) { |
280 params->response.server_status = HttpResponse::CONNECTION_UNAVAILABLE; | 283 params->response.server_status = HttpResponse::CONNECTION_UNAVAILABLE; |
281 return false; | 284 return false; |
282 } | 285 } |
283 | 286 |
284 // Note that |post| may be aborted by now, which will just cause Init to fail | 287 // Note that |post| may be aborted by now, which will just cause Init to fail |
285 // with CONNECTION_UNAVAILABLE. | 288 // with CONNECTION_UNAVAILABLE. |
286 bool ok = post.get()->Init( | 289 bool ok = post.get()->Init( |
287 path.c_str(), auth_token, params->buffer_in, ¶ms->response); | 290 path.c_str(), auth_token, params->buffer_in, ¶ms->response); |
288 | 291 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 DCHECK(thread_checker_.CalledOnValidThread()); | 336 DCHECK(thread_checker_.CalledOnValidThread()); |
334 listeners_.AddObserver(listener); | 337 listeners_.AddObserver(listener); |
335 } | 338 } |
336 | 339 |
337 void ServerConnectionManager::RemoveListener( | 340 void ServerConnectionManager::RemoveListener( |
338 ServerConnectionEventListener* listener) { | 341 ServerConnectionEventListener* listener) { |
339 DCHECK(thread_checker_.CalledOnValidThread()); | 342 DCHECK(thread_checker_.CalledOnValidThread()); |
340 listeners_.RemoveObserver(listener); | 343 listeners_.RemoveObserver(listener); |
341 } | 344 } |
342 | 345 |
343 scoped_ptr<ServerConnectionManager::Connection> | 346 ServerConnectionManager::Connection* ServerConnectionManager::MakeConnection() |
344 ServerConnectionManager::MakeConnection() | |
345 { | 347 { |
346 return scoped_ptr<Connection>(); // For testing. | 348 return NULL; // For testing. |
| 349 } |
| 350 |
| 351 void ServerConnectionManager::TerminateAllIO() { |
| 352 base::AutoLock lock(terminate_connection_lock_); |
| 353 terminated_ = true; |
| 354 if (active_connection_) |
| 355 active_connection_->Abort(); |
| 356 |
| 357 // Sever our ties to this connection object. Note that it still may exist, |
| 358 // since we don't own it, but it has been neutered. |
| 359 active_connection_ = NULL; |
347 } | 360 } |
348 | 361 |
349 std::ostream& operator << (std::ostream& s, const struct HttpResponse& hr) { | 362 std::ostream& operator << (std::ostream& s, const struct HttpResponse& hr) { |
350 s << " Response Code (bogus on error): " << hr.response_code; | 363 s << " Response Code (bogus on error): " << hr.response_code; |
351 s << " Content-Length (bogus on error): " << hr.content_length; | 364 s << " Content-Length (bogus on error): " << hr.content_length; |
352 s << " Server Status: " | 365 s << " Server Status: " |
353 << HttpResponse::GetServerConnectionCodeString(hr.server_status); | 366 << HttpResponse::GetServerConnectionCodeString(hr.server_status); |
354 return s; | 367 return s; |
355 } | 368 } |
356 | 369 |
357 } // namespace syncer | 370 } // namespace syncer |
OLD | NEW |