• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/host/gnubby_socket.h"
6 
7 #include "base/macros.h"
8 #include "base/timer/timer.h"
9 #include "net/socket/stream_listen_socket.h"
10 
11 namespace remoting {
12 
13 namespace {
14 
15 const size_t kRequestSizeBytes = 4;
16 const size_t kMaxRequestLength = 16384;
17 const unsigned int kRequestTimeoutSeconds = 60;
18 
19 // SSH Failure Code
20 const char kSshError[] = {0x05};
21 
22 }  // namespace
23 
GnubbySocket(scoped_ptr<net::StreamListenSocket> socket,const base::Closure & timeout_callback)24 GnubbySocket::GnubbySocket(scoped_ptr<net::StreamListenSocket> socket,
25                            const base::Closure& timeout_callback)
26     : socket_(socket.Pass()) {
27   timer_.reset(new base::Timer(false, false));
28   timer_->Start(FROM_HERE,
29                 base::TimeDelta::FromSeconds(kRequestTimeoutSeconds),
30                 timeout_callback);
31 }
32 
~GnubbySocket()33 GnubbySocket::~GnubbySocket() {}
34 
AddRequestData(const char * data,int data_len)35 void GnubbySocket::AddRequestData(const char* data, int data_len) {
36   DCHECK(CalledOnValidThread());
37 
38   request_data_.insert(request_data_.end(), data, data + data_len);
39   ResetTimer();
40 }
41 
GetAndClearRequestData(std::string * data_out)42 void GnubbySocket::GetAndClearRequestData(std::string* data_out) {
43   DCHECK(CalledOnValidThread());
44   DCHECK(IsRequestComplete() && !IsRequestTooLarge());
45 
46   // The request size is not part of the data; don't send it.
47   data_out->assign(request_data_.begin() + kRequestSizeBytes,
48                    request_data_.end());
49   request_data_.clear();
50 }
51 
IsRequestComplete() const52 bool GnubbySocket::IsRequestComplete() const {
53   DCHECK(CalledOnValidThread());
54 
55   if (request_data_.size() < kRequestSizeBytes)
56     return false;
57   return GetRequestLength() <= request_data_.size();
58 }
59 
IsRequestTooLarge() const60 bool GnubbySocket::IsRequestTooLarge() const {
61   DCHECK(CalledOnValidThread());
62 
63   if (request_data_.size() < kRequestSizeBytes)
64     return false;
65   return GetRequestLength() > kMaxRequestLength;
66 }
67 
SendResponse(const std::string & response_data)68 void GnubbySocket::SendResponse(const std::string& response_data) {
69   DCHECK(CalledOnValidThread());
70 
71   socket_->Send(GetResponseLengthAsBytes(response_data));
72   socket_->Send(response_data);
73   ResetTimer();
74 }
75 
SendSshError()76 void GnubbySocket::SendSshError() {
77   DCHECK(CalledOnValidThread());
78 
79   SendResponse(std::string(kSshError, arraysize(kSshError)));
80 }
81 
IsSocket(net::StreamListenSocket * socket) const82 bool GnubbySocket::IsSocket(net::StreamListenSocket* socket) const {
83   return socket == socket_.get();
84 }
85 
SetTimerForTesting(scoped_ptr<base::Timer> timer)86 void GnubbySocket::SetTimerForTesting(scoped_ptr<base::Timer> timer) {
87   timer->Start(FROM_HERE, timer_->GetCurrentDelay(), timer_->user_task());
88   timer_ = timer.Pass();
89 }
90 
GetRequestLength() const91 size_t GnubbySocket::GetRequestLength() const {
92   DCHECK(request_data_.size() >= kRequestSizeBytes);
93 
94   return ((request_data_[0] & 255) << 24) + ((request_data_[1] & 255) << 16) +
95          ((request_data_[2] & 255) << 8) + (request_data_[3] & 255) +
96          kRequestSizeBytes;
97 }
98 
GetResponseLengthAsBytes(const std::string & response) const99 std::string GnubbySocket::GetResponseLengthAsBytes(
100     const std::string& response) const {
101   std::string response_len;
102   int len = response.size();
103 
104   response_len.push_back((len >> 24) & 255);
105   response_len.push_back((len >> 16) & 255);
106   response_len.push_back((len >> 8) & 255);
107   response_len.push_back(len & 255);
108 
109   return response_len;
110 }
111 
ResetTimer()112 void GnubbySocket::ResetTimer() {
113   if (timer_->IsRunning())
114     timer_->Reset();
115 }
116 
117 }  // namespace remoting
118