#ifndef GOOGLE_APIS_GCM_ENGINE_CONNECTION_FACTORY_IMPL_H_
#define GOOGLE_APIS_GCM_ENGINE_CONNECTION_FACTORY_IMPL_H_
#include "google_apis/gcm/engine/connection_factory.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "google_apis/gcm/protocol/mcs.pb.h"
#include "net/base/backoff_entry.h"
#include "net/base/network_change_notifier.h"
#include "net/proxy/proxy_info.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/client_socket_handle.h"
#include "url/gurl.h"
namespace net {
class HttpNetworkSession;
class NetLog;
}
namespace gcm {
class ConnectionHandlerImpl;
class GCM_EXPORT ConnectionFactoryImpl :
public ConnectionFactory,
public net::NetworkChangeNotifier::ConnectionTypeObserver,
public net::NetworkChangeNotifier::IPAddressObserver {
public:
ConnectionFactoryImpl(
const std::vector<GURL>& mcs_endpoints,
const net::BackoffEntry::Policy& backoff_policy,
scoped_refptr<net::HttpNetworkSession> network_session,
net::NetLog* net_log);
virtual ~ConnectionFactoryImpl();
virtual void Initialize(
const BuildLoginRequestCallback& request_builder,
const ConnectionHandler::ProtoReceivedCallback& read_callback,
const ConnectionHandler::ProtoSentCallback& write_callback) OVERRIDE;
virtual ConnectionHandler* GetConnectionHandler() const OVERRIDE;
virtual void Connect() OVERRIDE;
virtual bool IsEndpointReachable() const OVERRIDE;
virtual base::TimeTicks NextRetryAttempt() const OVERRIDE;
virtual void SignalConnectionReset(ConnectionResetReason reason) OVERRIDE;
virtual void OnConnectionTypeChanged(
net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
virtual void OnIPAddressChanged() OVERRIDE;
GURL GetCurrentEndpoint() const;
protected:
virtual void ConnectImpl();
virtual void InitHandler();
virtual scoped_ptr<net::BackoffEntry> CreateBackoffEntry(
const net::BackoffEntry::Policy* const policy);
virtual scoped_ptr<ConnectionHandler> CreateConnectionHandler(
base::TimeDelta read_timeout,
const ConnectionHandler::ProtoReceivedCallback& read_callback,
const ConnectionHandler::ProtoSentCallback& write_callback,
const ConnectionHandler::ConnectionChangedCallback& connection_callback);
virtual base::TimeTicks NowTicks();
void OnConnectDone(int result);
void ConnectionHandlerCallback(int result);
private:
void ConnectWithBackoff();
void OnProxyResolveDone(int status);
void OnProxyConnectDone(int status);
int ReconsiderProxyAfterError(int error);
void ReportSuccessfulProxyConnection();
void CloseSocket();
const std::vector<GURL> mcs_endpoints_;
size_t next_endpoint_;
size_t last_successful_endpoint_;
const net::BackoffEntry::Policy backoff_policy_;
const scoped_refptr<net::HttpNetworkSession> network_session_;
net::BoundNetLog bound_net_log_;
net::ProxyService::PacRequest* pac_request_;
net::ProxyInfo proxy_info_;
net::ClientSocketHandle socket_handle_;
scoped_ptr<net::BackoffEntry> backoff_entry_;
scoped_ptr<net::BackoffEntry> previous_backoff_;
bool connecting_;
bool waiting_for_backoff_;
bool logging_in_;
base::TimeTicks last_login_time_;
scoped_ptr<ConnectionHandler> connection_handler_;
BuildLoginRequestCallback request_builder_;
base::WeakPtrFactory<ConnectionFactoryImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ConnectionFactoryImpl);
};
}
#endif