1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file.
4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#ifndef GOOGLE_APIS_GCM_ENGINE_MCS_CLIENT_H_
6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#define GOOGLE_APIS_GCM_ENGINE_MCS_CLIENT_H_
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <deque>
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <map>
10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <string>
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <vector>
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/files/file_path.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/memory/linked_ptr.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/memory/weak_ptr.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/gcm/base/gcm_export.h"
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/gcm/base/mcs_message.h"
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/gcm/engine/connection_handler.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gcm/engine/gcm_store.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gcm/engine/heartbeat_manager.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace base {
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Clock;
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace base
25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace google {
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace protobuf {
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MessageLite;
29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace protobuf
30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace google
31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace mcs_proto {
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class LoginRequest;
34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace gcm {
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class CollapseKey;
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class ConnectionFactory;
400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochclass GCMStatsRecorder;
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)struct ReliablePacketInfo;
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// An MCS client. This client is in charge of all communications with an
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// MCS endpoint, and is capable of reliably sending/receiving GCM messages.
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// NOTE: Not thread safe. This class should live on the same thread as that
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// network requests are performed on.
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class GCM_EXPORT MCSClient {
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Any change made to this enum should have corresponding change in the
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // GetStateString(...) function.
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  enum State {
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UNINITIALIZED,  // Uninitialized.
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOADED,         // GCM Load finished, waiting to connect.
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CONNECTING,     // Connection in progress.
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CONNECTED,      // Connected and running.
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  };
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Any change made to this enum should have corresponding change in the
590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // GetMessageSendStatusString(...) function in mcs_client.cc.
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  enum MessageSendStatus {
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Message was queued succcessfully.
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    QUEUED,
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Message was sent to the server and the ACK was received.
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SENT,
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Message not saved, because total queue size limit reached.
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    QUEUE_SIZE_LIMIT_REACHED,
670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // Message not saved, because app queue size limit reached.
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    APP_QUEUE_SIZE_LIMIT_REACHED,
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Message too large to send.
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MESSAGE_TOO_LARGE,
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Message not send becuase of TTL = 0 and no working connection.
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    NO_CONNECTION_ON_ZERO_TTL,
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Message exceeded TTL.
740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    TTL_EXCEEDED,
750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // NOTE: always keep this entry at the end. Add new status types only
770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // immediately above this line. Make sure to update the corresponding
780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // histogram enum accordingly.
790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    SEND_STATUS_COUNT
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Callback for MCSClient's error conditions.
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(fgorski): Keeping it as a callback with intention to add meaningful
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // error information.
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  typedef base::Callback<void()> ErrorCallback;
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Callback when a message is received.
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  typedef base::Callback<void(const MCSMessage& message)>
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      OnMessageReceivedCallback;
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Callback when a message is sent (and receipt has been acknowledged by
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // the MCS endpoint).
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  typedef base::Callback<
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      void(int64 user_serial_number,
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           const std::string& app_id,
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           const std::string& message_id,
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           MessageSendStatus status)> OnMessageSentCallback;
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MCSClient(const std::string& version_string,
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            base::Clock* clock,
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            ConnectionFactory* connection_factory,
1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            GCMStore* gcm_store,
1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            GCMStatsRecorder* recorder);
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual ~MCSClient();
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Initialize the client. Will load any previous id/token information as well
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // as unacknowledged message information from the GCM storage, if it exists,
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // passing the id/token information back via |initialization_callback| along
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // with a |success == true| result. If no GCM information is present (and
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // this is therefore a fresh client), a clean GCM store will be created and
109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // values of 0 will be returned via |initialization_callback| with
110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // |success == true|.
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  /// If an error loading the GCM store is encountered,
112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // |initialization_callback| will be invoked with |success == false|.
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Initialize(const ErrorCallback& initialization_callback,
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                  const OnMessageReceivedCallback& message_received_callback,
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  const OnMessageSentCallback& message_sent_callback,
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  scoped_ptr<GCMStore::LoadResult> load_result);
117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Logs the client into the server. Client must be initialized.
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // |android_id| and |security_token| are optional if this is not a new
120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // client, else they must be non-zero.
121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Successful login will result in |message_received_callback| being invoked
122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // with a valid LoginResponse.
123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Login failure (typically invalid id/token) will shut down the client, and
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // |initialization_callback| to be invoked with |success = false|.
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void Login(uint64 android_id, uint64 security_token);
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Sends a message, with or without reliable message queueing (RMQ) support.
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Will asynchronously invoke the OnMessageSent callback regardless.
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Whether to use RMQ depends on whether the protobuf has |ttl| set or not.
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |ttl == 0| denotes the message should only be sent if the connection is
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // open. |ttl > 0| will keep the message saved for |ttl| seconds, after which
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // it will be dropped if it was unable to be sent. When a message is dropped,
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |message_sent_callback_| is invoked with a TTL expiration error.
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void SendMessage(const MCSMessage& message);
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Returns the current state of the client.
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  State state() const { return state_; }
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Returns the size of the send message queue.
1400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  int GetSendQueueSize() const;
1410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Returns the size of the resend messaage queue.
1430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  int GetResendQueueSize() const;
1440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Returns text representation of the state enum.
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string GetStateString() const;
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  typedef uint32 StreamId;
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  typedef std::string PersistentId;
151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  typedef std::vector<StreamId> StreamIdList;
152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  typedef std::vector<PersistentId> PersistentIdList;
153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  typedef std::map<StreamId, PersistentId> StreamIdToPersistentIdMap;
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  typedef linked_ptr<ReliablePacketInfo> MCSPacketInternal;
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Resets the internal state and builds a new login request, acknowledging
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // any pending server-to-device messages and rebuilding the send queue
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // from all unacknowledged device-to-server messages.
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Should only be called when the connection has been reset.
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void ResetStateAndBuildLoginRequest(mcs_proto::LoginRequest* request);
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Send a heartbeat to the MCS server.
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void SendHeartbeat();
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // GCM Store callback.
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void OnGCMUpdateFinished(bool success);
167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Attempt to send a message.
169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void MaybeSendMessage();
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Helper for sending a protobuf along with any unacknowledged ids to the
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // wire.
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void SendPacketToWire(ReliablePacketInfo* packet_info);
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Handle a data message sent to the MCS client system from the MCS server.
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void HandleMCSDataMesssage(
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      scoped_ptr<google::protobuf::MessageLite> protobuf);
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Handle a packet received over the wire.
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void HandlePacketFromWire(scoped_ptr<google::protobuf::MessageLite> protobuf);
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // ReliableMessageQueue acknowledgment helpers.
183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Handle a StreamAck sent by the server confirming receipt of all
184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // messages up to the message with stream id |last_stream_id_received|.
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void HandleStreamAck(StreamId last_stream_id_received_);
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Handle a SelectiveAck sent by the server confirming all messages
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // in |id_list|.
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void HandleSelectiveAck(const PersistentIdList& id_list);
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Handle server confirmation of a device message, including device's
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // acknowledgment of receipt of messages.
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void HandleServerConfirmedReceipt(StreamId device_stream_id);
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Generates a new persistent id for messages.
194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Virtual for testing.
195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual PersistentId GetNextPersistentId();
196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Helper for the heartbeat manager to signal a connection reset.
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void OnConnectionResetByHeartbeat();
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Runs the message_sent_callback_ with send |status| of the |protobuf|.
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void NotifyMessageSendStatus(const google::protobuf::MessageLite& protobuf,
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               MessageSendStatus status);
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Pops the next message from the front of the send queue (cleaning up
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // any associated state).
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MCSPacketInternal PopMessageForSend();
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Local version string. Sent on login.
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const std::string version_string_;
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Clock for enforcing TTL. Passed in for testing.
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::Clock* const clock_;
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Client state.
215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  State state_;
216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Callbacks for owner.
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ErrorCallback mcs_error_callback_;
219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  OnMessageReceivedCallback message_received_callback_;
220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  OnMessageSentCallback message_sent_callback_;
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // The android id and security token in use by this device.
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  uint64 android_id_;
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  uint64 security_token_;
225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Factory for creating new connections and connection handlers.
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ConnectionFactory* connection_factory_;
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Connection handler to handle all over-the-wire protocol communication
230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // with the mobile connection server.
231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ConnectionHandler* connection_handler_;
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // -----  Reliablie Message Queue section -----
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Note: all queues/maps are ordered from oldest (front/begin) message to
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // most recent (back/end).
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Send/acknowledge queues.
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::deque<MCSPacketInternal> to_send_;
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::deque<MCSPacketInternal> to_resend_;
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Map of collapse keys to their pending messages.
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::map<CollapseKey, ReliablePacketInfo*> collapse_key_map_;
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Last device_to_server stream id acknowledged by the server.
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  StreamId last_device_to_server_stream_id_received_;
246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Last server_to_device stream id acknowledged by this device.
247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  StreamId last_server_to_device_stream_id_received_;
248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // The stream id for the last sent message. A new message should consume
249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // stream_id_out_ + 1.
250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  StreamId stream_id_out_;
251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // The stream id of the last received message. The LoginResponse will always
252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // have a stream id of 1, and stream ids increment by 1 for each received
253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // message.
254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  StreamId stream_id_in_;
255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // The server messages that have not been acked by the device yet. Keyed by
257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // server stream id.
258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  StreamIdToPersistentIdMap unacked_server_ids_;
259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Those server messages that have been acked. They must remain tracked
261a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // until the ack message is itself confirmed. The list of all message ids
262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // acknowledged are keyed off the device stream id of the message that
263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // acknowledged them.
264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::map<StreamId, PersistentIdList> acked_server_ids_;
265a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Those server messages from a previous connection that were not fully
267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // acknowledged. They do not have associated stream ids, and will be
268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // acknowledged on the next login attempt.
269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  PersistentIdList restored_unackeds_server_ids_;
270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The GCM persistent store. Not owned.
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GCMStore* gcm_store_;
273a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Manager to handle triggering/detecting heartbeats.
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  HeartbeatManager heartbeat_manager_;
276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Recorder that records GCM activities for debugging purpose. Not owned.
2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  GCMStatsRecorder* recorder_;
2790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::WeakPtrFactory<MCSClient> weak_ptr_factory_;
281a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
282a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MCSClient);
283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace gcm
286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif  // GOOGLE_APIS_GCM_ENGINE_MCS_CLIENT_H_
288