File: message_transfer_operation.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (170 lines) | stat: -rw-r--r-- 5,742 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromeos/ash/components/tether/message_transfer_operation.h"

#include <memory>
#include <set>

#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "chromeos/ash/components/multidevice/logging/logging.h"
#include "chromeos/ash/components/tether/message_wrapper.h"
#include "chromeos/ash/components/timer_factory/timer_factory_impl.h"

namespace ash::tether {

MessageTransferOperation::MessageTransferOperation(
    const TetherHost& tether_host,
    HostConnection::Factory::ConnectionPriority connection_priority,
    raw_ptr<HostConnection::Factory> host_connection_factory)
    : tether_host_(tether_host),
      connection_priority_(connection_priority),
      host_connection_factory_(host_connection_factory),
      timer_factory_(ash::timer_factory::TimerFactoryImpl::Factory::Create()) {}

MessageTransferOperation::~MessageTransferOperation() {
  // If initialization never occurred, devices were never registered.
  if (!initialized_) {
    return;
  }

  shutting_down_ = true;

  // Stop the operation if it's in flight, as the operation itself
  // will be destroyed.
  StopOperation();
}

void MessageTransferOperation::Initialize() {
  if (initialized_) {
    return;
  }

  initialized_ = true;

  // Store the message type for this connection as a private field. This is
  // necessary because when UnregisterDevice() is called in the destructor, the
  // derived class has already been destroyed, so invoking
  // GetMessageTypeForConnection() will fail due to it being a pure virtual
  // function at that time.
  message_type_for_connection_ = GetMessageTypeForConnection();

  OnOperationStarted();

  StartConnectionTimerForDevice();
  host_connection_factory_->Create(
      tether_host_, connection_priority_, /*payload_listener=*/this,
      base::BindOnce(&MessageTransferOperation::OnDisconnected,
                     weak_ptr_factory_.GetWeakPtr()),
      base::BindOnce(&MessageTransferOperation::OnConnectionAttemptComplete,
                     weak_ptr_factory_.GetWeakPtr()));
}

void MessageTransferOperation::StopOperation() {
  // Note: This function may be called from the destructor. It is invalid to
  // invoke any virtual methods if |shutting_down_| is true.

  StopTimerForDeviceIfRunning();

  host_connection_.reset();

  if (!shutting_down_) {
    OnOperationFinished();
  }
}

void MessageTransferOperation::SendMessage(
    std::unique_ptr<MessageWrapper> message_wrapper,
    HostConnection::OnMessageSentCallback on_message_sent) {
  CHECK(host_connection_);
  host_connection_->SendMessage(std::move(message_wrapper),
                                std::move(on_message_sent));
}

uint32_t MessageTransferOperation::GetMessageTimeoutSeconds() {
  return MessageTransferOperation::kDefaultMessageTimeoutSeconds;
}

void MessageTransferOperation::OnConnectionAttemptComplete(
    std::unique_ptr<HostConnection> host_connection) {
  if (!host_connection) {
    PA_LOG(WARNING) << "Failed to connect to device ["
                    << GetDeviceId(/*truncate_for_logs=*/true) << "].";
    StopOperation();
  } else {
    host_connection_ = std::move(host_connection);

    // Stop the timer which was started from StartConnectionTimerForDevice()
    // since the connection has now been established. Start another timer now
    // via StartMessageTimerForDevice() while waiting for messages to be sent to
    // and received by |remote_device|.
    StopTimerForDeviceIfRunning();
    StartMessageTimerForDevice();

    PA_LOG(INFO) << "Successfully opened connection to ["
                 << GetDeviceId(/*truncate_for_logs=*/true) << "].";
    OnDeviceAuthenticated();
  }
}

void MessageTransferOperation::OnDisconnected() {
  PA_LOG(VERBOSE) << "Remote device disconnected from this device: "
                  << GetDeviceId(/*truncate_for_logs=*/true);
  StopOperation();
}

void MessageTransferOperation::StartConnectionTimerForDevice() {
  StartTimerForDevice(kConnectionTimeoutSeconds);
}

void MessageTransferOperation::StartMessageTimerForDevice() {
  StartTimerForDevice(GetMessageTimeoutSeconds());
}

void MessageTransferOperation::StartTimerForDevice(uint32_t timeout_seconds) {
  PA_LOG(VERBOSE) << "Starting timer for operation with message type "
                  << message_type_for_connection_ << " from device with ID "
                  << GetDeviceId(/*truncate_for_logs=*/true) << ".";

  remote_device_timer_ = timer_factory_->CreateOneShotTimer();
  remote_device_timer_->Start(
      FROM_HERE, base::Seconds(timeout_seconds),
      base::BindOnce(&MessageTransferOperation::OnTimeout,
                     weak_ptr_factory_.GetWeakPtr()));
}

void MessageTransferOperation::StopTimerForDeviceIfRunning() {
  if (!remote_device_timer_) {
    return;
  }

  remote_device_timer_->Stop();
  remote_device_timer_.reset();
}

void MessageTransferOperation::OnTimeout() {
  PA_LOG(WARNING) << "Timed out operation for message type "
                  << message_type_for_connection_ << " from device with ID "
                  << GetDeviceId(/*truncate_for_logs=*/true) << ".";

  remote_device_timer_.reset();
  StopOperation();
}

void MessageTransferOperation::SetTimerFactoryForTest(
    std::unique_ptr<ash::timer_factory::TimerFactory> timer_factory_for_test) {
  timer_factory_ = std::move(timer_factory_for_test);
}

const std::string MessageTransferOperation::GetDeviceId(
    bool truncate_for_logs) const {
  if (truncate_for_logs) {
    return tether_host_.GetTruncatedDeviceIdForLogs();
  } else {
    return tether_host_.GetDeviceId();
  }
}

}  // namespace ash::tether