Home | History | Annotate | Download | only in protocol
      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