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.
5 #include "remoting/host/gnubby_socket.h"
7 #include "base/macros.h"
8 #include "base/timer/timer.h"
9 #include "net/socket/stream_listen_socket.h"
15 const size_t kRequestSizeBytes
= 4;
16 const size_t kMaxRequestLength
= 16384;
17 const unsigned int kRequestTimeoutSeconds
= 60;
20 const char kSshError
[] = {0x05};
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
),
33 GnubbySocket::~GnubbySocket() {}
35 void GnubbySocket::AddRequestData(const char* data
, int data_len
) {
36 DCHECK(CalledOnValidThread());
38 request_data_
.insert(request_data_
.end(), data
, data
+ data_len
);
42 void GnubbySocket::GetAndClearRequestData(std::string
* data_out
) {
43 DCHECK(CalledOnValidThread());
44 DCHECK(IsRequestComplete() && !IsRequestTooLarge());
46 // The request size is not part of the data; don't send it.
47 data_out
->assign(request_data_
.begin() + kRequestSizeBytes
,
49 request_data_
.clear();
52 bool GnubbySocket::IsRequestComplete() const {
53 DCHECK(CalledOnValidThread());
55 if (request_data_
.size() < kRequestSizeBytes
)
57 return GetRequestLength() <= request_data_
.size();
60 bool GnubbySocket::IsRequestTooLarge() const {
61 DCHECK(CalledOnValidThread());
63 if (request_data_
.size() < kRequestSizeBytes
)
65 return GetRequestLength() > kMaxRequestLength
;
68 void GnubbySocket::SendResponse(const std::string
& response_data
) {
69 DCHECK(CalledOnValidThread());
71 socket_
->Send(GetResponseLengthAsBytes(response_data
));
72 socket_
->Send(response_data
);
76 void GnubbySocket::SendSshError() {
77 DCHECK(CalledOnValidThread());
79 SendResponse(std::string(kSshError
, arraysize(kSshError
)));
82 bool GnubbySocket::IsSocket(net::StreamListenSocket
* socket
) const {
83 return socket
== socket_
.get();
86 void GnubbySocket::SetTimerForTesting(scoped_ptr
<base::Timer
> timer
) {
87 timer
->Start(FROM_HERE
, timer_
->GetCurrentDelay(), timer_
->user_task());
88 timer_
= timer
.Pass();
91 size_t GnubbySocket::GetRequestLength() const {
92 DCHECK(request_data_
.size() >= kRequestSizeBytes
);
94 return ((request_data_
[0] & 255) << 24) + ((request_data_
[1] & 255) << 16) +
95 ((request_data_
[2] & 255) << 8) + (request_data_
[3] & 255) +
99 std::string
GnubbySocket::GetResponseLengthAsBytes(
100 const std::string
& response
) const {
101 std::string response_len
;
102 int len
= response
.size();
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);
112 void GnubbySocket::ResetTimer() {
113 if (timer_
->IsRunning())
117 } // namespace remoting