Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / remoting / protocol / pseudotcp_channel_factory.cc
1 // 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
7 #include "base/bind.h"
8 #include "jingle/glue/pseudotcp_adapter.h"
9 #include "net/base/net_errors.h"
10 #include "net/socket/stream_socket.h"
11 #include "remoting/base/constants.h"
12 #include "remoting/protocol/datagram_channel_factory.h"
13
14 namespace remoting {
15 namespace protocol {
16
17 namespace {
18
19 // Value is chosen to balance the extra latency against the reduced
20 // load due to ACK traffic.
21 const int kTcpAckDelayMilliseconds = 10;
22
23 // Values for the TCP send and receive buffer size. This should be tuned to
24 // accommodate high latency network but not backlog the decoding pipeline.
25 const int kTcpReceiveBufferSize = 256 * 1024;
26 const int kTcpSendBufferSize = kTcpReceiveBufferSize + 30 * 1024;
27
28 }  // namespace
29
30 PseudoTcpChannelFactory::PseudoTcpChannelFactory(
31     DatagramChannelFactory* datagram_channel_factory)
32     : datagram_channel_factory_(datagram_channel_factory) {
33 }
34
35 PseudoTcpChannelFactory::~PseudoTcpChannelFactory() {
36   // CancelChannelCreation() is expected to be called before destruction.
37   DCHECK(pending_sockets_.empty());
38 }
39
40 void PseudoTcpChannelFactory::CreateChannel(
41     const std::string& name,
42     const ChannelCreatedCallback& callback) {
43   datagram_channel_factory_->CreateChannel(
44       name,
45       base::Bind(&PseudoTcpChannelFactory::OnDatagramChannelCreated,
46                  base::Unretained(this), name, callback));
47 }
48
49 void PseudoTcpChannelFactory::CancelChannelCreation(const std::string& name) {
50   PendingSocketsMap::iterator it = pending_sockets_.find(name);
51   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
59 void PseudoTcpChannelFactory::OnDatagramChannelCreated(
60     const std::string& name,
61     const ChannelCreatedCallback& callback,
62     scoped_ptr<net::Socket> datagram_socket) {
63   jingle_glue::PseudoTcpAdapter* adapter =
64       new jingle_glue::PseudoTcpAdapter(datagram_socket.release());
65   pending_sockets_[name] = adapter;
66
67   adapter->SetSendBufferSize(kTcpSendBufferSize);
68   adapter->SetReceiveBufferSize(kTcpReceiveBufferSize);
69   adapter->SetNoDelay(true);
70   adapter->SetAckDelay(kTcpAckDelayMilliseconds);
71
72   // TODO(sergeyu): This is a hack to improve latency of the video channel.
73   // Consider removing it once we have better flow control implemented.
74   if (name == kVideoChannelName)
75     adapter->SetWriteWaitsForSend(true);
76
77   int result = adapter->Connect(
78       base::Bind(&PseudoTcpChannelFactory::OnPseudoTcpConnected,
79                  base::Unretained(this), name, callback));
80   if (result != net::ERR_IO_PENDING)
81     OnPseudoTcpConnected(name, callback, result);
82 }
83
84 void PseudoTcpChannelFactory::OnPseudoTcpConnected(
85     const std::string& name,
86     const ChannelCreatedCallback& callback,
87     int result) {
88   PendingSocketsMap::iterator it = pending_sockets_.find(name);
89   DCHECK(it != pending_sockets_.end());
90   scoped_ptr<net::StreamSocket> socket(it->second);
91   pending_sockets_.erase(it);
92
93   if (result != net::OK)
94     socket.reset();
95
96   callback.Run(socket.Pass());
97 }
98
99 }  // namespace protocol
100 }  // namespace remoting