<commit_before>//===-- sanitizer_symbolizer_report.cpp -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// This file is shared between AddressSanitizer and other sanitizer run-time
/// libraries and implements symbolized reports related functions.
///
//===----------------------------------------------------------------------===//

#include "sanitizer_common.h"
#include "sanitizer_file.h"
#include "sanitizer_flags.h"
#include "sanitizer_procmaps.h"
#include "sanitizer_report_decorator.h"
#include "sanitizer_stacktrace.h"
#include "sanitizer_stacktrace_printer.h"
#include "sanitizer_symbolizer.h"

#if SANITIZER_POSIX
# include "sanitizer_posix.h"
# include <sys/mman.h>
#endif

namespace __sanitizer {

#if !SANITIZER_GO
void ReportErrorSummary(const char *error_type, const AddressInfo &info,
                        const char *alt_tool_name) {
  if (!common_flags()->print_summary) return;
  InternalScopedString buff(kMaxSummaryLength);
  buff.append("%s ", error_type);
  RenderFrame(&buff, "%L %F", 0, info, common_flags()->symbolize_vs_style,
              common_flags()->strip_path_prefix);
  ReportErrorSummary(buff.data(), alt_tool_name);
}
#endif

#if !SANITIZER_FUCHSIA

bool ReportFile::SupportsColors() {
  SpinMutexLock l(mu);
  ReopenIfNecessary();
  return SupportsColoredOutput(fd);
}

static INLINE bool ReportSupportsColors() {
  return report_file.SupportsColors();
}

#else  // SANITIZER_FUCHSIA

// Fuchsia's logs always go through post-processing that handles colorization.
static INLINE bool ReportSupportsColors() { return true; }

#endif  // !SANITIZER_FUCHSIA

bool ColorizeReports() {
  // FIXME: Add proper Windows support to AnsiColorDecorator and re-enable color
  // printing on Windows.
  if (SANITIZER_WINDOWS)
    return false;

  const char *flag = common_flags()->color;
  return internal_strcmp(flag, "always") == 0 ||
         (internal_strcmp(flag, "auto") == 0 && ReportSupportsColors());
}

void ReportErrorSummary(const char *error_type, const StackTrace *stack,
                        const char *alt_tool_name) {
#if !SANITIZER_GO
  if (!common_flags()->print_summary)
    return;
  if (stack->size == 0) {
    ReportErrorSummary(error_type);
    return;
  }
  // Currently, we include the first stack frame into the report summary.
  // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
  uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
  SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc);
  ReportErrorSummary(error_type, frame->info, alt_tool_name);
  frame->ClearAll();
#endif
}

void ReportMmapWriteExec(int prot) {
#if SANITIZER_POSIX && (!SANITIZER_GO && !SANITIZER_ANDROID)
  if ((prot & (PROT_WRITE | PROT_EXEC)) != (PROT_WRITE | PROT_EXEC))
    return;

  ScopedErrorReportLock l;
  SanitizerCommonDecorator d;

  InternalMmapVector<BufferedStackTrace> stack_buffer(1);
  BufferedStackTrace *stack = stack_buffer.data();
  stack->Reset();
  uptr top = 0;
  uptr bottom = 0;
  GET_CALLER_PC_BP_SP;
  (void)sp;
  bool fast = common_flags()->fast_unwind_on_fatal;
  if (StackTrace::WillUseFastUnwind(fast)) {
    GetThreadStackTopAndBottom(false, &top, &bottom);
    stack->Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, true);
  } else {
    stack->Unwind(kStackTraceMax, pc, 0, nullptr, 0, 0, false);
  }

  Printf("%s", d.Warning());
  Report("WARNING: %s: writable-executable page usage\n", SanitizerToolName);
  Printf("%s", d.Default());

  stack->Print();
  ReportErrorSummary("w-and-x-usage", stack);
#endif
}

#if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS && !SANITIZER_GO
void StartReportDeadlySignal() {
  // Write the first message using fd=2, just in case.
  // It may actually fail to write in case stderr is closed.
  CatastrophicErrorWrite(SanitizerToolName, internal_strlen(SanitizerToolName));
  static const char kDeadlySignal[] = ":DEADLYSIGNAL\n";
  CatastrophicErrorWrite(kDeadlySignal, sizeof(kDeadlySignal) - 1);
}

static void MaybeReportNonExecRegion(uptr pc) {
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
  MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
  MemoryMappedSegment segment;
  while (proc_maps.Next(&segment)) {
    if (pc >= segment.start && pc < segment.end && !segment.IsExecutable())
      Report("Hint: PC is at a non-executable region. Maybe a wild jump?\n");
  }
#endif
}

static void PrintMemoryByte(InternalScopedString *str, const char *before,
                            u8 byte) {
  SanitizerCommonDecorator d;
  str->append("%s%s%x%x%s ", before, d.MemoryByte(), byte >> 4, byte & 15,
              d.Default());
}

static void MaybeDumpInstructionBytes(uptr pc) {
  if (!common_flags()->dump_instruction_bytes || (pc < GetPageSizeCached()))
    return;
  InternalScopedString str(1024);
  str.append("First 16 instruction bytes at pc: ");
  if (IsAccessibleMemoryRange(pc, 16)) {
    for (int i = 0; i < 16; ++i) {
      PrintMemoryByte(&str, "", ((u8 *)pc)[i]);
    }
    str.append("\n");
  } else {
    str.append("unaccessible\n");
  }
  Report("%s", str.data());
}

static void MaybeDumpRegisters(void *context) {
  if (!common_flags()->dump_registers) return;
  SignalContext::DumpAllRegisters(context);
}

static void ReportStackOverflowImpl(const SignalContext &sig, u32 tid,
                                    UnwindSignalStackCallbackType unwind,
                                    const void *unwind_context) {
  SanitizerCommonDecorator d;
  Printf("%s", d.Warning());
  static const char kDescription[] = "stack-overflow";
  Report("ERROR: %s: %s on address %p (pc %p bp %p sp %p T%d)\n",
         SanitizerToolName, kDescription, (void *)sig.addr, (void *)sig.pc,
         (void *)sig.bp, (void *)sig.sp, tid);
  Printf("%s", d.Default());
  InternalMmapVector<BufferedStackTrace> stack_buffer(1);
  BufferedStackTrace *stack = stack_buffer.data();
  stack->Reset();
  unwind(sig, unwind_context, stack);
  stack->Print();
  ReportErrorSummary(kDescription, stack);
}

static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
                                   UnwindSignalStackCallbackType unwind,
                                   const void *unwind_context) {
  SanitizerCommonDecorator d;
  Printf("%s", d.Warning());
  const char *description = sig.Describe();
  if (sig.is_memory_access && !sig.is_true_faulting_addr)
    Report("ERROR: %s: %s on unknown address (pc %p bp %p sp %p T%d)\n",
           SanitizerToolName, description, (void *)sig.pc, (void *)sig.bp,
           (void *)sig.sp, tid);
  else
    Report("ERROR: %s: %s on unknown address %p (pc %p bp %p sp %p T%d)\n",
           SanitizerToolName, description, (void *)sig.addr, (void *)sig.pc,
           (void *)sig.bp, (void *)sig.sp, tid);
  Printf("%s", d.Default());
  if (sig.pc < GetPageSizeCached())
    Report("Hint: pc points to the zero page.\n");
  if (sig.is_memory_access) {
    const char *access_type =
        sig.write_flag == SignalContext::WRITE
            ? "WRITE"
            : (sig.write_flag == SignalContext::READ ? "READ" : "UNKNOWN");
    Report("The signal is caused by a %s memory access.\n", access_type);
    if (!sig.is_true_faulting_addr)
      Report("Hint: this fault was caused by a dereference of a high value "
             "address (see register values below).\n");
    else if (sig.addr < GetPageSizeCached())
      Report("Hint: address points to the zero page.\n");
  }
  MaybeReportNonExecRegion(sig.pc);
  InternalMmapVector<BufferedStackTrace> stack_buffer(1);
  BufferedStackTrace *stack = stack_buffer.data();
  stack->Reset();
  unwind(sig, unwind_context, stack);
  stack->Print();
  MaybeDumpInstructionBytes(sig.pc);
  MaybeDumpRegisters(sig.context);
  Printf("%s can not provide additional info.\n", SanitizerToolName);
  ReportErrorSummary(description, stack);
}

void ReportDeadlySignal(const SignalContext &sig, u32 tid,
                        UnwindSignalStackCallbackType unwind,
                        const void *unwind_context) {
  if (sig.IsStackOverflow())
    ReportStackOverflowImpl(sig, tid, unwind, unwind_context);
  else
    ReportDeadlySignalImpl(sig, tid, unwind, unwind_context);
}

void HandleDeadlySignal(void *siginfo, void *context, u32 tid,
                        UnwindSignalStackCallbackType unwind,
                        const void *unwind_context) {
  StartReportDeadlySignal();
  ScopedErrorReportLock rl;
  SignalContext sig(siginfo, context);
  ReportDeadlySignal(sig, tid, unwind, unwind_context);
  Report("ABORTING\n");
  Die();
}

#endif  // !SANITIZER_FUCHSIA && !SANITIZER_GO

static atomic_uintptr_t reporting_thread = {0};
static StaticSpinMutex CommonSanitizerReportMutex;

ScopedErrorReportLock::ScopedErrorReportLock() {
  uptr current = GetThreadSelf();
  for (;;) {
    uptr expected = 0;
    if (atomic_compare_exchange_strong(&reporting_thread, &expected, current,
                                       memory_order_relaxed)) {
      // We've claimed reporting_thread so proceed.
      CommonSanitizerReportMutex.Lock();
      return;
    }

    if (expected == current) {
      // This is either asynch signal or nested error during error reporting.
      // Fail simple to avoid deadlocks in Report().

      // Can't use Report() here because of potential deadlocks in nested
      // signal handlers.
      CatastrophicErrorWrite(SanitizerToolName,
                             internal_strlen(SanitizerToolName));
      static const char msg[] = ": nested bug in the same thread, aborting.\n";
      CatastrophicErrorWrite(msg, sizeof(msg) - 1);

      internal__exit(common_flags()->exitcode);
    }

    internal_sched_yield();
  }
}

ScopedErrorReportLock::~ScopedErrorReportLock() {
  CommonSanitizerReportMutex.Unlock();
  atomic_store_relaxed(&reporting_thread, 0);
}

void ScopedErrorReportLock::CheckLocked() {
  CommonSanitizerReportMutex.CheckLocked();
}

}  // namespace __sanitizer
<commit_msg>Revert "[ASan] Refine diagnoses messages"<commit_after>//===-- sanitizer_symbolizer_report.cpp -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// This file is shared between AddressSanitizer and other sanitizer run-time
/// libraries and implements symbolized reports related functions.
///
//===----------------------------------------------------------------------===//

#include "sanitizer_common.h"
#include "sanitizer_file.h"
#include "sanitizer_flags.h"
#include "sanitizer_procmaps.h"
#include "sanitizer_report_decorator.h"
#include "sanitizer_stacktrace.h"
#include "sanitizer_stacktrace_printer.h"
#include "sanitizer_symbolizer.h"

#if SANITIZER_POSIX
# include "sanitizer_posix.h"
# include <sys/mman.h>
#endif

namespace __sanitizer {

#if !SANITIZER_GO
void ReportErrorSummary(const char *error_type, const AddressInfo &info,
                        const char *alt_tool_name) {
  if (!common_flags()->print_summary) return;
  InternalScopedString buff(kMaxSummaryLength);
  buff.append("%s ", error_type);
  RenderFrame(&buff, "%L %F", 0, info, common_flags()->symbolize_vs_style,
              common_flags()->strip_path_prefix);
  ReportErrorSummary(buff.data(), alt_tool_name);
}
#endif

#if !SANITIZER_FUCHSIA

bool ReportFile::SupportsColors() {
  SpinMutexLock l(mu);
  ReopenIfNecessary();
  return SupportsColoredOutput(fd);
}

static INLINE bool ReportSupportsColors() {
  return report_file.SupportsColors();
}

#else  // SANITIZER_FUCHSIA

// Fuchsia's logs always go through post-processing that handles colorization.
static INLINE bool ReportSupportsColors() { return true; }

#endif  // !SANITIZER_FUCHSIA

bool ColorizeReports() {
  // FIXME: Add proper Windows support to AnsiColorDecorator and re-enable color
  // printing on Windows.
  if (SANITIZER_WINDOWS)
    return false;

  const char *flag = common_flags()->color;
  return internal_strcmp(flag, "always") == 0 ||
         (internal_strcmp(flag, "auto") == 0 && ReportSupportsColors());
}

void ReportErrorSummary(const char *error_type, const StackTrace *stack,
                        const char *alt_tool_name) {
#if !SANITIZER_GO
  if (!common_flags()->print_summary)
    return;
  if (stack->size == 0) {
    ReportErrorSummary(error_type);
    return;
  }
  // Currently, we include the first stack frame into the report summary.
  // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
  uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
  SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc);
  ReportErrorSummary(error_type, frame->info, alt_tool_name);
  frame->ClearAll();
#endif
}

void ReportMmapWriteExec(int prot) {
#if SANITIZER_POSIX && (!SANITIZER_GO && !SANITIZER_ANDROID)
  if ((prot & (PROT_WRITE | PROT_EXEC)) != (PROT_WRITE | PROT_EXEC))
    return;

  ScopedErrorReportLock l;
  SanitizerCommonDecorator d;

  InternalMmapVector<BufferedStackTrace> stack_buffer(1);
  BufferedStackTrace *stack = stack_buffer.data();
  stack->Reset();
  uptr top = 0;
  uptr bottom = 0;
  GET_CALLER_PC_BP_SP;
  (void)sp;
  bool fast = common_flags()->fast_unwind_on_fatal;
  if (StackTrace::WillUseFastUnwind(fast)) {
    GetThreadStackTopAndBottom(false, &top, &bottom);
    stack->Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, true);
  } else {
    stack->Unwind(kStackTraceMax, pc, 0, nullptr, 0, 0, false);
  }

  Printf("%s", d.Warning());
  Report("WARNING: %s: writable-executable page usage\n", SanitizerToolName);
  Printf("%s", d.Default());

  stack->Print();
  ReportErrorSummary("w-and-x-usage", stack);
#endif
}

#if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS && !SANITIZER_GO
void StartReportDeadlySignal() {
  // Write the first message using fd=2, just in case.
  // It may actually fail to write in case stderr is closed.
  CatastrophicErrorWrite(SanitizerToolName, internal_strlen(SanitizerToolName));
  static const char kDeadlySignal[] = ":DEADLYSIGNAL\n";
  CatastrophicErrorWrite(kDeadlySignal, sizeof(kDeadlySignal) - 1);
}

static void MaybeReportNonExecRegion(uptr pc) {
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
  MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
  MemoryMappedSegment segment;
  while (proc_maps.Next(&segment)) {
    if (pc >= segment.start && pc < segment.end && !segment.IsExecutable())
      Report("Hint: PC is at a non-executable region. Maybe a wild jump?\n");
  }
#endif
}

static void PrintMemoryByte(InternalScopedString *str, const char *before,
                            u8 byte) {
  SanitizerCommonDecorator d;
  str->append("%s%s%x%x%s ", before, d.MemoryByte(), byte >> 4, byte & 15,
              d.Default());
}

static void MaybeDumpInstructionBytes(uptr pc) {
  if (!common_flags()->dump_instruction_bytes || (pc < GetPageSizeCached()))
    return;
  InternalScopedString str(1024);
  str.append("First 16 instruction bytes at pc: ");
  if (IsAccessibleMemoryRange(pc, 16)) {
    for (int i = 0; i < 16; ++i) {
      PrintMemoryByte(&str, "", ((u8 *)pc)[i]);
    }
    str.append("\n");
  } else {
    str.append("unaccessible\n");
  }
  Report("%s", str.data());
}

static void MaybeDumpRegisters(void *context) {
  if (!common_flags()->dump_registers) return;
  SignalContext::DumpAllRegisters(context);
}

static void ReportStackOverflowImpl(const SignalContext &sig, u32 tid,
                                    UnwindSignalStackCallbackType unwind,
                                    const void *unwind_context) {
  SanitizerCommonDecorator d;
  Printf("%s", d.Warning());
  static const char kDescription[] = "stack-overflow";
  Report("ERROR: %s: %s on address %p (pc %p bp %p sp %p T%d)\n",
         SanitizerToolName, kDescription, (void *)sig.addr, (void *)sig.pc,
         (void *)sig.bp, (void *)sig.sp, tid);
  Printf("%s", d.Default());
  InternalMmapVector<BufferedStackTrace> stack_buffer(1);
  BufferedStackTrace *stack = stack_buffer.data();
  stack->Reset();
  unwind(sig, unwind_context, stack);
  stack->Print();
  ReportErrorSummary(kDescription, stack);
}

static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
                                   UnwindSignalStackCallbackType unwind,
                                   const void *unwind_context) {
  SanitizerCommonDecorator d;
  Printf("%s", d.Warning());
  const char *description = sig.Describe();
  if (sig.is_memory_access && !sig.is_true_faulting_addr)
    Report("ERROR: %s: %s on unknown address (pc %p bp %p sp %p T%d)\n",
           SanitizerToolName, description, (void *)sig.pc, (void *)sig.bp,
           (void *)sig.sp, tid);
  else
    Report("ERROR: %s: %s on unknown address %p (pc %p bp %p sp %p T%d)\n",
           SanitizerToolName, description, (void *)sig.addr, (void *)sig.pc,
           (void *)sig.bp, (void *)sig.sp, tid);
  Printf("%s", d.Default());
  if (sig.pc < GetPageSizeCached())
    Report("Hint: pc points to the zero page.\n");
  if (sig.is_memory_access) {
    const char *access_type =
        sig.write_flag == SignalContext::WRITE
            ? "WRITE"
            : (sig.write_flag == SignalContext::READ ? "READ" : "UNKNOWN");
    Report("The signal is caused by a %s memory access.\n", access_type);
    if (!sig.is_true_faulting_addr)
      Report("Hint: this fault was caused by a dereference of a high value "
             "address (see register values below).  Dissassemble the provided "
             "pc to learn which register was used.\n");
    else if (sig.addr < GetPageSizeCached())
      Report("Hint: address points to the zero page.\n");
  }
  MaybeReportNonExecRegion(sig.pc);
  InternalMmapVector<BufferedStackTrace> stack_buffer(1);
  BufferedStackTrace *stack = stack_buffer.data();
  stack->Reset();
  unwind(sig, unwind_context, stack);
  stack->Print();
  MaybeDumpInstructionBytes(sig.pc);
  MaybeDumpRegisters(sig.context);
  Printf("%s can not provide additional info.\n", SanitizerToolName);
  ReportErrorSummary(description, stack);
}

void ReportDeadlySignal(const SignalContext &sig, u32 tid,
                        UnwindSignalStackCallbackType unwind,
                        const void *unwind_context) {
  if (sig.IsStackOverflow())
    ReportStackOverflowImpl(sig, tid, unwind, unwind_context);
  else
    ReportDeadlySignalImpl(sig, tid, unwind, unwind_context);
}

void HandleDeadlySignal(void *siginfo, void *context, u32 tid,
                        UnwindSignalStackCallbackType unwind,
                        const void *unwind_context) {
  StartReportDeadlySignal();
  ScopedErrorReportLock rl;
  SignalContext sig(siginfo, context);
  ReportDeadlySignal(sig, tid, unwind, unwind_context);
  Report("ABORTING\n");
  Die();
}

#endif  // !SANITIZER_FUCHSIA && !SANITIZER_GO

static atomic_uintptr_t reporting_thread = {0};
static StaticSpinMutex CommonSanitizerReportMutex;

ScopedErrorReportLock::ScopedErrorReportLock() {
  uptr current = GetThreadSelf();
  for (;;) {
    uptr expected = 0;
    if (atomic_compare_exchange_strong(&reporting_thread, &expected, current,
                                       memory_order_relaxed)) {
      // We've claimed reporting_thread so proceed.
      CommonSanitizerReportMutex.Lock();
      return;
    }

    if (expected == current) {
      // This is either asynch signal or nested error during error reporting.
      // Fail simple to avoid deadlocks in Report().

      // Can't use Report() here because of potential deadlocks in nested
      // signal handlers.
      CatastrophicErrorWrite(SanitizerToolName,
                             internal_strlen(SanitizerToolName));
      static const char msg[] = ": nested bug in the same thread, aborting.\n";
      CatastrophicErrorWrite(msg, sizeof(msg) - 1);

      internal__exit(common_flags()->exitcode);
    }

    internal_sched_yield();
  }
}

ScopedErrorReportLock::~ScopedErrorReportLock() {
  CommonSanitizerReportMutex.Unlock();
  atomic_store_relaxed(&reporting_thread, 0);
}

void ScopedErrorReportLock::CheckLocked() {
  CommonSanitizerReportMutex.CheckLocked();
}

}  // namespace __sanitizer
<|endoftext|>


<commit_before>// Copyright (c) 2011-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "recentrequeststablemodel.h"

#include "bitcoinunits.h"
#include "clientversion.h"
#include "guiutil.h"
#include "optionsmodel.h"
#include "streams.h"

#include <boost/foreach.hpp>

RecentRequestsTableModel::RecentRequestsTableModel(CWallet *wallet, WalletModel *parent) :
    walletModel(parent)
{
    Q_UNUSED(wallet);
    nReceiveRequestsMaxId = 0;

    // Load entries from wallet
    std::vector<std::string> vReceiveRequests;
    parent->loadReceiveRequests(vReceiveRequests);
    BOOST_FOREACH(const std::string& request, vReceiveRequests)
        addNewRequest(request);

    /* These columns must match the indices in the ColumnIndex enumeration */
    columns << tr("Date") << tr("Label") << tr("Message") << getAmountTitle();

    connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
}

RecentRequestsTableModel::~RecentRequestsTableModel()
{
    /* Intentionally left empty */
}

int RecentRequestsTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);

    return list.length();
}

int RecentRequestsTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);

    return columns.length();
}

QVariant RecentRequestsTableModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid() || index.row() >= list.length())
        return QVariant();

    const RecentRequestEntry *rec = &list[index.row()];

    if(role == Qt::DisplayRole || role == Qt::EditRole)
    {
        switch(index.column())
        {
        case Date:
            return GUIUtil::dateTimeStr(rec->date);
        case Label:
            if(rec->recipient.label.isEmpty() && role == Qt::DisplayRole)
            {
                return tr("(no label)");
            }
            else
            {
                return rec->recipient.label;
            }
        case Message:
            if(rec->recipient.message.isEmpty() && role == Qt::DisplayRole)
            {
                return tr("(no message)");
            }
            else
            {
                return rec->recipient.message;
            }
        case Amount:
            if (rec->recipient.amount == 0 && role == Qt::DisplayRole)
                return tr("(no amount)");
            else if (role == Qt::EditRole)
                return BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), rec->recipient.amount, false, BitcoinUnits::separatorNever);
            else
                return BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), rec->recipient.amount);
        }
    }
    else if (role == Qt::TextAlignmentRole)
    {
        if (index.column() == Amount)
            return (int)(Qt::AlignRight|Qt::AlignVCenter);
    }
    return QVariant();
}

bool RecentRequestsTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    return true;
}

QVariant RecentRequestsTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation == Qt::Horizontal)
    {
        if(role == Qt::DisplayRole && section < columns.size())
        {
            return columns[section];
        }
    }
    return QVariant();
}

/** Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table headers to react. */
void RecentRequestsTableModel::updateAmountColumnTitle()
{
    columns[Amount] = getAmountTitle();
    emit headerDataChanged(Qt::Horizontal,Amount,Amount);
}

/** Gets title for amount column including current display unit if optionsModel reference available. */
QString RecentRequestsTableModel::getAmountTitle()
{
    QString amountTitle = tr("Amount");
    if (this->walletModel->getOptionsModel() != NULL)
    {
        amountTitle += " ("+BitcoinUnits::name(this->walletModel->getOptionsModel()->getDisplayUnit()) + ")";
    }
    return amountTitle;
}

QModelIndex RecentRequestsTableModel::index(int row, int column, const QModelIndex &parent) const
{
    Q_UNUSED(parent);

    return createIndex(row, column);
}

bool RecentRequestsTableModel::removeRows(int row, int count, const QModelIndex &parent)
{
    Q_UNUSED(parent);

    if(count > 0 && row >= 0 && (row+count) <= list.size())
    {
        const RecentRequestEntry *rec;
        for (int i = 0; i < count; ++i)
        {
            rec = &list[row+i];
            if (!walletModel->saveReceiveRequest(rec->recipient.address.toStdString(), rec->id, ""))
                return false;
        }

        beginRemoveRows(parent, row, row + count - 1);
        list.erase(list.begin() + row, list.begin() + row + count);
        endRemoveRows();
        return true;
    } else {
        return false;
    }
}

Qt::ItemFlags RecentRequestsTableModel::flags(const QModelIndex &index) const
{
    return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
}

// called when adding a request from the GUI
void RecentRequestsTableModel::addNewRequest(const SendCoinsRecipient &recipient)
{
    RecentRequestEntry newEntry;
    newEntry.id = ++nReceiveRequestsMaxId;
    newEntry.date = QDateTime::currentDateTime();
    newEntry.recipient = recipient;

    CDataStream ss(SER_DISK, CLIENT_VERSION);
    ss << newEntry;

    if (!walletModel->saveReceiveRequest(recipient.address.toStdString(), newEntry.id, ss.str()))
        return;

    addNewRequest(newEntry);
}

// called from ctor when loading from wallet
void RecentRequestsTableModel::addNewRequest(const std::string &recipient)
{
    std::vector<char> data(recipient.begin(), recipient.end());
    CDataStream ss(data, SER_DISK, CLIENT_VERSION);

    RecentRequestEntry entry;
    ss >> entry;

    if (entry.id == 0) // should not happen
        return;

    if (entry.id > nReceiveRequestsMaxId)
        nReceiveRequestsMaxId = entry.id;

    addNewRequest(entry);
}

// actually add to table in GUI
void RecentRequestsTableModel::addNewRequest(RecentRequestEntry &recipient)
{
    beginInsertRows(QModelIndex(), 0, 0);
    list.prepend(recipient);
    endInsertRows();
}

void RecentRequestsTableModel::sort(int column, Qt::SortOrder order)
{
    qSort(list.begin(), list.end(), RecentRequestEntryLessThan(column, order));
    emit dataChanged(index(0, 0, QModelIndex()), index(list.size() - 1, NUMBER_OF_COLUMNS - 1, QModelIndex()));
}

void RecentRequestsTableModel::updateDisplayUnit()
{
    updateAmountColumnTitle();
}

bool RecentRequestEntryLessThan::operator()(RecentRequestEntry &left, RecentRequestEntry &right) const
{
    RecentRequestEntry *pLeft = &left;
    RecentRequestEntry *pRight = &right;
    if (order == Qt::DescendingOrder)
        std::swap(pLeft, pRight);

    switch(column)
    {
    case RecentRequestsTableModel::Date:
        return pLeft->date.toTime_t() < pRight->date.toTime_t();
    case RecentRequestsTableModel::Label:
        return pLeft->recipient.label < pRight->recipient.label;
    case RecentRequestsTableModel::Message:
        return pLeft->recipient.message < pRight->recipient.message;
    case RecentRequestsTableModel::Amount:
        return pLeft->recipient.amount < pRight->recipient.amount;
    default:
        return pLeft->id < pRight->id;
    }
}
<commit_msg>Delete recentrequeststablemodel.cpp<commit_after><|endoftext|>


<commit_before>/*
Copyright (C) 2016 - Gbor "Razzie" Grzsny

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
*/

#pragma once

#include <cstdint>
#include <cstring>
#include <exception>
#include <type_traits>
#include "raz/serialization.hpp"

namespace raz
{
	typedef uint32_t PacketType;

	template<size_t SIZE>
	class PacketBuffer
	{
	public:
		struct Head
		{
			PacketType packet_type;
			uint32_t packet_size;
		};

		struct Tail
		{
			uint32_t n = 0;
			bool ok() { return n == 0; }
		};

		struct PacketData
		{
			Head head;
			char data[SIZE];
			Tail tail;
		};

		explicit PacketBuffer(SerializationMode mode = SerializationMode::DESERIALIZE, PacketType type = 0) :
			m_mode(mode),
			m_data_pos(0)
		{
			m_data.head.packet_type = type;
			m_data.head.packet_size = 0;
		}

		PacketBuffer(const PacketBuffer&) = delete;

		SerializationMode getMode() const
		{
			return m_mode;
		}

		void setMode(SerializationMode mode)
		{
			m_mode = mode;
		}

		PacketType getType() const
		{
			return m_data.head.packet_type;
		}

		void setType(PacketType type)
		{
			m_data.head.packet_type = type;
		}

		PacketData* getPacketData()
		{
			return &m_data;
		}

		const PacketData& getPacketData() const
		{
			return &m_data;
		}

		static size_t getDataCapacity()
		{
			return SIZE;
		}

		size_t write(const char* ptr, size_t len)
		{
			if (SIZE - m_data.head.packet_size < len)
				len = SIZE - m_data.head.packet_size;

			std::memcpy(&m_data.data[m_data.head.packet_size], ptr, len);
			m_data.head.packet_size += static_cast<uint32_t>(len);
			return len;
		}

		size_t read(char* ptr, size_t len)
		{
			if (m_data.head.packet_size - m_data_pos < len)
				len = m_data.head.packet_size - m_data_pos;

			std::memcpy(ptr, &m_data.data[m_data_pos], len);
			m_data_pos += len;
			return len;
		}

		void reset()
		{
			m_data.head.packet_type = 0;
			m_data.head.packet_size = 0;
			m_data_pos = 0;
		}

	private:
		PacketData m_data;
		SerializationMode m_mode;
		size_t m_data_pos;
	};

	template<size_t SIZE = 2048>
	using Packet = typename Serializer<PacketBuffer<SIZE>>;

	class PacketCapacityException : public std::exception
	{
	public:
		virtual const char* what() const
		{
			return "Insufficient packet capacity";
		}
	};

	class CorruptedPacketException : public std::exception
	{
	public:
		virtual const char* what() const
		{
			return "Corrupted packet";
		}
	};

	template<class ClientBackend>
	class NetworkClient
	{
	public:
		template<class... Args>
		NetworkClient(Args... args) : m_backend(std::forward<Args>(args)...)
		{
		}

		template<class Packet>
		bool receive(Packet& packet, uint32_t timeous_ms = 0)
		{
			Packet::PacketData* pdata = packet.getPacketData();
			size_t netbuffer_len;

			netbuffer_len = m_backend.wait(timeous_ms); // waits until data is available and returns its size

			// check if at least the packet head could be read
			if (netbuffer_len < sizeof(pdata->head))
				return false;

			m_backend.peek(reinterpret_cast<char*>(&pdata->head), sizeof(pdata->head));

			// check if the whole packet data is available
			if ((netbuffer_len - sizeof(pdata->head) - sizeof(pdata->tail)) < pdata->head.packet_size)
				return false;

			if (pdata->head.packet_size > packet.getDataCapacity())
				throw PacketCapacityException();

			// reading actual data to the packet (note: we don't care about where the tail is copied)
			m_backend.read(reinterpret_cast<char*>(pdata), sizeof(pdata->head) + pdata->head.packet_size + sizeof(pdata->tail));

			if (!pdata->tail.ok())
				throw CorruptedPacketException();

			return true;
		}

		template<class Packet>
		void send(Packet& packet)
		{
			Packet::PacketData* pdata = packet.getPacketData();

			// move tailing bytes to the proper position if necessary
			if (reinterpret_cast<const char*>(&pdata->tail) != &pdata->data[pdata->head.packet_size])
				std::memcpy(&pdata->data[pdata->head.packet_size], &pdata->tail, sizeof(pdata->tail));

			m_backend.write(reinterpret_cast<const char*>(pdata), sizeof(pdata->head) + pdata->head.packet_size + sizeof(pdata->tail));
		}

		ClientBackend& getBackend()
		{
			return m_backend;
		}

		const ClientBackend& getBackend() const
		{
			return m_backend;
		}

	private:
		ClientBackend m_backend;
	};

	template<class ServerBackend>
	class NetworkServer
	{
	public:
		typedef typename ServerBackend::Client Client;
		typedef typename ServerBackend::ClientState ClientState;

		template<size_t SIZE>
		struct ClientData
		{
			Client client;
			Packet<SIZE> packet;
			ClientState state;
		};

		template<class... Args>
		NetworkServer(Args... args) : m_backend(std::forward<Args>(args)...)
		{
		}

		template<class ClientData>
		bool receive(ClientData& data, uint32_t timeous_ms = 0)
		{
			decltype(data.packet)::PacketData* pdata = data.packet.getPacketData();
			size_t netbuffer_len;

			netbuffer_len = m_backend.wait(std::ref(data.client), std::ref(data.state), timeous_ms); // waits until data is available and returns its size

			// check if at least the packet head could be read
			if (netbuffer_len < sizeof(pdata->head))
				return false;

			m_backend.peek(data.client, reinterpret_cast<char*>(&pdata->head), sizeof(pdata->head));

			// check if the whole packet data is available
			if ((netbuffer_len - sizeof(pdata->head) - sizeof(pdata->tail)) < pdata->head.packet_size)
				return false;

			if (pdata->head.packet_size > data.packet.getDataCapacity())
				throw PacketCapacityException();

			// reading actual data to the packet (note: we don't care about where the tail is copied)
			m_backend.read(data.client, reinterpret_cast<char*>(pdata), sizeof(pdata->head) + pdata->head.packet_size + sizeof(pdata->tail));

			if (!pdata->tail.ok())
				throw CorruptedPacketException();

			return true;
		}

		template<class Packet>
		void send(const Client& client, Packet& packet)
		{
			Packet::PacketData* pdata = packet.getPacketData();

			// move tailing bytes to the proper position if necessary
			if (reinterpret_cast<const char*>(&pdata->tail) != &pdata->data[pdata->head.packet_size])
				std::memcpy(&pdata->data[pdata->head.packet_size], &pdata->tail, sizeof(pdata->tail));

			m_backend.write(client, reinterpret_cast<const char*>(pdata), sizeof(pdata->head) + pdata->head.packet_size + sizeof(pdata->tail));
		}

		ServerBackend& getBackend()
		{
			return m_backend;
		}

		const ServerBackend& getBackend() const
		{
			return m_backend;
		}

	private:
		ServerBackend m_backend;
	};

	// include raz/networkbackend.hpp for definitions
	class NetworkClientBackendTCP;
	class NetworkServerBackendTCP;
	template<size_t> class NetworkClientBackendUDP;
	template<size_t> class NetworkServerBackendUDP;

	typedef NetworkClient<raz::NetworkClientBackendTCP> NetworkClientTCP;
	typedef NetworkServer<raz::NetworkServerBackendTCP> NetworkServerTCP;
	template<size_t SIZE = 2048> using NetworkClientUDP = typename NetworkClient<raz::NetworkClientBackendUDP<SIZE>>;
	template<size_t SIZE = 2048> using NetworkServerUDP = typename NetworkServer<raz::NetworkServerBackendUDP<SIZE>>;
}
<commit_msg>Added endianness conversion template flag to Packet<commit_after>/*
Copyright (C) 2016 - Gbor "Razzie" Grzsny

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
*/

#pragma once

#include <cstdint>
#include <cstring>
#include <exception>
#include <type_traits>
#include "raz/serialization.hpp"

namespace raz
{
	typedef uint32_t PacketType;

	template<size_t SIZE>
	class PacketBuffer
	{
	public:
		struct Head
		{
			PacketType packet_type;
			uint32_t packet_size;
		};

		struct Tail
		{
			uint32_t n = 0;
			bool ok() { return n == 0; }
		};

		struct PacketData
		{
			Head head;
			char data[SIZE];
			Tail tail;
		};

		explicit PacketBuffer(SerializationMode mode = SerializationMode::DESERIALIZE, PacketType type = 0) :
			m_mode(mode),
			m_data_pos(0)
		{
			m_data.head.packet_type = type;
			m_data.head.packet_size = 0;
		}

		PacketBuffer(const PacketBuffer&) = delete;

		SerializationMode getMode() const
		{
			return m_mode;
		}

		void setMode(SerializationMode mode)
		{
			m_mode = mode;
		}

		PacketType getType() const
		{
			return m_data.head.packet_type;
		}

		void setType(PacketType type)
		{
			m_data.head.packet_type = type;
		}

		PacketData* getPacketData()
		{
			return &m_data;
		}

		const PacketData& getPacketData() const
		{
			return &m_data;
		}

		static size_t getDataCapacity()
		{
			return SIZE;
		}

		size_t write(const char* ptr, size_t len)
		{
			if (SIZE - m_data.head.packet_size < len)
				len = SIZE - m_data.head.packet_size;

			std::memcpy(&m_data.data[m_data.head.packet_size], ptr, len);
			m_data.head.packet_size += static_cast<uint32_t>(len);
			return len;
		}

		size_t read(char* ptr, size_t len)
		{
			if (m_data.head.packet_size - m_data_pos < len)
				len = m_data.head.packet_size - m_data_pos;

			std::memcpy(ptr, &m_data.data[m_data_pos], len);
			m_data_pos += len;
			return len;
		}

		void reset()
		{
			m_data.head.packet_type = 0;
			m_data.head.packet_size = 0;
			m_data_pos = 0;
		}

	private:
		PacketData m_data;
		SerializationMode m_mode;
		size_t m_data_pos;
	};

	template<size_t SIZE = 2048, bool EndiannessConversion = false>
	using Packet = typename Serializer<PacketBuffer<SIZE>, EndiannessConversion>;

	class PacketCapacityException : public std::exception
	{
	public:
		virtual const char* what() const
		{
			return "Insufficient packet capacity";
		}
	};

	class CorruptedPacketException : public std::exception
	{
	public:
		virtual const char* what() const
		{
			return "Corrupted packet";
		}
	};

	template<class ClientBackend>
	class NetworkClient
	{
	public:
		template<class... Args>
		NetworkClient(Args... args) : m_backend(std::forward<Args>(args)...)
		{
		}

		template<class Packet>
		bool receive(Packet& packet, uint32_t timeous_ms = 0)
		{
			Packet::PacketData* pdata = packet.getPacketData();
			size_t netbuffer_len;

			netbuffer_len = m_backend.wait(timeous_ms); // waits until data is available and returns its size

			// check if at least the packet head could be read
			if (netbuffer_len < sizeof(pdata->head))
				return false;

			m_backend.peek(reinterpret_cast<char*>(&pdata->head), sizeof(pdata->head));

			// check if the whole packet data is available
			if ((netbuffer_len - sizeof(pdata->head) - sizeof(pdata->tail)) < pdata->head.packet_size)
				return false;

			if (pdata->head.packet_size > packet.getDataCapacity())
				throw PacketCapacityException();

			// reading actual data to the packet (note: we don't care about where the tail is copied)
			m_backend.read(reinterpret_cast<char*>(pdata), sizeof(pdata->head) + pdata->head.packet_size + sizeof(pdata->tail));

			if (!pdata->tail.ok())
				throw CorruptedPacketException();

			return true;
		}

		template<class Packet>
		void send(Packet& packet)
		{
			Packet::PacketData* pdata = packet.getPacketData();

			// move tailing bytes to the proper position if necessary
			if (reinterpret_cast<const char*>(&pdata->tail) != &pdata->data[pdata->head.packet_size])
				std::memcpy(&pdata->data[pdata->head.packet_size], &pdata->tail, sizeof(pdata->tail));

			m_backend.write(reinterpret_cast<const char*>(pdata), sizeof(pdata->head) + pdata->head.packet_size + sizeof(pdata->tail));
		}

		ClientBackend& getBackend()
		{
			return m_backend;
		}

		const ClientBackend& getBackend() const
		{
			return m_backend;
		}

	private:
		ClientBackend m_backend;
	};

	template<class ServerBackend>
	class NetworkServer
	{
	public:
		typedef typename ServerBackend::Client Client;
		typedef typename ServerBackend::ClientState ClientState;

		template<size_t SIZE>
		struct ClientData
		{
			Client client;
			Packet<SIZE> packet;
			ClientState state;
		};

		template<class... Args>
		NetworkServer(Args... args) : m_backend(std::forward<Args>(args)...)
		{
		}

		template<class ClientData>
		bool receive(ClientData& data, uint32_t timeous_ms = 0)
		{
			decltype(data.packet)::PacketData* pdata = data.packet.getPacketData();
			size_t netbuffer_len;

			netbuffer_len = m_backend.wait(std::ref(data.client), std::ref(data.state), timeous_ms); // waits until data is available and returns its size

			// check if at least the packet head could be read
			if (netbuffer_len < sizeof(pdata->head))
				return false;

			m_backend.peek(data.client, reinterpret_cast<char*>(&pdata->head), sizeof(pdata->head));

			// check if the whole packet data is available
			if ((netbuffer_len - sizeof(pdata->head) - sizeof(pdata->tail)) < pdata->head.packet_size)
				return false;

			if (pdata->head.packet_size > data.packet.getDataCapacity())
				throw PacketCapacityException();

			// reading actual data to the packet (note: we don't care about where the tail is copied)
			m_backend.read(data.client, reinterpret_cast<char*>(pdata), sizeof(pdata->head) + pdata->head.packet_size + sizeof(pdata->tail));

			if (!pdata->tail.ok())
				throw CorruptedPacketException();

			return true;
		}

		template<class Packet>
		void send(const Client& client, Packet& packet)
		{
			Packet::PacketData* pdata = packet.getPacketData();

			// move tailing bytes to the proper position if necessary
			if (reinterpret_cast<const char*>(&pdata->tail) != &pdata->data[pdata->head.packet_size])
				std::memcpy(&pdata->data[pdata->head.packet_size], &pdata->tail, sizeof(pdata->tail));

			m_backend.write(client, reinterpret_cast<const char*>(pdata), sizeof(pdata->head) + pdata->head.packet_size + sizeof(pdata->tail));
		}

		ServerBackend& getBackend()
		{
			return m_backend;
		}

		const ServerBackend& getBackend() const
		{
			return m_backend;
		}

	private:
		ServerBackend m_backend;
	};

	// include raz/networkbackend.hpp for definitions
	class NetworkClientBackendTCP;
	class NetworkServerBackendTCP;
	template<size_t> class NetworkClientBackendUDP;
	template<size_t> class NetworkServerBackendUDP;

	typedef NetworkClient<raz::NetworkClientBackendTCP> NetworkClientTCP;
	typedef NetworkServer<raz::NetworkServerBackendTCP> NetworkServerTCP;
	template<size_t SIZE = 2048> using NetworkClientUDP = typename NetworkClient<raz::NetworkClientBackendUDP<SIZE>>;
	template<size_t SIZE = 2048> using NetworkServerUDP = typename NetworkServer<raz::NetworkServerBackendUDP<SIZE>>;
}
<|endoftext|>


<commit_before><commit_msg>convert include/svx/itemwin.hxx from String to OUString<commit_after><|endoftext|>


<commit_before>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#ifndef _QIMESSAGING_DETAILS_FUNCTORRESULT_HXX_
#define _QIMESSAGING_DETAILS_FUNCTORRESULT_HXX_

#include <qimessaging/datastream.hpp>

namespace qi {

  class Buffer;
  namespace detail {

    template <typename T>
    class FunctorResultBase_Typed : public FunctorResultBase {
    public:
      FunctorResultBase_Typed() { }

      void setValue(const T &value) {
        _f._p->setValue(value);
      }

      virtual void setValue(const qi::Buffer &result)
      {
        qi::IDataStream ds(result);
        //TODO: avoid the copy
        T v;
        ds >> v;
        if (ds.status() != qi::IDataStream::Status_Ok)
          _f.setError("Serialization error.");
        else
          _f.setValue(v);
      }

      virtual void setError(const std::string &signature,
                            const qi::Buffer &message)
      {
        qi::IDataStream ds(message);

        if (signature != "s") {
          std::stringstream ss;
          ss << "Can't report the correct error message because the error signature is :" << signature;
          _f.setError(ss.str());
          return;
        }
        std::string err;
        ds >> err;
        if (ds.status() != qi::IDataStream::Status_Ok)
          qiLogVerbose("qimessaging.functorresult") << "Can't report error in FunctorResult.setError";
        _f.setError(err);
      }

      Future<T> future() { return _f.future(); }

    protected:
      Promise<T> _f;
    };

    template <>
    class FunctorResultBase_Typed<void> : public FunctorResultBase {
    public:
      FunctorResultBase_Typed() { }

      void setValue(const void *value) {
        _f.setValue(value);
      }
      virtual void setValue(const qi::Buffer &QI_UNUSED(result))
      {
        _f.setValue(0);
      }

      virtual void setError(const std::string &signature,
                            const qi::Buffer &message)
      {
        qi::IDataStream ds(message);

        if (signature != "s") {
          std::stringstream ss;
          ss << "Can't report the correct error message because the error signature is :" << signature;
          _f.setError(ss.str());
          return;
        }
        std::string err;
        ds >> err;
        if (ds.status() != qi::IDataStream::Status_Ok)
          qiLogVerbose("qimessaging.functorresult") << "Can't report error in FunctorResult.setError";
        _f.setError(err);
      }

      Future<void> future() { return _f.future(); }

    protected:
      Promise<void> _f;
    };

    template <typename T>
    class FutureFunctorResult : public FunctorResult {
    public:
      FutureFunctorResult(qi::Future<T> *future) {
        boost::shared_ptr< FunctorResultBase_Typed<T> > p(new FunctorResultBase_Typed<T>());
        // FIXME Maybe we can do better
        // save callback
        std::vector<std::pair<FutureInterface<T> *, void *> > tmpCallbacks = future->callbacks();
        *future = p->future();

        typename std::vector<std::pair<FutureInterface<T> *, void *> >::iterator it;
        for (it = tmpCallbacks.begin(); it != tmpCallbacks.end(); ++it)
          future->addCallbacks((*it).first, (*it).second);
        _p = p;
      };
    };

  }

}

#endif

<commit_msg>FunctorResult: Remove dead code preventing Future<Buffer> from working.<commit_after>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#ifndef _QIMESSAGING_DETAILS_FUNCTORRESULT_HXX_
#define _QIMESSAGING_DETAILS_FUNCTORRESULT_HXX_

#include <qimessaging/datastream.hpp>

namespace qi {

  class Buffer;
  namespace detail {

    template <typename T>
    class FunctorResultBase_Typed : public FunctorResultBase {
    public:
      FunctorResultBase_Typed() { }

      virtual void setValue(const qi::Buffer &result)
      {
        qi::IDataStream ds(result);
        //TODO: avoid the copy
        T v;
        ds >> v;
        if (ds.status() != qi::IDataStream::Status_Ok)
          _f.setError("Serialization error.");
        else
          _f.setValue(v);
      }

      virtual void setError(const std::string &signature,
                            const qi::Buffer &message)
      {
        qi::IDataStream ds(message);

        if (signature != "s") {
          std::stringstream ss;
          ss << "Can't report the correct error message because the error signature is :" << signature;
          _f.setError(ss.str());
          return;
        }
        std::string err;
        ds >> err;
        if (ds.status() != qi::IDataStream::Status_Ok)
          qiLogVerbose("qimessaging.functorresult") << "Can't report error in FunctorResult.setError";
        _f.setError(err);
      }

      Future<T> future() { return _f.future(); }

    protected:
      Promise<T> _f;
    };

    template <>
    class FunctorResultBase_Typed<void> : public FunctorResultBase {
    public:
      FunctorResultBase_Typed() { }

      void setValue(const void *value) {
        _f.setValue(value);
      }
      virtual void setValue(const qi::Buffer &QI_UNUSED(result))
      {
        _f.setValue(0);
      }

      virtual void setError(const std::string &signature,
                            const qi::Buffer &message)
      {
        qi::IDataStream ds(message);

        if (signature != "s") {
          std::stringstream ss;
          ss << "Can't report the correct error message because the error signature is :" << signature;
          _f.setError(ss.str());
          return;
        }
        std::string err;
        ds >> err;
        if (ds.status() != qi::IDataStream::Status_Ok)
          qiLogVerbose("qimessaging.functorresult") << "Can't report error in FunctorResult.setError";
        _f.setError(err);
      }

      Future<void> future() { return _f.future(); }

    protected:
      Promise<void> _f;
    };

    template <typename T>
    class FutureFunctorResult : public FunctorResult {
    public:
      FutureFunctorResult(qi::Future<T> *future) {
        boost::shared_ptr< FunctorResultBase_Typed<T> > p(new FunctorResultBase_Typed<T>());
        // FIXME Maybe we can do better
        // save callback
        std::vector<std::pair<FutureInterface<T> *, void *> > tmpCallbacks = future->callbacks();
        *future = p->future();

        typename std::vector<std::pair<FutureInterface<T> *, void *> >::iterator it;
        for (it = tmpCallbacks.begin(); it != tmpCallbacks.end(); ++it)
          future->addCallbacks((*it).first, (*it).second);
        _p = p;
      };
    };

  }

}

#endif

<|endoftext|>


<commit_before>#include "CLIVerb.h"

namespace  ros2_components {

CLIVerb::CLIVerb(std::__cxx11::string _verb, std::__cxx11::string _description, std::shared_ptr<CLIVerb> _parent)
{
    this->name = _verb;
    this->description = _description;
    this->parent = _parent;
    this->found = nullptr;
}

CLIVerb::CLIVerb(std::__cxx11::string _verb, std::__cxx11::string _description, std::shared_ptr<CLIVerb> _parent, bool *_found):CLIVerb(_verb,_description,_parent)
{
    this->found = _found;
    if(found != nullptr)
        *(this->found) = false;
}

bool CLIVerb::addVerb(CLIVerb::SharedPtr _child)
{
    if(this->childVerbs.find(_child->getName()) != this->childVerbs.end())
        return false;
    this->childVerbs[_child->getName()] = _child;
    return true;
}

bool CLIVerb::addArgument(CLIArgument::SharedPtr _arg)
{
    //TODO return false if argument already in list
    this->cliArguments.push_back(_arg);
    this->allCliArguments.push_back(_arg);
    return true;
}

bool CLIVerb::addParameter(CLIParameter::SharedPtr _param)
{
    //TODO return fals if parameter is already in list
    this->cliParameters.push_back(_param);
    this->allCliParameter.push_back(_param);
}

bool CLIVerb::parse(std::vector<std::__cxx11::string> &str)
{
    if(str.size() <= 0)
        return false;
    std::vector<std::string> arguments;
    std::vector<std::string> parameters;
    int count = 0;
    for(auto it = str.begin(); it != str.end();)
    {

        std::string arg = *it;
        if(arg == "")
        {
            str.erase(it);
            continue;
        }
        //Second check if this arg was found
        if(arg == this->name)
        {
            if(found != nullptr)
                *this->found = true;
            str.erase(it);
            continue;
        }
        //First check for parameters
        if(count < this->allCliParameter.size())
        {
            parameters.push_back(arg);
            str.erase(it);
        }
        count++;

        if(isVerb(arg))
        {
            if(arg != "")
                if(childVerbs[arg] != nullptr)
                    childVerbs[arg]->parse(str);
        }
        else
        {
            QString qarg = QString::fromStdString(arg);
            arguments.push_back(arg);
            str.erase(it);

        }
    }
    for(std::string & argument: arguments)
    {
        for(CLIArgument::SharedPtr & cliArg: cliArguments)
        {
            if(cliArg->parse(argument))
            {
                if(cliArg->getName() != "help")
                {
                    this->cliArguments.remove(cliArg);
                    break;
                }
            }
        }
    }
    int i = 0;
    if(allCliParameter.size() != parameters.size())
        throw std::runtime_error("Wrong amount of parameters. Expecting: "+ std::to_string(allCliParameter.size()));

    for(CLIParameter::SharedPtr param: this->allCliParameter)
    {
        param->parse(parameters[i]);
        i++;
    }
}

bool CLIVerb::wasFound()
{
    return found;
}

std::string CLIVerb::getName() const
{
    return name;
}

std::shared_ptr<CLIVerb> CLIVerb::getParent() const
{
    return parent;
}

std::string CLIVerb::getDescription() const
{
    return description;
}

std::vector<CLIArgument::SharedPtr> CLIVerb::getAllCliArguments() const
{
    return allCliArguments;
}

std::map<std::string, CLIVerb::SharedPtr> CLIVerb::getChildVerbs() const
{
    return childVerbs;
}

std::vector<CLIParameter::SharedPtr> CLIVerb::getAllCliParameter() const
{
    return allCliParameter;
}

bool CLIVerb::isVerb(std::__cxx11::string arg)
{
    QString qarg = QString::fromStdString(arg);
    return !(qarg.startsWith("-") || qarg.startsWith("--"));
}

}
<commit_msg>fixed bug in parser<commit_after>#include "CLIVerb.h"

namespace  ros2_components {

CLIVerb::CLIVerb(std::__cxx11::string _verb, std::__cxx11::string _description, std::shared_ptr<CLIVerb> _parent)
{
    this->name = _verb;
    this->description = _description;
    this->parent = _parent;
    this->found = nullptr;
}

CLIVerb::CLIVerb(std::__cxx11::string _verb, std::__cxx11::string _description, std::shared_ptr<CLIVerb> _parent, bool *_found):CLIVerb(_verb,_description,_parent)
{
    this->found = _found;
    if(found != nullptr)
        *(this->found) = false;
}

bool CLIVerb::addVerb(CLIVerb::SharedPtr _child)
{
    if(this->childVerbs.find(_child->getName()) != this->childVerbs.end())
        return false;
    this->childVerbs[_child->getName()] = _child;
    return true;
}

bool CLIVerb::addArgument(CLIArgument::SharedPtr _arg)
{
    //TODO return false if argument already in list
    this->cliArguments.push_back(_arg);
    this->allCliArguments.push_back(_arg);
    return true;
}

bool CLIVerb::addParameter(CLIParameter::SharedPtr _param)
{
    //TODO return fals if parameter is already in list
    this->cliParameters.push_back(_param);
    this->allCliParameter.push_back(_param);
}

bool CLIVerb::parse(std::vector<std::__cxx11::string> &str)
{
    if(str.size() <= 0)
        return false;
    std::vector<std::string> arguments;
    std::vector<std::string> parameters;
    int count = 0;
    for(auto it = str.begin(); it != str.end();)
    {

        std::string arg = *it;

        if(arg == "")
        {
            str.erase(it);
            continue;
        }
        //Second check if this arg was found
        if(arg == this->name)
        {
            if(found != nullptr)
                *this->found = true;
            str.erase(it);
            continue;
        }
        //First check for parameters
        if(count < this->allCliParameter.size())
        {
            parameters.push_back(arg);
            str.erase(it);
        }
        count++;

        if(isVerb(arg))
        {
            if(arg != "")
                if(childVerbs[arg] != nullptr)
                    childVerbs[arg]->parse(str);
                else
                    str.erase(it);
        }
        else
        {
            QString qarg = QString::fromStdString(arg);
            arguments.push_back(arg);
            str.erase(it);

        }
    }
    for(std::string & argument: arguments)
    {
        for(CLIArgument::SharedPtr & cliArg: cliArguments)
        {
            if(cliArg->parse(argument))
            {
                if(cliArg->getName() != "help")
                {
                    this->cliArguments.remove(cliArg);
                    break;
                }
            }
        }
    }
    int i = 0;
    if(allCliParameter.size() != parameters.size())
        throw std::runtime_error("Wrong amount of parameters. Expecting: "+ std::to_string(allCliParameter.size()));

    for(CLIParameter::SharedPtr param: this->allCliParameter)
    {
        param->parse(parameters[i]);
        i++;
    }
}

bool CLIVerb::wasFound()
{
    return found;
}

std::string CLIVerb::getName() const
{
    return name;
}

std::shared_ptr<CLIVerb> CLIVerb::getParent() const
{
    return parent;
}

std::string CLIVerb::getDescription() const
{
    return description;
}

std::vector<CLIArgument::SharedPtr> CLIVerb::getAllCliArguments() const
{
    return allCliArguments;
}

std::map<std::string, CLIVerb::SharedPtr> CLIVerb::getChildVerbs() const
{
    return childVerbs;
}

std::vector<CLIParameter::SharedPtr> CLIVerb::getAllCliParameter() const
{
    return allCliParameter;
}

bool CLIVerb::isVerb(std::__cxx11::string arg)
{
    QString qarg = QString::fromStdString(arg);
    return !(qarg.startsWith("-") || qarg.startsWith("--"));
}

}
<|endoftext|>


<commit_before>#include <catch.hpp>

#include "mbedcrypto_mbedtls_config.h"
#include "mbedtls/pk.h"
#include "mbedcrypto/pki.hpp"
#include "mbedcrypto/random.hpp"
#include "mbedcrypto/hash.hpp"
#include "src/conversions.hpp"

#include "generator.hpp"
#include <cstring>
#include <iostream>
///////////////////////////////////////////////////////////////////////////////
namespace {
using namespace mbedcrypto;
///////////////////////////////////////////////////////////////////////////////
bool
icompare(const char* a, const char* b) {
    return std::strncmp(a, b, strlen(b)) == 0;
}
///////////////////////////////////////////////////////////////////////////////
} // namespace anon
///////////////////////////////////////////////////////////////////////////////
TEST_CASE("pk type checks", "[pki][types]") {
    using namespace mbedcrypto;
    SECTION("creation tests") {
        pki pk1;
        REQUIRE_FALSE(pk1.can_do(pk_t::rsa));

        pki pk2(pk_t::rsa);
        REQUIRE(pk2.can_do(pk_t::rsa));
        REQUIRE(icompare(pk2.name(), "RSA"));
        REQUIRE_FALSE(pk2.can_do(pk_t::rsa_alt));
        REQUIRE_FALSE(pk2.can_do(pk_t::ecdsa));

        pki pk3;
        REQUIRE_NOTHROW(pk3.parse_key(test::sample_private_key()));
        REQUIRE(icompare(pk3.name(), "RSA"));
        REQUIRE(pk3.can_do(pk_t::rsa));
        REQUIRE_FALSE(pk3.can_do(pk_t::rsa_alt));
        REQUIRE(pk3.bitlen() == 2048);

        pki pk4;
        REQUIRE_NOTHROW(pk4.parse_public_key(test::sample_public_key()));
        REQUIRE(icompare(pk4.name(), "RSA"));
        REQUIRE(pk4.can_do(pk_t::rsa));
        REQUIRE_FALSE(pk4.can_do(pk_t::rsa_alt));
        REQUIRE(pk4.bitlen() == 2048);

        // check key pair
        REQUIRE_THROWS( pki::check_pair(pk1, pk3) ); // pk1 is uninitialized
        REQUIRE( pki::check_pair(pk4, pk3) == true );

        // reuse of pk3
        REQUIRE_NOTHROW(pk3.parse_key(
                    test::sample_private_key_password(),
                    "mbedcrypto1234" // password
                    ));
        REQUIRE(icompare(pk3.name(), "RSA"));
        REQUIRE(pk3.can_do(pk_t::rsa));
        REQUIRE(pk3.bitlen() == 2048);

        // pk3 is still the same key (with or without password)
        REQUIRE( pki::check_pair(pk4, pk3) == true );

    }
}

TEST_CASE("pki cryptography", "[pki]") {
    using namespace mbedcrypto;

    SECTION("sign and verify") {
        // message is 455 bytes long > 2048 bits
        auto message = test::long_text();

        pki pks;
        pks.parse_key(test::sample_private_key());
        // invalid message size
        REQUIRE_THROWS( pks.sign(message) );

        auto signature = pks.sign(message, hash_t::sha1);
        REQUIRE( (signature == test::long_text_signature()) );
        // by self, a public key is rea
        REQUIRE( pks.verify(signature, message, hash_t::sha1) );

        pki pkv;
        pkv.parse_public_key(test::sample_public_key());
        REQUIRE( pkv.verify(signature, message, hash_t::sha1) );
    }

    SECTION("encrypt and decrypt") {
        const std::string message(test::long_text());
        const auto hvalue = hash::make(hash_t::sha256, message);

        pki pke;
        pke.parse_public_key(test::sample_public_key());

        REQUIRE_THROWS( pke.encrypt(message) );
        auto encv = pke.encrypt(message, hash_t::sha256);

        pki pkd;
        pkd.parse_key(test::sample_private_key());
        REQUIRE_THROWS( pkd.decrypt(message) );
        auto decv = pkd.decrypt(encv);
        REQUIRE( decv == hvalue );
    }
}

#if defined(MBEDTLS_GENPRIME)
TEST_CASE("rsa key gen", "[pki]") {
    using namespace mbedcrypto;

    SECTION("key generation") {
        pki pk1;
        // pk1 is not defined as rsa
        REQUIRE_THROWS( pk1.rsa_generate_key(1024) );

        pki pk2(pk_t::rsa);
        REQUIRE_NOTHROW( pk2.rsa_generate_key(1024) );
        REQUIRE_NOTHROW( pk2.rsa_generate_key(2048, 3) );
    }
}
#endif

#if defined(MBEDTLS_GENPRIME)  &&  defined(MBEDTLS_PEM_WRITE_C)
TEST_CASE("rsa tests", "[pki]") {
    using namespace mbedcrypto;

    const auto message = test::long_text();

    try {
        pki pk_g(pk_t::rsa);
        pk_g.rsa_generate_key(2048);
        const auto signature = pk_g.sign(message, hash_t::sha256);

        // test pem public
        pki pk_pub;
        pk_pub.parse_public_key(pk_g.export_public_key(pki::pem_format));
        REQUIRE( pk_pub.verify(signature, message, hash_t::sha256) );
        REQUIRE( pki::check_pair(pk_pub, pk_g) == true );

        // test pem private
        pki pk_pri;
        pk_pri.parse_key(pk_g.export_key(pki::pem_format));
        REQUIRE(( signature == pk_pri.sign(message, hash_t::sha256) ));
        REQUIRE( pki::check_pair(pk_pub, pk_pri) == true );

        // test der public
        pk_pub.parse_public_key(pk_g.export_public_key(pki::der_format));
        REQUIRE( pk_pub.verify(signature, message, hash_t::sha256) );
        REQUIRE( pki::check_pair(pk_pub, pk_g) == true );

        // test der private
        pk_pri.parse_key(pk_g.export_key(pki::der_format));
        REQUIRE(( signature == pk_pri.sign(message, hash_t::sha256) ));
        REQUIRE( pki::check_pair(pk_pub, pk_pri) == true );

        // recreate key
        REQUIRE_NOTHROW( pk_pri.rsa_generate_key(1024, 3) );
        REQUIRE( pki::check_pair(pk_pub, pk_pri) == false );

    } catch ( mbedcrypto::exception& cerr ) {
        std::cerr << "rsa test failed. " << cerr.to_string() << std::endl;
        REQUIRE_FALSE("exception thrown!");
    }

}
#endif // MBEDTLS_GENPRIME && MBEDTLS_PEM_WRITE_C
///////////////////////////////////////////////////////////////////////////////
<commit_msg>tests/tdd: add ec key generator tests<commit_after>#include <catch.hpp>

#include "mbedcrypto_mbedtls_config.h"
#include "mbedtls/pk.h"
#include "mbedcrypto/pki.hpp"
#include "mbedcrypto/random.hpp"
#include "mbedcrypto/hash.hpp"
#include "src/conversions.hpp"

#include "generator.hpp"
#include <cstring>
#include <iostream>
///////////////////////////////////////////////////////////////////////////////
namespace {
using namespace mbedcrypto;
///////////////////////////////////////////////////////////////////////////////
bool
icompare(const char* a, const char* b) {
    return std::strncmp(a, b, strlen(b)) == 0;
}
///////////////////////////////////////////////////////////////////////////////
} // namespace anon
///////////////////////////////////////////////////////////////////////////////
TEST_CASE("pk type checks", "[pki][types]") {
    using namespace mbedcrypto;
    SECTION("rsa creation tests") {
        pki pk1;
        REQUIRE_FALSE(pk1.can_do(pk_t::rsa));

        pki pk2(pk_t::rsa);
        REQUIRE(pk2.can_do(pk_t::rsa));
        REQUIRE(icompare(pk2.name(), "RSA"));
        REQUIRE_FALSE(pk2.can_do(pk_t::rsa_alt));
        REQUIRE_FALSE(pk2.can_do(pk_t::ecdsa));

        pki pk3;
        REQUIRE_NOTHROW(pk3.parse_key(test::sample_private_key()));
        REQUIRE(icompare(pk3.name(), "RSA"));
        REQUIRE(pk3.can_do(pk_t::rsa));
        REQUIRE_FALSE(pk3.can_do(pk_t::rsa_alt));
        REQUIRE(pk3.bitlen() == 2048);

        pki pk4;
        REQUIRE_NOTHROW(pk4.parse_public_key(test::sample_public_key()));
        REQUIRE(icompare(pk4.name(), "RSA"));
        REQUIRE(pk4.can_do(pk_t::rsa));
        REQUIRE_FALSE(pk4.can_do(pk_t::rsa_alt));
        REQUIRE(pk4.bitlen() == 2048);

        // check key pair
        REQUIRE_THROWS( pki::check_pair(pk1, pk3) ); // pk1 is uninitialized
        REQUIRE( pki::check_pair(pk4, pk3) == true );

        // reuse of pk3
        REQUIRE_NOTHROW(pk3.parse_key(
                    test::sample_private_key_password(),
                    "mbedcrypto1234" // password
                    ));
        REQUIRE(icompare(pk3.name(), "RSA"));
        REQUIRE(pk3.can_do(pk_t::rsa));
        REQUIRE(pk3.bitlen() == 2048);

        // pk3 is still the same key (with or without password)
        REQUIRE( pki::check_pair(pk4, pk3) == true );

    }

#if defined(MBEDTLS_ECP_C)
    SECTION("ec creation tests") {
        pki pk1;
        REQUIRE_FALSE(pk1.can_do(pk_t::eckey));

        pk1.reset_as(pk_t::eckey);
        REQUIRE( icompare(pk1.name(), "EC") );
        REQUIRE( pk1.can_do(pk_t::eckey) );
        REQUIRE( pk1.can_do(pk_t::eckey_dh) );
        REQUIRE( pk1.can_do(pk_t::ecdsa) );

        pk1.reset_as(pk_t::eckey_dh);
        REQUIRE( icompare(pk1.name(), "EC_DH") );
        REQUIRE( pk1.can_do(pk_t::eckey_dh) );
        REQUIRE( pk1.can_do(pk_t::eckey) );
        REQUIRE_FALSE( pk1.can_do(pk_t::ecdsa) );

    }
#endif // MBEDTLS_ECP_C

#if defined(MBEDTLS_ECDSA_C)
    SECTION("ecdsa creation tests") {
        pki pk1;
        REQUIRE_FALSE(pk1.can_do(pk_t::eckey));

        pk1.reset_as(pk_t::ecdsa);
        REQUIRE( icompare(pk1.name(), "ECDSA") );
        REQUIRE( pk1.can_do(pk_t::ecdsa) );
        REQUIRE_FALSE( pk1.can_do(pk_t::eckey) );
        REQUIRE_FALSE( pk1.can_do(pk_t::eckey_dh) );
    }

#endif // MBEDTLS_ECDSA_C
}

///////////////////////////////////////////////////////////////////////////////

TEST_CASE("pki cryptography", "[pki]") {
    using namespace mbedcrypto;

    SECTION("sign and verify") {
        // message is 455 bytes long > 2048 bits
        auto message = test::long_text();

        pki pks;
        pks.parse_key(test::sample_private_key());
        // invalid message size
        REQUIRE_THROWS( pks.sign(message) );

        auto signature = pks.sign(message, hash_t::sha1);
        REQUIRE( (signature == test::long_text_signature()) );
        // by self, a public key is rea
        REQUIRE( pks.verify(signature, message, hash_t::sha1) );

        pki pkv;
        pkv.parse_public_key(test::sample_public_key());
        REQUIRE( pkv.verify(signature, message, hash_t::sha1) );
    }

    SECTION("encrypt and decrypt") {
        const std::string message(test::long_text());
        const auto hvalue = hash::make(hash_t::sha256, message);

        pki pke;
        pke.parse_public_key(test::sample_public_key());

        REQUIRE_THROWS( pke.encrypt(message) );
        auto encv = pke.encrypt(message, hash_t::sha256);

        pki pkd;
        pkd.parse_key(test::sample_private_key());
        REQUIRE_THROWS( pkd.decrypt(message) );
        auto decv = pkd.decrypt(encv);
        REQUIRE( decv == hvalue );
    }
}

///////////////////////////////////////////////////////////////////////////////

TEST_CASE("key gen", "[pki]") {
    using namespace mbedcrypto;

#if defined(MBEDTLS_GENPRIME)
    SECTION("rsa key generation") {
        pki pk1;
        // pk1 is not defined as rsa
        REQUIRE_THROWS( pk1.rsa_generate_key(1024) );

        pki pk2(pk_t::rsa);
        REQUIRE_NOTHROW( pk2.rsa_generate_key(1024) );
        REQUIRE_NOTHROW( pk2.rsa_generate_key(2048, 3) );
    }
#endif

#if defined(MBEDTLS_ECP_C)
    SECTION("ec key generation") {
        pki pk1;
        REQUIRE_THROWS( pk1.ec_generate_key(curve_t::secp256k1) );

        pki pk2(pk_t::eckey);
        REQUIRE_THROWS( pk2.ec_generate_key(curve_t::none) );

        const std::initializer_list<curve_t> Items = {
            curve_t::secp192r1,
            curve_t::secp224r1,
            curve_t::secp256r1,
            curve_t::secp384r1,
            curve_t::secp521r1,
            curve_t::secp192k1,
            curve_t::secp224k1,
            curve_t::secp256k1,
            curve_t::bp256r1,
            curve_t::bp384r1,
            curve_t::bp512r1,
            curve_t::curve25519,
        };

        for ( auto i : Items ) {
            REQUIRE_NOTHROW( pk2.ec_generate_key(i) );
        }
    }
#endif // MBEDTLS_ECP_C
}

///////////////////////////////////////////////////////////////////////////////

#if defined(MBEDTLS_PEM_WRITE_C)
TEST_CASE("rsa tests", "[pki]") {
    using namespace mbedcrypto;

    const auto message = test::long_text();

#if defined(MBEDTLS_GENPRIME)
    try {
        pki pk_g(pk_t::rsa);
        pk_g.rsa_generate_key(2048);
        const auto signature = pk_g.sign(message, hash_t::sha256);

        // test pem public
        pki pk_pub;
        pk_pub.parse_public_key(pk_g.export_public_key(pki::pem_format));
        REQUIRE( pk_pub.verify(signature, message, hash_t::sha256) );
        REQUIRE( pki::check_pair(pk_pub, pk_g) == true );

        // test pem private
        pki pk_pri;
        pk_pri.parse_key(pk_g.export_key(pki::pem_format));
        REQUIRE(( signature == pk_pri.sign(message, hash_t::sha256) ));
        REQUIRE( pki::check_pair(pk_pub, pk_pri) == true );

        // test der public
        pk_pub.parse_public_key(pk_g.export_public_key(pki::der_format));
        REQUIRE( pk_pub.verify(signature, message, hash_t::sha256) );
        REQUIRE( pki::check_pair(pk_pub, pk_g) == true );

        // test der private
        pk_pri.parse_key(pk_g.export_key(pki::der_format));
        REQUIRE(( signature == pk_pri.sign(message, hash_t::sha256) ));
        REQUIRE( pki::check_pair(pk_pub, pk_pri) == true );

        // recreate key
        REQUIRE_NOTHROW( pk_pri.rsa_generate_key(1024, 3) );
        REQUIRE( pki::check_pair(pk_pub, pk_pri) == false );

    } catch ( mbedcrypto::exception& cerr ) {
        std::cerr << "rsa test failed. " << cerr.to_string() << std::endl;
        REQUIRE_FALSE("exception thrown!");
    }
#endif // MBEDTLS_GENPRIME

#if defined(MBEDTLS_ECP_C)
    try {

    } catch ( mbedcrypto::exception& cerr ) {
        std::cerr << "ec test faild. " << cerr.to_string() << std::endl;
        REQUIRE_FALSE("exception thrown!");
    }

#endif // MBEDTLS_ECP_C
}
#endif // MBEDTLS_GENPRIME && MBEDTLS_PEM_WRITE_C
///////////////////////////////////////////////////////////////////////////////

<|endoftext|>


<commit_before>#include "CLIVerb.h"

namespace  ros2_components {

CLIVerb::CLIVerb(std::__cxx11::string _verb, std::__cxx11::string _description, std::shared_ptr<CLIVerb> _parent)
{
    this->name = _verb;
    this->description = _description;
    this->parent = _parent;

}

CLIVerb::CLIVerb(std::__cxx11::string _verb, std::__cxx11::string _description, std::shared_ptr<CLIVerb> _parent, bool *_found):CLIVerb(_verb,_description,_parent)
{
    this->found = _found;
    *(this->found) = false;
}

bool CLIVerb::addVerb(CLIVerb::SharedPtr _child)
{
    this->childVerbs[_child->getName()] = _child;
}

bool CLIVerb::addArgument(CLIArgument::SharedPtr _arg)
{
    this->cliArguments.push_back(_arg);
    this->allCliArguments.push_back(_arg);
}

bool CLIVerb::parse(std::vector<std::__cxx11::string> &str)
{
    std::vector<std::string> arguments;

    for(auto it = str.begin(); it != str.end();)
    {
        std::string arg = *it;

        if(isVerb(arg))
        {
            if(arg == this->name)
                *this->found = true;
            if(childVerbs[arg] != nullptr)
                childVerbs[arg]->parse(str);
            it++;
        }
        else
        {
            QString qarg = QString::fromStdString(arg);
            arguments.push_back(arg);
            str.erase(it);

        }
    }
    for(std::string & argument: arguments)
    {

        for(CLIArgument::SharedPtr & cliArg: cliArguments)
        {
            if(cliArg->parse(argument))
            {

                 if(cliArg->getName() != "help")
                {
                    this->cliArguments.remove(cliArg);
                    break;
                }
            }
        }
    }
}

std::string CLIVerb::getName() const
{
    return name;
}

std::shared_ptr<CLIVerb> CLIVerb::getParent() const
{
    return parent;
}

std::string CLIVerb::getDescription() const
{
    return description;
}

std::vector<CLIArgument::SharedPtr> CLIVerb::getAllCliArguments() const
{
    return allCliArguments;
}

std::map<std::string, CLIVerb::SharedPtr> CLIVerb::getChildVerbs() const
{
    return childVerbs;
}

bool CLIVerb::isVerb(std::__cxx11::string arg)
{
    QString qarg = QString::fromStdString(arg);

    return !(qarg.startsWith("-") || qarg.startsWith("--"));

}

}
<commit_msg>fixed nullptr error<commit_after>#include "CLIVerb.h"

namespace  ros2_components {

CLIVerb::CLIVerb(std::__cxx11::string _verb, std::__cxx11::string _description, std::shared_ptr<CLIVerb> _parent)
{
    this->name = _verb;
    this->description = _description;
    this->parent = _parent;

}

CLIVerb::CLIVerb(std::__cxx11::string _verb, std::__cxx11::string _description, std::shared_ptr<CLIVerb> _parent, bool *_found):CLIVerb(_verb,_description,_parent)
{
    this->found = _found;
    if(found != nullptr)
    {
        *(this->found) = false;
    }
}

bool CLIVerb::addVerb(CLIVerb::SharedPtr _child)
{
    this->childVerbs[_child->getName()] = _child;
}

bool CLIVerb::addArgument(CLIArgument::SharedPtr _arg)
{
    this->cliArguments.push_back(_arg);
    this->allCliArguments.push_back(_arg);
}

bool CLIVerb::parse(std::vector<std::__cxx11::string> &str)
{
    std::vector<std::string> arguments;

    for(auto it = str.begin(); it != str.end();)
    {
        std::string arg = *it;

        if(isVerb(arg))
        {
            if(arg == this->name)
                if(found != nullptr)
                    *this->found = true;
            if(childVerbs[arg] != nullptr)
                childVerbs[arg]->parse(str);
            it++;
        }
        else
        {
            QString qarg = QString::fromStdString(arg);
            arguments.push_back(arg);
            str.erase(it);

        }
    }
    for(std::string & argument: arguments)
    {

        for(CLIArgument::SharedPtr & cliArg: cliArguments)
        {
            if(cliArg->parse(argument))
            {

                if(cliArg->getName() != "help")
                {
                    this->cliArguments.remove(cliArg);
                    break;
                }
            }
        }
    }
}

std::string CLIVerb::getName() const
{
    return name;
}

std::shared_ptr<CLIVerb> CLIVerb::getParent() const
{
    return parent;
}

std::string CLIVerb::getDescription() const
{
    return description;
}

std::vector<CLIArgument::SharedPtr> CLIVerb::getAllCliArguments() const
{
    return allCliArguments;
}

std::map<std::string, CLIVerb::SharedPtr> CLIVerb::getChildVerbs() const
{
    return childVerbs;
}

bool CLIVerb::isVerb(std::__cxx11::string arg)
{
    QString qarg = QString::fromStdString(arg);

    return !(qarg.startsWith("-") || qarg.startsWith("--"));

}

}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
Authors:
Michael Berg <michael.berg@zalf.de>

Maintainers:
Currently maintained by the authors.

This file is part of the MONICA model.
Copyright (C) Leibniz Centre for Agricultural Landscape Research (ZALF)
*/

#include <cstdio>
#include <iostream>
#include <fstream>
#include <cstdlib>

#include <string>

#include "zhelpers.hpp"
#include "json11/json11.hpp"

#include "tools/zmq-helper.h"
#include "tools/json11-helper.h"
#include "tools/helper.h"
#include "tools/debug.h"
#include "monica-zmq-defaults.h"

using namespace std;
using namespace Tools;
using namespace json11;
using namespace Monica;

string appName = "monica-zmq-control";
string version = "0.0.1";

int stopMonicaProcesses(zmq::context_t& context,
												string proxyAddress,
												int frontendProxyPort,
												int count)
{
	int stopped = 0;

	// setup a reply socket for managing (e.g. starting/stopping) MONICA processes
	zmq::socket_t socket(context, ZMQ_REQ);

	string address = string("tcp://") + proxyAddress + ":" + to_string(frontendProxyPort);
	try
	{
		socket.setsockopt(ZMQ_RCVTIMEO, 5000);
		socket.setsockopt(ZMQ_SNDTIMEO, 5000);
		socket.connect(address);
		debug() << "Bound " << appName << " zeromq request socket to address: " << address << "!" << endl;

		//send finish message and wait for reply from MONICA server process
		//might take too long in practice, then we have to shut down a MONICA process in a better way
		debug() << "Trying to finish " << count << " MONICA processes" << endl;
		for(int i = 0; i < count; i++)
		{
			J11Object resultMsg;
			resultMsg["type"] = "finish";
			try
			{
				if(s_send(socket, Json(resultMsg).dump()))
				{
					debug() << "Send 'finish' message to a MONICA process" << endl;

					try
					{
						auto msg = receiveMsg(socket);
						if(msg.valid)
						{
							stopped++;
							debug() << "Received ack: " << msg.type() << endl;
						}
					}
					catch(zmq::error_t e)
					{
						cerr
							<< "Exception on trying to receive 'ack' reply message on zmq socket with address: "
							<< address << "! Error: [" << e.what() << "]" << endl;
					}
				}
			}
			catch(zmq::error_t e)
			{
				cerr
					<< "Exception on trying to send 'finish' message on zmq socket with address: " << address
					<< "! Error: [" << e.what() << "]" << endl;
			}
		}
	}
	catch(zmq::error_t e)
	{
		cerr << "Couldn't connect socket to address: " << address << "! Error: [" << e.what() << "]" << endl;
	}

	return stopped;
}

int main (int argc,
					char** argv)
{
	int commPort = defaultControlPort;
	string proxyAddress = defaultProxyAddress;
	int frontendProxyPort = defaultProxyFrontendPort;
	int backendProxyPort = defaultProxyBackendPort;

	auto printHelp = [=]()
	{
		cout
			<< appName << " [options] " << endl
			<< endl
			<< "options:" << endl
			<< endl
			<< " -h | --help ... this help output" << endl
			<< " -v | --version ... outputs " << appName << " version" << endl
			<< endl
			<< " -c | --port COMM-PORT (default: " << commPort << ") ... run " << appName << " with given control port" << endl
			<< " -a | --proxy-address PROXY-ADDRESS (default: " << proxyAddress << ") ... connect client to give IP address" << endl
			<< " -f | --frontend-proxy-port PROXY-PORT (default: " << frontendProxyPort << ") ... communicate with started MONICA ZeroMQ servers via given frontend proxy port" << endl
			<< " -b | --backend-proxy-port PROXY-PORT (default: " << backendProxyPort << ") ... connect started MONICA ZeroMQ servers to given backend proxy port" << endl
			<< " -d | --debug ... enable debug outputs" << endl;
	};

	for(auto i = 1; i < argc; i++)
	{
		string arg = argv[i];
		if((arg == "-c" || arg == "--comm-port")
			 && i + 1 < argc)
			commPort = stoi(argv[++i]);
		else if((arg == "-a" || arg == "--proxy-address")
						&& i + 1 < argc)
			proxyAddress = argv[++i];
		else if((arg == "-f" || arg == "--frontend-proxy-port")
						&& i + 1 < argc)
			frontendProxyPort = stoi(argv[++i]);
		else if((arg == "-b" || arg == "--backend-proxy-port")
						&& i + 1 < argc)
			backendProxyPort = stoi(argv[++i]);
		else if(arg == "-d" || arg == "--debug")
			activateDebug = true;
		else if(arg == "-h" || arg == "--help")
			printHelp(), exit(0);
		else if(arg == "-v" || arg == "--version")
			cout << appName << " version " << version << endl, exit(0);
	}

	zmq::context_t context(1);

	// setup a reply socket for managing (e.g. starting/stopping) MONICA processes
	zmq::socket_t socket(context, ZMQ_REP);

	string address = string("tcp://*:") + to_string(commPort);
	try
	{
		socket.bind(address);

		map<string, int> started;

		//loop until receive finish message
		while(true)
		{
			try
			{
				auto msg = receiveMsg(socket);
				if(!msg.valid)
					continue;

				debug() << "Received message: " << msg.toString() << endl;

				string msgType = msg.type();
				if(msgType == "finish")
				{
					J11Object resultMsg;
					resultMsg["type"] = "ack";
					try
					{
						s_send(socket, Json(resultMsg).dump());
					}
					catch(zmq::error_t e)
					{
						cerr
							<< "Exception on trying to reply to 'finish' request with 'ack' message on zmq socket with address: "
							<< address << "! Still will finish " << appName << "! Error: [" << e.what() << "]" << endl;
					}
					socket.setsockopt(ZMQ_LINGER, 0);
					socket.close();

					break;
				}
				else if(msgType == "start-new"
								|| msgType == "start-max"
								|| msgType == "stop")
				{
					Json& fmsg = msg.json;

					int count = fmsg["count"].int_value();

					string proxyAddress = fmsg["proxy-address"].string_value();
					int proxyFrontendPort = fmsg["proxy-frontend-port"].int_value();
					int proxyBackendPort = fmsg["proxy-backend-port"].int_value();

					//string serviceAddress = fmsg["service-address"].string_value();
					bool isService = !fmsg["service-port"].is_null();
					int servicePort = fmsg["service-port"].int_value();

					string controlAddresses = fmsg["control-addresses"].string_value();
					string inputAddresses = fmsg["input-addresses"].string_value();
					string outputAddresses = fmsg["output-addresses"].string_value();

					string addresses;
					string stopAddress;
					int stopPort;
					if(!proxyAddress.empty())
					{
						stopAddress = proxyAddress, stopPort = proxyFrontendPort;
						addresses = string(" -p tcp://") + proxyAddress + ":" + to_string(proxyBackendPort);
						if(!controlAddresses.empty())
							addresses += " -c " + controlAddresses;
					}
					else if(isService)
					{
						count = max(count, 1);
						//stopAddress = "127.0.0.1", stopPort = servicePort;
						stopAddress = "localhost", stopPort = servicePort;
						addresses = string(" -s tcp://*:") + to_string(servicePort);
						if(!controlAddresses.empty())
							addresses += " -c " + controlAddresses;
					}
					else if(!outputAddresses.empty() && !inputAddresses.empty())
					{
						addresses = string(" -i ") + inputAddresses + " -o " + outputAddresses;
						if(!controlAddresses.empty())
							addresses += " -c " + controlAddresses;
					}

#ifdef WIN32
					string cmd = string("start /b monica-zmq-server ") + addresses;
#else
					string cmd = string("monica-zmq-server") + addresses + " &";
#endif
					//cout << "addresses: " << addresses << endl;

					bool isStartMax = msgType == "startMax";
					bool isStop = msgType == "stop";
					int& started_ = started[addresses];
					int successfullyStarted = 0;
					int i = isStartMax ? started_ : 0;
					int stop = 0;
					if(isStartMax)
						stop = max(0, started_ - count);
					else if(isStop)
						stop = max(0, min(count, started_));

					if(!isStop)
					{
						for(; i < count; i++)
						{
							int res = system(cmd.c_str());
							debug() << "result of running '" << cmd << "': " << res << endl;
							started[addresses]++, successfullyStarted++;
						}
					}

					if((isStartMax || isStop)
						 && !stopAddress.empty())
					{
						auto stopped = stopMonicaProcesses(context, stopAddress, stopPort, stop);
						if(isStop)
							started_ -= stopped;
					}

					J11Object resultMsg;
					resultMsg["type"] = "result";
					resultMsg["started"] = successfullyStarted;
					if(isStartMax || isStop)
						resultMsg["stopped"] = stop;
					try
					{
						s_send(socket, Json(resultMsg).dump());
					}
					catch(zmq::error_t e)
					{
						cerr
							<< "Exception on trying to reply with result message: " << Json(resultMsg).dump()
							<< " on zmq socket with address: " << address
							<< "! Will continue to receive requests! Error: [" << e.what() << "]" << endl;
					}
				}
			}
			catch(zmq::error_t e)
			{
				cerr
					<< "Exception on trying to receive request message on zmq socket with address: "
					<< address << "! Will continue to receive requests! Error: [" << e.what() << "]" << endl;
			}
		}
	}
	catch(zmq::error_t e)
	{
		cerr << "Coulnd't bind socket to address: " << address << "! Error: [" << e.what() << "]" << endl;
	}
	debug() << "Bound " << appName << " zeromq reply socket to address: " << address << "!" << endl;

	debug() << "exiting monica-zmq-control" << endl;
	return 0;
}
<commit_msg>fixed typo<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
Authors:
Michael Berg <michael.berg@zalf.de>

Maintainers:
Currently maintained by the authors.

This file is part of the MONICA model.
Copyright (C) Leibniz Centre for Agricultural Landscape Research (ZALF)
*/

#include <cstdio>
#include <iostream>
#include <fstream>
#include <cstdlib>

#include <string>

#include "zhelpers.hpp"
#include "json11/json11.hpp"

#include "tools/zmq-helper.h"
#include "tools/json11-helper.h"
#include "tools/helper.h"
#include "tools/debug.h"
#include "monica-zmq-defaults.h"

using namespace std;
using namespace Tools;
using namespace json11;
using namespace Monica;

string appName = "monica-zmq-control";
string version = "0.0.1";

int stopMonicaProcesses(zmq::context_t& context,
												string proxyAddress,
												int frontendProxyPort,
												int count)
{
	int stopped = 0;

	// setup a reply socket for managing (e.g. starting/stopping) MONICA processes
	zmq::socket_t socket(context, ZMQ_REQ);

	string address = string("tcp://") + proxyAddress + ":" + to_string(frontendProxyPort);
	try
	{
		socket.setsockopt(ZMQ_RCVTIMEO, 5000);
		socket.setsockopt(ZMQ_SNDTIMEO, 5000);
		socket.connect(address);
		debug() << "Bound " << appName << " zeromq request socket to address: " << address << "!" << endl;

		//send finish message and wait for reply from MONICA server process
		//might take too long in practice, then we have to shut down a MONICA process in a better way
		debug() << "Trying to finish " << count << " MONICA processes" << endl;
		for(int i = 0; i < count; i++)
		{
			J11Object resultMsg;
			resultMsg["type"] = "finish";
			try
			{
				if(s_send(socket, Json(resultMsg).dump()))
				{
					debug() << "Send 'finish' message to a MONICA process" << endl;

					try
					{
						auto msg = receiveMsg(socket);
						if(msg.valid)
						{
							stopped++;
							debug() << "Received ack: " << msg.type() << endl;
						}
					}
					catch(zmq::error_t e)
					{
						cerr
							<< "Exception on trying to receive 'ack' reply message on zmq socket with address: "
							<< address << "! Error: [" << e.what() << "]" << endl;
					}
				}
			}
			catch(zmq::error_t e)
			{
				cerr
					<< "Exception on trying to send 'finish' message on zmq socket with address: " << address
					<< "! Error: [" << e.what() << "]" << endl;
			}
		}
	}
	catch(zmq::error_t e)
	{
		cerr << "Couldn't connect socket to address: " << address << "! Error: [" << e.what() << "]" << endl;
	}

	return stopped;
}

int main (int argc,
					char** argv)
{
	int commPort = defaultControlPort;
	string proxyAddress = defaultProxyAddress;
	int frontendProxyPort = defaultProxyFrontendPort;
	int backendProxyPort = defaultProxyBackendPort;

	auto printHelp = [=]()
	{
		cout
			<< appName << " [options] " << endl
			<< endl
			<< "options:" << endl
			<< endl
			<< " -h | --help ... this help output" << endl
			<< " -v | --version ... outputs " << appName << " version" << endl
			<< endl
			<< " -c | --port COMM-PORT (default: " << commPort << ") ... run " << appName << " with given control port" << endl
			<< " -a | --proxy-address PROXY-ADDRESS (default: " << proxyAddress << ") ... connect client to give IP address" << endl
			<< " -f | --frontend-proxy-port PROXY-PORT (default: " << frontendProxyPort << ") ... communicate with started MONICA ZeroMQ servers via given frontend proxy port" << endl
			<< " -b | --backend-proxy-port PROXY-PORT (default: " << backendProxyPort << ") ... connect started MONICA ZeroMQ servers to given backend proxy port" << endl
			<< " -d | --debug ... enable debug outputs" << endl;
	};

	for(auto i = 1; i < argc; i++)
	{
		string arg = argv[i];
		if((arg == "-c" || arg == "--comm-port")
			 && i + 1 < argc)
			commPort = stoi(argv[++i]);
		else if((arg == "-a" || arg == "--proxy-address")
						&& i + 1 < argc)
			proxyAddress = argv[++i];
		else if((arg == "-f" || arg == "--frontend-proxy-port")
						&& i + 1 < argc)
			frontendProxyPort = stoi(argv[++i]);
		else if((arg == "-b" || arg == "--backend-proxy-port")
						&& i + 1 < argc)
			backendProxyPort = stoi(argv[++i]);
		else if(arg == "-d" || arg == "--debug")
			activateDebug = true;
		else if(arg == "-h" || arg == "--help")
			printHelp(), exit(0);
		else if(arg == "-v" || arg == "--version")
			cout << appName << " version " << version << endl, exit(0);
	}

	zmq::context_t context(1);

	// setup a reply socket for managing (e.g. starting/stopping) MONICA processes
	zmq::socket_t socket(context, ZMQ_REP);

	string address = string("tcp://*:") + to_string(commPort);
	try
	{
		socket.bind(address);

		map<string, int> started;

		//loop until receive finish message
		while(true)
		{
			try
			{
				auto msg = receiveMsg(socket);
				if(!msg.valid)
					continue;

				debug() << "Received message: " << msg.toString() << endl;

				string msgType = msg.type();
				if(msgType == "finish")
				{
					J11Object resultMsg;
					resultMsg["type"] = "ack";
					try
					{
						s_send(socket, Json(resultMsg).dump());
					}
					catch(zmq::error_t e)
					{
						cerr
							<< "Exception on trying to reply to 'finish' request with 'ack' message on zmq socket with address: "
							<< address << "! Still will finish " << appName << "! Error: [" << e.what() << "]" << endl;
					}
					socket.setsockopt(ZMQ_LINGER, 0);
					socket.close();

					break;
				}
				else if(msgType == "start-new"
								|| msgType == "start-max"
								|| msgType == "stop")
				{
					Json& fmsg = msg.json;

					int count = fmsg["count"].int_value();

					string proxyAddress = fmsg["proxy-address"].string_value();
					int proxyFrontendPort = fmsg["proxy-frontend-port"].int_value();
					int proxyBackendPort = fmsg["proxy-backend-port"].int_value();

					//string serviceAddress = fmsg["service-address"].string_value();
					bool isService = !fmsg["service-port"].is_null();
					int servicePort = fmsg["service-port"].int_value();

					string controlAddresses = fmsg["control-addresses"].string_value();
					string inputAddresses = fmsg["input-addresses"].string_value();
					string outputAddresses = fmsg["output-addresses"].string_value();

					string addresses;
					string stopAddress;
					int stopPort;
					if(!proxyAddress.empty())
					{
						stopAddress = proxyAddress, stopPort = proxyFrontendPort;
						addresses = string(" -p tcp://") + proxyAddress + ":" + to_string(proxyBackendPort);
						if(!controlAddresses.empty())
							addresses += " -c " + controlAddresses;
					}
					else if(isService)
					{
						count = max(count, 1);
						//stopAddress = "127.0.0.1", stopPort = servicePort;
						stopAddress = "localhost", stopPort = servicePort;
						addresses = string(" -s tcp://*:") + to_string(servicePort);
						if(!controlAddresses.empty())
							addresses += " -c " + controlAddresses;
					}
					else if(!outputAddresses.empty() && !inputAddresses.empty())
					{
						addresses = string(" -i ") + inputAddresses + " -o " + outputAddresses;
						if(!controlAddresses.empty())
							addresses += " -c " + controlAddresses;
					}

#ifdef WIN32
					string cmd = string("start /b monica-zmq-server ") + addresses;
#else
					string cmd = string("monica-zmq-server") + addresses + " &";
#endif
					//cout << "addresses: " << addresses << endl;

					bool isStartMax = msgType == "startMax";
					bool isStop = msgType == "stop";
					int& started_ = started[addresses];
					int successfullyStarted = 0;
					int i = isStartMax ? started_ : 0;
					int stop = 0;
					if(isStartMax)
						stop = max(0, started_ - count);
					else if(isStop)
						stop = max(0, min(count, started_));

					if(!isStop)
					{
						for(; i < count; i++)
						{
							int res = system(cmd.c_str());
							debug() << "result of running '" << cmd << "': " << res << endl;
							started[addresses]++, successfullyStarted++;
						}
					}

					if((isStartMax || isStop)
						 && !stopAddress.empty())
					{
						auto stopped = stopMonicaProcesses(context, stopAddress, stopPort, stop);
						if(isStop)
							started_ -= stopped;
					}

					J11Object resultMsg;
					resultMsg["type"] = "result";
					resultMsg["started"] = successfullyStarted;
					if(isStartMax || isStop)
						resultMsg["stopped"] = stop;
					try
					{
						s_send(socket, Json(resultMsg).dump());
					}
					catch(zmq::error_t e)
					{
						cerr
							<< "Exception on trying to reply with result message: " << Json(resultMsg).dump()
							<< " on zmq socket with address: " << address
							<< "! Will continue to receive requests! Error: [" << e.what() << "]" << endl;
					}
				}
			}
			catch(zmq::error_t e)
			{
				cerr
					<< "Exception on trying to receive request message on zmq socket with address: "
					<< address << "! Will continue to receive requests! Error: [" << e.what() << "]" << endl;
			}
		}
	}
	catch(zmq::error_t e)
	{
		cerr << "Couldn't bind socket to address: " << address << "! Error: [" << e.what() << "]" << endl;
	}
	debug() << "Bound " << appName << " zeromq reply socket to address: " << address << "!" << endl;

	debug() << "exiting monica-zmq-control" << endl;
	return 0;
}
<|endoftext|>