/*
 * libjingle
 * Copyright 2015 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/app/webrtc/dtlsidentitystore.h"

#include "talk/app/webrtc/webrtcsessiondescriptionfactory.h"
#include "webrtc/base/logging.h"

using webrtc::DTLSIdentityRequestObserver;
using webrtc::WebRtcSessionDescriptionFactory;

namespace webrtc {

namespace {

enum {
  MSG_GENERATE_IDENTITY,
  MSG_GENERATE_IDENTITY_RESULT,
  MSG_RETURN_FREE_IDENTITY
};

typedef rtc::ScopedMessageData<rtc::SSLIdentity> IdentityResultMessageData;

}  // namespace

// This class runs on the worker thread to generate the identity. It's necessary
// to separate this class from DtlsIdentityStore so that it can live on the
// worker thread after DtlsIdentityStore is destroyed.
class DtlsIdentityStore::WorkerTask : public sigslot::has_slots<>,
                                      public rtc::MessageHandler {
 public:
  explicit WorkerTask(DtlsIdentityStore* store) : store_(store) {
    store_->SignalDestroyed.connect(this, &WorkerTask::OnStoreDestroyed);
  };

  virtual ~WorkerTask() {}

  void GenerateIdentity() {
    rtc::scoped_ptr<rtc::SSLIdentity> identity(
      rtc::SSLIdentity::Generate(DtlsIdentityStore::kIdentityName));

    {
      rtc::CritScope cs(&cs_);
      if (store_) {
        store_->PostGenerateIdentityResult_w(identity.Pass());
      }
    }
  }

  void OnMessage(rtc::Message* msg) override {
    DCHECK(msg->message_id == MSG_GENERATE_IDENTITY);
    GenerateIdentity();
    // Deleting msg->pdata will destroy the WorkerTask.
    delete msg->pdata;
  }

 private:
  void OnStoreDestroyed() {
    rtc::CritScope cs(&cs_);
    store_ = NULL;
  }

  rtc::CriticalSection cs_;
  DtlsIdentityStore* store_;
};

// Arbitrary constant used as common name for the identity.
// Chosen to make the certificates more readable.
const char DtlsIdentityStore::kIdentityName[] = "WebRTC";

DtlsIdentityStore::DtlsIdentityStore(rtc::Thread* signaling_thread,
                                     rtc::Thread* worker_thread)
    : signaling_thread_(signaling_thread),
      worker_thread_(worker_thread),
      pending_jobs_(0) {}

DtlsIdentityStore::~DtlsIdentityStore() {
  SignalDestroyed();
}

void DtlsIdentityStore::Initialize() {
  // Do not aggressively generate the free identity if the worker thread and the
  // signaling thread are the same.
  if (worker_thread_ != signaling_thread_) {
    GenerateIdentity();
  }
}

void DtlsIdentityStore::RequestIdentity(DTLSIdentityRequestObserver* observer) {
  DCHECK(rtc::Thread::Current() == signaling_thread_);
  DCHECK(observer);

  // Must return the free identity async.
  if (free_identity_.get()) {
    IdentityResultMessageData* msg =
        new IdentityResultMessageData(free_identity_.release());
    signaling_thread_->Post(this, MSG_RETURN_FREE_IDENTITY, msg);
  }

  pending_observers_.push(observer);
  GenerateIdentity();
}

void DtlsIdentityStore::OnMessage(rtc::Message* msg) {
  switch (msg->message_id) {
    case MSG_GENERATE_IDENTITY_RESULT: {
      rtc::scoped_ptr<IdentityResultMessageData> pdata(
          static_cast<IdentityResultMessageData*>(msg->pdata));
      OnIdentityGenerated(pdata->data().Pass());
      break;
    }
    case MSG_RETURN_FREE_IDENTITY: {
      rtc::scoped_ptr<IdentityResultMessageData> pdata(
          static_cast<IdentityResultMessageData*>(msg->pdata));
      ReturnIdentity(pdata->data().Pass());
      break;
    }
  }
}

bool DtlsIdentityStore::HasFreeIdentityForTesting() const {
  return free_identity_.get();
}

void DtlsIdentityStore::GenerateIdentity() {
  pending_jobs_++;
  LOG(LS_VERBOSE) << "New DTLS identity generation is posted, "
                  << "pending_identities=" << pending_jobs_;

  WorkerTask* task = new WorkerTask(this);
  // The WorkerTask is owned by the message data to make sure it will not be
  // leaked even if the task does not get run.
  IdentityTaskMessageData* msg = new IdentityTaskMessageData(task);
  worker_thread_->Post(task, MSG_GENERATE_IDENTITY, msg);
}

void DtlsIdentityStore::OnIdentityGenerated(
    rtc::scoped_ptr<rtc::SSLIdentity> identity) {
  DCHECK(rtc::Thread::Current() == signaling_thread_);

  pending_jobs_--;
  LOG(LS_VERBOSE) << "A DTLS identity generation job returned, "
                  << "pending_identities=" << pending_jobs_;

  if (pending_observers_.empty()) {
    if (!free_identity_.get()) {
      free_identity_.reset(identity.release());
      LOG(LS_VERBOSE) << "A free DTLS identity is saved";
    }
    return;
  }
  ReturnIdentity(identity.Pass());
}

void DtlsIdentityStore::ReturnIdentity(
    rtc::scoped_ptr<rtc::SSLIdentity> identity) {
  DCHECK(!free_identity_.get());
  DCHECK(!pending_observers_.empty());

  rtc::scoped_refptr<DTLSIdentityRequestObserver> observer =
      pending_observers_.front();
  pending_observers_.pop();

  if (identity.get()) {
    observer->OnSuccessWithIdentityObj(identity.Pass());
  } else {
    // Pass an arbitrary error code.
    observer->OnFailure(0);
    LOG(LS_WARNING) << "Failed to generate SSL identity";
  }

  // Do not aggressively generate the free identity if the worker thread and the
  // signaling thread are the same.
  if (worker_thread_ != signaling_thread_ &&
      pending_observers_.empty() &&
      pending_jobs_ == 0) {
      // Generate a free identity in the background.
      GenerateIdentity();
  }
}

void DtlsIdentityStore::PostGenerateIdentityResult_w(
    rtc::scoped_ptr<rtc::SSLIdentity> identity) {
  DCHECK(rtc::Thread::Current() == worker_thread_);

  IdentityResultMessageData* msg =
      new IdentityResultMessageData(identity.release());
  signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg);
}
}  // namespace webrtc
