14ee2ad04344446e610172a0e73949212923014dfSebastian Redl// Copyright 2012 The Chromium Authors. All rights reserved. 22cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// Use of this source code is governed by a BSD-style license that can be 32cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// found in the LICENSE file. 42cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 52cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#ifndef SYNC_ENGINE_NET_SERVER_CONNECTION_MANAGER_H_ 62cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#define SYNC_ENGINE_NET_SERVER_CONNECTION_MANAGER_H_ 72cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 82cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <iosfwd> 92cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <string> 10a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl 112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/atomicops.h" 122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/memory/scoped_ptr.h" 132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/observer_list.h" 147faa2ec03a7ef120ac165bb45b6c70a8b20c9f1cSebastian Redl#include "base/strings/string_util.h" 150eca89e9890db4d8336ce762a5b359a1d58ca02bArgyrios Kyrtzidis#include "base/synchronization/lock.h" 16e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include "base/threading/non_thread_safe.h" 17e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include "base/threading/thread_checker.h" 182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "sync/base/sync_export.h" 192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "sync/internal_api/public/base/cancelation_observer.h" 202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "sync/syncable/syncable_id.h" 212a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall 2289eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidisnamespace sync_pb { 230b7489194f9f89fac39d57211c1e7953ae50251fDouglas Gregorclass ClientToServerMessage; 247a1fad38256eb4c5129359be85ba1ea1678eb5c9John McCall} 252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 26a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCallnamespace syncer { 276ab7cd853e9c15cf986a8a7c3db1f8d20e275409Sebastian Redl 28bbf38319edd4eddc55ec273934e990d7e84991deDouglas Gregorclass CancelationSignal; 297c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattner 306a5a23f8e7fb65e028c8092bc1d1a1d9dfe2e9bcDouglas Gregornamespace syncable { 317c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattnerclass Directory; 32a71a7d8a1ce4474e7bdb680658fb58b6caf391d3Douglas Gregor} 3383d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff 3414f79002e58556798e86168c63e48d533287eda5Douglas Gregorstatic const int32 kUnsetResponseCode = -1; 3510e286aa8d39fb51a21412850265d9dae74613eeChris Lattnerstatic const int32 kUnsetContentLength = -1; 363251ceb90b3fec68e86d6dcfa58836e20a7205c3Douglas Gregorstatic const int32 kUnsetPayloadLength = -1; 3714f79002e58556798e86168c63e48d533287eda5Douglas Gregor 38bd94500d3aa60092fb0f1e90f53fb0d03fa502a8Douglas Gregor// HttpResponse gathers the relevant output properties of an HTTP request. 392bec0410d268779f601bd509e0302a500af7ac6aDouglas Gregor// Depending on the value of the server_status code, response_code, and 4057016dda61498294120b1a881d9e6606337b29d9Douglas Gregor// content_length may not be valid. 41ab41e63821dc60ad144d0684df8d79a9eef86b75Douglas Gregorstruct SYNC_EXPORT_PRIVATE HttpResponse { 420a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor enum ServerConnectionCode { 4317fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor // For uninitialized state. 4417fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor NONE, 452596e429a61602312bdd149786045b8a90cd2d10Daniel Dunbar 462cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // CONNECTION_UNAVAILABLE is returned when InternetConnect() fails. 47fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer CONNECTION_UNAVAILABLE, 4814f79002e58556798e86168c63e48d533287eda5Douglas Gregor 4903013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer // IO_ERROR is returned when reading/writing to a buffer has failed. 50f62d43d2afe1960755a1b5813cae1e5983bcac1bDouglas Gregor IO_ERROR, 513c304bd9ec2b4611572d4cbae9e1727bbecb5dc9Chris Lattner 52cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor // SYNC_SERVER_ERROR is returned when the HTTP status code indicates that 53f62d43d2afe1960755a1b5813cae1e5983bcac1bDouglas Gregor // a non-auth error has occured. 542cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor SYNC_SERVER_ERROR, 558538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl 562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // SYNC_AUTH_ERROR is returned when the HTTP status code indicates that an 57ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl // auth error has occured (i.e. a 401 or sync-specific AUTH_INVALID 585f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner // response) 595f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner // TODO(tim): Caring about AUTH_INVALID is a layering violation. But 605f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner // this app-specific logic is being added as a stable branch hotfix so 616e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer // minimal changes prevail for the moment. Fix this! Bug 35060. 62ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl SYNC_AUTH_ERROR, 636e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer 646e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer // SERVER_CONNECTION_OK is returned when request was handled correctly. 655f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SERVER_CONNECTION_OK, 665f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner 676e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer // RETRY is returned when a Commit request fails with a RETRY response from 68ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl // the server. 69ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl // 702cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // TODO(idana): the server no longer returns RETRY so we should remove this 712cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // value. 722cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor RETRY, 7312b1c7615d4f9a2edc544be499f895f16ac100edChris Lattner }; 742cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 753397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl // The HTTP Status code. 76a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl int64 response_code; 7789eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis 782cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // The value of the Content-length header. 792cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor int64 content_length; 802cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 818538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl // The size of a download request's payload. 822cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor int64 payload_length; 8389eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis 848538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl // Identifies the type of failure, if any. 852cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ServerConnectionCode server_status; 862cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor HttpResponse(); 882cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor static const char* GetServerConnectionCodeString( 902cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ServerConnectionCode code); 912cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor static ServerConnectionCode ServerConnectionCodeFromNetError( 932cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor int error_code); 942cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor}; 952cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 963397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redlstruct ServerConnectionEvent { 97b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie HttpResponse::ServerConnectionCode connection_code; 982cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor explicit ServerConnectionEvent(HttpResponse::ServerConnectionCode code) : 992cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor connection_code(code) {} 1003397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl}; 1012cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1028538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redlclass SYNC_EXPORT_PRIVATE ServerConnectionEventListener { 1032cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor public: 1042cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor virtual void OnServerConnectionEvent(const ServerConnectionEvent& event) = 0; 1053397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl protected: 1062cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor virtual ~ServerConnectionEventListener() {} 1078538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl}; 1082cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1092cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorclass ServerConnectionManager; 1103397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl// A helper class that automatically notifies when the status changes. 1111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// TODO(tim): This class shouldn't be exposed outside of the implementation, 1128538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl// bug 35060. 1132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorclass SYNC_EXPORT_PRIVATE ScopedServerStatusWatcher 1142cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor : public base::NonThreadSafe { 1153397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl public: 116df1550fc59b51681d37225934fe4e3acac321621Richard Smith ScopedServerStatusWatcher(ServerConnectionManager* conn_mgr, 117df1550fc59b51681d37225934fe4e3acac321621Richard Smith HttpResponse* response); 1188538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl virtual ~ScopedServerStatusWatcher(); 1192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor private: 1202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ServerConnectionManager* const conn_mgr_; 1213397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl HttpResponse* const response_; 122df1550fc59b51681d37225934fe4e3acac321621Richard Smith DISALLOW_COPY_AND_ASSIGN(ScopedServerStatusWatcher); 1238538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl}; 1242cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// Use this class to interact with the sync server. 1263397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl// The ServerConnectionManager currently supports POSTing protocol buffers. 1271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// 1281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpclass SYNC_EXPORT_PRIVATE ServerConnectionManager : public CancelationObserver { 1298538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl public: 1302cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // buffer_in - will be POSTed 1312cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // buffer_out - string will be overwritten with response 1323397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl struct PostBufferParams { 1332cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor std::string buffer_in; 1342cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor std::string buffer_out; 1350953e767ff7817f97b3ab20896b229891eeff45bJohn McCall HttpResponse response; 1362cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor }; 1372cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1383397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl // Abstract class providing network-layer functionality to the 1392cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // ServerConnectionManager. Subclasses implement this using an HTTP stack of 1402cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // their choice. 1418538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl class Connection { 1422cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor public: 1432cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor explicit Connection(ServerConnectionManager* scm); 1443397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl virtual ~Connection(); 1452cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1468538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl // Called to initialize and perform an HTTP POST. 1472cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor virtual bool Init(const char* path, 1482cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const std::string& auth_token, 1493397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl const std::string& payload, 1502cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor HttpResponse* response) = 0; 1517e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor 1527e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor // Immediately abandons a pending HTTP POST request and unblocks caller 153c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor // in Init. 1548538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl virtual void Abort() = 0; 1552cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor bool ReadBufferResponse(std::string* buffer_out, HttpResponse* response, 1573397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl bool require_response); 1582cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor bool ReadDownloadResponse(HttpResponse* response, std::string* buffer_out); 1592cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 160e86d78cf4754a6aef2cf9a33d847aa15338e276fBob Wilson protected: 1618538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl std::string MakeConnectionURL(const std::string& sync_server, 1622cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const std::string& path, 1632cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor bool use_ssl) const; 1643397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 1652cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor void GetServerParams(std::string* server, 1668538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl int* server_port, 1672cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor bool* use_ssl) const { 1682cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor server->assign(scm_->sync_server_); 1693397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl *server_port = scm_->sync_server_port_; 1702cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *use_ssl = scm_->use_ssl_; 171264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola } 172264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola 173a49218e17bcbb1acde0245773173e2c0c42f4f19Eli Friedman std::string buffer_; 174425ef72306d4ff6b3698b744353e5f0e56b4b884Rafael Espindola ServerConnectionManager* scm_; 175ab8bbf4ebd3e3e6eab913cb044772a62b7581941Douglas Gregor 176264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola private: 177f85e193739c953358c865005855253af4f68a497John McCall int ReadResponse(void* buffer, int length); 1782cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor int ReadResponse(std::string* buffer, int length); 1792cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor }; 1803397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 1812cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ServerConnectionManager(const std::string& server, 1828538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl int port, 1832cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor bool use_ssl, 1842cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor CancelationSignal* cancelation_signal); 1853397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 1862cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor virtual ~ServerConnectionManager(); 1872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1882cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // POSTS buffer_in and reads a response into buffer_out. Uses our currently 1892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // set auth token in our headers. 1902cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // 191eefb3d5b49c844347f212073a7e975b8118fe8e9Richard Smith // Returns true if executed successfully. 1922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor virtual bool PostBufferWithCachedAuth(PostBufferParams* params, 193c938c1668b4fd12af154e965dd935a89e4801a70Douglas Gregor ScopedServerStatusWatcher* watcher); 19460618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl 19560618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl void AddListener(ServerConnectionEventListener* listener); 19660618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl void RemoveListener(ServerConnectionEventListener* listener); 19760618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl 19860618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl inline HttpResponse::ServerConnectionCode server_status() const { 19960618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl DCHECK(thread_checker_.CalledOnValidThread()); 20060618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl return server_status_; 2017bb698aa054de4c0e0aa23973b2c62dac9611262Richard Smith } 2027bb698aa054de4c0e0aa23973b2c62dac9611262Richard Smith 2037bb698aa054de4c0e0aa23973b2c62dac9611262Richard Smith const std::string client_id() const { return client_id_; } 204b9d0b76e42fd2d4cdfd135220302458d03ad09feRichard Smith 205b9d0b76e42fd2d4cdfd135220302458d03ad09feRichard Smith // Returns the current server parameters in server_url, port and use_ssl. 20660618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl void GetServerParameters(std::string* server_url, 2078538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl int* port, 2082cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor bool* use_ssl) const; 2092cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 2103397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl std::string GetServerHost() const; 211ed97649e9574b9d854fa4d6109c9333ae0993554John McCall 2128538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl // Factory method to create an Connection object we can use for 213ed97649e9574b9d854fa4d6109c9333ae0993554John McCall // communication with the server. 214ed97649e9574b9d854fa4d6109c9333ae0993554John McCall virtual Connection* MakeConnection(); 2153397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 2162cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Closes any active network connections to the sync server. 2179763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis // We expect this to get called on a different thread than the valid 2189763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis // ThreadChecker thread, as we want to kill any pending http traffic without 2198538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl // having to wait for the request to complete. 2202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor virtual void OnSignalReceived() OVERRIDE FINAL; 2212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 2223397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl void set_client_id(const std::string& client_id) { 223c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor DCHECK(thread_checker_.CalledOnValidThread()); 2248538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl DCHECK(client_id_.empty()); 2252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor client_id_.assign(client_id); 2262cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 2273397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 2282cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Sets a new auth token and time. 2298538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl bool SetAuthToken(const std::string& auth_token); 2302cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 2312cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor bool HasInvalidAuthToken() { 2323397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl return auth_token_.empty(); 233f8af98286022f72157d84951b48fde5fb369ab29Douglas Gregor } 234395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson 2358538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl const std::string auth_token() const { 236395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson DCHECK(thread_checker_.CalledOnValidThread()); 237395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson return auth_token_; 238ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt } 239ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt 240ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt protected: 241ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt inline std::string proto_sync_path() const { 242ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt return proto_sync_path_; 243ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt } 244ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt 24534b41d939a1328f484511c6002ba2456db879a29Richard Smith // Updates server_status_ and notifies listeners if server_status_ changed 24634b41d939a1328f484511c6002ba2456db879a29Richard Smith void SetServerStatus(HttpResponse::ServerConnectionCode server_status); 24734b41d939a1328f484511c6002ba2456db879a29Richard Smith 24834b41d939a1328f484511c6002ba2456db879a29Richard Smith // NOTE: Tests rely on this protected function being virtual. 24934b41d939a1328f484511c6002ba2456db879a29Richard Smith // 2503397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl // Internal PostBuffer base function. 251be191100e034b23a3e13053757a57b7f5068c24aArgyrios Kyrtzidis virtual bool PostBufferToPath(PostBufferParams*, 25256ca8a9c0fabd65418e9b2fd85140f4ed7d3c187Douglas Gregor const std::string& path, 2531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const std::string& auth_token, 2542cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor ScopedServerStatusWatcher* watcher); 2552cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 2562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // An internal helper to clear our auth_token_ and cache the old version 2573397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl // in |previously_invalidated_token_| to shelter us from retrying with a 2582cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // known bad token. 2598538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl void InvalidateAndClearAuthToken(); 2602cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 2612cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Helper to check terminated flags and build a Connection object, installing 2623397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl // it as the |active_connection_|. If this ServerConnectionManager has been 2632cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // terminated, this will return NULL. 2648538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl Connection* MakeActiveConnection(); 2652cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 2662cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Called by Connection objects as they are destroyed to allow the 2679d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall // ServerConnectionManager to cleanup active connections. 2689d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall void OnConnectionDestroyed(Connection* connection); 2699d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall 2709d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall // The sync_server_ is the server that requests will be made to. 2719d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall std::string sync_server_; 2729d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall 2739d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall // The sync_server_port_ is the port that HTTP requests will be made on. 2741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump int sync_server_port_; 2753397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 27649a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall // The unique id of the user's client. 27749a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall std::string client_id_; 27849a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall 2798538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl // Indicates whether or not requests should be made using HTTPS. 28049a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall bool use_ssl_; 28149a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall 28249a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall // The paths we post to. 283c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor std::string proto_sync_path_; 284c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor 285c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor // The auth token to use in authenticated requests. 286c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor std::string auth_token_; 287c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor 288c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor // The previous auth token that is invalid now. 289c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor std::string previously_invalidated_token; 290c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor 2913397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl ObserverList<ServerConnectionEventListener> listeners_; 2922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 293be191100e034b23a3e13053757a57b7f5068c24aArgyrios Kyrtzidis HttpResponse::ServerConnectionCode server_status_; 29490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis 29590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis base::ThreadChecker thread_checker_; 29690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis 29790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis // Protects all variables below to allow bailing out of active connections. 29890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis base::Lock terminate_connection_lock_; 2993e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smith 3003e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smith // If true, we've been told to terminate IO and expect to be destroyed 3019763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis // shortly. No future network requests will be made. 3029763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis bool terminated_; 3038538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl 30490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis // A non-owning pointer to any active http connection, so that we can abort 30590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis // it if necessary. 30690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis Connection* active_connection_; 3073397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 308ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis private: 309ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis friend class Connection; 310ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis friend class ScopedServerStatusWatcher; 3118538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl 31290b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis // A class to help deal with cleaning up active Connection objects when (for 31390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis // ex) multiple early-exits are present in some scope. ScopedConnectionHelper 31490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis // informs the ServerConnectionManager before the Connection object it takes 3153397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl // ownership of is destroyed. 31690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis class ScopedConnectionHelper { 31790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis public: 318b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie // |manager| must outlive this. Takes ownership of |connection|. 31990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis ScopedConnectionHelper(ServerConnectionManager* manager, 32090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis Connection* connection); 32190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis ~ScopedConnectionHelper(); 3223397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl Connection* get(); 32390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis private: 32490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis ServerConnectionManager* manager_; 32590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis scoped_ptr<Connection> connection_; 3264fb86f8c4585e53c21c847ad3de9e3b2de123cd9Chandler Carruth DISALLOW_COPY_AND_ASSIGN(ScopedConnectionHelper); 3278538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl }; 32890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis 32990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis void NotifyStatusChanged(); 33090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis 3313397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl CancelationSignal* const cancelation_signal_; 3328dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis bool signal_handler_registered_; 3338dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis 3348dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis DISALLOW_COPY_AND_ASSIGN(ServerConnectionManager); 335f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis}; 336f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis 337f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidisstd::ostream& operator<<(std::ostream& s, const struct HttpResponse& hr); 3388538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl 33990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis} // namespace syncer 34090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis 34190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis#endif // SYNC_ENGINE_NET_SERVER_CONNECTION_MANAGER_H_ 3423397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl