// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * 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.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 COPYRIGHT
// OWNER OR CONTRIBUTORS 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 "client/windows/crash_generation/crash_generation_client.h"
#include <cassert>
#include <utility>
#include "client/windows/common/ipc_protocol.h"

namespace google_breakpad {

const int kPipeBusyWaitTimeoutMs = 2000;

#ifdef _DEBUG
const DWORD kWaitForServerTimeoutMs = INFINITE;
#else
const DWORD kWaitForServerTimeoutMs = 15000;
#endif

const int kPipeConnectMaxAttempts = 2;

const DWORD kPipeDesiredAccess = FILE_READ_DATA |
                                 FILE_WRITE_DATA |
                                 FILE_WRITE_ATTRIBUTES;

const DWORD kPipeFlagsAndAttributes = SECURITY_IDENTIFICATION |
                                      SECURITY_SQOS_PRESENT;

const DWORD kPipeMode = PIPE_READMODE_MESSAGE;

const size_t kWaitEventCount = 2;

// This function is orphan for production code. It can be used
// for debugging to help repro some scenarios like the client
// is slow in writing to the pipe after connecting, the client
// is slow in reading from the pipe after writing, etc. The parameter
// overlapped below is not used and it is present to match the signature
// of this function to TransactNamedPipe Win32 API. Uncomment if needed
// for debugging.
/**
static bool TransactNamedPipeDebugHelper(HANDLE pipe,
                                         const void* in_buffer,
                                         DWORD in_size,
                                         void* out_buffer,
                                         DWORD out_size,
                                         DWORD* bytes_count,
                                         LPOVERLAPPED) {
  // Uncomment the next sleep to create a gap before writing
  // to pipe.
  // Sleep(5000);

  if (!WriteFile(pipe,
                 in_buffer,
                 in_size,
                 bytes_count,
                 NULL)) {
    return false;
  }

  // Uncomment the next sleep to create a gap between write
  // and read.
  // Sleep(5000);

  return ReadFile(pipe, out_buffer, out_size, bytes_count, NULL) != FALSE;
}
**/

CrashGenerationClient::CrashGenerationClient(
    const wchar_t* pipe_name,
    MINIDUMP_TYPE dump_type,
    const CustomClientInfo* custom_info)
        : pipe_name_(pipe_name),
          pipe_handle_(NULL),
          dump_type_(dump_type),
          thread_id_(0),
          server_process_id_(0),
          crash_event_(NULL),
          crash_generated_(NULL),
          server_alive_(NULL),
          exception_pointers_(NULL),
          custom_info_() {
  memset(&assert_info_, 0, sizeof(assert_info_));
  if (custom_info) {
    custom_info_ = *custom_info;
  }
}

CrashGenerationClient::CrashGenerationClient(
    HANDLE pipe_handle,
    MINIDUMP_TYPE dump_type,
    const CustomClientInfo* custom_info)
        : pipe_name_(),
          pipe_handle_(pipe_handle),
          dump_type_(dump_type),
          thread_id_(0),
          server_process_id_(0),
          crash_event_(NULL),
          crash_generated_(NULL),
          server_alive_(NULL),
          exception_pointers_(NULL),
          custom_info_() {
  memset(&assert_info_, 0, sizeof(assert_info_));
  if (custom_info) {
    custom_info_ = *custom_info;
  }
}

CrashGenerationClient::~CrashGenerationClient() {
  if (crash_event_) {
    CloseHandle(crash_event_);
  }

  if (crash_generated_) {
    CloseHandle(crash_generated_);
  }

  if (server_alive_) {
    CloseHandle(server_alive_);
  }
}

// Performs the registration step with the server process.
// The registration step involves communicating with the server
// via a named pipe. The client sends the following pieces of
// data to the server:
//
// * Message tag indicating the client is requesting registration.
// * Process id of the client process.
// * Address of a DWORD variable in the client address space
//   that will contain the thread id of the client thread that
//   caused the crash.
// * Address of a EXCEPTION_POINTERS* variable in the client
//   address space that will point to an instance of EXCEPTION_POINTERS
//   when the crash happens.
// * Address of an instance of MDRawAssertionInfo that will contain
//   relevant information in case of non-exception crashes like assertion
//   failures and pure calls.
//
// In return the client expects the following information from the server:
//
// * Message tag indicating successful registration.
// * Server process id.
// * Handle to an object that client can signal to request dump
//   generation from the server.
// * Handle to an object that client can wait on after requesting
//   dump generation for the server to finish dump generation.
// * Handle to a mutex object that client can wait on to make sure
//   server is still alive.
//
// If any step of the expected behavior mentioned above fails, the
// registration step is not considered successful and hence out-of-process
// dump generation service is not available.
//
// Returns true if the registration is successful; false otherwise.
bool CrashGenerationClient::Register() {
  if (IsRegistered()) {
    return true;
  }

  HANDLE pipe = ConnectToServer();
  if (!pipe) {
    return false;
  }

  bool success = RegisterClient(pipe);
  CloseHandle(pipe);
  return success;
}

bool CrashGenerationClient::RequestUpload(DWORD crash_id) {
  HANDLE pipe = ConnectToServer();
  if (!pipe) {
    return false;
  }

  CustomClientInfo custom_info = {NULL, 0};
  ProtocolMessage msg(MESSAGE_TAG_UPLOAD_REQUEST, crash_id,
                      static_cast<MINIDUMP_TYPE>(NULL), NULL, NULL, NULL,
                      custom_info, NULL, NULL, NULL);
  DWORD bytes_count = 0;
  bool success = WriteFile(pipe, &msg, sizeof(msg), &bytes_count, NULL) != 0;

  CloseHandle(pipe);
  return success;
}

HANDLE CrashGenerationClient::ConnectToServer() {
  HANDLE pipe = ConnectToPipe(pipe_name_.c_str(),
                              kPipeDesiredAccess,
                              kPipeFlagsAndAttributes);
  if (!pipe) {
    return NULL;
  }

  DWORD mode = kPipeMode;
  if (!SetNamedPipeHandleState(pipe, &mode, NULL, NULL)) {
    CloseHandle(pipe);
    pipe = NULL;
  }

  return pipe;
}

bool CrashGenerationClient::RegisterClient(HANDLE pipe) {
  ProtocolMessage msg(MESSAGE_TAG_REGISTRATION_REQUEST,
                      GetCurrentProcessId(),
                      dump_type_,
                      &thread_id_,
                      &exception_pointers_,
                      &assert_info_,
                      custom_info_,
                      NULL,
                      NULL,
                      NULL);
  ProtocolMessage reply;
  DWORD bytes_count = 0;
  // The call to TransactNamedPipe below can be changed to a call
  // to TransactNamedPipeDebugHelper to help repro some scenarios.
  // For details see comments for TransactNamedPipeDebugHelper.
  if (!TransactNamedPipe(pipe,
                         &msg,
                         sizeof(msg),
                         &reply,
                         sizeof(ProtocolMessage),
                         &bytes_count,
                         NULL)) {
    return false;
  }

  if (!ValidateResponse(reply)) {
    return false;
  }

  ProtocolMessage ack_msg;
  ack_msg.tag = MESSAGE_TAG_REGISTRATION_ACK;

  if (!WriteFile(pipe, &ack_msg, sizeof(ack_msg), &bytes_count, NULL)) {
    return false;
  }
  crash_event_ = reply.dump_request_handle;
  crash_generated_ = reply.dump_generated_handle;
  server_alive_ = reply.server_alive_handle;
  server_process_id_ = reply.id;

  return true;
}

HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name,
                                            DWORD pipe_access,
                                            DWORD flags_attrs) {
  if (pipe_handle_) {
    HANDLE t = pipe_handle_;
    pipe_handle_ = NULL;
    return t;
  }

  for (int i = 0; i < kPipeConnectMaxAttempts; ++i) {
    HANDLE pipe = CreateFile(pipe_name,
                             pipe_access,
                             0,
                             NULL,
                             OPEN_EXISTING,
                             flags_attrs,
                             NULL);
    if (pipe != INVALID_HANDLE_VALUE) {
      return pipe;
    }

    // Cannot continue retrying if error is something other than
    // ERROR_PIPE_BUSY.
    if (GetLastError() != ERROR_PIPE_BUSY) {
      break;
    }

    // Cannot continue retrying if wait on pipe fails.
    if (!WaitNamedPipe(pipe_name, kPipeBusyWaitTimeoutMs)) {
      break;
    }
  }

  return NULL;
}

bool CrashGenerationClient::ValidateResponse(
    const ProtocolMessage& msg) const {
  return (msg.tag == MESSAGE_TAG_REGISTRATION_RESPONSE) &&
         (msg.id != 0) &&
         (msg.dump_request_handle != NULL) &&
         (msg.dump_generated_handle != NULL) &&
         (msg.server_alive_handle != NULL);
}

bool CrashGenerationClient::IsRegistered() const {
  return crash_event_ != NULL;
}

bool CrashGenerationClient::RequestDump(EXCEPTION_POINTERS* ex_info,
                                        MDRawAssertionInfo* assert_info) {
  if (!IsRegistered()) {
    return false;
  }

  exception_pointers_ = ex_info;
  thread_id_ = GetCurrentThreadId();

  if (assert_info) {
    memcpy(&assert_info_, assert_info, sizeof(assert_info_));
  } else {
    memset(&assert_info_, 0, sizeof(assert_info_));
  }

  return SignalCrashEventAndWait();
}

bool CrashGenerationClient::RequestDump(EXCEPTION_POINTERS* ex_info) {
  return RequestDump(ex_info, NULL);
}

bool CrashGenerationClient::RequestDump(MDRawAssertionInfo* assert_info) {
  return RequestDump(NULL, assert_info);
}

bool CrashGenerationClient::SignalCrashEventAndWait() {
  assert(crash_event_);
  assert(crash_generated_);
  assert(server_alive_);

  // Reset the dump generated event before signaling the crash
  // event so that the server can set the dump generated event
  // once it is done generating the event.
  if (!ResetEvent(crash_generated_)) {
    return false;
  }

  if (!SetEvent(crash_event_)) {
    return false;
  }

  HANDLE wait_handles[kWaitEventCount] = {crash_generated_, server_alive_};

  DWORD result = WaitForMultipleObjects(kWaitEventCount,
                                        wait_handles,
                                        FALSE,
                                        kWaitForServerTimeoutMs);

  // Crash dump was successfully generated only if the server
  // signaled the crash generated event.
  return result == WAIT_OBJECT_0;
}

HANDLE CrashGenerationClient::DuplicatePipeToClientProcess(const wchar_t* pipe_name,
                                                           HANDLE hProcess) {
  for (int i = 0; i < kPipeConnectMaxAttempts; ++i) {
    HANDLE local_pipe = CreateFile(pipe_name, kPipeDesiredAccess,
                                   0, NULL, OPEN_EXISTING,
                                   kPipeFlagsAndAttributes, NULL);
    if (local_pipe != INVALID_HANDLE_VALUE) {
      HANDLE remotePipe = INVALID_HANDLE_VALUE;
      if (DuplicateHandle(GetCurrentProcess(), local_pipe,
                          hProcess, &remotePipe, 0, FALSE,
                          DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
        return remotePipe;
      } else {
        return INVALID_HANDLE_VALUE;
      }
    }

    // Cannot continue retrying if the error wasn't a busy pipe.
    if (GetLastError() != ERROR_PIPE_BUSY) {
      return INVALID_HANDLE_VALUE;
    }

    if (!WaitNamedPipe(pipe_name, kPipeBusyWaitTimeoutMs)) {
      return INVALID_HANDLE_VALUE;
    }
  }
  return INVALID_HANDLE_VALUE;
}

}  // namespace google_breakpad
