11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "remoting/protocol/pseudotcp_channel_factory.h" 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/bind.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "jingle/glue/pseudotcp_adapter.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/base/net_errors.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/socket/stream_socket.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "remoting/base/constants.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "remoting/protocol/datagram_channel_factory.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace remoting { 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace protocol { 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace { 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Value is chosen to balance the extra latency against the reduced 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// load due to ACK traffic. 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kTcpAckDelayMilliseconds = 10; 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Values for the TCP send and receive buffer size. This should be tuned to 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// accommodate high latency network but not backlog the decoding pipeline. 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kTcpReceiveBufferSize = 256 * 1024; 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kTcpSendBufferSize = kTcpReceiveBufferSize + 30 * 1024; 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPseudoTcpChannelFactory::PseudoTcpChannelFactory( 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DatagramChannelFactory* datagram_channel_factory) 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : datagram_channel_factory_(datagram_channel_factory) { 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPseudoTcpChannelFactory::~PseudoTcpChannelFactory() { 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // CancelChannelCreation() is expected to be called before destruction. 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(pending_sockets_.empty()); 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PseudoTcpChannelFactory::CreateChannel( 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& name, 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ChannelCreatedCallback& callback) { 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci datagram_channel_factory_->CreateChannel( 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci name, 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&PseudoTcpChannelFactory::OnDatagramChannelCreated, 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(this), name, callback)); 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PseudoTcpChannelFactory::CancelChannelCreation(const std::string& name) { 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PendingSocketsMap::iterator it = pending_sockets_.find(name); 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (it == pending_sockets_.end()) { 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci datagram_channel_factory_->CancelChannelCreation(name); 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delete it->second; 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_sockets_.erase(it); 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PseudoTcpChannelFactory::OnDatagramChannelCreated( 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& name, 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ChannelCreatedCallback& callback, 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<net::Socket> datagram_socket) { 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci jingle_glue::PseudoTcpAdapter* adapter = 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new jingle_glue::PseudoTcpAdapter(datagram_socket.release()); 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_sockets_[name] = adapter; 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adapter->SetSendBufferSize(kTcpSendBufferSize); 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adapter->SetReceiveBufferSize(kTcpReceiveBufferSize); 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adapter->SetNoDelay(true); 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adapter->SetAckDelay(kTcpAckDelayMilliseconds); 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(sergeyu): This is a hack to improve latency of the video channel. 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Consider removing it once we have better flow control implemented. 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (name == kVideoChannelName) 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci adapter->SetWriteWaitsForSend(true); 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int result = adapter->Connect( 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&PseudoTcpChannelFactory::OnPseudoTcpConnected, 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(this), name, callback)); 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result != net::ERR_IO_PENDING) 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnPseudoTcpConnected(name, callback, result); 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PseudoTcpChannelFactory::OnPseudoTcpConnected( 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& name, 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ChannelCreatedCallback& callback, 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int result) { 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PendingSocketsMap::iterator it = pending_sockets_.find(name); 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(it != pending_sockets_.end()); 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<net::StreamSocket> socket(it->second); 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_sockets_.erase(it); 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result != net::OK) 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci socket.reset(); 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(socket.Pass()); 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace protocol 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace remoting 101