Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / google_apis / gcm / engine / mcs_client.h
blob8d35fd480a17da211703cd2f19fdaffed28abdc5
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
3 // found in the LICENSE file.
5 #ifndef GOOGLE_APIS_GCM_ENGINE_MCS_CLIENT_H_
6 #define GOOGLE_APIS_GCM_ENGINE_MCS_CLIENT_H_
8 #include <deque>
9 #include <map>
10 #include <string>
11 #include <vector>
13 #include "base/files/file_path.h"
14 #include "base/memory/linked_ptr.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/weak_ptr.h"
17 #include "google_apis/gcm/base/gcm_export.h"
18 #include "google_apis/gcm/base/mcs_message.h"
19 #include "google_apis/gcm/engine/connection_factory.h"
20 #include "google_apis/gcm/engine/connection_handler.h"
21 #include "google_apis/gcm/engine/gcm_store.h"
22 #include "google_apis/gcm/engine/heartbeat_manager.h"
24 namespace base {
25 class Clock;
26 class Timer;
27 } // namespace base
29 namespace google {
30 namespace protobuf {
31 class MessageLite;
32 } // namespace protobuf
33 } // namespace google
35 namespace mcs_proto {
36 class LoginRequest;
39 namespace gcm {
41 class CollapseKey;
42 class ConnectionFactory;
43 class GCMStatsRecorder;
44 struct ReliablePacketInfo;
46 // An MCS client. This client is in charge of all communications with an
47 // MCS endpoint, and is capable of reliably sending/receiving GCM messages.
48 // NOTE: Not thread safe. This class should live on the same thread as that
49 // network requests are performed on.
50 class GCM_EXPORT MCSClient {
51 public:
52 // Any change made to this enum should have corresponding change in the
53 // GetStateString(...) function.
54 enum State {
55 UNINITIALIZED, // Uninitialized.
56 LOADED, // GCM Load finished, waiting to connect.
57 CONNECTING, // Connection in progress.
58 CONNECTED, // Connected and running.
61 // Any change made to this enum should have corresponding change in the
62 // GetMessageSendStatusString(...) function in mcs_client.cc.
63 enum MessageSendStatus {
64 // Message was queued succcessfully.
65 QUEUED,
66 // Message was sent to the server and the ACK was received.
67 SENT,
68 // Message not saved, because total queue size limit reached.
69 QUEUE_SIZE_LIMIT_REACHED,
70 // Message not saved, because app queue size limit reached.
71 APP_QUEUE_SIZE_LIMIT_REACHED,
72 // Message too large to send.
73 MESSAGE_TOO_LARGE,
74 // Message not send becuase of TTL = 0 and no working connection.
75 NO_CONNECTION_ON_ZERO_TTL,
76 // Message exceeded TTL.
77 TTL_EXCEEDED,
79 // NOTE: always keep this entry at the end. Add new status types only
80 // immediately above this line. Make sure to update the corresponding
81 // histogram enum accordingly.
82 SEND_STATUS_COUNT
85 // Callback for MCSClient's error conditions.
86 // TODO(fgorski): Keeping it as a callback with intention to add meaningful
87 // error information.
88 typedef base::Callback<void()> ErrorCallback;
89 // Callback when a message is received.
90 typedef base::Callback<void(const MCSMessage& message)>
91 OnMessageReceivedCallback;
92 // Callback when a message is sent (and receipt has been acknowledged by
93 // the MCS endpoint).
94 typedef base::Callback<
95 void(int64 user_serial_number,
96 const std::string& app_id,
97 const std::string& message_id,
98 MessageSendStatus status)> OnMessageSentCallback;
100 MCSClient(const std::string& version_string,
101 base::Clock* clock,
102 ConnectionFactory* connection_factory,
103 GCMStore* gcm_store,
104 GCMStatsRecorder* recorder);
105 virtual ~MCSClient();
107 // Initialize the client. Will load any previous id/token information as well
108 // as unacknowledged message information from the GCM storage, if it exists,
109 // passing the id/token information back via |initialization_callback| along
110 // with a |success == true| result. If no GCM information is present (and
111 // this is therefore a fresh client), a clean GCM store will be created and
112 // values of 0 will be returned via |initialization_callback| with
113 // |success == true|.
114 // If an error loading the GCM store is encountered,
115 // |initialization_callback| will be invoked with |success == false|.
116 void Initialize(const ErrorCallback& initialization_callback,
117 const OnMessageReceivedCallback& message_received_callback,
118 const OnMessageSentCallback& message_sent_callback,
119 scoped_ptr<GCMStore::LoadResult> load_result);
121 // Logs the client into the server. Client must be initialized.
122 // |android_id| and |security_token| are optional if this is not a new
123 // client, else they must be non-zero.
124 // Successful login will result in |message_received_callback| being invoked
125 // with a valid LoginResponse.
126 // Login failure (typically invalid id/token) will shut down the client, and
127 // |initialization_callback| to be invoked with |success = false|.
128 virtual void Login(uint64 android_id, uint64 security_token);
130 // Sends a message, with or without reliable message queueing (RMQ) support.
131 // Will asynchronously invoke the OnMessageSent callback regardless.
132 // Whether to use RMQ depends on whether the protobuf has |ttl| set or not.
133 // |ttl == 0| denotes the message should only be sent if the connection is
134 // open. |ttl > 0| will keep the message saved for |ttl| seconds, after which
135 // it will be dropped if it was unable to be sent. When a message is dropped,
136 // |message_sent_callback_| is invoked with a TTL expiration error.
137 virtual void SendMessage(const MCSMessage& message);
139 // Returns the current state of the client.
140 State state() const { return state_; }
142 // Returns the size of the send message queue.
143 int GetSendQueueSize() const;
145 // Returns the size of the resend messaage queue.
146 int GetResendQueueSize() const;
148 // Returns text representation of the state enum.
149 std::string GetStateString() const;
151 // Updates the timer used by |heartbeat_manager_| for sending heartbeats.
152 void UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer);
154 // Allows a caller to set a heartbeat interval (in milliseconds) with which
155 // the MCS connection will be monitored on both ends, to detect device
156 // presence. In case the newly set interval is less then the current one,
157 // connection will be restarted with new heartbeat interval. Valid values have
158 // to be between GetMax/GetMinClientHeartbeatIntervalMs of HeartbeatManager,
159 // otherwise the setting won't take effect.
160 void AddHeartbeatInterval(const std::string& scope, int interval_ms);
161 void RemoveHeartbeatInterval(const std::string& scope);
163 HeartbeatManager* GetHeartbeatManagerForTesting() {
164 return &heartbeat_manager_;
167 private:
168 typedef uint32 StreamId;
169 typedef std::string PersistentId;
170 typedef std::vector<StreamId> StreamIdList;
171 typedef std::vector<PersistentId> PersistentIdList;
172 typedef std::map<StreamId, PersistentId> StreamIdToPersistentIdMap;
173 typedef linked_ptr<ReliablePacketInfo> MCSPacketInternal;
175 // Resets the internal state and builds a new login request, acknowledging
176 // any pending server-to-device messages and rebuilding the send queue
177 // from all unacknowledged device-to-server messages.
178 // Should only be called when the connection has been reset.
179 void ResetStateAndBuildLoginRequest(mcs_proto::LoginRequest* request);
181 // Send a heartbeat to the MCS server.
182 void SendHeartbeat();
184 // GCM Store callback.
185 void OnGCMUpdateFinished(bool success);
187 // Attempt to send a message.
188 void MaybeSendMessage();
190 // Helper for sending a protobuf along with any unacknowledged ids to the
191 // wire.
192 void SendPacketToWire(ReliablePacketInfo* packet_info);
194 // Handle a data message sent to the MCS client system from the MCS server.
195 void HandleMCSDataMesssage(
196 scoped_ptr<google::protobuf::MessageLite> protobuf);
198 // Handle a packet received over the wire.
199 void HandlePacketFromWire(scoped_ptr<google::protobuf::MessageLite> protobuf);
201 // ReliableMessageQueue acknowledgment helpers.
202 // Handle a StreamAck sent by the server confirming receipt of all
203 // messages up to the message with stream id |last_stream_id_received|.
204 void HandleStreamAck(StreamId last_stream_id_received_);
205 // Handle a SelectiveAck sent by the server confirming all messages
206 // in |id_list|.
207 void HandleSelectiveAck(const PersistentIdList& id_list);
208 // Handle server confirmation of a device message, including device's
209 // acknowledgment of receipt of messages.
210 void HandleServerConfirmedReceipt(StreamId device_stream_id);
212 // Generates a new persistent id for messages.
213 // Virtual for testing.
214 virtual PersistentId GetNextPersistentId();
216 // Helper for the heartbeat manager to signal a connection reset.
217 void OnConnectionResetByHeartbeat(
218 ConnectionFactory::ConnectionResetReason reason);
220 // Runs the message_sent_callback_ with send |status| of the |protobuf|.
221 void NotifyMessageSendStatus(const google::protobuf::MessageLite& protobuf,
222 MessageSendStatus status);
224 // Pops the next message from the front of the send queue (cleaning up
225 // any associated state).
226 MCSPacketInternal PopMessageForSend();
228 // Gets the minimum interval from the map of scopes to intervals in
229 // milliseconds.
230 int GetMinHeartbeatIntervalMs();
232 // Local version string. Sent on login.
233 const std::string version_string_;
235 // Clock for enforcing TTL. Passed in for testing.
236 base::Clock* const clock_;
238 // Client state.
239 State state_;
241 // Callbacks for owner.
242 ErrorCallback mcs_error_callback_;
243 OnMessageReceivedCallback message_received_callback_;
244 OnMessageSentCallback message_sent_callback_;
246 // The android id and security token in use by this device.
247 uint64 android_id_;
248 uint64 security_token_;
250 // Factory for creating new connections and connection handlers.
251 ConnectionFactory* connection_factory_;
253 // Connection handler to handle all over-the-wire protocol communication
254 // with the mobile connection server.
255 ConnectionHandler* connection_handler_;
257 // ----- Reliablie Message Queue section -----
258 // Note: all queues/maps are ordered from oldest (front/begin) message to
259 // most recent (back/end).
261 // Send/acknowledge queues.
262 std::deque<MCSPacketInternal> to_send_;
263 std::deque<MCSPacketInternal> to_resend_;
265 // Map of collapse keys to their pending messages.
266 std::map<CollapseKey, ReliablePacketInfo*> collapse_key_map_;
268 // Last device_to_server stream id acknowledged by the server.
269 StreamId last_device_to_server_stream_id_received_;
270 // Last server_to_device stream id acknowledged by this device.
271 StreamId last_server_to_device_stream_id_received_;
272 // The stream id for the last sent message. A new message should consume
273 // stream_id_out_ + 1.
274 StreamId stream_id_out_;
275 // The stream id of the last received message. The LoginResponse will always
276 // have a stream id of 1, and stream ids increment by 1 for each received
277 // message.
278 StreamId stream_id_in_;
280 // The server messages that have not been acked by the device yet. Keyed by
281 // server stream id.
282 StreamIdToPersistentIdMap unacked_server_ids_;
284 // Those server messages that have been acked. They must remain tracked
285 // until the ack message is itself confirmed. The list of all message ids
286 // acknowledged are keyed off the device stream id of the message that
287 // acknowledged them.
288 std::map<StreamId, PersistentIdList> acked_server_ids_;
290 // Those server messages from a previous connection that were not fully
291 // acknowledged. They do not have associated stream ids, and will be
292 // acknowledged on the next login attempt.
293 PersistentIdList restored_unackeds_server_ids_;
295 // The GCM persistent store. Not owned.
296 GCMStore* gcm_store_;
298 // Manager to handle triggering/detecting heartbeats.
299 HeartbeatManager heartbeat_manager_;
301 // Custom heartbeat intervals requested by different components.
302 std::map<std::string, int> custom_heartbeat_intervals_;
304 // Recorder that records GCM activities for debugging purpose. Not owned.
305 GCMStatsRecorder* recorder_;
307 base::WeakPtrFactory<MCSClient> weak_ptr_factory_;
309 DISALLOW_COPY_AND_ASSIGN(MCSClient);
312 } // namespace gcm
314 #endif // GOOGLE_APIS_GCM_ENGINE_MCS_CLIENT_H_