/*
 *  Copyright 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/base/rtccertificategenerator.h"

#include <algorithm>
#include <memory>

#include "webrtc/base/checks.h"
#include "webrtc/base/sslidentity.h"

namespace rtc {

namespace {

// A certificates' subject and issuer name.
const char kIdentityName[] = "WebRTC";

uint64_t kYearInSeconds = 365 * 24 * 60 * 60;

enum {
  MSG_GENERATE,
  MSG_GENERATE_DONE,
};

// Helper class for generating certificates asynchronously; a single task
// instance is responsible for a single asynchronous certificate generation
// request. We are using a separate helper class so that a generation request
// can outlive the |RTCCertificateGenerator| that spawned it.
class RTCCertificateGenerationTask : public RefCountInterface,
                                     public MessageHandler {
 public:
  RTCCertificateGenerationTask(
      Thread* signaling_thread,
      Thread* worker_thread,
      const KeyParams& key_params,
      const Optional<uint64_t>& expires_ms,
      const scoped_refptr<RTCCertificateGeneratorCallback>& callback)
      : signaling_thread_(signaling_thread),
        worker_thread_(worker_thread),
        key_params_(key_params),
        expires_ms_(expires_ms),
        callback_(callback) {
    RTC_DCHECK(signaling_thread_);
    RTC_DCHECK(worker_thread_);
    RTC_DCHECK(callback_);
  }
  ~RTCCertificateGenerationTask() override {}

  // Handles |MSG_GENERATE| and its follow-up |MSG_GENERATE_DONE|.
  void OnMessage(Message* msg) override {
    switch (msg->message_id) {
      case MSG_GENERATE:
        RTC_DCHECK(worker_thread_->IsCurrent());

        // Perform the certificate generation work here on the worker thread.
        certificate_ = RTCCertificateGenerator::GenerateCertificate(
            key_params_, expires_ms_);

        // Handle callbacks on signaling thread. Pass on the |msg->pdata|
        // (which references |this| with ref counting) to that thread.
        signaling_thread_->Post(this, MSG_GENERATE_DONE, msg->pdata);
        break;
      case MSG_GENERATE_DONE:
        RTC_DCHECK(signaling_thread_->IsCurrent());

        // Perform callback with result here on the signaling thread.
        if (certificate_) {
          callback_->OnSuccess(certificate_);
        } else {
          callback_->OnFailure();
        }

        // Destroy |msg->pdata| which references |this| with ref counting. This
        // may result in |this| being deleted - do not touch member variables
        // after this line.
        delete msg->pdata;
        return;
      default:
        RTC_NOTREACHED();
    }
  }

 private:
  Thread* const signaling_thread_;
  Thread* const worker_thread_;
  const KeyParams key_params_;
  const Optional<uint64_t> expires_ms_;
  const scoped_refptr<RTCCertificateGeneratorCallback> callback_;
  scoped_refptr<RTCCertificate> certificate_;
};

}  // namespace

// static
scoped_refptr<RTCCertificate>
RTCCertificateGenerator::GenerateCertificate(
    const KeyParams& key_params,
    const Optional<uint64_t>& expires_ms) {
  if (!key_params.IsValid())
    return nullptr;
  SSLIdentity* identity;
  if (!expires_ms) {
    identity = SSLIdentity::Generate(kIdentityName, key_params);
  } else {
    uint64_t expires_s = *expires_ms / 1000;
    // Limit the expiration time to something reasonable (a year). This was
    // somewhat arbitrarily chosen. It also ensures that the value is not too
    // large for the unspecified |time_t|.
    expires_s = std::min(expires_s, kYearInSeconds);
    // TODO(torbjorng): Stop using |time_t|, its type is unspecified. It it safe
    // to assume it can hold up to a year's worth of seconds (and more), but
    // |SSLIdentity::Generate| should stop relying on |time_t|.
    // See bugs.webrtc.org/5720.
    time_t cert_lifetime_s = static_cast<time_t>(expires_s);
    identity = SSLIdentity::GenerateWithExpiration(
        kIdentityName, key_params, cert_lifetime_s);
  }
  if (!identity)
    return nullptr;
  std::unique_ptr<SSLIdentity> identity_sptr(identity);
  return RTCCertificate::Create(std::move(identity_sptr));
}

RTCCertificateGenerator::RTCCertificateGenerator(
    Thread* signaling_thread, Thread* worker_thread)
    : signaling_thread_(signaling_thread),
      worker_thread_(worker_thread) {
  RTC_DCHECK(signaling_thread_);
  RTC_DCHECK(worker_thread_);
}

void RTCCertificateGenerator::GenerateCertificateAsync(
    const KeyParams& key_params,
    const Optional<uint64_t>& expires_ms,
    const scoped_refptr<RTCCertificateGeneratorCallback>& callback) {
  RTC_DCHECK(signaling_thread_->IsCurrent());
  RTC_DCHECK(callback);

  // Create a new |RTCCertificateGenerationTask| for this generation request. It
  // is reference counted and referenced by the message data, ensuring it lives
  // until the task has completed (independent of |RTCCertificateGenerator|).
  ScopedRefMessageData<RTCCertificateGenerationTask>* msg_data =
      new ScopedRefMessageData<RTCCertificateGenerationTask>(
          new RefCountedObject<RTCCertificateGenerationTask>(
              signaling_thread_, worker_thread_, key_params, expires_ms,
              callback));
  worker_thread_->Post(msg_data->data().get(), MSG_GENERATE, msg_data);
}

}  // namespace rtc
