OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef GOOGLE_APIS_GCM_ENGINE_CONNECTION_HANDLER_H_ | 5 #ifndef GOOGLE_APIS_GCM_ENGINE_CONNECTION_HANDLER_H_ |
6 #define GOOGLE_APIS_GCM_ENGINE_CONNECTION_HANDLER_H_ | 6 #define GOOGLE_APIS_GCM_ENGINE_CONNECTION_HANDLER_H_ |
7 | 7 |
8 #include "base/memory/weak_ptr.h" | 8 #include "base/callback.h" |
9 #include "base/timer/timer.h" | |
10 #include "google_apis/gcm/base/gcm_export.h" | 9 #include "google_apis/gcm/base/gcm_export.h" |
11 #include "google_apis/gcm/protocol/mcs.pb.h" | |
12 | 10 |
13 namespace net{ | 11 namespace net{ |
14 class StreamSocket; | 12 class StreamSocket; |
| 13 } // namespace net |
| 14 |
| 15 namespace google { |
| 16 namespace protobuf { |
| 17 class MessageLite; |
| 18 } // namespace protobuf |
| 19 } // namepsace google |
| 20 |
| 21 namespace mcs_proto { |
| 22 class LoginRequest; |
15 } | 23 } |
16 | 24 |
17 namespace gcm { | 25 namespace gcm { |
18 | 26 |
19 class SocketInputStream; | 27 class SocketInputStream; |
20 class SocketOutputStream; | 28 class SocketOutputStream; |
21 | 29 |
22 // Handles performing the protocol handshake and sending/receiving protobuf | 30 // Handles performing the protocol handshake and sending/receiving protobuf |
23 // messages. Note that no retrying or queueing is enforced at this layer. | 31 // messages. Note that no retrying or queueing is enforced at this layer. |
24 // Once a connection error is encountered, the ConnectionHandler will disconnect | 32 // Once a connection error is encountered, the ConnectionHandler will disconnect |
25 // the socket and must be reinitialized with a new StreamSocket before | 33 // the socket and must be reinitialized with a new StreamSocket before |
26 // messages can be sent/received again. | 34 // messages can be sent/received again. |
27 class GCM_EXPORT ConnectionHandler { | 35 class GCM_EXPORT ConnectionHandler { |
28 public: | 36 public: |
29 typedef base::Callback<void(scoped_ptr<google::protobuf::MessageLite>)> | 37 typedef base::Callback<void(scoped_ptr<google::protobuf::MessageLite>)> |
30 ProtoReceivedCallback; | 38 ProtoReceivedCallback; |
31 typedef base::Closure ProtoSentCallback; | 39 typedef base::Closure ProtoSentCallback; |
32 typedef base::Callback<void(int)> ConnectionChangedCallback; | 40 typedef base::Callback<void(int)> ConnectionChangedCallback; |
33 | 41 |
34 explicit ConnectionHandler(base::TimeDelta read_timeout); | 42 ConnectionHandler(); |
35 ~ConnectionHandler(); | 43 virtual ~ConnectionHandler(); |
36 | 44 |
37 // Starts a new MCS connection handshake (using |login_request|) and, upon | 45 // Starts a new MCS connection handshake (using |login_request|) and, upon |
38 // success, begins listening for incoming/outgoing messages. A successful | 46 // success, begins listening for incoming/outgoing messages. |
39 // handshake is when a mcs_proto::LoginResponse is received, and is signaled | |
40 // via the |read_callback|. | |
41 // Outputs: | |
42 // |read_callback| will be invoked with the contents of any received protobuf | |
43 // message. | |
44 // |write_callback| will be invoked anytime a message has been successfully | |
45 // sent. Note: this just means the data was sent to the wire, not that the | |
46 // other end received it. | |
47 // |connection_callback| will be invoked with any fatal read/write errors | |
48 // encountered. | |
49 // | 47 // |
50 // Note: It is correct and expected to call Init more than once, as connection | 48 // Note: It is correct and expected to call Init more than once, as connection |
51 // issues are encountered and new connections must be made. | 49 // issues are encountered and new connections must be made. |
52 void Init(scoped_ptr<net::StreamSocket> socket, | 50 virtual void Init(const mcs_proto::LoginRequest& login_request, |
53 const google::protobuf::MessageLite& login_request, | 51 scoped_ptr<net::StreamSocket> socket) = 0; |
54 const ProtoReceivedCallback& read_callback, | |
55 const ProtoSentCallback& write_callback, | |
56 const ConnectionChangedCallback& connection_callback); | |
57 | 52 |
58 // Checks that a handshake has been completed and a message is not already | 53 // Checks that a handshake has been completed and a message is not already |
59 // in flight. | 54 // in flight. |
60 bool CanSendMessage() const; | 55 virtual bool CanSendMessage() const = 0; |
61 | 56 |
62 // Send an MCS protobuf message. CanSendMessage() must be true. | 57 // Send an MCS protobuf message. CanSendMessage() must be true. |
63 void SendMessage(const google::protobuf::MessageLite& message); | 58 virtual void SendMessage(const google::protobuf::MessageLite& message) = 0; |
64 | |
65 private: | |
66 // State machine for handling incoming data. See WaitForData(..) for usage. | |
67 enum ProcessingState { | |
68 // Processing the version, tag, and size packets (assuming minimum length | |
69 // size packet). Only used during the login handshake. | |
70 MCS_VERSION_TAG_AND_SIZE = 0, | |
71 // Processing the tag and size packets (assuming minimum length size | |
72 // packet). Used for normal messages. | |
73 MCS_TAG_AND_SIZE, | |
74 // Processing a maximum length size packet (for messages with length > 128). | |
75 // Used when a normal size packet was not sufficient to read the message | |
76 // size. | |
77 MCS_FULL_SIZE, | |
78 // Processing the protocol buffer bytes (for those messages with non-zero | |
79 // sizes). | |
80 MCS_PROTO_BYTES | |
81 }; | |
82 | |
83 // Sends the protocol version and login request. First step in the MCS | |
84 // connection handshake. | |
85 void Login(const google::protobuf::MessageLite& login_request); | |
86 | |
87 // SendMessage continuation. Invoked when Socket::Write completes. | |
88 void OnMessageSent(); | |
89 | |
90 // Starts the message processing process, which is comprised of the tag, | |
91 // message size, and bytes packet types. | |
92 void GetNextMessage(); | |
93 | |
94 // Performs any necessary SocketInputStream refreshing until the data | |
95 // associated with |packet_type| is fully ready, then calls the appropriate | |
96 // OnGot* message to process the packet data. If the read times out, | |
97 // will close the stream and invoke the connection callback. | |
98 void WaitForData(ProcessingState state); | |
99 | |
100 // Incoming data helper methods. | |
101 void OnGotVersion(); | |
102 void OnGotMessageTag(); | |
103 void OnGotMessageSize(); | |
104 void OnGotMessageBytes(); | |
105 | |
106 // Timeout handler. | |
107 void OnTimeout(); | |
108 | |
109 // Closes the current connection. | |
110 void CloseConnection(); | |
111 | |
112 // Timeout policy: the timeout is only enforced while waiting on the | |
113 // handshake (version and/or LoginResponse) or once at least a tag packet has | |
114 // been received. It is reset every time new data is received, and is | |
115 // only stopped when a full message is processed. | |
116 // TODO(zea): consider enforcing a separate timeout when waiting for | |
117 // a message to send. | |
118 const base::TimeDelta read_timeout_; | |
119 base::OneShotTimer<ConnectionHandler> read_timeout_timer_; | |
120 | |
121 // This connection's socket and the input/output streams attached to it. | |
122 scoped_ptr<net::StreamSocket> socket_; | |
123 scoped_ptr<SocketInputStream> input_stream_; | |
124 scoped_ptr<SocketOutputStream> output_stream_; | |
125 | |
126 // Whether the MCS login handshake has successfully completed. See Init(..) | |
127 // description for more info on what the handshake involves. | |
128 bool handshake_complete_; | |
129 | |
130 // State for the message currently being processed, if there is one. | |
131 uint8 message_tag_; | |
132 uint32 message_size_; | |
133 | |
134 ProtoReceivedCallback read_callback_; | |
135 ProtoSentCallback write_callback_; | |
136 ConnectionChangedCallback connection_callback_; | |
137 | |
138 base::WeakPtrFactory<ConnectionHandler> weak_ptr_factory_; | |
139 | |
140 DISALLOW_COPY_AND_ASSIGN(ConnectionHandler); | |
141 }; | 59 }; |
142 | 60 |
143 } // namespace gcm | 61 } // namespace gcm |
144 | 62 |
145 #endif // GOOGLE_APIS_GCM_ENGINE_CONNECTION_HANDLER_H_ | 63 #endif // GOOGLE_APIS_GCM_ENGINE_CONNECTION_HANDLER_H_ |
OLD | NEW |