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