| Index: remoting/protocol/pseudotcp_channel_factory.cc
|
| diff --git a/remoting/protocol/pseudotcp_channel_factory.cc b/remoting/protocol/pseudotcp_channel_factory.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..22a9c624d5079a9980baf16a00c15dfce409777e
|
| --- /dev/null
|
| +++ b/remoting/protocol/pseudotcp_channel_factory.cc
|
| @@ -0,0 +1,99 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "remoting/protocol/pseudotcp_channel_factory.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "jingle/glue/pseudotcp_adapter.h"
|
| +#include "net/base/net_errors.h"
|
| +#include "net/socket/stream_socket.h"
|
| +#include "remoting/base/constants.h"
|
| +#include "remoting/protocol/datagram_channel_factory.h"
|
| +
|
| +namespace remoting {
|
| +namespace protocol {
|
| +
|
| +namespace {
|
| +
|
| +// Value is chosen to balance the extra latency against the reduced
|
| +// load due to ACK traffic.
|
| +const int kTcpAckDelayMilliseconds = 10;
|
| +
|
| +// Values for the TCP send and receive buffer size. This should be tuned to
|
| +// accommodate high latency network but not backlog the decoding pipeline.
|
| +const int kTcpReceiveBufferSize = 256 * 1024;
|
| +const int kTcpSendBufferSize = kTcpReceiveBufferSize + 30 * 1024;
|
| +
|
| +} // namespace
|
| +
|
| +PseudoTcpChannelFactory::PseudoTcpChannelFactory(
|
| + DatagramChannelFactory* datagram_channel_factory)
|
| + : datagram_channel_factory_(datagram_channel_factory) {
|
| +}
|
| +
|
| +PseudoTcpChannelFactory::~PseudoTcpChannelFactory() {
|
| + DCHECK(pending_sockets_.empty());
|
| +}
|
| +
|
| +void PseudoTcpChannelFactory::CreateChannel(
|
| + const std::string& name,
|
| + const ChannelCreatedCallback& callback) {
|
| + datagram_channel_factory_->CreateChannel(
|
| + name,
|
| + base::Bind(&PseudoTcpChannelFactory::OnDatagramChannelCreated,
|
| + base::Unretained(this), name, callback));
|
| +}
|
| +
|
| +void PseudoTcpChannelFactory::CancelChannelCreation(const std::string& name) {
|
| + PendingSocketsMap::iterator it = pending_sockets_.find(name);
|
| + if (it == pending_sockets_.end()) {
|
| + datagram_channel_factory_->CancelChannelCreation(name);
|
| + } else {
|
| + delete it->second;
|
| + pending_sockets_.erase(it);
|
| + }
|
| +}
|
| +
|
| +void PseudoTcpChannelFactory::OnDatagramChannelCreated(
|
| + const std::string& name,
|
| + const ChannelCreatedCallback& callback,
|
| + scoped_ptr<net::Socket> datagram_socket) {
|
| + jingle_glue::PseudoTcpAdapter* adapter =
|
| + new jingle_glue::PseudoTcpAdapter(datagram_socket.release());
|
| + pending_sockets_[name] = adapter;
|
| +
|
| + adapter->SetSendBufferSize(kTcpSendBufferSize);
|
| + adapter->SetReceiveBufferSize(kTcpReceiveBufferSize);
|
| + adapter->SetNoDelay(true);
|
| + adapter->SetAckDelay(kTcpAckDelayMilliseconds);
|
| +
|
| + // TODO(sergeyu): This is a hack to improve latency of the video channel.
|
| + // Consider removing it once we have better flow control implemented.
|
| + if (name == kVideoChannelName)
|
| + adapter->SetWriteWaitsForSend(true);
|
| +
|
| + int result = adapter->Connect(
|
| + base::Bind(&PseudoTcpChannelFactory::OnPseudoTcpConnected,
|
| + base::Unretained(this), name, callback));
|
| + if (result != net::ERR_IO_PENDING)
|
| + OnPseudoTcpConnected(name, callback, result);
|
| +}
|
| +
|
| +void PseudoTcpChannelFactory::OnPseudoTcpConnected(
|
| + const std::string& name,
|
| + const ChannelCreatedCallback& callback,
|
| + int result) {
|
| + PendingSocketsMap::iterator it = pending_sockets_.find(name);
|
| + DCHECK(it != pending_sockets_.end());
|
| + scoped_ptr<net::StreamSocket> socket(it->second);
|
| + pending_sockets_.erase(it);
|
| +
|
| + if (result != net::OK)
|
| + socket.reset();
|
| +
|
| + callback.Run(socket.Pass());
|
| +}
|
| +
|
| +} // namespace protocol
|
| +} // namespace remoting
|
|
|