// 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 "net/test/spawner_communicator.h"

#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/stringprintf.h"
#include "base/supports_user_data.h"
#include "base/test/test_timeouts.h"
#include "base/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "googleurl/src/gurl.h"
#include "net/base/net_util.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request_test_util.h"

namespace net {

namespace {

GURL GenerateSpawnerCommandURL(const std::string& command, uint16 port) {
  // Always performs HTTP request for sending command to the spawner server.
  return GURL(base::StringPrintf("%s:%u/%s", "http://127.0.0.1", port,
                                 command.c_str()));
}

int kBufferSize = 2048;

// A class to hold all data needed to send a command to spawner server.
class SpawnerRequestData : public base::SupportsUserData::Data {
 public:
  SpawnerRequestData(int id, int* result_code, std::string* data_received)
      : request_id_(id),
        buf_(new IOBuffer(kBufferSize)),
        result_code_(result_code),
        data_received_(data_received),
        response_started_count_(0) {
    DCHECK(result_code);
    *result_code_ = OK;
    DCHECK(data_received);
    data_received_->clear();
  }

  virtual ~SpawnerRequestData() {}

  bool DoesRequestIdMatch(int request_id) const {
    return request_id_ == request_id;
  }

  IOBuffer* buf() const { return buf_.get(); }

  bool IsResultOK() const { return *result_code_ == OK; }

  void ClearReceivedData() { data_received_->clear(); }

  void SetResultCode(int result_code) { *result_code_ = result_code; }

  void IncreaseResponseStartedCount() { response_started_count_++; }

  int response_started_count() const { return response_started_count_; }

  // Write data read from URLRequest::Read() to |data_received_|. Returns true
  // if |num_bytes| is great than 0. |num_bytes| is 0 for EOF, < 0 on errors.
  bool ConsumeBytesRead(int num_bytes) {
    // Error while reading, or EOF.
    if (num_bytes <= 0)
      return false;

    data_received_->append(buf_->data(), num_bytes);
    return true;
  }

 private:
  // Unique ID for the current request.
  int request_id_;

  // Buffer that URLRequest writes into.
  scoped_refptr<IOBuffer> buf_;

  // Holds the error condition that was hit on the current request, or OK.
  int* result_code_;

  // Data received from server;
  std::string* data_received_;

  // Used to track how many times the OnResponseStarted get called after
  // sending a command to spawner server.
  int response_started_count_;

  DISALLOW_COPY_AND_ASSIGN(SpawnerRequestData);
};

}  // namespace

SpawnerCommunicator::SpawnerCommunicator(uint16 port)
    : io_thread_("spawner_communicator"),
      event_(false, false),
      port_(port),
      next_id_(0),
      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
      is_running_(false) {}

SpawnerCommunicator::~SpawnerCommunicator() {}

void SpawnerCommunicator::WaitForResponse() {
  DCHECK_NE(MessageLoop::current(), io_thread_.message_loop());
  event_.Wait();
  event_.Reset();
}

void SpawnerCommunicator::StartIOThread() {
  DCHECK_NE(MessageLoop::current(), io_thread_.message_loop());
  if (is_running_)
    return;

  allowed_port_.reset(new ScopedPortException(port_));
  base::Thread::Options options;
  options.message_loop_type = MessageLoop::TYPE_IO;
  is_running_ = io_thread_.StartWithOptions(options);
  DCHECK(is_running_);
}

void SpawnerCommunicator::Shutdown() {
  DCHECK_NE(MessageLoop::current(), io_thread_.message_loop());
  DCHECK(is_running_);
  DCHECK(!cur_request_.get());
  io_thread_.Stop();
  allowed_port_.reset();
}

void SpawnerCommunicator::SendCommandAndWaitForResult(
    const std::string& command,
    const std::string& post_data,
    int* result_code,
    std::string* data_received) {
  if (!result_code || !data_received)
    return;
  // Start the communicator thread to talk to test server spawner.
  StartIOThread();
  DCHECK(io_thread_.message_loop());

  // Since the method will be blocked until SpawnerCommunicator gets result
  // from the spawner server or timed-out. It's safe to use base::Unretained
  // when using base::Bind.
  io_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
      &SpawnerCommunicator::SendCommandAndWaitForResultOnIOThread,
      base::Unretained(this), command, post_data, result_code, data_received));
  WaitForResponse();
}

void SpawnerCommunicator::SendCommandAndWaitForResultOnIOThread(
    const std::string& command,
    const std::string& post_data,
    int* result_code,
    std::string* data_received) {
  MessageLoop* loop = io_thread_.message_loop();
  DCHECK(loop);
  DCHECK_EQ(MessageLoop::current(), loop);

  // Prepare the URLRequest for sending the command.
  DCHECK(!cur_request_.get());
  cur_request_.reset(new URLRequest(GenerateSpawnerCommandURL(command, port_),
                                    this));
  DCHECK(cur_request_.get());
  int current_request_id = ++next_id_;
  SpawnerRequestData* data = new SpawnerRequestData(current_request_id,
                                                    result_code,
                                                    data_received);
  DCHECK(data);
  cur_request_->SetUserData(this, data);

  // Build the URLRequest.
  scoped_refptr<TestURLRequestContext> context(new TestURLRequestContext());
  cur_request_->set_context(context);
  if (post_data.empty()) {
    cur_request_->set_method("GET");
  } else {
    cur_request_->set_method("POST");
    cur_request_->AppendBytesToUpload(post_data.c_str(), post_data.size());
    net::HttpRequestHeaders headers;
    headers.SetHeader(net::HttpRequestHeaders::kContentType,
                      "application/json");
    cur_request_->SetExtraRequestHeaders(headers);
  }

  // Post a task to timeout this request if it takes too long.
  MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&SpawnerCommunicator::OnTimeout, weak_factory_.GetWeakPtr(),
                 current_request_id),
      TestTimeouts::action_max_timeout());

  // Start the request.
  cur_request_->Start();
}

void SpawnerCommunicator::OnTimeout(int id) {
  // Timeout tasks may outlive the URLRequest they reference. Make sure it
  // is still applicable.
  if (!cur_request_.get())
    return;
  SpawnerRequestData* data =
      static_cast<SpawnerRequestData*>(cur_request_->GetUserData(this));
  DCHECK(data);

  if (!data->DoesRequestIdMatch(id))
    return;
  // Set the result code and cancel the timed-out task.
  data->SetResultCode(ERR_TIMED_OUT);
  cur_request_->Cancel();
  OnSpawnerCommandCompleted(cur_request_.get());
}

void SpawnerCommunicator::OnSpawnerCommandCompleted(URLRequest* request) {
  if (!cur_request_.get())
    return;
  DCHECK_EQ(request, cur_request_.get());
  SpawnerRequestData* data =
      static_cast<SpawnerRequestData*>(cur_request_->GetUserData(this));
  DCHECK(data);

  // If request is faild,return the error code.
  if (!cur_request_->status().is_success())
    data->SetResultCode(cur_request_->status().error());

  if (!data->IsResultOK()) {
    LOG(ERROR) << "request failed, status: "
               << static_cast<int>(request->status().status())
               << ", error: " << request->status().error();
    // Clear the buffer of received data if any net error happened.
    data->ClearReceivedData();
  } else {
    DCHECK_EQ(1, data->response_started_count());
  }

  // Clear current request to indicate the completion of sending a command
  // to spawner server and getting the result.
  cur_request_.reset();
  // Wakeup the caller in user thread.
  event_.Signal();
}

void SpawnerCommunicator::ReadResult(URLRequest* request) {
  DCHECK_EQ(request, cur_request_.get());
  SpawnerRequestData* data =
      static_cast<SpawnerRequestData*>(cur_request_->GetUserData(this));
  DCHECK(data);

  IOBuffer* buf = data->buf();
  // Read as many bytes as are available synchronously.
  while (true) {
    int num_bytes;
    if (!request->Read(buf, kBufferSize, &num_bytes)) {
      // Check whether the read failed synchronously.
      if (!request->status().is_io_pending())
        OnSpawnerCommandCompleted(request);
      return;
    }
    if (!data->ConsumeBytesRead(num_bytes)) {
      OnSpawnerCommandCompleted(request);
      return;
    }
  }
}

void SpawnerCommunicator::OnResponseStarted(URLRequest* request) {
  DCHECK_EQ(request, cur_request_.get());
  SpawnerRequestData* data =
      static_cast<SpawnerRequestData*>(cur_request_->GetUserData(this));
  DCHECK(data);

  data->IncreaseResponseStartedCount();

  if (!request->status().is_success()) {
    OnSpawnerCommandCompleted(request);
    return;
  }

  // Require HTTP responses to have a success status code.
  if (request->GetResponseCode() != 200) {
    LOG(ERROR) << "Spawner server returned bad status: "
               << request->response_headers()->GetStatusLine();
    data->SetResultCode(ERR_FAILED);
    request->Cancel();
    OnSpawnerCommandCompleted(request);
    return;
  }

  ReadResult(request);
}

void SpawnerCommunicator::OnReadCompleted(URLRequest* request, int num_bytes) {
  if (!cur_request_.get())
    return;
  DCHECK_EQ(request, cur_request_.get());
  SpawnerRequestData* data =
      static_cast<SpawnerRequestData*>(cur_request_->GetUserData(this));
  DCHECK(data);

  if (data->ConsumeBytesRead(num_bytes)) {
    // Keep reading.
    ReadResult(request);
  } else {
    OnSpawnerCommandCompleted(request);
  }
}

bool SpawnerCommunicator::StartServer(const std::string& arguments,
                                      uint16* port) {
  *port = 0;
  // Send the start command to spawner server to start the Python test server
  // on remote machine.
  std::string server_return_data;
  int result_code;
  SendCommandAndWaitForResult("start", arguments, &result_code,
                              &server_return_data);
  if (OK != result_code || server_return_data.empty())
    return false;

  // Check whether the data returned from spawner server is JSON-formatted.
  base::JSONReader json_reader;
  scoped_ptr<base::Value> value(json_reader.JsonToValue(server_return_data,
                                                        true, false));
  if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) {
    LOG(ERROR) << "Invalid server data: " << server_return_data.c_str();
    return false;
  }

  // Check whether spawner server returns valid data.
  DictionaryValue* server_data = static_cast<DictionaryValue*>(value.get());
  std::string message;
  if (!server_data->GetString("message", &message) || message != "started") {
    LOG(ERROR) << "Invalid message in server data: ";
    return false;
  }
  int int_port;
  if (!server_data->GetInteger("port", &int_port) || int_port <= 0 ||
      int_port > kuint16max) {
    LOG(ERROR) << "Invalid port value: " << int_port;
    return false;
  }
  *port = static_cast<uint16>(int_port);
  return true;
}

bool SpawnerCommunicator::StopServer() {
  // It's OK to stop the SpawnerCommunicator without starting it. Some tests
  // have test server on their test fixture but do not actually use it.
  if (!is_running_)
    return true;

  // When the test is done, ask the test server spawner to kill the test server
  // on the remote machine.
  std::string server_return_data;
  int result_code;
  SendCommandAndWaitForResult("kill", "", &result_code, &server_return_data);
  if (OK != result_code || server_return_data != "killed")
    return false;
  Shutdown();
  return true;
}

}  // namespace net

