Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / google_apis / gcm / engine / mcs_client.h
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.
4
5 #ifndef GOOGLE_APIS_GCM_ENGINE_MCS_CLIENT_H_
6 #define GOOGLE_APIS_GCM_ENGINE_MCS_CLIENT_H_
7
8 #include <deque>
9 #include <map>
10 #include <string>
11 #include <vector>
12
13 #include "base/files/file_path.h"
14 #include "base/memory/linked_ptr.h"
15 #include "base/memory/weak_ptr.h"
16 #include "google_apis/gcm/base/gcm_export.h"
17 #include "google_apis/gcm/base/mcs_message.h"
18 #include "google_apis/gcm/engine/connection_handler.h"
19 #include "google_apis/gcm/engine/gcm_store.h"
20 #include "google_apis/gcm/engine/heartbeat_manager.h"
21
22 namespace base {
23 class Clock;
24 }  // namespace base
25
26 namespace google {
27 namespace protobuf {
28 class MessageLite;
29 }  // namespace protobuf
30 }  // namespace google
31
32 namespace mcs_proto {
33 class LoginRequest;
34 }
35
36 namespace gcm {
37
38 class CollapseKey;
39 class ConnectionFactory;
40 struct ReliablePacketInfo;
41
42 // An MCS client. This client is in charge of all communications with an
43 // MCS endpoint, and is capable of reliably sending/receiving GCM messages.
44 // NOTE: Not thread safe. This class should live on the same thread as that
45 // network requests are performed on.
46 class GCM_EXPORT MCSClient {
47  public:
48   enum State {
49     UNINITIALIZED,  // Uninitialized.
50     LOADED,         // GCM Load finished, waiting to connect.
51     CONNECTING,     // Connection in progress.
52     CONNECTED,      // Connected and running.
53   };
54
55   enum MessageSendStatus {
56     // Message was queued succcessfully.
57     QUEUED,
58     // Message was sent to the server and the ACK was received.
59     SENT,
60     // Message not saved, because total queue size limit reached.
61     QUEUE_SIZE_LIMIT_REACHED,
62     // Messgae not saved, because app queue size limit reached.
63     APP_QUEUE_SIZE_LIMIT_REACHED,
64     // Message too large to send.
65     MESSAGE_TOO_LARGE,
66     // Message not send becuase of TTL = 0 and no working connection.
67     NO_CONNECTION_ON_ZERO_TTL,
68     // Message exceeded TTL.
69     TTL_EXCEEDED
70   };
71
72   // Callback for MCSClient's error conditions.
73   // TODO(fgorski): Keeping it as a callback with intention to add meaningful
74   // error information.
75   typedef base::Callback<void()> ErrorCallback;
76   // Callback when a message is received.
77   typedef base::Callback<void(const MCSMessage& message)>
78       OnMessageReceivedCallback;
79   // Callback when a message is sent (and receipt has been acknowledged by
80   // the MCS endpoint).
81   typedef base::Callback<
82       void(int64 user_serial_number,
83            const std::string& app_id,
84            const std::string& message_id,
85            MessageSendStatus status)> OnMessageSentCallback;
86
87   MCSClient(const std::string& version_string,
88             base::Clock* clock,
89             ConnectionFactory* connection_factory,
90             GCMStore* gcm_store);
91   virtual ~MCSClient();
92
93   // Initialize the client. Will load any previous id/token information as well
94   // as unacknowledged message information from the GCM storage, if it exists,
95   // passing the id/token information back via |initialization_callback| along
96   // with a |success == true| result. If no GCM information is present (and
97   // this is therefore a fresh client), a clean GCM store will be created and
98   // values of 0 will be returned via |initialization_callback| with
99   // |success == true|.
100   /// If an error loading the GCM store is encountered,
101   // |initialization_callback| will be invoked with |success == false|.
102   void Initialize(const ErrorCallback& initialization_callback,
103                   const OnMessageReceivedCallback& message_received_callback,
104                   const OnMessageSentCallback& message_sent_callback,
105                   scoped_ptr<GCMStore::LoadResult> load_result);
106
107   // Logs the client into the server. Client must be initialized.
108   // |android_id| and |security_token| are optional if this is not a new
109   // client, else they must be non-zero.
110   // Successful login will result in |message_received_callback| being invoked
111   // with a valid LoginResponse.
112   // Login failure (typically invalid id/token) will shut down the client, and
113   // |initialization_callback| to be invoked with |success = false|.
114   virtual void Login(uint64 android_id, uint64 security_token);
115
116   // Sends a message, with or without reliable message queueing (RMQ) support.
117   // Will asynchronously invoke the OnMessageSent callback regardless.
118   // Whether to use RMQ depends on whether the protobuf has |ttl| set or not.
119   // |ttl == 0| denotes the message should only be sent if the connection is
120   // open. |ttl > 0| will keep the message saved for |ttl| seconds, after which
121   // it will be dropped if it was unable to be sent. When a message is dropped,
122   // |message_sent_callback_| is invoked with a TTL expiration error.
123   virtual void SendMessage(const MCSMessage& message);
124
125   // Disconnects the client and permanently destroys the persistent GCM store.
126   // WARNING: This is permanent, and the client must be recreated with new
127   // credentials afterwards.
128   // TODO(jianli): destroying the persistent GCM store should be moved to
129   // GCMClient.
130   void Destroy();
131
132   // Returns the current state of the client.
133   State state() const { return state_; }
134
135  protected:
136   // Sets a |gcm_store| for testing. Does not take ownership.
137   // TODO(fgorski): Remove this method. Create GCMEngineFactory that will create
138   // components of the engine.
139   void SetGCMStoreForTesting(GCMStore* gcm_store);
140
141  private:
142   typedef uint32 StreamId;
143   typedef std::string PersistentId;
144   typedef std::vector<StreamId> StreamIdList;
145   typedef std::vector<PersistentId> PersistentIdList;
146   typedef std::map<StreamId, PersistentId> StreamIdToPersistentIdMap;
147   typedef linked_ptr<ReliablePacketInfo> MCSPacketInternal;
148
149   // Resets the internal state and builds a new login request, acknowledging
150   // any pending server-to-device messages and rebuilding the send queue
151   // from all unacknowledged device-to-server messages.
152   // Should only be called when the connection has been reset.
153   void ResetStateAndBuildLoginRequest(mcs_proto::LoginRequest* request);
154
155   // Send a heartbeat to the MCS server.
156   void SendHeartbeat();
157
158   // GCM Store callback.
159   void OnGCMUpdateFinished(bool success);
160
161   // Attempt to send a message.
162   void MaybeSendMessage();
163
164   // Helper for sending a protobuf along with any unacknowledged ids to the
165   // wire.
166   void SendPacketToWire(ReliablePacketInfo* packet_info);
167
168   // Handle a data message sent to the MCS client system from the MCS server.
169   void HandleMCSDataMesssage(
170       scoped_ptr<google::protobuf::MessageLite> protobuf);
171
172   // Handle a packet received over the wire.
173   void HandlePacketFromWire(scoped_ptr<google::protobuf::MessageLite> protobuf);
174
175   // ReliableMessageQueue acknowledgment helpers.
176   // Handle a StreamAck sent by the server confirming receipt of all
177   // messages up to the message with stream id |last_stream_id_received|.
178   void HandleStreamAck(StreamId last_stream_id_received_);
179   // Handle a SelectiveAck sent by the server confirming all messages
180   // in |id_list|.
181   void HandleSelectiveAck(const PersistentIdList& id_list);
182   // Handle server confirmation of a device message, including device's
183   // acknowledgment of receipt of messages.
184   void HandleServerConfirmedReceipt(StreamId device_stream_id);
185
186   // Generates a new persistent id for messages.
187   // Virtual for testing.
188   virtual PersistentId GetNextPersistentId();
189
190   // Helper for the heartbeat manager to signal a connection reset.
191   void OnConnectionResetByHeartbeat();
192
193   // Runs the message_sent_callback_ with send |status| of the |protobuf|.
194   void NotifyMessageSendStatus(const google::protobuf::MessageLite& protobuf,
195                                MessageSendStatus status);
196
197   // Pops the next message from the front of the send queue (cleaning up
198   // any associated state).
199   MCSPacketInternal PopMessageForSend();
200
201   // Local version string. Sent on login.
202   const std::string version_string_;
203
204   // Clock for enforcing TTL. Passed in for testing.
205   base::Clock* const clock_;
206
207   // Client state.
208   State state_;
209
210   // Callbacks for owner.
211   ErrorCallback mcs_error_callback_;
212   OnMessageReceivedCallback message_received_callback_;
213   OnMessageSentCallback message_sent_callback_;
214
215   // The android id and security token in use by this device.
216   uint64 android_id_;
217   uint64 security_token_;
218
219   // Factory for creating new connections and connection handlers.
220   ConnectionFactory* connection_factory_;
221
222   // Connection handler to handle all over-the-wire protocol communication
223   // with the mobile connection server.
224   ConnectionHandler* connection_handler_;
225
226   // -----  Reliablie Message Queue section -----
227   // Note: all queues/maps are ordered from oldest (front/begin) message to
228   // most recent (back/end).
229
230   // Send/acknowledge queues.
231   std::deque<MCSPacketInternal> to_send_;
232   std::deque<MCSPacketInternal> to_resend_;
233
234   // Map of collapse keys to their pending messages.
235   std::map<CollapseKey, ReliablePacketInfo*> collapse_key_map_;
236
237   // Last device_to_server stream id acknowledged by the server.
238   StreamId last_device_to_server_stream_id_received_;
239   // Last server_to_device stream id acknowledged by this device.
240   StreamId last_server_to_device_stream_id_received_;
241   // The stream id for the last sent message. A new message should consume
242   // stream_id_out_ + 1.
243   StreamId stream_id_out_;
244   // The stream id of the last received message. The LoginResponse will always
245   // have a stream id of 1, and stream ids increment by 1 for each received
246   // message.
247   StreamId stream_id_in_;
248
249   // The server messages that have not been acked by the device yet. Keyed by
250   // server stream id.
251   StreamIdToPersistentIdMap unacked_server_ids_;
252
253   // Those server messages that have been acked. They must remain tracked
254   // until the ack message is itself confirmed. The list of all message ids
255   // acknowledged are keyed off the device stream id of the message that
256   // acknowledged them.
257   std::map<StreamId, PersistentIdList> acked_server_ids_;
258
259   // Those server messages from a previous connection that were not fully
260   // acknowledged. They do not have associated stream ids, and will be
261   // acknowledged on the next login attempt.
262   PersistentIdList restored_unackeds_server_ids_;
263
264   // The GCM persistent store. Not owned.
265   GCMStore* gcm_store_;
266
267   // Manager to handle triggering/detecting heartbeats.
268   HeartbeatManager heartbeat_manager_;
269
270   base::WeakPtrFactory<MCSClient> weak_ptr_factory_;
271
272   DISALLOW_COPY_AND_ASSIGN(MCSClient);
273 };
274
275 } // namespace gcm
276
277 #endif  // GOOGLE_APIS_GCM_ENGINE_MCS_CLIENT_H_