// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "remoting/protocol/fake_authenticator.h" #include "base/message_loop/message_loop.h" #include "base/strings/string_number_conversions.h" #include "net/base/io_buffer.h" #include "net/socket/stream_socket.h" #include "remoting/base/constants.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" namespace remoting { namespace protocol { FakeChannelAuthenticator::FakeChannelAuthenticator(bool accept, bool async) : result_(accept ? net::OK : net::ERR_FAILED), async_(async), did_read_bytes_(false), did_write_bytes_(false), weak_factory_(this) { } FakeChannelAuthenticator::~FakeChannelAuthenticator() { } void FakeChannelAuthenticator::SecureAndAuthenticate( scoped_ptr<net::StreamSocket> socket, const DoneCallback& done_callback) { socket_ = socket.Pass(); if (async_) { done_callback_ = done_callback; scoped_refptr<net::IOBuffer> write_buf = new net::IOBuffer(1); write_buf->data()[0] = 0; int result = socket_->Write(write_buf.get(), 1, base::Bind(&FakeChannelAuthenticator::OnAuthBytesWritten, weak_factory_.GetWeakPtr())); if (result != net::ERR_IO_PENDING) { // This will not call the callback because |did_read_bytes_| is // still set to false. OnAuthBytesWritten(result); } scoped_refptr<net::IOBuffer> read_buf = new net::IOBuffer(1); result = socket_->Read(read_buf.get(), 1, base::Bind(&FakeChannelAuthenticator::OnAuthBytesRead, weak_factory_.GetWeakPtr())); if (result != net::ERR_IO_PENDING) OnAuthBytesRead(result); } else { if (result_ != net::OK) socket_.reset(); done_callback.Run(result_, socket_.Pass()); } } void FakeChannelAuthenticator::OnAuthBytesWritten(int result) { EXPECT_EQ(1, result); EXPECT_FALSE(did_write_bytes_); did_write_bytes_ = true; if (did_read_bytes_) done_callback_.Run(result_, socket_.Pass()); } void FakeChannelAuthenticator::OnAuthBytesRead(int result) { EXPECT_EQ(1, result); EXPECT_FALSE(did_read_bytes_); did_read_bytes_ = true; if (did_write_bytes_) done_callback_.Run(result_, socket_.Pass()); } FakeAuthenticator::FakeAuthenticator( Type type, int round_trips, Action action, bool async) : type_(type), round_trips_(round_trips), action_(action), async_(async), messages_(0) { } FakeAuthenticator::~FakeAuthenticator() { } Authenticator::State FakeAuthenticator::state() const { EXPECT_LE(messages_, round_trips_ * 2); if (messages_ >= round_trips_ * 2) { if (action_ == REJECT) { return REJECTED; } else { return ACCEPTED; } } // Don't send the last message if this is a host that wants to // reject a connection. if (messages_ == round_trips_ * 2 - 1 && type_ == HOST && action_ == REJECT) { return REJECTED; } // We are not done yet. process next message. if ((messages_ % 2 == 0 && type_ == CLIENT) || (messages_ % 2 == 1 && type_ == HOST)) { return MESSAGE_READY; } else { return WAITING_MESSAGE; } } Authenticator::RejectionReason FakeAuthenticator::rejection_reason() const { EXPECT_EQ(REJECTED, state()); return INVALID_CREDENTIALS; } void FakeAuthenticator::ProcessMessage(const buzz::XmlElement* message, const base::Closure& resume_callback) { EXPECT_EQ(WAITING_MESSAGE, state()); std::string id = message->TextNamed(buzz::QName(kChromotingXmlNamespace, "id")); EXPECT_EQ(id, base::IntToString(messages_)); ++messages_; resume_callback.Run(); } scoped_ptr<buzz::XmlElement> FakeAuthenticator::GetNextMessage() { EXPECT_EQ(MESSAGE_READY, state()); scoped_ptr<buzz::XmlElement> result(new buzz::XmlElement( buzz::QName(kChromotingXmlNamespace, "authentication"))); buzz::XmlElement* id = new buzz::XmlElement( buzz::QName(kChromotingXmlNamespace, "id")); id->AddText(base::IntToString(messages_)); result->AddElement(id); ++messages_; return result.Pass(); } scoped_ptr<ChannelAuthenticator> FakeAuthenticator::CreateChannelAuthenticator() const { EXPECT_EQ(ACCEPTED, state()); return scoped_ptr<ChannelAuthenticator>( new FakeChannelAuthenticator(action_ != REJECT_CHANNEL, async_)); } FakeHostAuthenticatorFactory::FakeHostAuthenticatorFactory( int round_trips, FakeAuthenticator::Action action, bool async) : round_trips_(round_trips), action_(action), async_(async) { } FakeHostAuthenticatorFactory::~FakeHostAuthenticatorFactory() { } scoped_ptr<Authenticator> FakeHostAuthenticatorFactory::CreateAuthenticator( const std::string& local_jid, const std::string& remote_jid, const buzz::XmlElement* first_message) { return scoped_ptr<Authenticator>(new FakeAuthenticator( FakeAuthenticator::HOST, round_trips_, action_, async_)); } } // namespace protocol } // namespace remoting