| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "google_apis/gcm/engine/mcs_client.h" | 5 #include "google_apis/gcm/engine/mcs_client.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/location.h" | 12 #include "base/location.h" |
| 13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/thread_task_runner_handle.h" | 15 #include "base/thread_task_runner_handle.h" |
| 16 #include "base/time/clock.h" | 16 #include "base/time/clock.h" |
| 17 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 18 #include "base/timer/timer.h" | 18 #include "base/timer/timer.h" |
| 19 #include "google_apis/gcm/base/mcs_util.h" | 19 #include "google_apis/gcm/base/mcs_util.h" |
| 20 #include "google_apis/gcm/base/socket_stream.h" | 20 #include "google_apis/gcm/base/socket_stream.h" |
| 21 #include "google_apis/gcm/engine/connection_factory.h" | 21 #include "google_apis/gcm/engine/connection_factory.h" |
| 22 #include "google_apis/gcm/monitoring/gcm_stats_recorder.h" | 22 #include "google_apis/gcm/monitoring/gcm_stats_recorder.h" |
| 23 | 23 |
| 24 using namespace google::protobuf::io; | 24 using namespace google::protobuf::io; |
| 25 | 25 |
| 26 namespace gcm { | 26 namespace gcm { |
| 27 | 27 |
| 28 namespace { | 28 namespace { |
| 29 | 29 |
| 30 typedef scoped_ptr<google::protobuf::MessageLite> MCSProto; | 30 typedef std::unique_ptr<google::protobuf::MessageLite> MCSProto; |
| 31 | 31 |
| 32 // The category of messages intended for the GCM client itself from MCS. | 32 // The category of messages intended for the GCM client itself from MCS. |
| 33 const char kMCSCategory[] = "com.google.android.gsf.gtalkservice"; | 33 const char kMCSCategory[] = "com.google.android.gsf.gtalkservice"; |
| 34 | 34 |
| 35 // The from field for messages originating in the GCM client. | 35 // The from field for messages originating in the GCM client. |
| 36 const char kGCMFromField[] = "gcm@android.com"; | 36 const char kGCMFromField[] = "gcm@android.com"; |
| 37 | 37 |
| 38 // MCS status message types. | 38 // MCS status message types. |
| 39 // TODO(zea): handle these at the GCMClient layer. | 39 // TODO(zea): handle these at the GCMClient layer. |
| 40 const char kIdleNotification[] = "IdleNotification"; | 40 const char kIdleNotification[] = "IdleNotification"; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 weak_ptr_factory_(this) { | 182 weak_ptr_factory_(this) { |
| 183 } | 183 } |
| 184 | 184 |
| 185 MCSClient::~MCSClient() { | 185 MCSClient::~MCSClient() { |
| 186 } | 186 } |
| 187 | 187 |
| 188 void MCSClient::Initialize( | 188 void MCSClient::Initialize( |
| 189 const ErrorCallback& error_callback, | 189 const ErrorCallback& error_callback, |
| 190 const OnMessageReceivedCallback& message_received_callback, | 190 const OnMessageReceivedCallback& message_received_callback, |
| 191 const OnMessageSentCallback& message_sent_callback, | 191 const OnMessageSentCallback& message_sent_callback, |
| 192 scoped_ptr<GCMStore::LoadResult> load_result) { | 192 std::unique_ptr<GCMStore::LoadResult> load_result) { |
| 193 DCHECK_EQ(state_, UNINITIALIZED); | 193 DCHECK_EQ(state_, UNINITIALIZED); |
| 194 | 194 |
| 195 state_ = LOADED; | 195 state_ = LOADED; |
| 196 mcs_error_callback_ = error_callback; | 196 mcs_error_callback_ = error_callback; |
| 197 message_received_callback_ = message_received_callback; | 197 message_received_callback_ = message_received_callback; |
| 198 message_sent_callback_ = message_sent_callback; | 198 message_sent_callback_ = message_sent_callback; |
| 199 | 199 |
| 200 connection_factory_->Initialize( | 200 connection_factory_->Initialize( |
| 201 base::Bind(&MCSClient::ResetStateAndBuildLoginRequest, | 201 base::Bind(&MCSClient::ResetStateAndBuildLoginRequest, |
| 202 weak_ptr_factory_.GetWeakPtr()), | 202 weak_ptr_factory_.GetWeakPtr()), |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 DCHECK_GE(ttl, 0); | 310 DCHECK_GE(ttl, 0); |
| 311 if (to_send_.size() > kMaxSendQueueSize) { | 311 if (to_send_.size() > kMaxSendQueueSize) { |
| 312 NotifyMessageSendStatus(message.GetProtobuf(), QUEUE_SIZE_LIMIT_REACHED); | 312 NotifyMessageSendStatus(message.GetProtobuf(), QUEUE_SIZE_LIMIT_REACHED); |
| 313 return; | 313 return; |
| 314 } | 314 } |
| 315 if (message.size() > kMaxMessageBytes) { | 315 if (message.size() > kMaxMessageBytes) { |
| 316 NotifyMessageSendStatus(message.GetProtobuf(), MESSAGE_TOO_LARGE); | 316 NotifyMessageSendStatus(message.GetProtobuf(), MESSAGE_TOO_LARGE); |
| 317 return; | 317 return; |
| 318 } | 318 } |
| 319 | 319 |
| 320 scoped_ptr<ReliablePacketInfo> packet_info(new ReliablePacketInfo()); | 320 std::unique_ptr<ReliablePacketInfo> packet_info(new ReliablePacketInfo()); |
| 321 packet_info->tag = message.tag(); | 321 packet_info->tag = message.tag(); |
| 322 packet_info->protobuf = message.CloneProtobuf(); | 322 packet_info->protobuf = message.CloneProtobuf(); |
| 323 | 323 |
| 324 if (ttl > 0) { | 324 if (ttl > 0) { |
| 325 DCHECK_EQ(message.tag(), kDataMessageStanzaTag); | 325 DCHECK_EQ(message.tag(), kDataMessageStanzaTag); |
| 326 | 326 |
| 327 // First check if this message should replace a pending message with the | 327 // First check if this message should replace a pending message with the |
| 328 // same collapse key. | 328 // same collapse key. |
| 329 mcs_proto::DataMessageStanza* data_message = | 329 mcs_proto::DataMessageStanza* data_message = |
| 330 reinterpret_cast<mcs_proto::DataMessageStanza*>( | 330 reinterpret_cast<mcs_proto::DataMessageStanza*>( |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 | 371 |
| 372 to_send_.push_back(make_linked_ptr(packet_info.release())); | 372 to_send_.push_back(make_linked_ptr(packet_info.release())); |
| 373 | 373 |
| 374 // Notify that the messages has been succsfully queued for sending. | 374 // Notify that the messages has been succsfully queued for sending. |
| 375 // TODO(jianli): We should report QUEUED after writing to GCM store succeeds. | 375 // TODO(jianli): We should report QUEUED after writing to GCM store succeeds. |
| 376 NotifyMessageSendStatus(message.GetProtobuf(), QUEUED); | 376 NotifyMessageSendStatus(message.GetProtobuf(), QUEUED); |
| 377 | 377 |
| 378 MaybeSendMessage(); | 378 MaybeSendMessage(); |
| 379 } | 379 } |
| 380 | 380 |
| 381 void MCSClient::UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) { | 381 void MCSClient::UpdateHeartbeatTimer(std::unique_ptr<base::Timer> timer) { |
| 382 heartbeat_manager_.UpdateHeartbeatTimer(std::move(timer)); | 382 heartbeat_manager_.UpdateHeartbeatTimer(std::move(timer)); |
| 383 } | 383 } |
| 384 | 384 |
| 385 void MCSClient::AddHeartbeatInterval(const std::string& scope, | 385 void MCSClient::AddHeartbeatInterval(const std::string& scope, |
| 386 int interval_ms) { | 386 int interval_ms) { |
| 387 if (!heartbeat_manager_.IsValidClientHeartbeatInterval(interval_ms)) | 387 if (!heartbeat_manager_.IsValidClientHeartbeatInterval(interval_ms)) |
| 388 return; | 388 return; |
| 389 | 389 |
| 390 custom_heartbeat_intervals_[scope] = interval_ms; | 390 custom_heartbeat_intervals_[scope] = interval_ms; |
| 391 gcm_store_->AddHeartbeatInterval(scope, interval_ms, | 391 gcm_store_->AddHeartbeatInterval(scope, interval_ms, |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 persistent_id_list.push_back(iter->second); | 599 persistent_id_list.push_back(iter->second); |
| 600 } | 600 } |
| 601 unacked_server_ids_.clear(); | 601 unacked_server_ids_.clear(); |
| 602 acked_server_ids_[stream_id_out_] = persistent_id_list; | 602 acked_server_ids_[stream_id_out_] = persistent_id_list; |
| 603 } | 603 } |
| 604 | 604 |
| 605 connection_handler_->SendMessage(*packet_info->protobuf); | 605 connection_handler_->SendMessage(*packet_info->protobuf); |
| 606 } | 606 } |
| 607 | 607 |
| 608 void MCSClient::HandleMCSDataMesssage( | 608 void MCSClient::HandleMCSDataMesssage( |
| 609 scoped_ptr<google::protobuf::MessageLite> protobuf) { | 609 std::unique_ptr<google::protobuf::MessageLite> protobuf) { |
| 610 mcs_proto::DataMessageStanza* data_message = | 610 mcs_proto::DataMessageStanza* data_message = |
| 611 reinterpret_cast<mcs_proto::DataMessageStanza*>(protobuf.get()); | 611 reinterpret_cast<mcs_proto::DataMessageStanza*>(protobuf.get()); |
| 612 // TODO(zea): implement a proper status manager rather than hardcoding these | 612 // TODO(zea): implement a proper status manager rather than hardcoding these |
| 613 // values. | 613 // values. |
| 614 scoped_ptr<mcs_proto::DataMessageStanza> response( | 614 std::unique_ptr<mcs_proto::DataMessageStanza> response( |
| 615 new mcs_proto::DataMessageStanza()); | 615 new mcs_proto::DataMessageStanza()); |
| 616 response->set_from(kGCMFromField); | 616 response->set_from(kGCMFromField); |
| 617 response->set_sent(clock_->Now().ToInternalValue() / | 617 response->set_sent(clock_->Now().ToInternalValue() / |
| 618 base::Time::kMicrosecondsPerSecond); | 618 base::Time::kMicrosecondsPerSecond); |
| 619 response->set_ttl(0); | 619 response->set_ttl(0); |
| 620 bool send = false; | 620 bool send = false; |
| 621 for (int i = 0; i < data_message->app_data_size(); ++i) { | 621 for (int i = 0; i < data_message->app_data_size(); ++i) { |
| 622 const mcs_proto::AppData& app_data = data_message->app_data(i); | 622 const mcs_proto::AppData& app_data = data_message->app_data(i); |
| 623 if (app_data.key() == kIdleNotification) { | 623 if (app_data.key() == kIdleNotification) { |
| 624 // Tell the MCS server the client is not idle. | 624 // Tell the MCS server the client is not idle. |
| 625 send = true; | 625 send = true; |
| 626 mcs_proto::AppData data; | 626 mcs_proto::AppData data; |
| 627 data.set_key(kIdleNotification); | 627 data.set_key(kIdleNotification); |
| 628 data.set_value("false"); | 628 data.set_value("false"); |
| 629 response->add_app_data()->CopyFrom(data); | 629 response->add_app_data()->CopyFrom(data); |
| 630 response->set_category(kMCSCategory); | 630 response->set_category(kMCSCategory); |
| 631 } | 631 } |
| 632 } | 632 } |
| 633 | 633 |
| 634 if (send) { | 634 if (send) { |
| 635 SendMessage(MCSMessage(kDataMessageStanzaTag, std::move(response))); | 635 SendMessage(MCSMessage(kDataMessageStanzaTag, std::move(response))); |
| 636 } | 636 } |
| 637 } | 637 } |
| 638 | 638 |
| 639 void MCSClient::HandlePacketFromWire( | 639 void MCSClient::HandlePacketFromWire( |
| 640 scoped_ptr<google::protobuf::MessageLite> protobuf) { | 640 std::unique_ptr<google::protobuf::MessageLite> protobuf) { |
| 641 if (!protobuf.get()) | 641 if (!protobuf.get()) |
| 642 return; | 642 return; |
| 643 uint8_t tag = GetMCSProtoTag(*protobuf); | 643 uint8_t tag = GetMCSProtoTag(*protobuf); |
| 644 PersistentId persistent_id = GetPersistentId(*protobuf); | 644 PersistentId persistent_id = GetPersistentId(*protobuf); |
| 645 StreamId last_stream_id_received = GetLastStreamIdReceived(*protobuf); | 645 StreamId last_stream_id_received = GetLastStreamIdReceived(*protobuf); |
| 646 | 646 |
| 647 if (last_stream_id_received != 0) { | 647 if (last_stream_id_received != 0) { |
| 648 last_device_to_server_stream_id_received_ = last_stream_id_received; | 648 last_device_to_server_stream_id_received_ = last_stream_id_received; |
| 649 | 649 |
| 650 // Process device to server messages that have now been acknowledged by the | 650 // Process device to server messages that have now been acknowledged by the |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 963 reinterpret_cast<mcs_proto::DataMessageStanza*>(packet->protobuf.get()); | 963 reinterpret_cast<mcs_proto::DataMessageStanza*>(packet->protobuf.get()); |
| 964 CollapseKey collapse_key(*data_message); | 964 CollapseKey collapse_key(*data_message); |
| 965 if (collapse_key.IsValid()) | 965 if (collapse_key.IsValid()) |
| 966 collapse_key_map_.erase(collapse_key); | 966 collapse_key_map_.erase(collapse_key); |
| 967 } | 967 } |
| 968 | 968 |
| 969 return packet; | 969 return packet; |
| 970 } | 970 } |
| 971 | 971 |
| 972 } // namespace gcm | 972 } // namespace gcm |
| OLD | NEW |