Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: components/cast_channel/keep_alive_delegate.cc

Issue 2926313002: Revert of [cast_channel] Move cast_channel related files from //extensions to //components (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 #include "components/cast_channel/keep_alive_delegate.h"
6
7 #include <string>
8 #include <utility>
9
10 #include "base/json/json_reader.h"
11 #include "base/json/json_writer.h"
12 #include "base/values.h"
13 #include "components/cast_channel/cast_socket.h"
14 #include "components/cast_channel/logger.h"
15 #include "components/cast_channel/proto/cast_channel.pb.h"
16 #include "components/cast_channel/proto/logging.pb.h"
17 #include "net/base/net_errors.h"
18
19 namespace cast_channel {
20 namespace {
21
22 const char kHeartbeatNamespace[] = "urn:x-cast:com.google.cast.tp.heartbeat";
23 const char kPingSenderId[] = "chrome";
24 const char kPingReceiverId[] = "receiver-0";
25 const char kTypeNodeId[] = "type";
26
27 // Parses the JSON-encoded payload of |message| and returns the value in the
28 // "type" field or the empty string if the parse fails or the field is not
29 // found.
30 std::string ParseForPayloadType(const CastMessage& message) {
31 std::unique_ptr<base::Value> parsed_payload(
32 base::JSONReader::Read(message.payload_utf8()));
33 base::DictionaryValue* payload_as_dict;
34 if (!parsed_payload || !parsed_payload->GetAsDictionary(&payload_as_dict))
35 return std::string();
36 std::string type_string;
37 if (!payload_as_dict->GetString(kTypeNodeId, &type_string))
38 return std::string();
39 return type_string;
40 }
41
42 } // namespace
43
44 // static
45 const char KeepAliveDelegate::kHeartbeatPingType[] = "PING";
46
47 // static
48 const char KeepAliveDelegate::kHeartbeatPongType[] = "PONG";
49
50 using ::cast_channel::ChannelError;
51
52 // static
53 CastMessage KeepAliveDelegate::CreateKeepAliveMessage(
54 const char* message_type) {
55 CastMessage output;
56 output.set_protocol_version(CastMessage::CASTV2_1_0);
57 output.set_source_id(kPingSenderId);
58 output.set_destination_id(kPingReceiverId);
59 output.set_namespace_(kHeartbeatNamespace);
60 base::DictionaryValue type_dict;
61 type_dict.SetString(kTypeNodeId, message_type);
62 if (!base::JSONWriter::Write(type_dict, output.mutable_payload_utf8())) {
63 LOG(ERROR) << "Failed to serialize dictionary.";
64 return output;
65 }
66 output.set_payload_type(
67 CastMessage::PayloadType::CastMessage_PayloadType_STRING);
68 return output;
69 }
70
71 KeepAliveDelegate::KeepAliveDelegate(
72 CastSocket* socket,
73 scoped_refptr<Logger> logger,
74 std::unique_ptr<CastTransport::Delegate> inner_delegate,
75 base::TimeDelta ping_interval,
76 base::TimeDelta liveness_timeout)
77 : started_(false),
78 socket_(socket),
79 logger_(logger),
80 inner_delegate_(std::move(inner_delegate)),
81 liveness_timeout_(liveness_timeout),
82 ping_interval_(ping_interval) {
83 DCHECK(ping_interval_ < liveness_timeout_);
84 DCHECK(inner_delegate_);
85 DCHECK(socket_);
86 ping_message_ = CreateKeepAliveMessage(kHeartbeatPingType);
87 pong_message_ = CreateKeepAliveMessage(kHeartbeatPongType);
88 }
89
90 KeepAliveDelegate::~KeepAliveDelegate() {}
91
92 void KeepAliveDelegate::SetTimersForTest(
93 std::unique_ptr<base::Timer> injected_ping_timer,
94 std::unique_ptr<base::Timer> injected_liveness_timer) {
95 ping_timer_ = std::move(injected_ping_timer);
96 liveness_timer_ = std::move(injected_liveness_timer);
97 }
98
99 void KeepAliveDelegate::Start() {
100 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
101 DCHECK(!started_);
102
103 VLOG(1) << "Starting keep-alive timers.";
104 VLOG(1) << "Ping timeout: " << ping_interval_;
105 VLOG(1) << "Liveness timeout: " << liveness_timeout_;
106
107 // Use injected mock timers, if provided.
108 if (!ping_timer_) {
109 ping_timer_.reset(new base::Timer(true, false));
110 }
111 if (!liveness_timer_) {
112 liveness_timer_.reset(new base::Timer(true, false));
113 }
114
115 ping_timer_->Start(
116 FROM_HERE, ping_interval_,
117 base::Bind(&KeepAliveDelegate::SendKeepAliveMessage,
118 base::Unretained(this), ping_message_, kHeartbeatPingType));
119 liveness_timer_->Start(
120 FROM_HERE, liveness_timeout_,
121 base::Bind(&KeepAliveDelegate::LivenessTimeout, base::Unretained(this)));
122
123 started_ = true;
124 inner_delegate_->Start();
125 }
126
127 void KeepAliveDelegate::ResetTimers() {
128 DCHECK(started_);
129 ping_timer_->Reset();
130 liveness_timer_->Reset();
131 }
132
133 void KeepAliveDelegate::SendKeepAliveMessage(const CastMessage& message,
134 const char* message_type) {
135 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
136 VLOG(2) << "Sending " << message_type;
137 socket_->transport()->SendMessage(
138 message, base::Bind(&KeepAliveDelegate::SendKeepAliveMessageComplete,
139 base::Unretained(this), message_type));
140 }
141
142 void KeepAliveDelegate::SendKeepAliveMessageComplete(const char* message_type,
143 int rv) {
144 VLOG(2) << "Sending " << message_type << " complete, rv=" << rv;
145 if (rv != net::OK) {
146 // An error occurred while sending the ping response.
147 VLOG(1) << "Error sending " << message_type;
148 logger_->LogSocketEventWithRv(socket_->id(), proto::PING_WRITE_ERROR, rv);
149 OnError(ChannelError::CAST_SOCKET_ERROR);
150 }
151 }
152
153 void KeepAliveDelegate::LivenessTimeout() {
154 OnError(ChannelError::PING_TIMEOUT);
155 Stop();
156 }
157
158 // CastTransport::Delegate interface.
159 void KeepAliveDelegate::OnError(ChannelError error_state) {
160 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
161 VLOG(1) << "KeepAlive::OnError: "
162 << ::cast_channel::ChannelErrorToString(error_state);
163 inner_delegate_->OnError(error_state);
164 Stop();
165 }
166
167 void KeepAliveDelegate::OnMessage(const CastMessage& message) {
168 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
169 VLOG(2) << "KeepAlive::OnMessage : " << message.payload_utf8();
170
171 if (started_)
172 ResetTimers();
173
174 // PING and PONG messages are intercepted and handled by KeepAliveDelegate
175 // here. All other messages are passed through to |inner_delegate_|.
176 const std::string payload_type = ParseForPayloadType(message);
177 if (payload_type == kHeartbeatPingType) {
178 VLOG(2) << "Received PING.";
179 if (started_)
180 SendKeepAliveMessage(pong_message_, kHeartbeatPongType);
181 } else if (payload_type == kHeartbeatPongType) {
182 VLOG(2) << "Received PONG.";
183 } else {
184 inner_delegate_->OnMessage(message);
185 }
186 }
187
188 void KeepAliveDelegate::Stop() {
189 if (started_) {
190 started_ = false;
191 ping_timer_->Stop();
192 liveness_timer_->Stop();
193 }
194 }
195
196 } // namespace cast_channel
OLDNEW
« no previous file with comments | « components/cast_channel/keep_alive_delegate.h ('k') | components/cast_channel/keep_alive_delegate_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698