Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1444)

Side by Side Diff: google_apis/gcm/engine/connection_factory_impl.cc

Issue 54743007: [GCM] Add connection factory for creating MCS connections (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix compile Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 #include "google_apis/gcm/engine/connection_factory_impl.h"
6
7 #include "base/message_loop/message_loop.h"
8 #include "google_apis/gcm/engine/connection_handler_impl.h"
9 #include "google_apis/gcm/protocol/mcs.pb.h"
10 #include "net/base/net_errors.h"
11 #include "net/http/http_network_session.h"
12 #include "net/http/http_request_headers.h"
13 #include "net/proxy/proxy_info.h"
14 #include "net/socket/client_socket_handle.h"
15 #include "net/socket/client_socket_pool_manager.h"
16 #include "net/ssl/ssl_config_service.h"
17
18 namespace gcm {
19
20 namespace {
21
22 // The amount of time a Socket read should wait before timing out.
23 const int kReadTimeoutMs = 30000; // 30 seconds.
24
25 // Backoff policy.
26 const net::BackoffEntry::Policy kConnectionBackoffPolicy = {
27 // Number of initial errors (in sequence) to ignore before applying
28 // exponential back-off rules.
29 0,
30
31 // Initial delay for exponential back-off in ms.
32 10000, // 10 seconds.
33
34 // Factor by which the waiting time will be multiplied.
35 2,
36
37 // Fuzzing percentage. ex: 10% will spread requests randomly
38 // between 90%-100% of the calculated time.
39 0.2, // 20%.
40
41 // Maximum amount of time we are willing to delay our request in ms.
42 1000 * 3600 * 4, // 4 hours.
43
44 // Time to keep an entry from being discarded even when it
45 // has no significant state, -1 to never discard.
46 -1,
47
48 // Don't use initial delay unless the last request was an error.
49 false,
50 };
51
52 } // namespace
53
54 ConnectionFactoryImpl::ConnectionFactoryImpl(
55 const GURL& mcs_endpoint,
56 scoped_refptr<net::HttpNetworkSession> network_session,
57 net::NetLog* net_log)
58 : mcs_endpoint_(mcs_endpoint),
59 network_session_(network_session),
60 net_log_(net_log),
61 weak_ptr_factory_(this) {
62 }
63
64 ConnectionFactoryImpl::~ConnectionFactoryImpl() {
65 }
66
67 ConnectionHandler* ConnectionFactoryImpl::BuildConnectionHandler(
68 const ConnectionHandler::ProtoReceivedCallback& read_callback,
69 const ConnectionHandler::ProtoSentCallback& write_callback) {
70 DCHECK(!connection_handler_);
71
72 backoff_entry_ = CreateBackoffEntry(&kConnectionBackoffPolicy);
73
74 net::NetworkChangeNotifier::AddIPAddressObserver(this);
75 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
76 connection_handler_.reset(
77 new ConnectionHandlerImpl(
78 base::TimeDelta::FromMilliseconds(kReadTimeoutMs),
79 read_callback,
80 write_callback,
81 base::Bind(&ConnectionFactoryImpl::ConnectionHandlerCallback,
82 weak_ptr_factory_.GetWeakPtr())));
83 return connection_handler_.get();
84 }
85
86 void ConnectionFactoryImpl::Connect(
87 const mcs_proto::LoginRequest& login_request) {
88 DCHECK(connection_handler_);
89 DCHECK(!IsEndpointReachable());
90
91 if (login_request.IsInitialized()) {
92 DCHECK(!login_request_.IsInitialized());
93 login_request_ = login_request;
94 }
95
96 if (backoff_entry_->ShouldRejectRequest()) {
97 DVLOG(1) << "Delaying MCS endpoint connection for "
98 << backoff_entry_->GetTimeUntilRelease().InMilliseconds()
99 << " milliseconds.";
100 base::MessageLoop::current()->PostDelayedTask(
101 FROM_HERE,
102 base::Bind(&ConnectionFactoryImpl::Connect,
103 weak_ptr_factory_.GetWeakPtr(),
104 login_request_),
105 NextRetryAttempt() - base::TimeTicks::Now());
106 return;
107 }
108
109 DVLOG(1) << "Attempting connection to MCS endpoint.";
110 ConnectImpl();
111 }
112
113 bool ConnectionFactoryImpl::IsEndpointReachable() const {
114 return connection_handler_ && connection_handler_->CanSendMessage();
115 }
116
117 base::TimeTicks ConnectionFactoryImpl::NextRetryAttempt() const {
118 if (!backoff_entry_)
119 return base::TimeTicks();
120 return backoff_entry_->GetReleaseTime();
121 }
122
123 void ConnectionFactoryImpl::OnConnectionTypeChanged(
124 net::NetworkChangeNotifier::ConnectionType type) {
125 if (type == net::NetworkChangeNotifier::CONNECTION_NONE)
126 return;
127
128 // TODO(zea): implement different backoff/retry policies based on connection
129 // type.
130 DVLOG(1) << "Connection type changed to " << type << ", resetting backoff.";
131 backoff_entry_->Reset();
132 // Connect(..) should be retrying with backoff already if a connection is
133 // necessary, so no need to call again.
134 }
135
136 void ConnectionFactoryImpl::OnIPAddressChanged() {
137 DVLOG(1) << "IP Address changed, resetting backoff.";
138 backoff_entry_->Reset();
139 // Connect(..) should be retrying with backoff already if a connection is
140 // necessary, so no need to call again.
141 }
142
143 void ConnectionFactoryImpl::ConnectImpl() {
144 DCHECK(!IsEndpointReachable());
145
146 // TODO(zea): resolve proxies.
147 net::ProxyInfo proxy_info;
148 proxy_info.UseDirect();
149 net::SSLConfig ssl_config;
150 network_session_->ssl_config_service()->GetSSLConfig(&ssl_config);
151
152 int status = net::InitSocketHandleForTlsConnect(
153 net::HostPortPair::FromURL(mcs_endpoint_),
154 network_session_.get(),
155 proxy_info,
156 ssl_config,
157 ssl_config,
158 net::kPrivacyModeDisabled,
159 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_SOCKET),
160 &socket_handle_,
161 base::Bind(&ConnectionFactoryImpl::OnConnectDone,
162 weak_ptr_factory_.GetWeakPtr()));
163 if (status != net::ERR_IO_PENDING)
164 OnConnectDone(status);
165 }
166
167 void ConnectionFactoryImpl::InitHandler() {
168 connection_handler_->Init(login_request_, socket_handle_.PassSocket());
169 }
170
171 scoped_ptr<net::BackoffEntry> ConnectionFactoryImpl::CreateBackoffEntry(
172 const net::BackoffEntry::Policy* const policy) {
173 return scoped_ptr<net::BackoffEntry>(new net::BackoffEntry(policy));
174 }
175
176 void ConnectionFactoryImpl::OnConnectDone(int result) {
177 if (result != net::OK) {
178 LOG(ERROR) << "Failed to connect to MCS endpoint with error " << result;
179 backoff_entry_->InformOfRequest(false);
180 Connect(mcs_proto::LoginRequest());
181 return;
182 }
183
184 DVLOG(1) << "MCS endpoint connection success.";
185
186 // Reset the backoff.
187 backoff_entry_->Reset();
188
189 InitHandler();
190 }
191
192 void ConnectionFactoryImpl::ConnectionHandlerCallback(int result) {
193 // TODO(zea): Consider how to handle errors that may require some sort of
194 // user intervention (login page, etc.).
195 LOG(ERROR) << "Connection reset with error " << result;
196 backoff_entry_->InformOfRequest(false);
197 Connect(mcs_proto::LoginRequest());
198 }
199
200 } // namespace gcm
OLDNEW
« no previous file with comments | « google_apis/gcm/engine/connection_factory_impl.h ('k') | google_apis/gcm/engine/connection_factory_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698