blob: 6d6669094c6a1f0236a8cd2ba3653e357ed13bb4 [file] [log] [blame]
sergeyu9cb142f2014-09-12 20:43:011// Copyright 2014 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 "remoting/protocol/pseudotcp_channel_factory.h"
6
sergeyu89d088b2015-12-24 00:22:447#include <utility>
8
sergeyu9cb142f2014-09-12 20:43:019#include "base/bind.h"
sergeyu9cb142f2014-09-12 20:43:0110#include "net/base/net_errors.h"
sergeyu9cb142f2014-09-12 20:43:0111#include "remoting/base/constants.h"
12#include "remoting/protocol/datagram_channel_factory.h"
sergeyuaa22c082015-07-20 19:41:1313#include "remoting/protocol/p2p_datagram_socket.h"
sergeyu031ce3b32015-07-06 19:00:4614#include "remoting/protocol/pseudotcp_adapter.h"
sergeyu9cb142f2014-09-12 20:43:0115
16namespace remoting {
17namespace protocol {
18
19namespace {
20
21// Value is chosen to balance the extra latency against the reduced
22// load due to ACK traffic.
23const int kTcpAckDelayMilliseconds = 10;
24
25// Values for the TCP send and receive buffer size. This should be tuned to
26// accommodate high latency network but not backlog the decoding pipeline.
27const int kTcpReceiveBufferSize = 256 * 1024;
28const int kTcpSendBufferSize = kTcpReceiveBufferSize + 30 * 1024;
29
30} // namespace
31
32PseudoTcpChannelFactory::PseudoTcpChannelFactory(
33 DatagramChannelFactory* datagram_channel_factory)
34 : datagram_channel_factory_(datagram_channel_factory) {
35}
36
37PseudoTcpChannelFactory::~PseudoTcpChannelFactory() {
38 // CancelChannelCreation() is expected to be called before destruction.
39 DCHECK(pending_sockets_.empty());
40}
41
Evan Stade3f80bc32020-06-03 02:34:3342void PseudoTcpChannelFactory::CreateChannel(const std::string& name,
43 ChannelCreatedCallback callback) {
sergeyu9cb142f2014-09-12 20:43:0144 datagram_channel_factory_->CreateChannel(
Evan Stade3f80bc32020-06-03 02:34:3345 name, base::BindOnce(&PseudoTcpChannelFactory::OnDatagramChannelCreated,
46 base::Unretained(this), name, std::move(callback)));
sergeyu9cb142f2014-09-12 20:43:0147}
48
49void PseudoTcpChannelFactory::CancelChannelCreation(const std::string& name) {
jdoerried0539eeb2018-10-02 20:54:2950 auto it = pending_sockets_.find(name);
sergeyu9cb142f2014-09-12 20:43:0151 if (it == pending_sockets_.end()) {
52 datagram_channel_factory_->CancelChannelCreation(name);
53 } else {
54 delete it->second;
55 pending_sockets_.erase(it);
56 }
57}
58
59void PseudoTcpChannelFactory::OnDatagramChannelCreated(
60 const std::string& name,
Evan Stade3f80bc32020-06-03 02:34:3361 ChannelCreatedCallback callback,
dcheng0765c492016-04-06 22:41:5362 std::unique_ptr<P2PDatagramSocket> datagram_socket) {
sergeyuaa6fa2342015-12-22 23:26:4863 PseudoTcpAdapter* adapter = new PseudoTcpAdapter(std::move(datagram_socket));
sergeyu9cb142f2014-09-12 20:43:0164 pending_sockets_[name] = adapter;
65
66 adapter->SetSendBufferSize(kTcpSendBufferSize);
67 adapter->SetReceiveBufferSize(kTcpReceiveBufferSize);
68 adapter->SetNoDelay(true);
69 adapter->SetAckDelay(kTcpAckDelayMilliseconds);
70
71 // TODO(sergeyu): This is a hack to improve latency of the video channel.
72 // Consider removing it once we have better flow control implemented.
73 if (name == kVideoChannelName)
74 adapter->SetWriteWaitsForSend(true);
75
Evan Stade3f80bc32020-06-03 02:34:3376 net::CompletionOnceCallback returned_callback = adapter->Connect(
Jan Wilken Dörriea0e772a2020-04-01 18:28:1977 base::BindOnce(&PseudoTcpChannelFactory::OnPseudoTcpConnected,
Evan Stade3f80bc32020-06-03 02:34:3378 base::Unretained(this), name, std::move(callback)));
79 if (returned_callback)
80 std::move(returned_callback).Run(net::ERR_FAILED);
sergeyu9cb142f2014-09-12 20:43:0181}
82
83void PseudoTcpChannelFactory::OnPseudoTcpConnected(
84 const std::string& name,
Evan Stade3f80bc32020-06-03 02:34:3385 ChannelCreatedCallback callback,
sergeyu9cb142f2014-09-12 20:43:0186 int result) {
jdoerried0539eeb2018-10-02 20:54:2987 auto it = pending_sockets_.find(name);
sergeyu9cb142f2014-09-12 20:43:0188 DCHECK(it != pending_sockets_.end());
dcheng0765c492016-04-06 22:41:5389 std::unique_ptr<P2PStreamSocket> socket(it->second);
sergeyu9cb142f2014-09-12 20:43:0190 pending_sockets_.erase(it);
91
92 if (result != net::OK)
93 socket.reset();
94
Evan Stade3f80bc32020-06-03 02:34:3395 std::move(callback).Run(std::move(socket));
sergeyu9cb142f2014-09-12 20:43:0196}
97
98} // namespace protocol
99} // namespace remoting