// Copyright (c) 2010 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/mac/crash_generation/crash_generation_server.h"

#include <pthread.h>

#include "client/mac/crash_generation/client_info.h"
#include "client/mac/handler/minidump_generator.h"
#include "common/mac/scoped_task_suspend-inl.h"

namespace google_breakpad {

CrashGenerationServer::CrashGenerationServer(
    const char *mach_port_name,
    FilterCallback filter,
    void *filter_context,
    OnClientDumpRequestCallback dump_callback,
    void *dump_context,
    OnClientExitingCallback exit_callback,
    void *exit_context,
    bool generate_dumps,
    const std::string &dump_path)
    : filter_(filter),
      filter_context_(filter_context),
      dump_callback_(dump_callback),
      dump_context_(dump_context),
      exit_callback_(exit_callback),
      exit_context_(exit_context),
      generate_dumps_(generate_dumps),
      dump_dir_(dump_path.empty() ? "/tmp" : dump_path),
      started_(false),
      receive_port_(mach_port_name),
      mach_port_name_(mach_port_name) {
}

CrashGenerationServer::~CrashGenerationServer() {
  if (started_)
    Stop();
}

bool CrashGenerationServer::Start() {
  int thread_create_result = pthread_create(&server_thread_, NULL,
                                            &WaitForMessages, this);
  started_ = thread_create_result == 0;
  return started_;
}

bool CrashGenerationServer::Stop() {
  if (!started_)
    return false;

  // Send a quit message to the background thread, and then join it.
  MachPortSender sender(mach_port_name_.c_str());
  MachSendMessage quit_message(kQuitMessage);
  const mach_msg_timeout_t kSendTimeoutMs = 2 * 1000;
  kern_return_t result = sender.SendMessage(quit_message, kSendTimeoutMs);
  if (result == KERN_SUCCESS) {
    int thread_join_result = pthread_join(server_thread_, NULL);
    started_ = thread_join_result != 0;
  }

  return !started_;
}

// static
void *CrashGenerationServer::WaitForMessages(void *server) {
  CrashGenerationServer *self =
      reinterpret_cast<CrashGenerationServer*>(server);
  while (self->WaitForOneMessage()) {}
  return NULL;
}

bool CrashGenerationServer::WaitForOneMessage() {
  MachReceiveMessage message;
  kern_return_t result = receive_port_.WaitForMessage(&message,
                                                      MACH_MSG_TIMEOUT_NONE);
  if (result == KERN_SUCCESS) {
    switch (message.GetMessageID()) {
      case kDumpRequestMessage: {
        ExceptionInfo &info = (ExceptionInfo &)*message.GetData();
      
        mach_port_t remote_task = message.GetTranslatedPort(0);
        mach_port_t crashing_thread = message.GetTranslatedPort(1);
        mach_port_t handler_thread = message.GetTranslatedPort(2);
        mach_port_t ack_port = message.GetTranslatedPort(3);
        pid_t remote_pid = -1;
        pid_for_task(remote_task, &remote_pid);
        ClientInfo client(remote_pid);

        bool result;
        std::string dump_path;
        if (generate_dumps_ && (!filter_ || filter_(filter_context_))) {
          ScopedTaskSuspend suspend(remote_task);

          MinidumpGenerator generator(remote_task, handler_thread);
          dump_path = generator.UniqueNameInDirectory(dump_dir_, NULL);
        
          if (info.exception_type && info.exception_code) {
            generator.SetExceptionInformation(info.exception_type,
                                              info.exception_code,
                                              info.exception_subcode,
                                              crashing_thread);
          }
          result = generator.Write(dump_path.c_str());
        } else {
          result = true;
        }

        if (result && dump_callback_) {
          dump_callback_(dump_context_, client, dump_path);
        }

        // TODO(ted): support a way for the client to send additional data,
        // perhaps with a callback so users of the server can read the data
        // themselves?
      
        if (ack_port != MACH_PORT_DEAD && ack_port != MACH_PORT_NULL) {
          MachPortSender sender(ack_port);
          MachSendMessage ack_message(kAcknowledgementMessage);
          const mach_msg_timeout_t kSendTimeoutMs = 2 * 1000;

          sender.SendMessage(ack_message, kSendTimeoutMs);
        }

        if (exit_callback_) {
          exit_callback_(exit_context_, client);
        }
        break;
      }
      case kQuitMessage:
        return false;
    }
  } else {  // result != KERN_SUCCESS
    return false;
  }
  return true;
}

}  // namespace google_breakpad
