// Copyright (c) 2007, 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.
//
// Interface file between the Breakpad.framework and
// the Inspector process.

#import "common/mac/SimpleStringDictionary.h"

#import <Foundation/Foundation.h>
#import "client/mac/handler/minidump_generator.h"

#define VERBOSE 0

extern bool gDebugLog;

#define DEBUGLOG if (gDebugLog) fprintf

// Types of mach messsages (message IDs)
enum {
  kMsgType_InspectorInitialInfo = 0,    // data is InspectorInfo
  kMsgType_InspectorKeyValuePair = 1,   // data is KeyValueMessageData
  kMsgType_InspectorAcknowledgement = 2 // no data sent
};

// Initial information sent from the crashed process by
// Breakpad.framework to the Inspector process
// The mach message with this struct as data will also include
// several descriptors for sending mach port rights to the crashed
// task, etc.
struct InspectorInfo {
  int           exception_type;
  int           exception_code;
  int           exception_subcode;
  unsigned int  parameter_count;  // key-value pairs
};

// Key/value message data to be sent to the Inspector
struct KeyValueMessageData {
 public:
  KeyValueMessageData() {}
  KeyValueMessageData(const google_breakpad::KeyValueEntry &inEntry) {
    strlcpy(key, inEntry.GetKey(), sizeof(key) );
    strlcpy(value, inEntry.GetValue(), sizeof(value) );
  }

  char key[google_breakpad::KeyValueEntry::MAX_STRING_STORAGE_SIZE];
  char value[google_breakpad::KeyValueEntry::MAX_STRING_STORAGE_SIZE];
};

using std::string;
using google_breakpad::MinidumpGenerator;

namespace google_breakpad {

BOOL EnsureDirectoryPathExists(NSString *dirPath);

//=============================================================================
class ConfigFile {
 public:
  ConfigFile() {
    config_file_ = -1;
    config_file_path_[0] = 0;
    has_created_file_ = false;
  };

  ~ConfigFile() {
  };

  void WriteFile(const SimpleStringDictionary *configurationParameters,
                 const char *dump_dir,
                 const char *minidump_id);

  const char *GetFilePath() { return config_file_path_; }

  void Unlink() {
    if (config_file_ != -1)
      unlink(config_file_path_);

    config_file_ = -1;
  }

 private:
  BOOL WriteData(const void *data, size_t length);

  BOOL AppendConfigData(const char *key,
                        const void *data,
                        size_t length);

  BOOL AppendConfigString(const char *key,
                          const char *value);

  int   config_file_;                    // descriptor for config file
  char  config_file_path_[PATH_MAX];     // Path to configuration file
  bool  has_created_file_;
};

//=============================================================================
class MinidumpLocation {
 public:
  MinidumpLocation(NSString *minidumpDir) {
    // Ensure that the path exists.  Fallback to /tmp if unable to locate path.
    assert(minidumpDir);
    if (!EnsureDirectoryPathExists(minidumpDir)) {
      DEBUGLOG(stderr, "Unable to create: %s\n", [minidumpDir UTF8String]);
      minidumpDir = @"/tmp";
    }

    strlcpy(minidump_dir_path_, [minidumpDir fileSystemRepresentation],
            sizeof(minidump_dir_path_));

    // now generate a unique ID
    string dump_path(minidump_dir_path_);
    string next_minidump_id;

    string next_minidump_path_ =
      (MinidumpGenerator::UniqueNameInDirectory(dump_path, &next_minidump_id));

    strlcpy(minidump_id_, next_minidump_id.c_str(), sizeof(minidump_id_));
  };

  const char *GetPath() { return minidump_dir_path_; }
  const char *GetID() { return minidump_id_; }

 private:
  char minidump_dir_path_[PATH_MAX];             // Path to minidump directory
  char minidump_id_[128];
};

//=============================================================================
class Inspector {
 public:
  Inspector() {};

  // given a bootstrap service name, receives mach messages
  // from a crashed process, then inspects it, creates a minidump file
  // and asks the user if he wants to upload it to a server.
  void            Inspect(const char *receive_port_name);

 private:
  kern_return_t   ServiceCheckIn(const char *receive_port_name);
  kern_return_t   ServiceCheckOut(const char *receive_port_name);

  kern_return_t   ReadMessages();

  bool            InspectTask();
  kern_return_t   SendAcknowledgement();
  void            LaunchReporter(const char *inConfigFilePath);

  void            SetCrashTimeParameters();

  mach_port_t     service_rcv_port_;

  int             exception_type_;
  int             exception_code_;
  int             exception_subcode_;
  mach_port_t     remote_task_;
  mach_port_t     crashing_thread_;
  mach_port_t     handler_thread_;
  mach_port_t     ack_port_;

  SimpleStringDictionary config_params_;

  ConfigFile      config_file_;
};


} // namespace google_breakpad
