OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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/host/client_connection.h" |
| 6 |
| 7 #include "google/protobuf/message.h" |
| 8 #include "media/base/data_buffer.h" |
| 9 #include "remoting/base/protocol_decoder.h" |
| 10 #include "remoting/base/protocol_util.h" |
| 11 |
| 12 using media::DataBuffer; |
| 13 |
| 14 namespace remoting { |
| 15 |
| 16 // Determine how many update streams we should count to find the size of |
| 17 // average update stream. |
| 18 static const int kAverageUpdateStream = 10; |
| 19 |
| 20 ClientConnection::ClientConnection(MessageLoop* message_loop, |
| 21 ProtocolDecoder* decoder, |
| 22 EventHandler* handler) |
| 23 : loop_(message_loop), |
| 24 decoder_(decoder), |
| 25 size_in_queue_(0), |
| 26 update_stream_size_(0), |
| 27 handler_(handler) { |
| 28 DCHECK(loop_); |
| 29 DCHECK(decoder_.get()); |
| 30 DCHECK(handler_); |
| 31 } |
| 32 |
| 33 ClientConnection::~ClientConnection() { |
| 34 // TODO(hclam): When we shut down the viewer we may have to close the |
| 35 // jingle channel. |
| 36 } |
| 37 |
| 38 void ClientConnection::SendInitClientMessage(int width, int height) { |
| 39 DCHECK_EQ(loop_, MessageLoop::current()); |
| 40 DCHECK(!update_stream_size_); |
| 41 DCHECK(channel_.get()); |
| 42 |
| 43 chromotocol_pb::HostMessage msg; |
| 44 msg.mutable_init_client()->set_width(width); |
| 45 msg.mutable_init_client()->set_height(height); |
| 46 DCHECK(msg.IsInitialized()); |
| 47 channel_->Write(SerializeAndFrameMessage(msg)); |
| 48 } |
| 49 |
| 50 void ClientConnection::SendBeginUpdateStreamMessage() { |
| 51 DCHECK_EQ(loop_, MessageLoop::current()); |
| 52 DCHECK(channel_.get()); |
| 53 |
| 54 chromotocol_pb::HostMessage msg; |
| 55 msg.mutable_begin_update_stream(); |
| 56 DCHECK(msg.IsInitialized()); |
| 57 |
| 58 scoped_refptr<DataBuffer> data = SerializeAndFrameMessage(msg); |
| 59 DCHECK(!update_stream_size_); |
| 60 update_stream_size_ += data->GetDataSize(); |
| 61 channel_->Write(data); |
| 62 } |
| 63 |
| 64 void ClientConnection::SendUpdateStreamPacketMessage( |
| 65 chromotocol_pb::UpdateStreamPacketHeader* header, |
| 66 scoped_refptr<DataBuffer> data) { |
| 67 DCHECK_EQ(loop_, MessageLoop::current()); |
| 68 DCHECK(channel_.get()); |
| 69 |
| 70 chromotocol_pb::HostMessage msg; |
| 71 msg.mutable_update_stream_packet()->mutable_header()->CopyFrom(*header); |
| 72 // TODO(hclam): This introduce one memory copy. Eliminate it. |
| 73 msg.mutable_update_stream_packet()->set_data( |
| 74 data->GetData(), data->GetDataSize()); |
| 75 DCHECK(msg.IsInitialized()); |
| 76 |
| 77 scoped_refptr<DataBuffer> encoded_data = SerializeAndFrameMessage(msg); |
| 78 update_stream_size_ += data->GetDataSize(); |
| 79 channel_->Write(encoded_data); |
| 80 } |
| 81 |
| 82 void ClientConnection::SendEndUpdateStreamMessage() { |
| 83 DCHECK_EQ(loop_, MessageLoop::current()); |
| 84 DCHECK(channel_.get()); |
| 85 |
| 86 chromotocol_pb::HostMessage msg; |
| 87 msg.mutable_end_update_stream(); |
| 88 DCHECK(msg.IsInitialized()); |
| 89 |
| 90 scoped_refptr<DataBuffer> data = SerializeAndFrameMessage(msg); |
| 91 update_stream_size_ += data->GetDataSize(); |
| 92 channel_->Write(data); |
| 93 |
| 94 // Here's some logic to help finding the average update stream size. |
| 95 size_in_queue_ += update_stream_size_; |
| 96 size_queue_.push_back(update_stream_size_); |
| 97 if (size_queue_.size() > kAverageUpdateStream) { |
| 98 size_in_queue_ -= size_queue_.front(); |
| 99 size_queue_.pop_front(); |
| 100 DCHECK_GE(size_in_queue_, 0); |
| 101 } |
| 102 update_stream_size_ = 0; |
| 103 } |
| 104 |
| 105 int ClientConnection::GetPendingUpdateStreamMessages() { |
| 106 DCHECK_EQ(loop_, MessageLoop::current()); |
| 107 |
| 108 if (!size_queue_.size()) |
| 109 return 0; |
| 110 int average_size = size_in_queue_ / size_queue_.size(); |
| 111 if (!average_size) |
| 112 return 0; |
| 113 return channel_->write_buffer_size() / average_size; |
| 114 } |
| 115 |
| 116 void ClientConnection::Disconnect() { |
| 117 DCHECK_EQ(loop_, MessageLoop::current()); |
| 118 |
| 119 DCHECK(channel_.get()); |
| 120 channel_->Close(); |
| 121 } |
| 122 |
| 123 void ClientConnection::OnStateChange(JingleChannel* channel, |
| 124 JingleChannel::State state) { |
| 125 DCHECK(channel); |
| 126 loop_->PostTask(FROM_HERE, |
| 127 NewRunnableMethod(this, &ClientConnection::StateChangeTask, state)); |
| 128 } |
| 129 |
| 130 void ClientConnection::OnPacketReceived(JingleChannel* channel, |
| 131 scoped_refptr<DataBuffer> data) { |
| 132 DCHECK_EQ(channel_.get(), channel); |
| 133 loop_->PostTask(FROM_HERE, |
| 134 NewRunnableMethod(this, &ClientConnection::PacketReceivedTask, data)); |
| 135 } |
| 136 |
| 137 void ClientConnection::StateChangeTask(JingleChannel::State state) { |
| 138 DCHECK_EQ(loop_, MessageLoop::current()); |
| 139 |
| 140 DCHECK(handler_); |
| 141 switch(state) { |
| 142 case JingleChannel::CONNECTING: |
| 143 break; |
| 144 // Don't care about this message. |
| 145 case JingleChannel::OPEN: |
| 146 handler_->OnConnectionOpened(this); |
| 147 break; |
| 148 case JingleChannel::CLOSED: |
| 149 handler_->OnConnectionClosed(this); |
| 150 break; |
| 151 case JingleChannel::FAILED: |
| 152 handler_->OnConnectionFailed(this); |
| 153 break; |
| 154 default: |
| 155 // We shouldn't receive other states. |
| 156 NOTREACHED(); |
| 157 } |
| 158 } |
| 159 |
| 160 void ClientConnection::PacketReceivedTask(scoped_refptr<DataBuffer> data) { |
| 161 DCHECK_EQ(loop_, MessageLoop::current()); |
| 162 |
| 163 // Use the decoder to parse incoming data. |
| 164 DCHECK(decoder_.get()); |
| 165 ClientMessageList list; |
| 166 decoder_->ParseClientMessages(data, &list); |
| 167 |
| 168 // Then submit the messages to the handler. |
| 169 DCHECK(handler_); |
| 170 handler_->HandleMessages(this, &list); |
| 171 } |
| 172 |
| 173 } // namespace remoting |
OLD | NEW |