<commit_before>/*
* Copyright (c) 2017, Ford Motor Company
* 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 the Ford Motor Company 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 HOLDER 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 "life_cycle.h"
#include "utils/signals.h"
#include "utils/make_shared.h"
#include "config_profile/profile.h"
#include "resumption/last_state_impl.h"

#ifdef ENABLE_SECURITY
#include "security_manager/security_manager_impl.h"
#include "security_manager/crypto_manager_impl.h"
#include "security_manager/crypto_manager_settings_impl.h"
#include "application_manager/policies/policy_handler.h"
#endif  // ENABLE_SECURITY

#ifdef ENABLE_LOG
#include "utils/log_message_loop_thread.h"
#endif  // ENABLE_LOG

using threads::Thread;

namespace main_namespace {

CREATE_LOGGERPTR_GLOBAL(logger_, "SDLMain")

LifeCycle::LifeCycle(const profile::Profile& profile)
    : transport_manager_(NULL)
    , protocol_handler_(NULL)
    , connection_handler_(NULL)
    , app_manager_(NULL)
#ifdef ENABLE_SECURITY
    , crypto_manager_(NULL)
    , security_manager_(NULL)
#endif  // ENABLE_SECURITY
    , hmi_handler_(NULL)
    , hmi_message_adapter_(NULL)
    , media_manager_(NULL)
    , last_state_(NULL)
#ifdef TELEMETRY_MONITOR
    , telemetry_monitor_(NULL)
#endif  // TELEMETRY_MONITOR
#ifdef DBUS_HMIADAPTER
    , dbus_adapter_(NULL)
    , dbus_adapter_thread_(NULL)
#endif  // DBUS_HMIADAPTER
#ifdef MESSAGEBROKER_HMIADAPTER
    , mb_adapter_(NULL)
    , mb_adapter_thread_(NULL)
#endif  // MESSAGEBROKER_HMIADAPTER
    , profile_(profile) {
}

bool LifeCycle::StartComponents() {
  LOG4CXX_AUTO_TRACE(logger_);
  DCHECK(!last_state_);
  last_state_ = new resumption::LastStateImpl(profile_.app_storage_folder(),
                                              profile_.app_info_storage());

  DCHECK(!transport_manager_);
  transport_manager_ = new transport_manager::TransportManagerDefault(profile_);

  DCHECK(!connection_handler_);
  connection_handler_ = new connection_handler::ConnectionHandlerImpl(
      profile_, *transport_manager_);

  DCHECK(!protocol_handler_);
  protocol_handler_ =
      new protocol_handler::ProtocolHandlerImpl(profile_,
                                                *connection_handler_,
                                                *connection_handler_,
                                                *transport_manager_);
  DCHECK(protocol_handler_);

  DCHECK(!app_manager_);
  app_manager_ =
      new application_manager::ApplicationManagerImpl(profile_, profile_);

  DCHECK(!hmi_handler_);
  hmi_handler_ = new hmi_message_handler::HMIMessageHandlerImpl(profile_);

  hmi_handler_->set_message_observer(app_manager_);
  app_manager_->set_hmi_message_handler(hmi_handler_);

  media_manager_ = new media_manager::MediaManagerImpl(*app_manager_, profile_);
  app_manager_->set_connection_handler(connection_handler_);
  if (!app_manager_->Init(*last_state_, media_manager_)) {
    LOG4CXX_ERROR(logger_, "Application manager init failed.");
    return false;
  }

#ifdef ENABLE_SECURITY
  security_manager_ = new security_manager::SecurityManagerImpl();
  crypto_manager_ = new security_manager::CryptoManagerImpl(
      utils::MakeShared<security_manager::CryptoManagerSettingsImpl>(
          profile_, app_manager_->GetPolicyHandler().RetrieveCertificate()));
  protocol_handler_->AddProtocolObserver(security_manager_);
  protocol_handler_->set_security_manager(security_manager_);

  security_manager_->set_session_observer(connection_handler_);
  security_manager_->set_protocol_handler(protocol_handler_);
  security_manager_->set_crypto_manager(crypto_manager_);
  security_manager_->AddListener(app_manager_);

  app_manager_->AddPolicyObserver(crypto_manager_);
  app_manager_->AddPolicyObserver(protocol_handler_);
  if (!crypto_manager_->Init()) {
    LOG4CXX_ERROR(logger_, "CryptoManager initialization fail.");
    return false;
  }
#endif  // ENABLE_SECURITY

  transport_manager_->AddEventListener(protocol_handler_);
  transport_manager_->AddEventListener(connection_handler_);

  protocol_handler_->AddProtocolObserver(media_manager_);
  protocol_handler_->AddProtocolObserver(app_manager_);

  media_manager_->SetProtocolHandler(protocol_handler_);

  connection_handler_->set_protocol_handler(protocol_handler_);
  connection_handler_->set_connection_handler_observer(app_manager_);

// it is important to initialise TelemetryMonitor before TM to listen TM
// Adapters
#ifdef TELEMETRY_MONITOR
  telemetry_monitor_ = new telemetry_monitor::TelemetryMonitor(
      profile_.server_address(), profile_.time_testing_port());
  telemetry_monitor_->Start();
  telemetry_monitor_->Init(protocol_handler_, app_manager_, transport_manager_);
#endif  // TELEMETRY_MONITOR
  // It's important to initialise TM after setting up listener chain
  // [TM -> CH -> AM], otherwise some events from TM could arrive at nowhere
  app_manager_->set_protocol_handler(protocol_handler_);

  transport_manager_->Init(*last_state_);
  // start transport manager
  transport_manager_->Visibility(true);

  return true;
}

#ifdef MESSAGEBROKER_HMIADAPTER
bool LifeCycle::InitMessageSystem() {
  mb_adapter_ = new hmi_message_handler::MessageBrokerAdapter(
      hmi_handler_, profile_.server_address(), profile_.server_port());

  if (!mb_adapter_->StartListener()) {
    return false;
  }

  hmi_handler_->AddHMIMessageAdapter(mb_adapter_);
  mb_adapter_thread_ = new std::thread(
      &hmi_message_handler::MessageBrokerAdapter::Run, mb_adapter_);
  return true;
}
#endif  // MESSAGEBROKER_HMIADAPTER

#ifdef DBUS_HMIADAPTER
/**
 * Initialize DBus component
 * @return true if success otherwise false.
 */
bool LifeCycle::InitMessageSystem() {
  dbus_adapter_ = new hmi_message_handler::DBusMessageAdapter(hmi_handler_);

  hmi_handler_->AddHMIMessageAdapter(dbus_adapter_);
  if (!dbus_adapter_->Init()) {
    LOG4CXX_FATAL(logger_, "Cannot init DBus service!");
    return false;
  }

  dbus_adapter_->SubscribeTo();

  LOG4CXX_INFO(logger_, "Start DBusMessageAdapter thread!");
  dbus_adapter_thread_ = new std::thread(
      &hmi_message_handler::DBusMessageAdapter::Run, dbus_adapter_);

  return true;
}
#endif  // DBUS_HMIADAPTER

namespace {
void sig_handler(int sig) {
  switch (sig) {
    case SIGINT:
      LOG4CXX_DEBUG(logger_, "SIGINT signal has been caught");
      break;
    case SIGTERM:
      LOG4CXX_DEBUG(logger_, "SIGTERM signal has been caught");
      break;
    case SIGSEGV:
      LOG4CXX_DEBUG(logger_, "SIGSEGV signal has been caught");
      FLUSH_LOGGER();
      // exit need to prevent endless sending SIGSEGV
      // http://stackoverflow.com/questions/2663456/how-to-write-a-signal-handler-to-catch-sigsegv
      abort();
    default:
      LOG4CXX_DEBUG(logger_, "Unexpected signal has been caught");
      exit(EXIT_FAILURE);
  }
}
}  //  namespace

void LifeCycle::Run() {
  LOG4CXX_AUTO_TRACE(logger_);
  // Register signal handlers and wait sys signals
  // from OS
  if (!utils::WaitTerminationSignals(&sig_handler)) {
    LOG4CXX_FATAL(logger_, "Fail to catch system signal!");
  }
}

void LifeCycle::StopComponents() {
  LOG4CXX_AUTO_TRACE(logger_);

  DCHECK_OR_RETURN_VOID(hmi_handler_);
  hmi_handler_->set_message_observer(NULL);

  DCHECK_OR_RETURN_VOID(connection_handler_);
  connection_handler_->set_connection_handler_observer(NULL);

  DCHECK_OR_RETURN_VOID(protocol_handler_);
  protocol_handler_->RemoveProtocolObserver(app_manager_);

  DCHECK_OR_RETURN_VOID(app_manager_);
  app_manager_->Stop();

  LOG4CXX_INFO(logger_, "Stopping Protocol Handler");
  DCHECK_OR_RETURN_VOID(protocol_handler_);
  protocol_handler_->RemoveProtocolObserver(media_manager_);

#ifdef ENABLE_SECURITY
  protocol_handler_->RemoveProtocolObserver(security_manager_);
  if (security_manager_) {
    security_manager_->RemoveListener(app_manager_);
    LOG4CXX_INFO(logger_, "Destroying Crypto Manager");
    delete crypto_manager_;
    crypto_manager_ = NULL;
    LOG4CXX_INFO(logger_, "Destroying Security Manager");
    delete security_manager_;
    security_manager_ = NULL;
  }
#endif  // ENABLE_SECURITY
  protocol_handler_->Stop();

  LOG4CXX_INFO(logger_, "Destroying Media Manager");
  DCHECK_OR_RETURN_VOID(media_manager_);
  media_manager_->SetProtocolHandler(NULL);
  delete media_manager_;
  media_manager_ = NULL;

  LOG4CXX_INFO(logger_, "Destroying Transport Manager.");
  DCHECK_OR_RETURN_VOID(transport_manager_);
  transport_manager_->Visibility(false);
  transport_manager_->Stop();
  delete transport_manager_;
  transport_manager_ = NULL;

  LOG4CXX_INFO(logger_, "Stopping Connection Handler.");
  DCHECK_OR_RETURN_VOID(connection_handler_);
  connection_handler_->Stop();

  LOG4CXX_INFO(logger_, "Destroying Protocol Handler");
  DCHECK(protocol_handler_);
  delete protocol_handler_;
  protocol_handler_ = NULL;

  LOG4CXX_INFO(logger_, "Destroying Connection Handler.");
  delete connection_handler_;
  connection_handler_ = NULL;

  LOG4CXX_INFO(logger_, "Destroying Last State");
  DCHECK(last_state_);
  delete last_state_;
  last_state_ = NULL;

  LOG4CXX_INFO(logger_, "Destroying Application Manager.");
  DCHECK(app_manager_);
  delete app_manager_;
  app_manager_ = NULL;

  LOG4CXX_INFO(logger_, "Destroying HMI Message Handler and MB adapter.");

#ifdef DBUS_HMIADAPTER
  if (dbus_adapter_) {
    DCHECK_OR_RETURN_VOID(hmi_handler_);
    hmi_handler_->RemoveHMIMessageAdapter(dbus_adapter_);
    dbus_adapter_->Shutdown();
    dbus_adapter_thread_->join();
    delete dbus_adapter_;
    dbus_adapter_ = NULL;
    delete dbus_adapter_thread_;
    dbus_adapter_thread_ = NULL;
  }
#endif  // DBUS_HMIADAPTER

#ifdef MESSAGEBROKER_HMIADAPTER
  if (mb_adapter_) {
    DCHECK_OR_RETURN_VOID(hmi_handler_);
    hmi_handler_->RemoveHMIMessageAdapter(mb_adapter_);
    mb_adapter_->unregisterController();
    mb_adapter_->exitReceivingThread();
    mb_adapter_thread_->join();
    delete mb_adapter_;
    mb_adapter_ = NULL;
  }

  DCHECK_OR_RETURN_VOID(hmi_handler_);
  delete hmi_handler_;
  hmi_handler_ = NULL;

  LOG4CXX_INFO(logger_, "Destroying Message Broker");
#endif  // MESSAGEBROKER_HMIADAPTER

#ifdef TELEMETRY_MONITOR
  // It's important to delete tester Obcervers after TM adapters destruction
  if (telemetry_monitor_) {
    telemetry_monitor_->Stop();
    delete telemetry_monitor_;
    telemetry_monitor_ = NULL;
  }
#endif  // TELEMETRY_MONITOR
}

}  //  namespace main_namespace
<commit_msg>Fix crash and memory leaks in message broker cleanup<commit_after>/*
* Copyright (c) 2017, Ford Motor Company
* 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 the Ford Motor Company 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 HOLDER 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 "life_cycle.h"
#include "utils/signals.h"
#include "utils/make_shared.h"
#include "config_profile/profile.h"
#include "resumption/last_state_impl.h"

#ifdef ENABLE_SECURITY
#include "security_manager/security_manager_impl.h"
#include "security_manager/crypto_manager_impl.h"
#include "security_manager/crypto_manager_settings_impl.h"
#include "application_manager/policies/policy_handler.h"
#endif  // ENABLE_SECURITY

#ifdef ENABLE_LOG
#include "utils/log_message_loop_thread.h"
#endif  // ENABLE_LOG

using threads::Thread;

namespace main_namespace {

CREATE_LOGGERPTR_GLOBAL(logger_, "SDLMain")

LifeCycle::LifeCycle(const profile::Profile& profile)
    : transport_manager_(NULL)
    , protocol_handler_(NULL)
    , connection_handler_(NULL)
    , app_manager_(NULL)
#ifdef ENABLE_SECURITY
    , crypto_manager_(NULL)
    , security_manager_(NULL)
#endif  // ENABLE_SECURITY
    , hmi_handler_(NULL)
    , hmi_message_adapter_(NULL)
    , media_manager_(NULL)
    , last_state_(NULL)
#ifdef TELEMETRY_MONITOR
    , telemetry_monitor_(NULL)
#endif  // TELEMETRY_MONITOR
#ifdef DBUS_HMIADAPTER
    , dbus_adapter_(NULL)
    , dbus_adapter_thread_(NULL)
#endif  // DBUS_HMIADAPTER
#ifdef MESSAGEBROKER_HMIADAPTER
    , mb_adapter_(NULL)
    , mb_adapter_thread_(NULL)
#endif  // MESSAGEBROKER_HMIADAPTER
    , profile_(profile) {
}

bool LifeCycle::StartComponents() {
  LOG4CXX_AUTO_TRACE(logger_);
  DCHECK(!last_state_);
  last_state_ = new resumption::LastStateImpl(profile_.app_storage_folder(),
                                              profile_.app_info_storage());

  DCHECK(!transport_manager_);
  transport_manager_ = new transport_manager::TransportManagerDefault(profile_);

  DCHECK(!connection_handler_);
  connection_handler_ = new connection_handler::ConnectionHandlerImpl(
      profile_, *transport_manager_);

  DCHECK(!protocol_handler_);
  protocol_handler_ =
      new protocol_handler::ProtocolHandlerImpl(profile_,
                                                *connection_handler_,
                                                *connection_handler_,
                                                *transport_manager_);
  DCHECK(protocol_handler_);

  DCHECK(!app_manager_);
  app_manager_ =
      new application_manager::ApplicationManagerImpl(profile_, profile_);

  DCHECK(!hmi_handler_);
  hmi_handler_ = new hmi_message_handler::HMIMessageHandlerImpl(profile_);

  hmi_handler_->set_message_observer(app_manager_);
  app_manager_->set_hmi_message_handler(hmi_handler_);

  media_manager_ = new media_manager::MediaManagerImpl(*app_manager_, profile_);
  app_manager_->set_connection_handler(connection_handler_);
  if (!app_manager_->Init(*last_state_, media_manager_)) {
    LOG4CXX_ERROR(logger_, "Application manager init failed.");
    return false;
  }

#ifdef ENABLE_SECURITY
  security_manager_ = new security_manager::SecurityManagerImpl();
  crypto_manager_ = new security_manager::CryptoManagerImpl(
      utils::MakeShared<security_manager::CryptoManagerSettingsImpl>(
          profile_, app_manager_->GetPolicyHandler().RetrieveCertificate()));
  protocol_handler_->AddProtocolObserver(security_manager_);
  protocol_handler_->set_security_manager(security_manager_);

  security_manager_->set_session_observer(connection_handler_);
  security_manager_->set_protocol_handler(protocol_handler_);
  security_manager_->set_crypto_manager(crypto_manager_);
  security_manager_->AddListener(app_manager_);

  app_manager_->AddPolicyObserver(crypto_manager_);
  app_manager_->AddPolicyObserver(protocol_handler_);
  if (!crypto_manager_->Init()) {
    LOG4CXX_ERROR(logger_, "CryptoManager initialization fail.");
    return false;
  }
#endif  // ENABLE_SECURITY

  transport_manager_->AddEventListener(protocol_handler_);
  transport_manager_->AddEventListener(connection_handler_);

  protocol_handler_->AddProtocolObserver(media_manager_);
  protocol_handler_->AddProtocolObserver(app_manager_);

  media_manager_->SetProtocolHandler(protocol_handler_);

  connection_handler_->set_protocol_handler(protocol_handler_);
  connection_handler_->set_connection_handler_observer(app_manager_);

// it is important to initialise TelemetryMonitor before TM to listen TM
// Adapters
#ifdef TELEMETRY_MONITOR
  telemetry_monitor_ = new telemetry_monitor::TelemetryMonitor(
      profile_.server_address(), profile_.time_testing_port());
  telemetry_monitor_->Start();
  telemetry_monitor_->Init(protocol_handler_, app_manager_, transport_manager_);
#endif  // TELEMETRY_MONITOR
  // It's important to initialise TM after setting up listener chain
  // [TM -> CH -> AM], otherwise some events from TM could arrive at nowhere
  app_manager_->set_protocol_handler(protocol_handler_);

  transport_manager_->Init(*last_state_);
  // start transport manager
  transport_manager_->Visibility(true);

  return true;
}

#ifdef MESSAGEBROKER_HMIADAPTER
bool LifeCycle::InitMessageSystem() {
  mb_adapter_ = new hmi_message_handler::MessageBrokerAdapter(
      hmi_handler_, profile_.server_address(), profile_.server_port());

  if (!mb_adapter_->StartListener()) {
    return false;
  }

  hmi_handler_->AddHMIMessageAdapter(mb_adapter_);
  mb_adapter_thread_ = new std::thread(
      &hmi_message_handler::MessageBrokerAdapter::Run, mb_adapter_);
  return true;
}
#endif  // MESSAGEBROKER_HMIADAPTER

#ifdef DBUS_HMIADAPTER
/**
 * Initialize DBus component
 * @return true if success otherwise false.
 */
bool LifeCycle::InitMessageSystem() {
  dbus_adapter_ = new hmi_message_handler::DBusMessageAdapter(hmi_handler_);

  hmi_handler_->AddHMIMessageAdapter(dbus_adapter_);
  if (!dbus_adapter_->Init()) {
    LOG4CXX_FATAL(logger_, "Cannot init DBus service!");
    return false;
  }

  dbus_adapter_->SubscribeTo();

  LOG4CXX_INFO(logger_, "Start DBusMessageAdapter thread!");
  dbus_adapter_thread_ = new std::thread(
      &hmi_message_handler::DBusMessageAdapter::Run, dbus_adapter_);

  return true;
}
#endif  // DBUS_HMIADAPTER

namespace {
void sig_handler(int sig) {
  switch (sig) {
    case SIGINT:
      LOG4CXX_DEBUG(logger_, "SIGINT signal has been caught");
      break;
    case SIGTERM:
      LOG4CXX_DEBUG(logger_, "SIGTERM signal has been caught");
      break;
    case SIGSEGV:
      LOG4CXX_DEBUG(logger_, "SIGSEGV signal has been caught");
      FLUSH_LOGGER();
      // exit need to prevent endless sending SIGSEGV
      // http://stackoverflow.com/questions/2663456/how-to-write-a-signal-handler-to-catch-sigsegv
      abort();
    default:
      LOG4CXX_DEBUG(logger_, "Unexpected signal has been caught");
      exit(EXIT_FAILURE);
  }
}
}  //  namespace

void LifeCycle::Run() {
  LOG4CXX_AUTO_TRACE(logger_);
  // Register signal handlers and wait sys signals
  // from OS
  if (!utils::WaitTerminationSignals(&sig_handler)) {
    LOG4CXX_FATAL(logger_, "Fail to catch system signal!");
  }
}

void LifeCycle::StopComponents() {
  LOG4CXX_AUTO_TRACE(logger_);

  DCHECK_OR_RETURN_VOID(hmi_handler_);
  hmi_handler_->set_message_observer(NULL);

  DCHECK_OR_RETURN_VOID(connection_handler_);
  connection_handler_->set_connection_handler_observer(NULL);

  DCHECK_OR_RETURN_VOID(protocol_handler_);
  protocol_handler_->RemoveProtocolObserver(app_manager_);

  DCHECK_OR_RETURN_VOID(app_manager_);
  app_manager_->Stop();

  LOG4CXX_INFO(logger_, "Stopping Protocol Handler");
  DCHECK_OR_RETURN_VOID(protocol_handler_);
  protocol_handler_->RemoveProtocolObserver(media_manager_);

#ifdef ENABLE_SECURITY
  protocol_handler_->RemoveProtocolObserver(security_manager_);
  if (security_manager_) {
    security_manager_->RemoveListener(app_manager_);
    LOG4CXX_INFO(logger_, "Destroying Crypto Manager");
    delete crypto_manager_;
    crypto_manager_ = NULL;
    LOG4CXX_INFO(logger_, "Destroying Security Manager");
    delete security_manager_;
    security_manager_ = NULL;
  }
#endif  // ENABLE_SECURITY
  protocol_handler_->Stop();

  LOG4CXX_INFO(logger_, "Destroying Media Manager");
  DCHECK_OR_RETURN_VOID(media_manager_);
  media_manager_->SetProtocolHandler(NULL);
  delete media_manager_;
  media_manager_ = NULL;

  LOG4CXX_INFO(logger_, "Destroying Transport Manager.");
  DCHECK_OR_RETURN_VOID(transport_manager_);
  transport_manager_->Visibility(false);
  transport_manager_->Stop();
  delete transport_manager_;
  transport_manager_ = NULL;

  LOG4CXX_INFO(logger_, "Stopping Connection Handler.");
  DCHECK_OR_RETURN_VOID(connection_handler_);
  connection_handler_->Stop();

  LOG4CXX_INFO(logger_, "Destroying Protocol Handler");
  DCHECK(protocol_handler_);
  delete protocol_handler_;
  protocol_handler_ = NULL;

  LOG4CXX_INFO(logger_, "Destroying Connection Handler.");
  delete connection_handler_;
  connection_handler_ = NULL;

  LOG4CXX_INFO(logger_, "Destroying Last State");
  DCHECK(last_state_);
  delete last_state_;
  last_state_ = NULL;

  LOG4CXX_INFO(logger_, "Destroying Application Manager.");
  DCHECK(app_manager_);
  delete app_manager_;
  app_manager_ = NULL;

  LOG4CXX_INFO(logger_, "Destroying HMI Message Handler and MB adapter.");

#ifdef DBUS_HMIADAPTER
  if (dbus_adapter_) {
    DCHECK_OR_RETURN_VOID(hmi_handler_);
    hmi_handler_->RemoveHMIMessageAdapter(dbus_adapter_);
    dbus_adapter_->Shutdown();
    if (dbus_adapter_thread_ != NULL) {
      dbus_adapter_thread_->join();
    }
    delete dbus_adapter_;
    dbus_adapter_ = NULL;
    delete dbus_adapter_thread_;
    dbus_adapter_thread_ = NULL;
  }
#endif  // DBUS_HMIADAPTER

#ifdef MESSAGEBROKER_HMIADAPTER
  if (mb_adapter_) {
    DCHECK_OR_RETURN_VOID(hmi_handler_);
    hmi_handler_->RemoveHMIMessageAdapter(mb_adapter_);
    mb_adapter_->unregisterController();
    mb_adapter_->exitReceivingThread();
    if (mb_adapter_thread_ != NULL) {
      mb_adapter_thread_->join();
    }
    delete mb_adapter_;
    mb_adapter_ = NULL;
    delete mb_adapter_thread_;
    mb_adapter_thread_ = NULL;
  }
  LOG4CXX_INFO(logger_, "Destroying Message Broker");
#endif  // MESSAGEBROKER_HMIADAPTER
  DCHECK_OR_RETURN_VOID(hmi_handler_);
  delete hmi_handler_;
  hmi_handler_ = NULL;

#ifdef TELEMETRY_MONITOR
  // It's important to delete tester Obcervers after TM adapters destruction
  if (telemetry_monitor_) {
    telemetry_monitor_->Stop();
    delete telemetry_monitor_;
    telemetry_monitor_ = NULL;
  }
#endif  // TELEMETRY_MONITOR
}

}  //  namespace main_namespace
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2010 Gabe Black
 * 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 the copyright holders 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.
 *
 * Authors: Gabe Black
 */

#ifndef __ARCH_GENERIC_TYPES_HH__
#define __ARCH_GENERIC_TYPES_HH__

#include <iostream>

#include "base/trace.hh"
#include "base/types.hh"
#include "sim/serialize.hh"

namespace GenericISA
{

// The guaranteed interface.
class PCStateBase
{
  protected:
    Addr _pc;
    Addr _npc;

    PCStateBase() {}
    PCStateBase(Addr val) { set(val); }

  public:
    /**
     * Returns the memory address the bytes of this instruction came from.
     *
     * @return Memory address of the current instruction's encoding.
     */
    Addr
    instAddr() const
    {
        return _pc;
    }

    /**
     * Returns the memory address the bytes of the next instruction came from.
     *
     * @return Memory address of the next instruction's encoding.
     */
    Addr
    nextInstAddr() const
    {
        return _npc;
    }

    /**
     * Returns the current micropc.
     *
     * @return The current micropc.
     */
    MicroPC
    microPC() const
    {
        return 0;
    }

    /**
     * Force this PC to reflect a particular value, resetting all its other
     * fields around it. This is useful for in place (re)initialization.
     *
     * @param val The value to set the PC to.
     */
    void set(Addr val);

    bool
    operator == (const PCStateBase &opc) const
    {
        return _pc == opc._pc && _npc == opc._npc;
    }

    bool
    operator != (const PCStateBase &opc) const
    {
        return !(*this == opc);
    }

    void
    serialize(std::ostream &os)
    {
        SERIALIZE_SCALAR(_pc);
        SERIALIZE_SCALAR(_npc);
    }

    void
    unserialize(Checkpoint *cp, const std::string &section)
    {
        UNSERIALIZE_SCALAR(_pc);
        UNSERIALIZE_SCALAR(_npc);
    }
};

/*
 * Different flavors of PC state. Only ISA specific code should rely on
 * any particular type of PC state being available. All other code should
 * use the interface above.
 */

// The most basic type of PC.
template <class MachInst>
class SimplePCState : public PCStateBase
{
  protected:
    typedef PCStateBase Base;

  public:

    Addr pc() const { return _pc; }
    void pc(Addr val) { _pc = val; }

    Addr npc() const { return _npc; }
    void npc(Addr val) { _npc = val; }

    void
    set(Addr val)
    {
        pc(val);
        npc(val + sizeof(MachInst));
    };

    SimplePCState() {}
    SimplePCState(Addr val) { set(val); }

    bool
    branching() const
    {
        return this->npc() != this->pc() + sizeof(MachInst);
    }

    // Advance the PC.
    void
    advance()
    {
        _pc = _npc;
        _npc += sizeof(MachInst);
    }
};

template <class MachInst>
std::ostream &
operator<<(std::ostream & os, const SimplePCState<MachInst> &pc)
{
    ccprintf(os, "(%#x=>%#x)", pc.pc(), pc.npc());
    return os;
}

// A PC and microcode PC.
template <class MachInst>
class UPCState : public SimplePCState<MachInst>
{
  protected:
    typedef SimplePCState<MachInst> Base;

    MicroPC _upc;
    MicroPC _nupc;

  public:

    MicroPC upc() const { return _upc; }
    void upc(MicroPC val) { _upc = val; }

    MicroPC nupc() const { return _nupc; }
    void nupc(MicroPC val) { _nupc = val; }

    MicroPC
    microPC() const
    {
        return _upc;
    }

    void
    set(Addr val)
    {
        Base::set(val);
        upc(0);
        nupc(1);
    }

    UPCState() {}
    UPCState(Addr val) { set(val); }

    bool
    branching() const
    {
        return this->npc() != this->pc() + sizeof(MachInst) ||
               this->nupc() != this->upc() + 1;
    }

    // Advance the upc within the instruction.
    void
    uAdvance()
    {
        _upc = _nupc;
        _nupc++;
    }

    // End the macroop by resetting the upc and advancing the regular pc.
    void
    uEnd()
    {
        this->advance();
        _upc = 0;
        _nupc = 1;
    }

    bool
    operator == (const UPCState<MachInst> &opc) const
    {
        return Base::_pc == opc._pc &&
               Base::_npc == opc._npc &&
               _upc == opc._upc && _nupc == opc._nupc;
    }

    bool
    operator != (const UPCState<MachInst> &opc) const
    {
        return !(*this == opc);
    }

    void
    serialize(std::ostream &os)
    {
        Base::serialize(os);
        SERIALIZE_SCALAR(_upc);
        SERIALIZE_SCALAR(_nupc);
    }

    void
    unserialize(Checkpoint *cp, const std::string &section)
    {
        Base::unserialize(cp, section);
        UNSERIALIZE_SCALAR(_upc);
        UNSERIALIZE_SCALAR(_nupc);
    }
};

template <class MachInst>
std::ostream &
operator<<(std::ostream & os, const UPCState<MachInst> &pc)
{
    ccprintf(os, "(%#x=>%#x).(%d=>%d)",
            pc.pc(), pc.npc(), pc.upc(), pc.npc());
    return os;
}

// A PC with a delay slot.
template <class MachInst>
class DelaySlotPCState : public SimplePCState<MachInst>
{
  protected:
    typedef SimplePCState<MachInst> Base;

    Addr _nnpc;

  public:

    Addr nnpc() const { return _nnpc; }
    void nnpc(Addr val) { _nnpc = val; }

    void
    set(Addr val)
    {
        Base::set(val);
        nnpc(val + 2 * sizeof(MachInst));
    }

    DelaySlotPCState() {}
    DelaySlotPCState(Addr val) { set(val); }

    bool
    branching() const
    {
        return !(this->nnpc() == this->npc() + sizeof(MachInst) &&
                 (this->npc() == this->pc() + sizeof(MachInst) ||
                  this->npc() == this->pc() + 2 * sizeof(MachInst)));
    }

    // Advance the PC.
    void
    advance()
    {
        Base::_pc = Base::_npc;
        Base::_npc = _nnpc;
        _nnpc += sizeof(MachInst);
    }

    bool
    operator == (const DelaySlotPCState<MachInst> &opc) const
    {
        return Base::_pc == opc._pc &&
               Base::_npc == opc._npc &&
               _nnpc == opc._nnpc;
    }

    bool
    operator != (const DelaySlotPCState<MachInst> &opc) const
    {
        return !(*this == opc);
    }

    void
    serialize(std::ostream &os)
    {
        Base::serialize(os);
        SERIALIZE_SCALAR(_nnpc);
    }

    void
    unserialize(Checkpoint *cp, const std::string &section)
    {
        Base::unserialize(cp, section);
        UNSERIALIZE_SCALAR(_nnpc);
    }
};

template <class MachInst>
std::ostream &
operator<<(std::ostream & os, const DelaySlotPCState<MachInst> &pc)
{
    ccprintf(os, "(%#x=>%#x=>%#x)",
            pc.pc(), pc.npc(), pc.nnpc());
    return os;
}

// A PC with a delay slot and a microcode PC.
template <class MachInst>
class DelaySlotUPCState : public DelaySlotPCState<MachInst>
{
  protected:
    typedef DelaySlotPCState<MachInst> Base;

    MicroPC _upc;
    MicroPC _nupc;

  public:

    MicroPC upc() const { return _upc; }
    void upc(MicroPC val) { _upc = val; }

    MicroPC nupc() const { return _nupc; }
    void nupc(MicroPC val) { _nupc = val; }

    MicroPC
    microPC() const
    {
        return _upc;
    }

    void
    set(Addr val)
    {
        Base::set(val);
        upc(0);
        nupc(1);
    }

    DelaySlotUPCState() {}
    DelaySlotUPCState(Addr val) { set(val); }

    bool
    branching() const
    {
        return Base::branching() || this->nupc() != this->upc() + 1;
    }

    // Advance the upc within the instruction.
    void
    uAdvance()
    {
        _upc = _nupc;
        _nupc++;
    }

    // End the macroop by resetting the upc and advancing the regular pc.
    void
    uEnd()
    {
        this->advance();
        _upc = 0;
        _nupc = 1;
    }

    bool
    operator == (const DelaySlotUPCState<MachInst> &opc) const
    {
        return Base::_pc == opc._pc &&
               Base::_npc == opc._npc &&
               Base::_nnpc == opc._nnpc &&
               _upc == opc._upc && _nupc == opc._nupc;
    }

    bool
    operator != (const DelaySlotUPCState<MachInst> &opc) const
    {
        return !(*this == opc);
    }

    void
    serialize(std::ostream &os)
    {
        Base::serialize(os);
        SERIALIZE_SCALAR(_upc);
        SERIALIZE_SCALAR(_nupc);
    }

    void
    unserialize(Checkpoint *cp, const std::string &section)
    {
        Base::unserialize(cp, section);
        UNSERIALIZE_SCALAR(_upc);
        UNSERIALIZE_SCALAR(_nupc);
    }
};

template <class MachInst>
std::ostream &
operator<<(std::ostream & os, const DelaySlotUPCState<MachInst> &pc)
{
    ccprintf(os, "(%#x=>%#x=>%#x).(%d=>%d)",
            pc.pc(), pc.npc(), pc.nnpc(), pc.upc(), pc.nupc());
    return os;
}

}

#endif
<commit_msg>arch: print next upc correctly The patch corrects the print statement which prints the current and the next pc. Instead of the next upc, the next pc was being printed.<commit_after>/*
 * Copyright (c) 2010 Gabe Black
 * 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 the copyright holders 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.
 *
 * Authors: Gabe Black
 */

#ifndef __ARCH_GENERIC_TYPES_HH__
#define __ARCH_GENERIC_TYPES_HH__

#include <iostream>

#include "base/trace.hh"
#include "base/types.hh"
#include "sim/serialize.hh"

namespace GenericISA
{

// The guaranteed interface.
class PCStateBase
{
  protected:
    Addr _pc;
    Addr _npc;

    PCStateBase() {}
    PCStateBase(Addr val) { set(val); }

  public:
    /**
     * Returns the memory address the bytes of this instruction came from.
     *
     * @return Memory address of the current instruction's encoding.
     */
    Addr
    instAddr() const
    {
        return _pc;
    }

    /**
     * Returns the memory address the bytes of the next instruction came from.
     *
     * @return Memory address of the next instruction's encoding.
     */
    Addr
    nextInstAddr() const
    {
        return _npc;
    }

    /**
     * Returns the current micropc.
     *
     * @return The current micropc.
     */
    MicroPC
    microPC() const
    {
        return 0;
    }

    /**
     * Force this PC to reflect a particular value, resetting all its other
     * fields around it. This is useful for in place (re)initialization.
     *
     * @param val The value to set the PC to.
     */
    void set(Addr val);

    bool
    operator == (const PCStateBase &opc) const
    {
        return _pc == opc._pc && _npc == opc._npc;
    }

    bool
    operator != (const PCStateBase &opc) const
    {
        return !(*this == opc);
    }

    void
    serialize(std::ostream &os)
    {
        SERIALIZE_SCALAR(_pc);
        SERIALIZE_SCALAR(_npc);
    }

    void
    unserialize(Checkpoint *cp, const std::string &section)
    {
        UNSERIALIZE_SCALAR(_pc);
        UNSERIALIZE_SCALAR(_npc);
    }
};

/*
 * Different flavors of PC state. Only ISA specific code should rely on
 * any particular type of PC state being available. All other code should
 * use the interface above.
 */

// The most basic type of PC.
template <class MachInst>
class SimplePCState : public PCStateBase
{
  protected:
    typedef PCStateBase Base;

  public:

    Addr pc() const { return _pc; }
    void pc(Addr val) { _pc = val; }

    Addr npc() const { return _npc; }
    void npc(Addr val) { _npc = val; }

    void
    set(Addr val)
    {
        pc(val);
        npc(val + sizeof(MachInst));
    };

    SimplePCState() {}
    SimplePCState(Addr val) { set(val); }

    bool
    branching() const
    {
        return this->npc() != this->pc() + sizeof(MachInst);
    }

    // Advance the PC.
    void
    advance()
    {
        _pc = _npc;
        _npc += sizeof(MachInst);
    }
};

template <class MachInst>
std::ostream &
operator<<(std::ostream & os, const SimplePCState<MachInst> &pc)
{
    ccprintf(os, "(%#x=>%#x)", pc.pc(), pc.npc());
    return os;
}

// A PC and microcode PC.
template <class MachInst>
class UPCState : public SimplePCState<MachInst>
{
  protected:
    typedef SimplePCState<MachInst> Base;

    MicroPC _upc;
    MicroPC _nupc;

  public:

    MicroPC upc() const { return _upc; }
    void upc(MicroPC val) { _upc = val; }

    MicroPC nupc() const { return _nupc; }
    void nupc(MicroPC val) { _nupc = val; }

    MicroPC
    microPC() const
    {
        return _upc;
    }

    void
    set(Addr val)
    {
        Base::set(val);
        upc(0);
        nupc(1);
    }

    UPCState() {}
    UPCState(Addr val) { set(val); }

    bool
    branching() const
    {
        return this->npc() != this->pc() + sizeof(MachInst) ||
               this->nupc() != this->upc() + 1;
    }

    // Advance the upc within the instruction.
    void
    uAdvance()
    {
        _upc = _nupc;
        _nupc++;
    }

    // End the macroop by resetting the upc and advancing the regular pc.
    void
    uEnd()
    {
        this->advance();
        _upc = 0;
        _nupc = 1;
    }

    bool
    operator == (const UPCState<MachInst> &opc) const
    {
        return Base::_pc == opc._pc &&
               Base::_npc == opc._npc &&
               _upc == opc._upc && _nupc == opc._nupc;
    }

    bool
    operator != (const UPCState<MachInst> &opc) const
    {
        return !(*this == opc);
    }

    void
    serialize(std::ostream &os)
    {
        Base::serialize(os);
        SERIALIZE_SCALAR(_upc);
        SERIALIZE_SCALAR(_nupc);
    }

    void
    unserialize(Checkpoint *cp, const std::string &section)
    {
        Base::unserialize(cp, section);
        UNSERIALIZE_SCALAR(_upc);
        UNSERIALIZE_SCALAR(_nupc);
    }
};

template <class MachInst>
std::ostream &
operator<<(std::ostream & os, const UPCState<MachInst> &pc)
{
    ccprintf(os, "(%#x=>%#x).(%d=>%d)",
            pc.pc(), pc.npc(), pc.upc(), pc.nupc());
    return os;
}

// A PC with a delay slot.
template <class MachInst>
class DelaySlotPCState : public SimplePCState<MachInst>
{
  protected:
    typedef SimplePCState<MachInst> Base;

    Addr _nnpc;

  public:

    Addr nnpc() const { return _nnpc; }
    void nnpc(Addr val) { _nnpc = val; }

    void
    set(Addr val)
    {
        Base::set(val);
        nnpc(val + 2 * sizeof(MachInst));
    }

    DelaySlotPCState() {}
    DelaySlotPCState(Addr val) { set(val); }

    bool
    branching() const
    {
        return !(this->nnpc() == this->npc() + sizeof(MachInst) &&
                 (this->npc() == this->pc() + sizeof(MachInst) ||
                  this->npc() == this->pc() + 2 * sizeof(MachInst)));
    }

    // Advance the PC.
    void
    advance()
    {
        Base::_pc = Base::_npc;
        Base::_npc = _nnpc;
        _nnpc += sizeof(MachInst);
    }

    bool
    operator == (const DelaySlotPCState<MachInst> &opc) const
    {
        return Base::_pc == opc._pc &&
               Base::_npc == opc._npc &&
               _nnpc == opc._nnpc;
    }

    bool
    operator != (const DelaySlotPCState<MachInst> &opc) const
    {
        return !(*this == opc);
    }

    void
    serialize(std::ostream &os)
    {
        Base::serialize(os);
        SERIALIZE_SCALAR(_nnpc);
    }

    void
    unserialize(Checkpoint *cp, const std::string &section)
    {
        Base::unserialize(cp, section);
        UNSERIALIZE_SCALAR(_nnpc);
    }
};

template <class MachInst>
std::ostream &
operator<<(std::ostream & os, const DelaySlotPCState<MachInst> &pc)
{
    ccprintf(os, "(%#x=>%#x=>%#x)",
            pc.pc(), pc.npc(), pc.nnpc());
    return os;
}

// A PC with a delay slot and a microcode PC.
template <class MachInst>
class DelaySlotUPCState : public DelaySlotPCState<MachInst>
{
  protected:
    typedef DelaySlotPCState<MachInst> Base;

    MicroPC _upc;
    MicroPC _nupc;

  public:

    MicroPC upc() const { return _upc; }
    void upc(MicroPC val) { _upc = val; }

    MicroPC nupc() const { return _nupc; }
    void nupc(MicroPC val) { _nupc = val; }

    MicroPC
    microPC() const
    {
        return _upc;
    }

    void
    set(Addr val)
    {
        Base::set(val);
        upc(0);
        nupc(1);
    }

    DelaySlotUPCState() {}
    DelaySlotUPCState(Addr val) { set(val); }

    bool
    branching() const
    {
        return Base::branching() || this->nupc() != this->upc() + 1;
    }

    // Advance the upc within the instruction.
    void
    uAdvance()
    {
        _upc = _nupc;
        _nupc++;
    }

    // End the macroop by resetting the upc and advancing the regular pc.
    void
    uEnd()
    {
        this->advance();
        _upc = 0;
        _nupc = 1;
    }

    bool
    operator == (const DelaySlotUPCState<MachInst> &opc) const
    {
        return Base::_pc == opc._pc &&
               Base::_npc == opc._npc &&
               Base::_nnpc == opc._nnpc &&
               _upc == opc._upc && _nupc == opc._nupc;
    }

    bool
    operator != (const DelaySlotUPCState<MachInst> &opc) const
    {
        return !(*this == opc);
    }

    void
    serialize(std::ostream &os)
    {
        Base::serialize(os);
        SERIALIZE_SCALAR(_upc);
        SERIALIZE_SCALAR(_nupc);
    }

    void
    unserialize(Checkpoint *cp, const std::string &section)
    {
        Base::unserialize(cp, section);
        UNSERIALIZE_SCALAR(_upc);
        UNSERIALIZE_SCALAR(_nupc);
    }
};

template <class MachInst>
std::ostream &
operator<<(std::ostream & os, const DelaySlotUPCState<MachInst> &pc)
{
    ccprintf(os, "(%#x=>%#x=>%#x).(%d=>%d)",
            pc.pc(), pc.npc(), pc.nnpc(), pc.upc(), pc.nupc());
    return os;
}

}

#endif
<|endoftext|>


<commit_before>/*
===============================================================================

  FILE:  arithmeticencoder.cpp

  CONTENTS:

    A modular C++ wrapper for an adapted version of Amir Said's FastAC Code.
    see: http://www.cipr.rpi.edu/~said/FastAC.html

  PROGRAMMERS:

    martin.isenburg@gmail.com

  COPYRIGHT:

    (c) 2011, Martin Isenburg, LASSO - tools to catch reality

    This is free software; you can redistribute and/or modify it under the
    terms of the GNU Lesser General Licence as published by the Free Software
    Foundation. See the COPYING file for more information.

    This software is distributed WITHOUT ANY WARRANTY and without even the
    implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

  CHANGE HISTORY:

    see header file

===============================================================================
*/

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//                                                                           -
// Fast arithmetic coding implementation                                     -
// -> 32-bit variables, 32-bit product, periodic updates, table decoding     -
//                                                                           -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//                                                                           -
// Version 1.00  -  April 25, 2004                                           -
//                                                                           -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//                                                                           -
//                                  WARNING                                  -
//                                 =========                                 -
//                                                                           -
// The only purpose of this program is to demonstrate the basic principles   -
// of arithmetic coding. It is provided as is, without any express or        -
// implied warranty, without even the warranty of fitness for any particular -
// purpose, or that the implementations are correct.                         -
//                                                                           -
// Permission to copy and redistribute this code is hereby granted, provided -
// that this warning and copyright notices are not removed or altered.       -
//                                                                           -
// Copyright (c) 2004 by Amir Said (said@ieee.org) &                         -
//                       William A. Pearlman (pearlw@ecse.rpi.edu)           -
//                                                                           -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//                                                                           -
// A description of the arithmetic coding method used here is available in   -
//                                                                           -
// Lossless Compression Handbook, ed. K. Sayood                              -
// Chapter 5: Arithmetic Coding (A. Said), pp. 101-152, Academic Press, 2003 -
//                                                                           -
// A. Said, Introduction to Arithetic Coding Theory and Practice             -
// HP Labs report HPL-2004-76  -  http://www.hpl.hp.com/techreports/         -
//                                                                           -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

#include "arithmeticencoder.hpp"

#include <string.h>
#include <assert.h>

#include "arithmeticmodel.hpp"

ArithmeticEncoder::ArithmeticEncoder()
{
  outstream = 0;

  outbuffer = (U8*)malloc(sizeof(U8)*2*AC_BUFFER_SIZE);
  endbuffer = outbuffer + 2 * AC_BUFFER_SIZE;
}

ArithmeticEncoder::~ArithmeticEncoder()
{
  free(outbuffer);
}

BOOL ArithmeticEncoder::init(ByteStreamOut* outstream)
{
  if (outstream == 0) return FALSE;
  this->outstream = outstream;
  base   = 0;
  length = AC__MaxLength;
  outbyte = outbuffer;
  endbyte = endbuffer;
  return TRUE;
}

void ArithmeticEncoder::done()
{
  U32 init_base = base;                 // done encoding: set final data bytes

  if (length > 2 * AC__MinLength) {
    base  += AC__MinLength;                                     // base offset
    length = AC__MinLength >> 1;             // set new length for 1 more byte
  }
  else {
    base  += AC__MinLength >> 1;                                // base offset
    length = AC__MinLength >> 9;            // set new length for 2 more bytes
  }

  if (init_base > base) propagate_carry();                 // overflow = carry
  renorm_enc_interval();                // renormalization = output last bytes

  if (endbyte != endbuffer)
  {
    assert(outbyte < outbuffer + AC_BUFFER_SIZE);
    outstream->putBytes(outbuffer + AC_BUFFER_SIZE, AC_BUFFER_SIZE);
  }
  U32 buffer_size = outbyte - outbuffer;
  if (buffer_size) outstream->putBytes(outbuffer, buffer_size);

  // write three zero bytes to be sure the decoder does not read past the array
  outstream->putByte(0);
  outstream->putByte(0);
  outstream->putByte(0);

  outstream = 0;
}

EntropyModel* ArithmeticEncoder::createBitModel()
{
  ArithmeticBitModel* m = new ArithmeticBitModel();
  return (EntropyModel*)m;
}

void ArithmeticEncoder::initBitModel(EntropyModel* model)
{
  ArithmeticBitModel* m = (ArithmeticBitModel*)model;
  m->init();
}

void ArithmeticEncoder::destroyBitModel(EntropyModel* model)
{
  ArithmeticBitModel* m = (ArithmeticBitModel*)model;
  delete m;
}

EntropyModel* ArithmeticEncoder::createSymbolModel(U32 n)
{
  ArithmeticModel* m = new ArithmeticModel(n, true);
  return (EntropyModel*)m;
}

void ArithmeticEncoder::initSymbolModel(EntropyModel* model, U32* table)
{
  ArithmeticModel* m = (ArithmeticModel*)model;
  m->init(table);
}

void ArithmeticEncoder::destroySymbolModel(EntropyModel* model)
{
  ArithmeticModel* m = (ArithmeticModel*)model;
  delete m;
}

void ArithmeticEncoder::encodeBit(EntropyModel* model, U32 sym)
{
  assert(model && (sym <= 1));

  ArithmeticBitModel* m = (ArithmeticBitModel*)model;
  U32 x = m->bit_0_prob * (length >> BM__LengthShift);       // product l x p0
                                                            // update interval
  if (sym == 0) {
    length = x;
    ++m->bit_0_count;
  }
  else {
    U32 init_base = base;
    base += x;
    length -= x;
    if (init_base > base) propagate_carry();               // overflow = carry
  }

  if (length < AC__MinLength) renorm_enc_interval();        // renormalization
  if (--m->bits_until_update == 0) m->update();       // periodic model update
}

void ArithmeticEncoder::encodeSymbol(EntropyModel* model, U32 sym)
{
  assert(model);
  ArithmeticModel* m = (ArithmeticModel*)model;
  assert(sym <= m->last_symbol);
  U32 x, init_base = base;
                                                           // compute products
  if (sym == m->last_symbol) {
    x = m->distribution[sym] * (length >> DM__LengthShift);
    base   += x;                                            // update interval
    length -= x;                                          // no product needed
  }
  else {
    x = m->distribution[sym] * (length >>= DM__LengthShift);
    base   += x;                                            // update interval
    length  = m->distribution[sym+1] * length - x;
  }

  if (init_base > base) propagate_carry();                 // overflow = carry
  if (length < AC__MinLength) renorm_enc_interval();        // renormalization

  ++m->symbol_count[sym];
  if (--m->symbols_until_update == 0) m->update();    // periodic model update
}

void ArithmeticEncoder::writeBit(U32 sym)
{
  assert(sym < 2);

  U32 init_base = base;
  base += sym * (length >>= 1);                // new interval base and length

  if (init_base > base) propagate_carry();                 // overflow = carry
  if (length < AC__MinLength) renorm_enc_interval();        // renormalization
}

void ArithmeticEncoder::writeBits(U32 bits, U32 sym)
{
  assert(bits && (bits <= 32) && (sym < (1u<<bits)));

  if (bits > 19)
  {
    writeShort(sym&U16_MAX);
    sym = sym >> 16;
    bits = bits - 16;
  }

  U32 init_base = base;
  base += sym * (length >>= bits);             // new interval base and length

  if (init_base > base) propagate_carry();                 // overflow = carry
  if (length < AC__MinLength) renorm_enc_interval();        // renormalization
}

void ArithmeticEncoder::writeByte(U8 sym)
{
  U32 init_base = base;
  base += (U32)(sym) * (length >>= 8);           // new interval base and length

  if (init_base > base) propagate_carry();                 // overflow = carry
  if (length < AC__MinLength) renorm_enc_interval();        // renormalization
}

void ArithmeticEncoder::writeShort(U16 sym)
{
  U32 init_base = base;
  base += (U32)(sym) * (length >>= 16);          // new interval base and length

  if (init_base > base) propagate_carry();                 // overflow = carry
  if (length < AC__MinLength) renorm_enc_interval();        // renormalization
}

inline void ArithmeticEncoder::writeInt(U32 sym)
{
  writeShort((U16)(sym & 0xFFFF)); // lower 16 bits
  writeShort((U16)(sym >> 16));    // UPPER 16 bits
}

inline void ArithmeticEncoder::writeFloat(F32 sym) /* danger in float reinterpretation */
{
  U32I32F32 u32i32f32;
  u32i32f32.f32 = sym;
  writeInt(u32i32f32.u32);
}

inline void ArithmeticEncoder::writeInt64(U64 sym)
{
  writeInt((U32)(sym & 0xFFFFFFFF)); // lower 32 bits
  writeInt((U32)(sym >> 32));        // UPPER 32 bits
}

inline void ArithmeticEncoder::writeDouble(F64 sym) /* danger in float reinterpretation */
{
  U64I64F64 u64i64f64;
  u64i64f64.f64 = sym;
  writeInt64(u64i64f64.u64);
}

inline void ArithmeticEncoder::propagate_carry()
{
  U8 * p;
  if (outbyte == outbuffer)
    p = endbuffer - 1;
  else
    p = outbyte - 1;
  while (*p == 0xFFU)
  {
    *p = 0;
    if (p == outbuffer)
      p = endbuffer - 1;
    else
      p--;
    assert(outbuffer <= p);
    assert(p < endbuffer);
    assert(outbyte < endbuffer);
  }
  ++*p;
}

inline void ArithmeticEncoder::renorm_enc_interval()
{
  do {                                          // output and discard top byte
    assert(outbuffer <= outbyte);
    assert(outbyte < endbuffer);
    assert(outbyte < endbyte);
    *outbyte++ = (U8)(base >> 24);
    if (outbyte == endbyte) manage_outbuffer();
    base <<= 8;
  } while ((length <<= 8) < AC__MinLength);        // length multiplied by 256
}

inline void ArithmeticEncoder::manage_outbuffer()
{
  if (outbyte == endbuffer) outbyte = outbuffer;
  outstream->putBytes(outbyte, AC_BUFFER_SIZE);
  endbyte = outbyte + AC_BUFFER_SIZE;
  assert(endbyte > outbyte);
  assert(outbyte < endbuffer);
}
<commit_msg>fixed wrong number of end bytes bug<commit_after>/*
===============================================================================

  FILE:  arithmeticencoder.cpp

  CONTENTS:

    A modular C++ wrapper for an adapted version of Amir Said's FastAC Code.
    see: http://www.cipr.rpi.edu/~said/FastAC.html

  PROGRAMMERS:

    martin.isenburg@gmail.com

  COPYRIGHT:

    (c) 2011, Martin Isenburg, LASSO - tools to catch reality

    This is free software; you can redistribute and/or modify it under the
    terms of the GNU Lesser General Licence as published by the Free Software
    Foundation. See the COPYING file for more information.

    This software is distributed WITHOUT ANY WARRANTY and without even the
    implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

  CHANGE HISTORY:

    see header file

===============================================================================
*/

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//                                                                           -
// Fast arithmetic coding implementation                                     -
// -> 32-bit variables, 32-bit product, periodic updates, table decoding     -
//                                                                           -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//                                                                           -
// Version 1.00  -  April 25, 2004                                           -
//                                                                           -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//                                                                           -
//                                  WARNING                                  -
//                                 =========                                 -
//                                                                           -
// The only purpose of this program is to demonstrate the basic principles   -
// of arithmetic coding. It is provided as is, without any express or        -
// implied warranty, without even the warranty of fitness for any particular -
// purpose, or that the implementations are correct.                         -
//                                                                           -
// Permission to copy and redistribute this code is hereby granted, provided -
// that this warning and copyright notices are not removed or altered.       -
//                                                                           -
// Copyright (c) 2004 by Amir Said (said@ieee.org) &                         -
//                       William A. Pearlman (pearlw@ecse.rpi.edu)           -
//                                                                           -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//                                                                           -
// A description of the arithmetic coding method used here is available in   -
//                                                                           -
// Lossless Compression Handbook, ed. K. Sayood                              -
// Chapter 5: Arithmetic Coding (A. Said), pp. 101-152, Academic Press, 2003 -
//                                                                           -
// A. Said, Introduction to Arithetic Coding Theory and Practice             -
// HP Labs report HPL-2004-76  -  http://www.hpl.hp.com/techreports/         -
//                                                                           -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

#include "arithmeticencoder.hpp"

#include <string.h>
#include <assert.h>

#include <stdio.h>

FILE* file = 0;

#include "arithmeticmodel.hpp"

ArithmeticEncoder::ArithmeticEncoder()
{
  outstream = 0;

  outbuffer = (U8*)malloc(sizeof(U8)*2*AC_BUFFER_SIZE);
  endbuffer = outbuffer + 2 * AC_BUFFER_SIZE;
}

ArithmeticEncoder::~ArithmeticEncoder()
{
  free(outbuffer);
}

BOOL ArithmeticEncoder::init(ByteStreamOut* outstream)
{
  if (outstream == 0) return FALSE;
  this->outstream = outstream;
  base   = 0;
  length = AC__MaxLength;
  outbyte = outbuffer;
  endbyte = endbuffer;
  return TRUE;
}

void ArithmeticEncoder::done()
{
  U32 init_base = base;                 // done encoding: set final data bytes
  BOOL another_byte = TRUE;

  if (length > 2 * AC__MinLength) {
    base  += AC__MinLength;                                     // base offset
    length = AC__MinLength >> 1;             // set new length for 1 more byte
  }
  else {
    base  += AC__MinLength >> 1;                                // base offset
    length = AC__MinLength >> 9;            // set new length for 2 more bytes
    another_byte = FALSE;
  }

  if (init_base > base) propagate_carry();                 // overflow = carry
  renorm_enc_interval();                // renormalization = output last bytes

  if (endbyte != endbuffer)
  {
    assert(outbyte < outbuffer + AC_BUFFER_SIZE);
    outstream->putBytes(outbuffer + AC_BUFFER_SIZE, AC_BUFFER_SIZE);
  }
  U32 buffer_size = outbyte - outbuffer;
  if (buffer_size) outstream->putBytes(outbuffer, buffer_size);

  // write two or three zero bytes to be in sync with the decoder's byte reads
  outstream->putByte(0);
  outstream->putByte(0);
  if (another_byte) outstream->putByte(0);

  outstream = 0;
}

EntropyModel* ArithmeticEncoder::createBitModel()
{
  ArithmeticBitModel* m = new ArithmeticBitModel();
  return (EntropyModel*)m;
}

void ArithmeticEncoder::initBitModel(EntropyModel* model)
{
  ArithmeticBitModel* m = (ArithmeticBitModel*)model;
  m->init();
}

void ArithmeticEncoder::destroyBitModel(EntropyModel* model)
{
  ArithmeticBitModel* m = (ArithmeticBitModel*)model;
  delete m;
}

EntropyModel* ArithmeticEncoder::createSymbolModel(U32 n)
{
  ArithmeticModel* m = new ArithmeticModel(n, true);
  return (EntropyModel*)m;
}

void ArithmeticEncoder::initSymbolModel(EntropyModel* model, U32* table)
{
  ArithmeticModel* m = (ArithmeticModel*)model;
  m->init(table);
}

void ArithmeticEncoder::destroySymbolModel(EntropyModel* model)
{
  ArithmeticModel* m = (ArithmeticModel*)model;
  delete m;
}

void ArithmeticEncoder::encodeBit(EntropyModel* model, U32 sym)
{
  assert(model && (sym <= 1));

  ArithmeticBitModel* m = (ArithmeticBitModel*)model;
  U32 x = m->bit_0_prob * (length >> BM__LengthShift);       // product l x p0
                                                            // update interval
  if (sym == 0) {
    length = x;
    ++m->bit_0_count;
  }
  else {
    U32 init_base = base;
    base += x;
    length -= x;
    if (init_base > base) propagate_carry();               // overflow = carry
  }

  if (length < AC__MinLength) renorm_enc_interval();        // renormalization
  if (--m->bits_until_update == 0) m->update();       // periodic model update
}

void ArithmeticEncoder::encodeSymbol(EntropyModel* model, U32 sym)
{
  assert(model);
  ArithmeticModel* m = (ArithmeticModel*)model;
  assert(sym <= m->last_symbol);
  U32 x, init_base = base;
                                                           // compute products
  if (sym == m->last_symbol) {
    x = m->distribution[sym] * (length >> DM__LengthShift);
    base   += x;                                            // update interval
    length -= x;                                          // no product needed
  }
  else {
    x = m->distribution[sym] * (length >>= DM__LengthShift);
    base   += x;                                            // update interval
    length  = m->distribution[sym+1] * length - x;
  }

  if (init_base > base) propagate_carry();                 // overflow = carry
  if (length < AC__MinLength) renorm_enc_interval();        // renormalization

  ++m->symbol_count[sym];
  if (--m->symbols_until_update == 0) m->update();    // periodic model update
}

void ArithmeticEncoder::writeBit(U32 sym)
{
  assert(sym < 2);

  U32 init_base = base;
  base += sym * (length >>= 1);                // new interval base and length

  if (init_base > base) propagate_carry();                 // overflow = carry
  if (length < AC__MinLength) renorm_enc_interval();        // renormalization
}

void ArithmeticEncoder::writeBits(U32 bits, U32 sym)
{
  assert(bits && (bits <= 32) && (sym < (1u<<bits)));

  if (bits > 19)
  {
    writeShort(sym&U16_MAX);
    sym = sym >> 16;
    bits = bits - 16;
  }

  U32 init_base = base;
  base += sym * (length >>= bits);             // new interval base and length

  if (init_base > base) propagate_carry();                 // overflow = carry
  if (length < AC__MinLength) renorm_enc_interval();        // renormalization
}

void ArithmeticEncoder::writeByte(U8 sym)
{
  U32 init_base = base;
  base += (U32)(sym) * (length >>= 8);           // new interval base and length

  if (init_base > base) propagate_carry();                 // overflow = carry
  if (length < AC__MinLength) renorm_enc_interval();        // renormalization
}

void ArithmeticEncoder::writeShort(U16 sym)
{
  U32 init_base = base;
  base += (U32)(sym) * (length >>= 16);          // new interval base and length

  if (init_base > base) propagate_carry();                 // overflow = carry
  if (length < AC__MinLength) renorm_enc_interval();        // renormalization
}

inline void ArithmeticEncoder::writeInt(U32 sym)
{
  writeShort((U16)(sym & 0xFFFF)); // lower 16 bits
  writeShort((U16)(sym >> 16));    // UPPER 16 bits
}

inline void ArithmeticEncoder::writeFloat(F32 sym) /* danger in float reinterpretation */
{
  U32I32F32 u32i32f32;
  u32i32f32.f32 = sym;
  writeInt(u32i32f32.u32);
}

inline void ArithmeticEncoder::writeInt64(U64 sym)
{
  writeInt((U32)(sym & 0xFFFFFFFF)); // lower 32 bits
  writeInt((U32)(sym >> 32));        // UPPER 32 bits
}

inline void ArithmeticEncoder::writeDouble(F64 sym) /* danger in float reinterpretation */
{
  U64I64F64 u64i64f64;
  u64i64f64.f64 = sym;
  writeInt64(u64i64f64.u64);
}

inline void ArithmeticEncoder::propagate_carry()
{
  U8 * p;
  if (outbyte == outbuffer)
    p = endbuffer - 1;
  else
    p = outbyte - 1;
  while (*p == 0xFFU)
  {
    *p = 0;
    if (p == outbuffer)
      p = endbuffer - 1;
    else
      p--;
    assert(outbuffer <= p);
    assert(p < endbuffer);
    assert(outbyte < endbuffer);
  }
  ++*p;
}

inline void ArithmeticEncoder::renorm_enc_interval()
{
  do {                                          // output and discard top byte
    assert(outbuffer <= outbyte);
    assert(outbyte < endbuffer);
    assert(outbyte < endbyte);
    *outbyte++ = (U8)(base >> 24);
    if (outbyte == endbyte) manage_outbuffer();
    base <<= 8;
  } while ((length <<= 8) < AC__MinLength);        // length multiplied by 256
}

inline void ArithmeticEncoder::manage_outbuffer()
{
  if (outbyte == endbuffer) outbyte = outbuffer;
  outstream->putBytes(outbyte, AC_BUFFER_SIZE);
  endbyte = outbyte + AC_BUFFER_SIZE;
  assert(endbyte > outbyte);
  assert(outbyte < endbuffer);
}
<|endoftext|>


<commit_before>/*************************************************************************/
/*  jsonrpc.cpp                                                          */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "jsonrpc.h"
#include "core/io/json.h"

JSONRPC::JSONRPC() {
}

JSONRPC::~JSONRPC() {
}

void JSONRPC::_bind_methods() {
	ClassDB::bind_method(D_METHOD("set_scope", "scope", "target"), &JSONRPC::set_scope);
	ClassDB::bind_method(D_METHOD("process_action", "action", "recurse"), &JSONRPC::process_action, DEFVAL(false));
	ClassDB::bind_method(D_METHOD("process_string", "action"), &JSONRPC::process_string);

	ClassDB::bind_method(D_METHOD("make_request", "method", "params", "id"), &JSONRPC::make_request);
	ClassDB::bind_method(D_METHOD("make_response", "result", "id"), &JSONRPC::make_response);
	ClassDB::bind_method(D_METHOD("make_notification", "method", "params"), &JSONRPC::make_notification);
	ClassDB::bind_method(D_METHOD("make_response_error", "code", "message", "id"), &JSONRPC::make_response_error, DEFVAL(Variant()));

	BIND_ENUM_CONSTANT(PARSE_ERROR);
	BIND_ENUM_CONSTANT(INVALID_REQUEST);
	BIND_ENUM_CONSTANT(METHOD_NOT_FOUND);
	BIND_ENUM_CONSTANT(INVALID_PARAMS);
	BIND_ENUM_CONSTANT(INTERNAL_ERROR);
}

Dictionary JSONRPC::make_response_error(int p_code, const String &p_message, const Variant &p_id) const {
	Dictionary dict;
	dict["jsonrpc"] = "2.0";

	Dictionary err;
	err["code"] = p_code;
	err["message"] = p_message;

	dict["error"] = err;
	dict["id"] = p_id;

	return dict;
}

Dictionary JSONRPC::make_response(const Variant &p_value, const Variant &p_id) {
	Dictionary dict;
	dict["jsonrpc"] = "2.0";
	dict["id"] = p_id;
	dict["result"] = p_value;
	return dict;
}

Dictionary JSONRPC::make_notification(const String &p_method, const Variant &p_params) {
	Dictionary dict;
	dict["jsonrpc"] = "2.0";
	dict["method"] = p_method;
	dict["params"] = p_params;
	return dict;
}

Dictionary JSONRPC::make_request(const String &p_method, const Variant &p_params, const Variant &p_id) {
	Dictionary dict;
	dict["jsonrpc"] = "2.0";
	dict["method"] = p_method;
	dict["params"] = p_params;
	dict["id"] = p_id;
	return dict;
}

Variant JSONRPC::process_action(const Variant &p_action, bool p_process_arr_elements) {
	Variant ret;
	if (p_action.get_type() == Variant::DICTIONARY) {
		Dictionary dict = p_action;
		String method = dict.get("method", "");
		Array args;
		if (dict.has("params")) {
			Variant params = dict.get("params", Variant());
			if (params.get_type() == Variant::ARRAY) {
				args = params;
			} else {
				args.push_back(params);
			}
		}

		Object *object = this;
		if (method_scopes.has(method.get_base_dir())) {
			object = method_scopes[method.get_base_dir()];
			method = method.get_file();
		}

		Variant id;
		if (dict.has("id")) {
			id = dict["id"];
		}

		if (object == NULL || !object->has_method(method)) {
			ret = make_response_error(JSONRPC::METHOD_NOT_FOUND, "Method not found", id);
		} else {
			Variant call_ret = object->callv(method, args);
			if (id.get_type() != Variant::NIL) {
				ret = make_response(call_ret, id);
			}
		}
	} else if (p_action.get_type() == Variant::ARRAY && p_process_arr_elements) {
		Array arr = p_action;
		int size = arr.size();
		if (size) {
			Array arr_ret;
			for (int i = 0; i < size; i++) {
				const Variant &var = arr.get(i);
				arr_ret.push_back(process_action(var));
			}
			ret = arr_ret;
		} else {
			ret = make_response_error(JSONRPC::INVALID_REQUEST, "Invalid Request");
		}
	} else {
		ret = make_response_error(JSONRPC::INVALID_REQUEST, "Invalid Request");
	}
	return ret;
}

String JSONRPC::process_string(const String &p_input) {

	if (p_input.empty()) return String();

	Variant ret;
	Variant input;
	String err_message;
	int err_line;
	if (OK != JSON::parse(p_input, input, err_message, err_line)) {
		ret = make_response_error(JSONRPC::PARSE_ERROR, "Parse error");
	} else {
		ret = process_action(input, true);
	}

	if (ret.get_type() == Variant::NIL) {
		return "";
	}
	return JSON::print(ret);
}

void JSONRPC::set_scope(const String &p_scope, Object *p_obj) {
	method_scopes[p_scope] = p_obj;
}
<commit_msg>Improve jsonrpc error reporting<commit_after>/*************************************************************************/
/*  jsonrpc.cpp                                                          */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "jsonrpc.h"
#include "core/io/json.h"

JSONRPC::JSONRPC() {
}

JSONRPC::~JSONRPC() {
}

void JSONRPC::_bind_methods() {
	ClassDB::bind_method(D_METHOD("set_scope", "scope", "target"), &JSONRPC::set_scope);
	ClassDB::bind_method(D_METHOD("process_action", "action", "recurse"), &JSONRPC::process_action, DEFVAL(false));
	ClassDB::bind_method(D_METHOD("process_string", "action"), &JSONRPC::process_string);

	ClassDB::bind_method(D_METHOD("make_request", "method", "params", "id"), &JSONRPC::make_request);
	ClassDB::bind_method(D_METHOD("make_response", "result", "id"), &JSONRPC::make_response);
	ClassDB::bind_method(D_METHOD("make_notification", "method", "params"), &JSONRPC::make_notification);
	ClassDB::bind_method(D_METHOD("make_response_error", "code", "message", "id"), &JSONRPC::make_response_error, DEFVAL(Variant()));

	BIND_ENUM_CONSTANT(PARSE_ERROR);
	BIND_ENUM_CONSTANT(INVALID_REQUEST);
	BIND_ENUM_CONSTANT(METHOD_NOT_FOUND);
	BIND_ENUM_CONSTANT(INVALID_PARAMS);
	BIND_ENUM_CONSTANT(INTERNAL_ERROR);
}

Dictionary JSONRPC::make_response_error(int p_code, const String &p_message, const Variant &p_id) const {
	Dictionary dict;
	dict["jsonrpc"] = "2.0";

	Dictionary err;
	err["code"] = p_code;
	err["message"] = p_message;

	dict["error"] = err;
	dict["id"] = p_id;

	return dict;
}

Dictionary JSONRPC::make_response(const Variant &p_value, const Variant &p_id) {
	Dictionary dict;
	dict["jsonrpc"] = "2.0";
	dict["id"] = p_id;
	dict["result"] = p_value;
	return dict;
}

Dictionary JSONRPC::make_notification(const String &p_method, const Variant &p_params) {
	Dictionary dict;
	dict["jsonrpc"] = "2.0";
	dict["method"] = p_method;
	dict["params"] = p_params;
	return dict;
}

Dictionary JSONRPC::make_request(const String &p_method, const Variant &p_params, const Variant &p_id) {
	Dictionary dict;
	dict["jsonrpc"] = "2.0";
	dict["method"] = p_method;
	dict["params"] = p_params;
	dict["id"] = p_id;
	return dict;
}

Variant JSONRPC::process_action(const Variant &p_action, bool p_process_arr_elements) {
	Variant ret;
	if (p_action.get_type() == Variant::DICTIONARY) {
		Dictionary dict = p_action;
		String method = dict.get("method", "");
		Array args;
		if (dict.has("params")) {
			Variant params = dict.get("params", Variant());
			if (params.get_type() == Variant::ARRAY) {
				args = params;
			} else {
				args.push_back(params);
			}
		}

		Object *object = this;
		if (method_scopes.has(method.get_base_dir())) {
			object = method_scopes[method.get_base_dir()];
			method = method.get_file();
		}

		Variant id;
		if (dict.has("id")) {
			id = dict["id"];
		}

		if (object == NULL || !object->has_method(method)) {
			ret = make_response_error(JSONRPC::METHOD_NOT_FOUND, "Method not found: " + method, id);
		} else {
			Variant call_ret = object->callv(method, args);
			if (id.get_type() != Variant::NIL) {
				ret = make_response(call_ret, id);
			}
		}
	} else if (p_action.get_type() == Variant::ARRAY && p_process_arr_elements) {
		Array arr = p_action;
		int size = arr.size();
		if (size) {
			Array arr_ret;
			for (int i = 0; i < size; i++) {
				const Variant &var = arr.get(i);
				arr_ret.push_back(process_action(var));
			}
			ret = arr_ret;
		} else {
			ret = make_response_error(JSONRPC::INVALID_REQUEST, "Invalid Request");
		}
	} else {
		ret = make_response_error(JSONRPC::INVALID_REQUEST, "Invalid Request");
	}
	return ret;
}

String JSONRPC::process_string(const String &p_input) {

	if (p_input.empty()) return String();

	Variant ret;
	Variant input;
	String err_message;
	int err_line;
	if (OK != JSON::parse(p_input, input, err_message, err_line)) {
		ret = make_response_error(JSONRPC::PARSE_ERROR, "Parse error");
	} else {
		ret = process_action(input, true);
	}

	if (ret.get_type() == Variant::NIL) {
		return "";
	}
	return JSON::print(ret);
}

void JSONRPC::set_scope(const String &p_scope, Object *p_obj) {
	method_scopes[p_scope] = p_obj;
}
<|endoftext|>


<commit_before>// Copyright 2004-present Facebook. All Rights Reserved.

#include <vector>
#include <string>

#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/predicate.hpp>

#include <glog/logging.h>

#include <osquery/core.h>
#include <osquery/tables.h>
#include <osquery/filesystem.h>

namespace osquery {
namespace tables {

QueryData parseNfsSharesContent(const std::string& content) {
  QueryData results;

  for (const auto& i : split(content, "\n")) {
    auto line = split(i);
    if (line.size() == 0 || boost::starts_with(line[0], "#")) {
      continue;
    }
    std::vector<std::string> lineExports;
    unsigned int readonly = 0;
    int index_of_options = -1;

    for (const auto& iter : line) {
      index_of_options++;
      if (iter[0] == '/') {
        lineExports.push_back(iter);

      } else {
        break;
      }
    }
    // Start looping through starting at the first options
    // (so skip the exports)
    for (std::vector<std::string>::iterator iter =
             line.begin() + index_of_options;
         iter != line.end();
         ++iter) {
      if (iter->compare("-ro") == 0 || iter->compare("-o") == 0) {
        readonly = 1;
      }
    }
    for (std::vector<std::string>::iterator iter = lineExports.begin();
         iter != lineExports.end();
         ++iter) {
      Row r;
      r["share"] = *iter;
      if (readonly) {
        r["readonly"] = "true";
      } else {
        r["readonly"] = "false";
      }
      std::ostringstream oss;
      std::copy(line.begin() + index_of_options,
                line.end(),
                std::ostream_iterator<std::string>(oss, " "));
      r["options"] = oss.str();
      results.push_back(r);
    }
  }
  return results;
}

QueryData genNfsShares(QueryContext& context) {
  std::string content;
  auto s = osquery::readFile("/etc/exports", content);
  if (s.ok()) {
    return parseNfsSharesContent(content);
  } else {
    VLOG(1) << "Error reading /etc/exports: " << s.toString();
    return {};
  }
}
}
}
<commit_msg>More minor changes to address marpias requests<commit_after>// Copyright 2004-present Facebook. All Rights Reserved.

#include <vector>
#include <string>

#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/predicate.hpp>

#include <glog/logging.h>

#include <osquery/core.h>
#include <osquery/tables.h>
#include <osquery/filesystem.h>

namespace osquery {
namespace tables {

QueryData parseNfsSharesContent(const std::string& content) {
  QueryData results;

  for (const auto& i : split(content, "\n")) {
    auto line = split(i);
    if (line.size() == 0 || boost::starts_with(line[0], "#")) {
      continue;
    }
    std::vector<std::string> line_exports;
    unsigned int readonly = 0;
    int index_of_options = -1;

    for (const auto& iter : line) {
      index_of_options++;
      if (iter[0] == '/') {
        line_exports.push_back(iter);

      } else {
        break;
      }
    }
    // Start looping through starting at the first options
    // (so skip the exports)
    for (std::vector<std::string>::iterator iter =
             line.begin() + index_of_options;
         iter != line.end();
         ++iter) {
      if (iter->compare("-ro") == 0 || iter->compare("-o") == 0) {
        readonly = 1;
      }
    }
    for (const auto& iter : line_exports) {
      Row r;
      r["share"] = iter;
      if (readonly) {
        r["readonly"] = "true";
      } else {
        r["readonly"] = "false";
      }
      std::ostringstream oss;
      std::copy(line.begin() + index_of_options,
                line.end(),
                std::ostream_iterator<std::string>(oss, " "));
      r["options"] = oss.str();
      results.push_back(r);
    }
  }
  return results;
}

QueryData genNfsShares(QueryContext& context) {
  std::string content;
  auto s = osquery::readFile("/etc/exports", content);
  if (s.ok()) {
    return parseNfsSharesContent(content);
  } else {
    VLOG(1) << "Error reading /etc/exports: " << s.toString();
    return {};
  }
}
}
}
<|endoftext|>