blob: 9adf225da662dd954da1b50cbc5bf5baa755e407 [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
42void PseudoTcpChannelFactory::CreateChannel(
43 const std::string& name,
44 const ChannelCreatedCallback& callback) {
45 datagram_channel_factory_->CreateChannel(
46 name,
47 base::Bind(&PseudoTcpChannelFactory::OnDatagramChannelCreated,
48 base::Unretained(this), name, callback));
49}
50
51void PseudoTcpChannelFactory::CancelChannelCreation(const std::string& name) {
52 PendingSocketsMap::iterator it = pending_sockets_.find(name);
53 if (it == pending_sockets_.end()) {
54 datagram_channel_factory_->CancelChannelCreation(name);
55 } else {
56 delete it->second;
57 pending_sockets_.erase(it);
58 }
59}
60
61void PseudoTcpChannelFactory::OnDatagramChannelCreated(
62 const std::string& name,
63 const ChannelCreatedCallback& callback,
dcheng0765c492016-04-06 22:41:5364 std::unique_ptr<P2PDatagramSocket> datagram_socket) {
sergeyuaa6fa2342015-12-22 23:26:4865 PseudoTcpAdapter* adapter = new PseudoTcpAdapter(std::move(datagram_socket));
sergeyu9cb142f2014-09-12 20:43:0166 pending_sockets_[name] = adapter;
67
68 adapter->SetSendBufferSize(kTcpSendBufferSize);
69 adapter->SetReceiveBufferSize(kTcpReceiveBufferSize);
70 adapter->SetNoDelay(true);
71 adapter->SetAckDelay(kTcpAckDelayMilliseconds);
72
73 // TODO(sergeyu): This is a hack to improve latency of the video channel.
74 // Consider removing it once we have better flow control implemented.
75 if (name == kVideoChannelName)
76 adapter->SetWriteWaitsForSend(true);
77
78 int result = adapter->Connect(
79 base::Bind(&PseudoTcpChannelFactory::OnPseudoTcpConnected,
80 base::Unretained(this), name, callback));
81 if (result != net::ERR_IO_PENDING)
82 OnPseudoTcpConnected(name, callback, result);
83}
84
85void PseudoTcpChannelFactory::OnPseudoTcpConnected(
86 const std::string& name,
87 const ChannelCreatedCallback& callback,
88 int result) {
89 PendingSocketsMap::iterator it = pending_sockets_.find(name);
90 DCHECK(it != pending_sockets_.end());
dcheng0765c492016-04-06 22:41:5391 std::unique_ptr<P2PStreamSocket> socket(it->second);
sergeyu9cb142f2014-09-12 20:43:0192 pending_sockets_.erase(it);
93
94 if (result != net::OK)
95 socket.reset();
96
sergeyuaa6fa2342015-12-22 23:26:4897 callback.Run(std::move(socket));
sergeyu9cb142f2014-09-12 20:43:0198}
99
100} // namespace protocol
101} // namespace remoting