keep_alive_handler.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright 2020 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. #include "components/cast_channel/keep_alive_handler.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "components/cast_channel/cast_channel_enum.h"
  9. #include "components/cast_channel/cast_message_util.h"
  10. #include "components/cast_channel/cast_socket.h"
  11. #include "components/cast_channel/logger.h"
  12. #include "net/base/net_errors.h"
  13. #include "net/traffic_annotation/network_traffic_annotation.h"
  14. #include "third_party/openscreen/src/cast/common/channel/proto/cast_channel.pb.h"
  15. namespace cast_channel {
  16. KeepAliveHandler::KeepAliveHandler(CastSocket* socket,
  17. scoped_refptr<Logger> logger,
  18. base::TimeDelta ping_interval,
  19. base::TimeDelta liveness_timeout,
  20. OnErrorCallback on_error_cb)
  21. : started_(false),
  22. socket_(socket),
  23. logger_(logger),
  24. liveness_timeout_(liveness_timeout),
  25. ping_interval_(ping_interval),
  26. ping_message_(CreateKeepAlivePingMessage()),
  27. pong_message_(CreateKeepAlivePongMessage()),
  28. on_error_cb_(std::move(on_error_cb)) {
  29. DCHECK(ping_interval_ < liveness_timeout_);
  30. DCHECK(socket_);
  31. DCHECK(!on_error_cb_.is_null());
  32. }
  33. KeepAliveHandler::~KeepAliveHandler() {
  34. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  35. }
  36. void KeepAliveHandler::SetTimersForTest(
  37. std::unique_ptr<base::RetainingOneShotTimer> injected_ping_timer,
  38. std::unique_ptr<base::RetainingOneShotTimer> injected_liveness_timer) {
  39. ping_timer_ = std::move(injected_ping_timer);
  40. liveness_timer_ = std::move(injected_liveness_timer);
  41. }
  42. void KeepAliveHandler::Start() {
  43. DCHECK(!started_);
  44. DVLOG(1) << "Starting keep-alive timers.";
  45. DVLOG(1) << "Ping interval: " << ping_interval_;
  46. DVLOG(1) << "Liveness timeout: " << liveness_timeout_;
  47. // Use injected mock timers, if provided.
  48. if (!ping_timer_) {
  49. ping_timer_ = std::make_unique<base::RetainingOneShotTimer>();
  50. }
  51. if (!liveness_timer_) {
  52. liveness_timer_ = std::make_unique<base::RetainingOneShotTimer>();
  53. }
  54. ping_timer_->Start(
  55. FROM_HERE, ping_interval_,
  56. base::BindRepeating(&KeepAliveHandler::SendKeepAliveMessage,
  57. base::Unretained(this), ping_message_,
  58. CastMessageType::kPing));
  59. liveness_timer_->Start(FROM_HERE, liveness_timeout_,
  60. base::BindRepeating(&KeepAliveHandler::LivenessTimeout,
  61. base::Unretained(this)));
  62. started_ = true;
  63. }
  64. bool KeepAliveHandler::HandleMessage(const CastMessage& message) {
  65. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  66. DVLOG(2) << "KeepAlive::OnMessage : " << message.payload_utf8();
  67. if (started_) {
  68. ResetTimers();
  69. }
  70. // Keep-alive messages are intercepted and handled by KeepAliveHandler
  71. // here. All other messages are passed through to |inner_delegate_|.
  72. // Keep-alive messages are assumed to be in the form { "type": "PING|PONG" }.
  73. if (message.namespace_() == kHeartbeatNamespace) {
  74. static const char* ping_message_type = ToString(CastMessageType::kPing);
  75. if (message.payload_utf8().find(ping_message_type) != std::string::npos) {
  76. DVLOG(2) << "Received PING.";
  77. if (started_)
  78. SendKeepAliveMessage(pong_message_, CastMessageType::kPong);
  79. } else {
  80. DCHECK_NE(std::string::npos,
  81. message.payload_utf8().find(ToString(CastMessageType::kPong)));
  82. DVLOG(2) << "Received PONG.";
  83. }
  84. return true;
  85. }
  86. return false;
  87. }
  88. void KeepAliveHandler::ResetTimers() {
  89. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  90. DCHECK(started_);
  91. ping_timer_->Reset();
  92. liveness_timer_->Reset();
  93. }
  94. void KeepAliveHandler::SendKeepAliveMessage(const CastMessage& message,
  95. CastMessageType message_type) {
  96. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  97. DVLOG(2) << "Sending " << ToString(message_type);
  98. socket_->transport()->SendMessage(
  99. message, base::BindOnce(&KeepAliveHandler::SendKeepAliveMessageComplete,
  100. weak_factory_.GetWeakPtr(), message_type));
  101. }
  102. void KeepAliveHandler::SendKeepAliveMessageComplete(
  103. CastMessageType message_type,
  104. int rv) {
  105. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  106. DVLOG(2) << "Sending " << ToString(message_type) << " complete, rv=" << rv;
  107. if (rv != net::OK) {
  108. // An error occurred while sending the ping response.
  109. DVLOG(1) << "Error sending " << ToString(message_type);
  110. logger_->LogSocketEventWithRv(socket_->id(), ChannelEvent::PING_WRITE_ERROR,
  111. rv);
  112. on_error_cb_.Run(ChannelError::CAST_SOCKET_ERROR);
  113. return;
  114. }
  115. if (liveness_timer_)
  116. liveness_timer_->Reset();
  117. }
  118. void KeepAliveHandler::LivenessTimeout() {
  119. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  120. on_error_cb_.Run(ChannelError::PING_TIMEOUT);
  121. Stop();
  122. }
  123. void KeepAliveHandler::Stop() {
  124. if (started_) {
  125. started_ = false;
  126. ping_timer_->Stop();
  127. liveness_timer_->Stop();
  128. }
  129. }
  130. } // namespace cast_channel