Home | History | Annotate | Download | only in engine
      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_CONNECTION_HANDLER_IMPL_H_
      6 #define GOOGLE_APIS_GCM_ENGINE_CONNECTION_HANDLER_IMPL_H_
      7 
      8 #include "base/memory/weak_ptr.h"
      9 #include "base/time/time.h"
     10 #include "base/timer/timer.h"
     11 #include "google_apis/gcm/engine/connection_handler.h"
     12 
     13 namespace mcs_proto {
     14 class LoginRequest;
     15 }  // namespace mcs_proto
     16 
     17 namespace gcm {
     18 
     19 class GCM_EXPORT ConnectionHandlerImpl : public ConnectionHandler {
     20  public:
     21   // |read_callback| will be invoked with the contents of any received protobuf
     22   // message.
     23   // |write_callback| will be invoked anytime a message has been successfully
     24   // sent. Note: this just means the data was sent to the wire, not that the
     25   // other end received it.
     26   // |connection_callback| will be invoked with any fatal read/write errors
     27   // encountered.
     28   ConnectionHandlerImpl(
     29       base::TimeDelta read_timeout,
     30       const ProtoReceivedCallback& read_callback,
     31       const ProtoSentCallback& write_callback,
     32       const ConnectionChangedCallback& connection_callback);
     33   virtual ~ConnectionHandlerImpl();
     34 
     35   // ConnectionHandler implementation.
     36   virtual void Init(const mcs_proto::LoginRequest& login_request,
     37                     net::StreamSocket* socket) OVERRIDE;
     38   virtual void Reset() OVERRIDE;
     39   virtual bool CanSendMessage() const OVERRIDE;
     40   virtual void SendMessage(const google::protobuf::MessageLite& message)
     41       OVERRIDE;
     42 
     43  private:
     44   // State machine for handling incoming data. See WaitForData(..) for usage.
     45   enum ProcessingState {
     46     // Processing the version, tag, and size packets (assuming minimum length
     47     // size packet). Only used during the login handshake.
     48     MCS_VERSION_TAG_AND_SIZE = 0,
     49     // Processing the tag and size packets (assuming minimum length size
     50     // packet). Used for normal messages.
     51     MCS_TAG_AND_SIZE,
     52     // Processing a maximum length size packet (for messages with length > 128).
     53     // Used when a normal size packet was not sufficient to read the message
     54     // size.
     55     MCS_FULL_SIZE,
     56     // Processing the protocol buffer bytes (for those messages with non-zero
     57     // sizes).
     58     MCS_PROTO_BYTES
     59   };
     60 
     61   // Sends the protocol version and login request. First step in the MCS
     62   // connection handshake.
     63   void Login(const google::protobuf::MessageLite& login_request);
     64 
     65   // SendMessage continuation. Invoked when Socket::Write completes.
     66   void OnMessageSent();
     67 
     68   // Starts the message processing process, which is comprised of the tag,
     69   // message size, and bytes packet types.
     70   void GetNextMessage();
     71 
     72   // Performs any necessary SocketInputStream refreshing until the data
     73   // associated with |packet_type| is fully ready, then calls the appropriate
     74   // OnGot* message to process the packet data. If the read times out,
     75   // will close the stream and invoke the connection callback.
     76   void WaitForData(ProcessingState state);
     77 
     78   // Incoming data helper methods.
     79   void OnGotVersion();
     80   void OnGotMessageTag();
     81   void OnGotMessageSize();
     82   void OnGotMessageBytes();
     83 
     84   // Timeout handler.
     85   void OnTimeout();
     86 
     87   // Closes the current connection.
     88   void CloseConnection();
     89 
     90   // Timeout policy: the timeout is only enforced while waiting on the
     91   // handshake (version and/or LoginResponse) or once at least a tag packet has
     92   // been received. It is reset every time new data is received, and is
     93   // only stopped when a full message is processed.
     94   // TODO(zea): consider enforcing a separate timeout when waiting for
     95   // a message to send.
     96   const base::TimeDelta read_timeout_;
     97   base::OneShotTimer<ConnectionHandlerImpl> read_timeout_timer_;
     98 
     99   // This connection's socket and the input/output streams attached to it.
    100   net::StreamSocket* socket_;
    101   scoped_ptr<SocketInputStream> input_stream_;
    102   scoped_ptr<SocketOutputStream> output_stream_;
    103 
    104   // Whether the MCS login handshake has successfully completed. See Init(..)
    105   // description for more info on what the handshake involves.
    106   bool handshake_complete_;
    107 
    108   // State for the message currently being processed, if there is one.
    109   uint8 message_tag_;
    110   uint32 message_size_;
    111 
    112   ProtoReceivedCallback read_callback_;
    113   ProtoSentCallback write_callback_;
    114   ConnectionChangedCallback connection_callback_;
    115 
    116   base::WeakPtrFactory<ConnectionHandlerImpl> weak_ptr_factory_;
    117 
    118   DISALLOW_COPY_AND_ASSIGN(ConnectionHandlerImpl);
    119 };
    120 
    121 }  // namespace gcm
    122 
    123 #endif  // GOOGLE_APIS_GCM_ENGINE_CONNECTION_HANDLER_IMPL_H_
    124