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