| 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 <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| 11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
| 12 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
| 13 #include "base/strings/stringprintf.h" |
| 13 #include "base/time/clock.h" | 14 #include "base/time/clock.h" |
| 14 #include "base/time/time.h" | 15 #include "base/time/time.h" |
| 15 #include "google_apis/gcm/base/mcs_util.h" | 16 #include "google_apis/gcm/base/mcs_util.h" |
| 16 #include "google_apis/gcm/base/socket_stream.h" | 17 #include "google_apis/gcm/base/socket_stream.h" |
| 17 #include "google_apis/gcm/engine/connection_factory.h" | 18 #include "google_apis/gcm/engine/connection_factory.h" |
| 18 | 19 |
| 19 using namespace google::protobuf::io; | 20 using namespace google::protobuf::io; |
| 20 | 21 |
| 21 namespace gcm { | 22 namespace gcm { |
| 22 | 23 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 return false; | 57 return false; |
| 57 std::vector<std::string> new_list; | 58 std::vector<std::string> new_list; |
| 58 for (int i = 0; i < selective_ack.id_size(); ++i) { | 59 for (int i = 0; i < selective_ack.id_size(); ++i) { |
| 59 DCHECK(!selective_ack.id(i).empty()); | 60 DCHECK(!selective_ack.id(i).empty()); |
| 60 new_list.push_back(selective_ack.id(i)); | 61 new_list.push_back(selective_ack.id(i)); |
| 61 } | 62 } |
| 62 id_list->swap(new_list); | 63 id_list->swap(new_list); |
| 63 return true; | 64 return true; |
| 64 } | 65 } |
| 65 | 66 |
| 67 // Helper for getting string representation of the MessageSendStatus enum. |
| 68 std::string GetMessageSendStatusString( |
| 69 gcm::MCSClient::MessageSendStatus status) { |
| 70 switch (status) { |
| 71 case gcm::MCSClient::QUEUED: |
| 72 return "QUEUED"; |
| 73 case gcm::MCSClient::SENT: |
| 74 return "SENT"; |
| 75 case gcm::MCSClient::QUEUE_SIZE_LIMIT_REACHED: |
| 76 return "QUEUE_SIZE_LIMIT_REACHED"; |
| 77 case gcm::MCSClient::APP_QUEUE_SIZE_LIMIT_REACHED: |
| 78 return "APP_QUEUE_SIZE_LIMIT_REACHED"; |
| 79 case gcm::MCSClient::MESSAGE_TOO_LARGE: |
| 80 return "MESSAGE_TOO_LARGE"; |
| 81 case gcm::MCSClient::NO_CONNECTION_ON_ZERO_TTL: |
| 82 return "NO_CONNECTION_ON_ZERO_TTL"; |
| 83 case gcm::MCSClient::TTL_EXCEEDED: |
| 84 return "TTL_EXCEEDED"; |
| 85 default: |
| 86 NOTREACHED(); |
| 87 return "UNKNOWN"; |
| 88 } |
| 89 } |
| 90 |
| 66 } // namespace | 91 } // namespace |
| 67 | 92 |
| 68 class CollapseKey { | 93 class CollapseKey { |
| 69 public: | 94 public: |
| 70 explicit CollapseKey(const mcs_proto::DataMessageStanza& message); | 95 explicit CollapseKey(const mcs_proto::DataMessageStanza& message); |
| 71 ~CollapseKey(); | 96 ~CollapseKey(); |
| 72 | 97 |
| 73 // Comparison operator for use in maps. | 98 // Comparison operator for use in maps. |
| 74 bool operator<(const CollapseKey& right) const; | 99 bool operator<(const CollapseKey& right) const; |
| 75 | 100 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 | 146 |
| 122 // The protobuf of the message itself. | 147 // The protobuf of the message itself. |
| 123 MCSProto protobuf; | 148 MCSProto protobuf; |
| 124 }; | 149 }; |
| 125 | 150 |
| 126 ReliablePacketInfo::ReliablePacketInfo() | 151 ReliablePacketInfo::ReliablePacketInfo() |
| 127 : stream_id(0), tag(0) { | 152 : stream_id(0), tag(0) { |
| 128 } | 153 } |
| 129 ReliablePacketInfo::~ReliablePacketInfo() {} | 154 ReliablePacketInfo::~ReliablePacketInfo() {} |
| 130 | 155 |
| 156 int MCSClient::GetSendQueueSize() const { |
| 157 return to_send_.size(); |
| 158 } |
| 159 |
| 160 int MCSClient::GetUnackedQueueSize() const { |
| 161 return to_resend_.size(); |
| 162 } |
| 163 |
| 131 std::string MCSClient::GetStateString() const { | 164 std::string MCSClient::GetStateString() const { |
| 132 switch(state_) { | 165 switch(state_) { |
| 133 case UNINITIALIZED: | 166 case UNINITIALIZED: |
| 134 return "UNINITIALIZED"; | 167 return "UNINITIALIZED"; |
| 135 case LOADED: | 168 case LOADED: |
| 136 return "LOADED"; | 169 return "LOADED"; |
| 137 case CONNECTING: | 170 case CONNECTING: |
| 138 return "CONNECTING"; | 171 return "CONNECTING"; |
| 139 case CONNECTED: | 172 case CONNECTED: |
| 140 return "CONNECTED"; | 173 return "CONNECTED"; |
| 141 default: | 174 default: |
| 142 NOTREACHED(); | 175 NOTREACHED(); |
| 143 return std::string(); | 176 return std::string(); |
| 144 } | 177 } |
| 145 } | 178 } |
| 146 | 179 |
| 147 MCSClient::MCSClient(const std::string& version_string, | 180 MCSClient::MCSClient(const std::string& version_string, |
| 148 base::Clock* clock, | 181 base::Clock* clock, |
| 149 ConnectionFactory* connection_factory, | 182 ConnectionFactory* connection_factory, |
| 150 GCMStore* gcm_store) | 183 GCMStore* gcm_store, |
| 184 GCMStatsRecorder* recorder) |
| 151 : version_string_(version_string), | 185 : version_string_(version_string), |
| 152 clock_(clock), | 186 clock_(clock), |
| 153 state_(UNINITIALIZED), | 187 state_(UNINITIALIZED), |
| 154 android_id_(0), | 188 android_id_(0), |
| 155 security_token_(0), | 189 security_token_(0), |
| 156 connection_factory_(connection_factory), | 190 connection_factory_(connection_factory), |
| 157 connection_handler_(NULL), | 191 connection_handler_(NULL), |
| 158 last_device_to_server_stream_id_received_(0), | 192 last_device_to_server_stream_id_received_(0), |
| 159 last_server_to_device_stream_id_received_(0), | 193 last_server_to_device_stream_id_received_(0), |
| 160 stream_id_out_(0), | 194 stream_id_out_(0), |
| 161 stream_id_in_(0), | 195 stream_id_in_(0), |
| 162 gcm_store_(gcm_store), | 196 gcm_store_(gcm_store), |
| 197 recorder_(recorder), |
| 163 weak_ptr_factory_(this) { | 198 weak_ptr_factory_(this) { |
| 164 } | 199 } |
| 165 | 200 |
| 166 MCSClient::~MCSClient() { | 201 MCSClient::~MCSClient() { |
| 167 } | 202 } |
| 168 | 203 |
| 169 void MCSClient::Initialize( | 204 void MCSClient::Initialize( |
| 170 const ErrorCallback& error_callback, | 205 const ErrorCallback& error_callback, |
| 171 const OnMessageReceivedCallback& message_received_callback, | 206 const OnMessageReceivedCallback& message_received_callback, |
| 172 const OnMessageSentCallback& message_sent_callback, | 207 const OnMessageSentCallback& message_sent_callback, |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 if (packet_info->tag == kDataMessageStanzaTag) { | 523 if (packet_info->tag == kDataMessageStanzaTag) { |
| 489 mcs_proto::DataMessageStanza* data_message = | 524 mcs_proto::DataMessageStanza* data_message = |
| 490 reinterpret_cast<mcs_proto::DataMessageStanza*>( | 525 reinterpret_cast<mcs_proto::DataMessageStanza*>( |
| 491 packet_info->protobuf.get()); | 526 packet_info->protobuf.get()); |
| 492 uint64 sent = data_message->sent(); | 527 uint64 sent = data_message->sent(); |
| 493 DCHECK_GT(sent, 0U); | 528 DCHECK_GT(sent, 0U); |
| 494 int queued = (clock_->Now().ToInternalValue() / | 529 int queued = (clock_->Now().ToInternalValue() / |
| 495 base::Time::kMicrosecondsPerSecond) - sent; | 530 base::Time::kMicrosecondsPerSecond) - sent; |
| 496 DVLOG(1) << "Message was queued for " << queued << " seconds."; | 531 DVLOG(1) << "Message was queued for " << queued << " seconds."; |
| 497 data_message->set_queued(queued); | 532 data_message->set_queued(queued); |
| 533 recorder_->RecordSending( |
| 534 data_message->category(), |
| 535 data_message->to(), |
| 536 data_message->id(), |
| 537 "Sent to wire", |
| 538 base::StringPrintf("Msg queued for %d seconds", queued)); |
| 498 } | 539 } |
| 499 | 540 |
| 500 // Set the proper last received stream id to acknowledge received server | 541 // Set the proper last received stream id to acknowledge received server |
| 501 // packets. | 542 // packets. |
| 502 DVLOG(1) << "Setting last stream id received to " | 543 DVLOG(1) << "Setting last stream id received to " |
| 503 << stream_id_in_; | 544 << stream_id_in_; |
| 504 SetLastStreamIdReceived(stream_id_in_, | 545 SetLastStreamIdReceived(stream_id_in_, |
| 505 packet_info->protobuf.get()); | 546 packet_info->protobuf.get()); |
| 506 if (stream_id_in_ != last_server_to_device_stream_id_received_) { | 547 if (stream_id_in_ != last_server_to_device_stream_id_received_) { |
| 507 last_server_to_device_stream_id_received_ = stream_id_in_; | 548 last_server_to_device_stream_id_received_ = stream_id_in_; |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 855 } | 896 } |
| 856 | 897 |
| 857 void MCSClient::NotifyMessageSendStatus( | 898 void MCSClient::NotifyMessageSendStatus( |
| 858 const google::protobuf::MessageLite& protobuf, | 899 const google::protobuf::MessageLite& protobuf, |
| 859 MessageSendStatus status) { | 900 MessageSendStatus status) { |
| 860 if (GetMCSProtoTag(protobuf) != kDataMessageStanzaTag) | 901 if (GetMCSProtoTag(protobuf) != kDataMessageStanzaTag) |
| 861 return; | 902 return; |
| 862 | 903 |
| 863 const mcs_proto::DataMessageStanza* data_message_stanza = | 904 const mcs_proto::DataMessageStanza* data_message_stanza = |
| 864 reinterpret_cast<const mcs_proto::DataMessageStanza*>(&protobuf); | 905 reinterpret_cast<const mcs_proto::DataMessageStanza*>(&protobuf); |
| 906 recorder_->RecordSendingWithUMAEnum( |
| 907 data_message_stanza->category(), |
| 908 data_message_stanza->to(), |
| 909 data_message_stanza->id(), |
| 910 base::StringPrintf("SEND status: %s", |
| 911 GetMessageSendStatusString(status).c_str()), |
| 912 base::StringPrintf("Msg size: %d bytes, TTL: %d", protobuf.ByteSize(), |
| 913 data_message_stanza->ttl()), |
| 914 "GCM.SendMessageStatus", |
| 915 status, |
| 916 gcm::MCSClient::SEND_STATUS_COUNT); |
| 865 message_sent_callback_.Run( | 917 message_sent_callback_.Run( |
| 866 data_message_stanza->device_user_id(), | 918 data_message_stanza->device_user_id(), |
| 867 data_message_stanza->category(), | 919 data_message_stanza->category(), |
| 868 data_message_stanza->id(), | 920 data_message_stanza->id(), |
| 869 status); | 921 status); |
| 870 } | 922 } |
| 871 | 923 |
| 872 void MCSClient::SetGCMStoreForTesting(GCMStore* gcm_store) { | 924 void MCSClient::SetGCMStoreForTesting(GCMStore* gcm_store) { |
| 873 gcm_store_ = gcm_store; | 925 gcm_store_ = gcm_store; |
| 874 } | 926 } |
| 875 | 927 |
| 876 MCSClient::MCSPacketInternal MCSClient::PopMessageForSend() { | 928 MCSClient::MCSPacketInternal MCSClient::PopMessageForSend() { |
| 877 MCSPacketInternal packet = to_send_.front(); | 929 MCSPacketInternal packet = to_send_.front(); |
| 878 to_send_.pop_front(); | 930 to_send_.pop_front(); |
| 879 | 931 |
| 880 if (packet->tag == kDataMessageStanzaTag) { | 932 if (packet->tag == kDataMessageStanzaTag) { |
| 881 mcs_proto::DataMessageStanza* data_message = | 933 mcs_proto::DataMessageStanza* data_message = |
| 882 reinterpret_cast<mcs_proto::DataMessageStanza*>(packet->protobuf.get()); | 934 reinterpret_cast<mcs_proto::DataMessageStanza*>(packet->protobuf.get()); |
| 883 CollapseKey collapse_key(*data_message); | 935 CollapseKey collapse_key(*data_message); |
| 884 if (collapse_key.IsValid()) | 936 if (collapse_key.IsValid()) |
| 885 collapse_key_map_.erase(collapse_key); | 937 collapse_key_map_.erase(collapse_key); |
| 886 } | 938 } |
| 887 | 939 |
| 888 return packet; | 940 return packet; |
| 889 } | 941 } |
| 890 | 942 |
| 891 } // namespace gcm | 943 } // namespace gcm |
| OLD | NEW |