Index: google_apis/gcm/engine/mcs_client.cc |
diff --git a/google_apis/gcm/engine/mcs_client.cc b/google_apis/gcm/engine/mcs_client.cc |
index 07f1004af2eab3e4365b2019065e6b486d6f3591..9b639c3bbd035e40472b9e31d4d96472119ee862 100644 |
--- a/google_apis/gcm/engine/mcs_client.cc |
+++ b/google_apis/gcm/engine/mcs_client.cc |
@@ -20,9 +20,6 @@ namespace { |
typedef scoped_ptr<google::protobuf::MessageLite> MCSProto; |
-// TODO(zea): get these values from MCS settings. |
-const int64 kHeartbeatDefaultSeconds = 60 * 15; // 15 minutes. |
- |
// The category of messages intended for the GCM client itself from MCS. |
const char kMCSCategory[] = "com.google.android.gsf.gtalkservice"; |
@@ -30,8 +27,8 @@ const char kMCSCategory[] = "com.google.android.gsf.gtalkservice"; |
const char kGCMFromField[] = "gcm@android.com"; |
// MCS status message types. |
+// TODO(zea): handle these at the GCMClient layer. |
const char kIdleNotification[] = "IdleNotification"; |
-// TODO(zea): consume the following message types: |
// const char kAlwaysShowOnIdle[] = "ShowAwayOnIdle"; |
// const char kPowerNotification[] = "PowerNotification"; |
// const char kDataActiveNotification[] = "DataActiveNotification"; |
@@ -97,9 +94,6 @@ MCSClient::MCSClient(ConnectionFactory* connection_factory, RMQStore* rmq_store) |
stream_id_out_(0), |
stream_id_in_(0), |
rmq_store_(rmq_store), |
- heartbeat_interval_( |
- base::TimeDelta::FromSeconds(kHeartbeatDefaultSeconds)), |
- heartbeat_timer_(true, true), |
weak_ptr_factory_(this) { |
} |
@@ -183,7 +177,6 @@ void MCSClient::Initialize( |
} |
void MCSClient::Login(uint64 android_id, uint64 security_token) { |
- DCHECK_EQ(state_, LOADED); |
if (android_id != android_id_ && security_token != security_token_) { |
DCHECK(android_id); |
DCHECK(security_token); |
@@ -257,6 +250,8 @@ void MCSClient::ResetStateAndBuildLoginRequest( |
last_device_to_server_stream_id_received_ = 0; |
last_server_to_device_stream_id_received_ = 0; |
+ heartbeat_manager_.Stop(); |
+ |
// TODO(zea): expire all messages older than their TTL. |
// Add any pending acknowledgments to the list of ids. |
@@ -299,8 +294,6 @@ void MCSClient::ResetStateAndBuildLoginRequest( |
<< " incoming acks pending, and " << to_send_.size() |
<< " pending outgoing messages."; |
- heartbeat_timer_.Stop(); |
- |
state_ = CONNECTING; |
} |
@@ -332,8 +325,6 @@ void MCSClient::MaybeSendMessage() { |
} |
void MCSClient::SendPacketToWire(ReliablePacketInfo* packet_info) { |
- // Reset the heartbeat interval. |
- heartbeat_timer_.Reset(); |
packet_info->stream_id = ++stream_id_out_; |
DVLOG(1) << "Sending packet of type " << packet_info->protobuf->GetTypeName(); |
@@ -447,6 +438,9 @@ void MCSClient::HandlePacketFromWire( |
false); |
} |
+ // The connection is alive, treat this message as a heartbeat ack. |
+ heartbeat_manager_.OnHeartbeatAcked(); |
+ |
switch (tag) { |
case kLoginResponseTag: { |
DCHECK_EQ(CONNECTING, state_); |
@@ -455,7 +449,7 @@ void MCSClient::HandlePacketFromWire( |
DVLOG(1) << "Received login response:"; |
DVLOG(1) << " Id: " << login_response->id(); |
DVLOG(1) << " Timestamp: " << login_response->server_timestamp(); |
- if (login_response->has_error()) { |
+ if (login_response->has_error() && login_response->error().code() != 0) { |
state_ = UNINITIALIZED; |
DVLOG(1) << " Error code: " << login_response->error().code(); |
DVLOG(1) << " Error message: " << login_response->error().message(); |
@@ -463,6 +457,11 @@ void MCSClient::HandlePacketFromWire( |
return; |
} |
+ if (login_response->has_heartbeat_config()) { |
+ heartbeat_manager_.UpdateHeartbeatConfig( |
+ login_response->heartbeat_config()); |
+ } |
+ |
state_ = CONNECTED; |
stream_id_in_ = 1; // To account for the login response. |
DCHECK_EQ(1U, stream_id_out_); |
@@ -483,10 +482,11 @@ void MCSClient::HandlePacketFromWire( |
weak_ptr_factory_.GetWeakPtr())); |
} |
- heartbeat_timer_.Start(FROM_HERE, |
- heartbeat_interval_, |
- base::Bind(&MCSClient::SendHeartbeat, |
- weak_ptr_factory_.GetWeakPtr())); |
+ heartbeat_manager_.Start( |
+ base::Bind(&MCSClient::SendHeartbeat, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&MCSClient::OnConnectionResetByHeartbeat, |
+ weak_ptr_factory_.GetWeakPtr())); |
return; |
} |
case kHeartbeatPingTag: |
@@ -498,8 +498,7 @@ void MCSClient::HandlePacketFromWire( |
case kHeartbeatAckTag: |
DCHECK_GE(stream_id_in_, 1U); |
DVLOG(1) << "Received heartbeat ack."; |
- // TODO(zea): add logic to reconnect if no ack received within a certain |
- // timeout (with backoff). |
+ // Do nothing else, all messages act as heartbeat acks. |
return; |
case kCloseTag: |
LOG(ERROR) << "Received close command, resetting connection."; |
@@ -657,4 +656,8 @@ MCSClient::PersistentId MCSClient::GetNextPersistentId() { |
return base::Uint64ToString(base::TimeTicks::Now().ToInternalValue()); |
} |
+void MCSClient::OnConnectionResetByHeartbeat() { |
+ connection_factory_->SignalConnectionReset(); |
+} |
+ |
} // namespace gcm |