1 // Copyright (c) 2012 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/fake_authenticator.h" 6 7 #include "base/message_loop/message_loop.h" 8 #include "base/strings/string_number_conversions.h" 9 #include "net/base/io_buffer.h" 10 #include "net/base/net_errors.h" 11 #include "net/socket/stream_socket.h" 12 #include "remoting/base/constants.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" 15 16 namespace remoting { 17 namespace protocol { 18 19 FakeChannelAuthenticator::FakeChannelAuthenticator(bool accept, bool async) 20 : result_(accept ? net::OK : net::ERR_FAILED), 21 async_(async), 22 did_read_bytes_(false), 23 did_write_bytes_(false), 24 weak_factory_(this) { 25 } 26 27 FakeChannelAuthenticator::~FakeChannelAuthenticator() { 28 } 29 30 void FakeChannelAuthenticator::SecureAndAuthenticate( 31 scoped_ptr<net::StreamSocket> socket, 32 const DoneCallback& done_callback) { 33 socket_ = socket.Pass(); 34 35 if (async_) { 36 done_callback_ = done_callback; 37 38 if (result_ != net::OK) { 39 // Don't write anything if we are going to reject auth to make test 40 // ordering deterministic. 41 did_write_bytes_ = true; 42 } else { 43 scoped_refptr<net::IOBuffer> write_buf = new net::IOBuffer(1); 44 write_buf->data()[0] = 0; 45 int result = socket_->Write( 46 write_buf.get(), 1, 47 base::Bind(&FakeChannelAuthenticator::OnAuthBytesWritten, 48 weak_factory_.GetWeakPtr())); 49 if (result != net::ERR_IO_PENDING) { 50 // This will not call the callback because |did_read_bytes_| is 51 // still set to false. 52 OnAuthBytesWritten(result); 53 } 54 } 55 56 scoped_refptr<net::IOBuffer> read_buf = new net::IOBuffer(1); 57 int result = 58 socket_->Read(read_buf.get(), 1, 59 base::Bind(&FakeChannelAuthenticator::OnAuthBytesRead, 60 weak_factory_.GetWeakPtr())); 61 if (result != net::ERR_IO_PENDING) 62 OnAuthBytesRead(result); 63 } else { 64 CallDoneCallback(); 65 } 66 } 67 68 void FakeChannelAuthenticator::OnAuthBytesWritten(int result) { 69 EXPECT_EQ(1, result); 70 EXPECT_FALSE(did_write_bytes_); 71 did_write_bytes_ = true; 72 if (did_read_bytes_) 73 CallDoneCallback(); 74 } 75 76 void FakeChannelAuthenticator::OnAuthBytesRead(int result) { 77 EXPECT_EQ(1, result); 78 EXPECT_FALSE(did_read_bytes_); 79 did_read_bytes_ = true; 80 if (did_write_bytes_) 81 CallDoneCallback(); 82 } 83 84 void FakeChannelAuthenticator::CallDoneCallback() { 85 DoneCallback callback = done_callback_; 86 done_callback_.Reset(); 87 if (result_ != net::OK) 88 socket_.reset(); 89 callback.Run(result_, socket_.Pass()); 90 } 91 92 FakeAuthenticator::FakeAuthenticator( 93 Type type, int round_trips, Action action, bool async) 94 : type_(type), 95 round_trips_(round_trips), 96 action_(action), 97 async_(async), 98 messages_(0), 99 messages_till_started_(0) { 100 } 101 102 FakeAuthenticator::~FakeAuthenticator() { 103 } 104 105 void FakeAuthenticator::set_messages_till_started(int messages) { 106 messages_till_started_ = messages; 107 } 108 109 Authenticator::State FakeAuthenticator::state() const { 110 EXPECT_LE(messages_, round_trips_ * 2); 111 if (messages_ >= round_trips_ * 2) { 112 if (action_ == REJECT) { 113 return REJECTED; 114 } else { 115 return ACCEPTED; 116 } 117 } 118 119 // Don't send the last message if this is a host that wants to 120 // reject a connection. 121 if (messages_ == round_trips_ * 2 - 1 && 122 type_ == HOST && action_ == REJECT) { 123 return REJECTED; 124 } 125 126 // We are not done yet. process next message. 127 if ((messages_ % 2 == 0 && type_ == CLIENT) || 128 (messages_ % 2 == 1 && type_ == HOST)) { 129 return MESSAGE_READY; 130 } else { 131 return WAITING_MESSAGE; 132 } 133 } 134 135 bool FakeAuthenticator::started() const { 136 return messages_ > messages_till_started_; 137 } 138 139 Authenticator::RejectionReason FakeAuthenticator::rejection_reason() const { 140 EXPECT_EQ(REJECTED, state()); 141 return INVALID_CREDENTIALS; 142 } 143 144 void FakeAuthenticator::ProcessMessage(const buzz::XmlElement* message, 145 const base::Closure& resume_callback) { 146 EXPECT_EQ(WAITING_MESSAGE, state()); 147 std::string id = 148 message->TextNamed(buzz::QName(kChromotingXmlNamespace, "id")); 149 EXPECT_EQ(id, base::IntToString(messages_)); 150 ++messages_; 151 resume_callback.Run(); 152 } 153 154 scoped_ptr<buzz::XmlElement> FakeAuthenticator::GetNextMessage() { 155 EXPECT_EQ(MESSAGE_READY, state()); 156 157 scoped_ptr<buzz::XmlElement> result(new buzz::XmlElement( 158 buzz::QName(kChromotingXmlNamespace, "authentication"))); 159 buzz::XmlElement* id = new buzz::XmlElement( 160 buzz::QName(kChromotingXmlNamespace, "id")); 161 id->AddText(base::IntToString(messages_)); 162 result->AddElement(id); 163 164 ++messages_; 165 return result.Pass(); 166 } 167 168 scoped_ptr<ChannelAuthenticator> 169 FakeAuthenticator::CreateChannelAuthenticator() const { 170 EXPECT_EQ(ACCEPTED, state()); 171 return scoped_ptr<ChannelAuthenticator>( 172 new FakeChannelAuthenticator(action_ != REJECT_CHANNEL, async_)); 173 } 174 175 FakeHostAuthenticatorFactory::FakeHostAuthenticatorFactory( 176 int round_trips, int messages_till_started, 177 FakeAuthenticator::Action action, bool async) 178 : round_trips_(round_trips), 179 messages_till_started_(messages_till_started), 180 action_(action), async_(async) { 181 } 182 183 FakeHostAuthenticatorFactory::~FakeHostAuthenticatorFactory() { 184 } 185 186 scoped_ptr<Authenticator> FakeHostAuthenticatorFactory::CreateAuthenticator( 187 const std::string& local_jid, 188 const std::string& remote_jid, 189 const buzz::XmlElement* first_message) { 190 FakeAuthenticator* authenticator = new FakeAuthenticator( 191 FakeAuthenticator::HOST, round_trips_, action_, async_); 192 authenticator->set_messages_till_started(messages_till_started_); 193 194 scoped_ptr<Authenticator> result(authenticator); 195 return result.Pass(); 196 } 197 198 } // namespace protocol 199 } // namespace remoting 200