<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the LICENSE
 * file in the root directory of this source tree.
 */
#include "FlipperConnectionManagerImpl.h"
#include <folly/String.h>
#include <folly/futures/Future.h>
#include <folly/io/async/AsyncSocketException.h>
#include <folly/io/async/SSLContext.h>
#include <folly/json.h>
#include <rsocket/Payload.h>
#include <rsocket/RSocket.h>
#include <rsocket/transports/tcp/TcpConnectionFactory.h>
#include <stdexcept>
#include <thread>
#include "ConnectionContextStore.h"
#include "FlipperStep.h"
#include "Log.h"

#define WRONG_THREAD_EXIT_MSG \
  "ERROR: Aborting flipper initialization because it's not running in the flipper thread."

static constexpr int reconnectIntervalSeconds = 2;
static constexpr int connectionKeepaliveSeconds = 10;
static constexpr int securePort = 8088;
static constexpr int insecurePort = 8089;

static constexpr int maxPayloadSize = 0xFFFFFF;

namespace facebook {
namespace flipper {

class ConnectionEvents : public rsocket::RSocketConnectionEvents {
 private:
  FlipperConnectionManagerImpl* websocket_;

 public:
  ConnectionEvents(FlipperConnectionManagerImpl* websocket)
      : websocket_(websocket) {}

  void onConnected() {
    websocket_->isOpen_ = true;
    if (websocket_->connectionIsTrusted_) {
      websocket_->callbacks_->onConnected();
    }
  }

  void onDisconnected(const folly::exception_wrapper&) {
    if (!websocket_->isOpen_)
      return;
    websocket_->isOpen_ = false;
    if (websocket_->connectionIsTrusted_) {
      websocket_->connectionIsTrusted_ = false;
      websocket_->callbacks_->onDisconnected();
    }
    websocket_->reconnect();
  }

  void onClosed(const folly::exception_wrapper& e) {
    onDisconnected(e);
  }
};

class Responder : public rsocket::RSocketResponder {
 private:
  FlipperConnectionManagerImpl* websocket_;

 public:
  Responder(FlipperConnectionManagerImpl* websocket) : websocket_(websocket) {}

  void handleFireAndForget(
      rsocket::Payload request,
      rsocket::StreamId streamId) {
    const auto payload = request.moveDataToString();
    websocket_->callbacks_->onMessageReceived(folly::parseJson(payload));
  }
};

FlipperConnectionManagerImpl::FlipperConnectionManagerImpl(
    FlipperInitConfig config,
    std::shared_ptr<FlipperState> state,
    std::shared_ptr<ConnectionContextStore> contextStore)
    : deviceData_(config.deviceData),
      flipperState_(state),
      flipperEventBase_(config.callbackWorker),
      connectionEventBase_(config.connectionWorker),
      contextStore_(contextStore) {
  CHECK_THROW(config.callbackWorker, std::invalid_argument);
  CHECK_THROW(config.connectionWorker, std::invalid_argument);
}

FlipperConnectionManagerImpl::~FlipperConnectionManagerImpl() {
  stop();
}

void FlipperConnectionManagerImpl::start() {
  auto step = flipperState_->start("Start connection thread");

  folly::makeFuture()
      .via(flipperEventBase_->getEventBase())
      .delayed(std::chrono::milliseconds(0))
      .thenValue([this, step](auto&&) {
        step->complete();
        startSync();
      });
}

void FlipperConnectionManagerImpl::startSync() {
  if (!isRunningInOwnThread()) {
    log(WRONG_THREAD_EXIT_MSG);
    return;
  }
  if (isOpen()) {
    log("Already connected");
    return;
  }
  bool isClientSetupStep = isCertificateExchangeNeeded();
  auto step = flipperState_->start(
      isClientSetupStep ? "Establish pre-setup connection"
                        : "Establish main connection");
  try {
    if (isClientSetupStep) {
      doCertificateExchange();
    } else {
      connectSecurely();
    }
    step->complete();
  } catch (const folly::AsyncSocketException& e) {
    if (e.getType() == folly::AsyncSocketException::NOT_OPEN) {
      // The expected code path when flipper desktop is not running.
      // Don't count as a failed attempt.
      step->fail("Port not open");
    } else {
      log(e.what());
      failedConnectionAttempts_++;
      step->fail(e.what());
    }
    reconnect();
  } catch (const std::exception& e) {
    log(e.what());
    step->fail(e.what());
    failedConnectionAttempts_++;
    reconnect();
  }
}

void FlipperConnectionManagerImpl::doCertificateExchange() {
  rsocket::SetupParameters parameters;
  folly::SocketAddress address;

  parameters.payload = rsocket::Payload(
      folly::toJson(folly::dynamic::object("os", deviceData_.os)(
          "device", deviceData_.device)("app", deviceData_.app)));
  address.setFromHostPort(deviceData_.host, insecurePort);

  auto connectingInsecurely = flipperState_->start("Connect insecurely");
  connectionIsTrusted_ = false;
  client_ =
      rsocket::RSocket::createConnectedClient(
          std::make_unique<rsocket::TcpConnectionFactory>(
              *connectionEventBase_->getEventBase(), std::move(address)),
          std::move(parameters),
          nullptr,
          std::chrono::seconds(connectionKeepaliveSeconds), // keepaliveInterval
          nullptr, // stats
          std::make_shared<ConnectionEvents>(this))
          .get();
  connectingInsecurely->complete();

  requestSignedCertFromFlipper();
}

void FlipperConnectionManagerImpl::connectSecurely() {
  rsocket::SetupParameters parameters;
  folly::SocketAddress address;

  auto loadingDeviceId = flipperState_->start("Load Device Id");
  auto deviceId = contextStore_->getDeviceId();
  if (deviceId.compare("unknown")) {
    loadingDeviceId->complete();
  }
  parameters.payload = rsocket::Payload(folly::toJson(folly::dynamic::object(
      "os", deviceData_.os)("device", deviceData_.device)(
      "device_id", deviceId)("app", deviceData_.app)));
  address.setFromHostPort(deviceData_.host, securePort);

  std::shared_ptr<folly::SSLContext> sslContext =
      contextStore_->getSSLContext();
  auto connectingSecurely = flipperState_->start("Connect securely");
  connectionIsTrusted_ = true;
  client_ =
      rsocket::RSocket::createConnectedClient(
          std::make_unique<rsocket::TcpConnectionFactory>(
              *connectionEventBase_->getEventBase(),
              std::move(address),
              std::move(sslContext)),
          std::move(parameters),
          std::make_shared<Responder>(this),
          std::chrono::seconds(connectionKeepaliveSeconds), // keepaliveInterval
          nullptr, // stats
          std::make_shared<ConnectionEvents>(this))
          .get();
  connectingSecurely->complete();
  failedConnectionAttempts_ = 0;
}

void FlipperConnectionManagerImpl::reconnect() {
  folly::makeFuture()
      .via(flipperEventBase_->getEventBase())
      .delayed(std::chrono::seconds(reconnectIntervalSeconds))
      .thenValue([this](auto&&) { startSync(); });
}

void FlipperConnectionManagerImpl::stop() {
  if (client_) {
    client_->disconnect();
  }
  client_ = nullptr;
}

bool FlipperConnectionManagerImpl::isOpen() const {
  return isOpen_ && connectionIsTrusted_;
}

void FlipperConnectionManagerImpl::setCallbacks(Callbacks* callbacks) {
  callbacks_ = callbacks;
}

void FlipperConnectionManagerImpl::sendMessage(const folly::dynamic& message) {
  flipperEventBase_->add([this, message]() {
    std::string json = folly::toJson(message);
    rsocket::Payload payload = rsocket::Payload(json);
    auto payloadLength = payload.data->computeChainDataLength();

    DCHECK_LE(payloadLength, maxPayloadSize);
    if (payloadLength > maxPayloadSize) {
      auto logMessage =
          std::string(
              "Error: Skipping sending message larger than max rsocket payload: ") +
          json;
      log(logMessage);
      return;
    }
    if (client_) {
      client_->getRequester()
          ->fireAndForget(std::move(payload))
          ->subscribe([]() {});
    }
  });
}

bool FlipperConnectionManagerImpl::isCertificateExchangeNeeded() {
  if (failedConnectionAttempts_ >= 2) {
    return true;
  }

  auto step = flipperState_->start("Check required certificates are present");
  bool hasRequiredFiles = contextStore_->hasRequiredFiles();
  if (hasRequiredFiles) {
    step->complete();
  }
  return !hasRequiredFiles;
}

void FlipperConnectionManagerImpl::requestSignedCertFromFlipper() {
  auto generatingCSR = flipperState_->start("Generate CSR");
  std::string csr = contextStore_->createCertificateSigningRequest();
  generatingCSR->complete();

  folly::dynamic message =
      folly::dynamic::object("method", "signCertificate")("csr", csr.c_str())(
          "destination", contextStore_->getCertificateDirectoryPath().c_str());
  auto gettingCert = flipperState_->start("Getting cert from desktop");

  flipperEventBase_->add([this, message, gettingCert]() {
    client_->getRequester()
        ->requestResponse(rsocket::Payload(folly::toJson(message)))
        ->subscribe(
            [this, gettingCert](rsocket::Payload p) {
              auto response = p.moveDataToString();
              if (!response.empty()) {
                folly::dynamic config = folly::parseJson(response);
                contextStore_->storeConnectionConfig(config);
              }
              gettingCert->complete();
              log("Certificate exchange complete.");
              // Disconnect after message sending is complete.
              // This will trigger a reconnect which should use the secure
              // channel.
              // TODO: Connect immediately, without waiting for reconnect
              client_ = nullptr;
            },
            [this, message](folly::exception_wrapper e) {
              e.handle(
                  [&](rsocket::ErrorWithPayload& errorWithPayload) {
                    std::string errorMessage =
                        errorWithPayload.payload.moveDataToString();

                    if (errorMessage.compare("not implemented")) {
                      log("Desktop failed to provide certificates. Error from flipper desktop:\n" +
                          errorMessage);
                      client_ = nullptr;
                    } else {
                      sendLegacyCertificateRequest(message);
                    }
                  },
                  [e](...) {
                    log(("Error during certificate exchange:" + e.what())
                            .c_str());
                  });
            });
  });
  failedConnectionAttempts_ = 0;
}

void FlipperConnectionManagerImpl::sendLegacyCertificateRequest(
    folly::dynamic message) {
  // Desktop is using an old version of Flipper.
  // Fall back to fireAndForget, instead of requestResponse.
  auto sendingRequest =
      flipperState_->start("Sending fallback certificate request");
  client_->getRequester()
      ->fireAndForget(rsocket::Payload(folly::toJson(message)))
      ->subscribe([this, sendingRequest]() {
        sendingRequest->complete();
        folly::dynamic config = folly::dynamic::object();
        contextStore_->storeConnectionConfig(config);
        client_ = nullptr;
      });
}

bool FlipperConnectionManagerImpl::isRunningInOwnThread() {
  return flipperEventBase_->isInEventBaseThread();
}

} // namespace flipper
} // namespace facebook
<commit_msg>Don't invalidate connection files on Network Errors<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the LICENSE
 * file in the root directory of this source tree.
 */
#include "FlipperConnectionManagerImpl.h"
#include <folly/String.h>
#include <folly/futures/Future.h>
#include <folly/io/async/AsyncSocketException.h>
#include <folly/io/async/SSLContext.h>
#include <folly/json.h>
#include <rsocket/Payload.h>
#include <rsocket/RSocket.h>
#include <rsocket/transports/tcp/TcpConnectionFactory.h>
#include <stdexcept>
#include <thread>
#include "ConnectionContextStore.h"
#include "FlipperStep.h"
#include "Log.h"

#define WRONG_THREAD_EXIT_MSG \
  "ERROR: Aborting flipper initialization because it's not running in the flipper thread."

static constexpr int reconnectIntervalSeconds = 2;
static constexpr int connectionKeepaliveSeconds = 10;
static constexpr int securePort = 8088;
static constexpr int insecurePort = 8089;

static constexpr int maxPayloadSize = 0xFFFFFF;

namespace facebook {
namespace flipper {

class ConnectionEvents : public rsocket::RSocketConnectionEvents {
 private:
  FlipperConnectionManagerImpl* websocket_;

 public:
  ConnectionEvents(FlipperConnectionManagerImpl* websocket)
      : websocket_(websocket) {}

  void onConnected() {
    websocket_->isOpen_ = true;
    if (websocket_->connectionIsTrusted_) {
      websocket_->callbacks_->onConnected();
    }
  }

  void onDisconnected(const folly::exception_wrapper&) {
    if (!websocket_->isOpen_)
      return;
    websocket_->isOpen_ = false;
    if (websocket_->connectionIsTrusted_) {
      websocket_->connectionIsTrusted_ = false;
      websocket_->callbacks_->onDisconnected();
    }
    websocket_->reconnect();
  }

  void onClosed(const folly::exception_wrapper& e) {
    onDisconnected(e);
  }
};

class Responder : public rsocket::RSocketResponder {
 private:
  FlipperConnectionManagerImpl* websocket_;

 public:
  Responder(FlipperConnectionManagerImpl* websocket) : websocket_(websocket) {}

  void handleFireAndForget(
      rsocket::Payload request,
      rsocket::StreamId streamId) {
    const auto payload = request.moveDataToString();
    websocket_->callbacks_->onMessageReceived(folly::parseJson(payload));
  }
};

FlipperConnectionManagerImpl::FlipperConnectionManagerImpl(
    FlipperInitConfig config,
    std::shared_ptr<FlipperState> state,
    std::shared_ptr<ConnectionContextStore> contextStore)
    : deviceData_(config.deviceData),
      flipperState_(state),
      flipperEventBase_(config.callbackWorker),
      connectionEventBase_(config.connectionWorker),
      contextStore_(contextStore) {
  CHECK_THROW(config.callbackWorker, std::invalid_argument);
  CHECK_THROW(config.connectionWorker, std::invalid_argument);
}

FlipperConnectionManagerImpl::~FlipperConnectionManagerImpl() {
  stop();
}

void FlipperConnectionManagerImpl::start() {
  auto step = flipperState_->start("Start connection thread");

  folly::makeFuture()
      .via(flipperEventBase_->getEventBase())
      .delayed(std::chrono::milliseconds(0))
      .thenValue([this, step](auto&&) {
        step->complete();
        startSync();
      });
}

void FlipperConnectionManagerImpl::startSync() {
  if (!isRunningInOwnThread()) {
    log(WRONG_THREAD_EXIT_MSG);
    return;
  }
  if (isOpen()) {
    log("Already connected");
    return;
  }
  bool isClientSetupStep = isCertificateExchangeNeeded();
  auto step = flipperState_->start(
      isClientSetupStep ? "Establish pre-setup connection"
                        : "Establish main connection");
  try {
    if (isClientSetupStep) {
      doCertificateExchange();
    } else {
      connectSecurely();
    }
    step->complete();
  } catch (const folly::AsyncSocketException& e) {
    if (e.getType() == folly::AsyncSocketException::NOT_OPEN ||
        e.getType() == folly::AsyncSocketException::NETWORK_ERROR) {
      // The expected code path when flipper desktop is not running.
      // Don't count as a failed attempt, or it would invalidate the connection
      // files for no reason. On iOS devices, we can always connect to the local
      // port forwarding server even when it can't connect to flipper. In that
      // case we get a Network error instead of a Port not open error, so we
      // treat them the same.
      step->fail(
          "No route to flipper found. Is flipper desktop running? Retrying...");
    } else {
      log(e.what());
      failedConnectionAttempts_++;
      step->fail(e.what());
    }
    reconnect();
  } catch (const std::exception& e) {
    log(e.what());
    step->fail(e.what());
    failedConnectionAttempts_++;
    reconnect();
  }
}

void FlipperConnectionManagerImpl::doCertificateExchange() {
  rsocket::SetupParameters parameters;
  folly::SocketAddress address;

  parameters.payload = rsocket::Payload(
      folly::toJson(folly::dynamic::object("os", deviceData_.os)(
          "device", deviceData_.device)("app", deviceData_.app)));
  address.setFromHostPort(deviceData_.host, insecurePort);

  auto connectingInsecurely = flipperState_->start("Connect insecurely");
  connectionIsTrusted_ = false;
  client_ =
      rsocket::RSocket::createConnectedClient(
          std::make_unique<rsocket::TcpConnectionFactory>(
              *connectionEventBase_->getEventBase(), std::move(address)),
          std::move(parameters),
          nullptr,
          std::chrono::seconds(connectionKeepaliveSeconds), // keepaliveInterval
          nullptr, // stats
          std::make_shared<ConnectionEvents>(this))
          .get();
  connectingInsecurely->complete();

  requestSignedCertFromFlipper();
}

void FlipperConnectionManagerImpl::connectSecurely() {
  rsocket::SetupParameters parameters;
  folly::SocketAddress address;

  auto loadingDeviceId = flipperState_->start("Load Device Id");
  auto deviceId = contextStore_->getDeviceId();
  if (deviceId.compare("unknown")) {
    loadingDeviceId->complete();
  }
  parameters.payload = rsocket::Payload(folly::toJson(folly::dynamic::object(
      "os", deviceData_.os)("device", deviceData_.device)(
      "device_id", deviceId)("app", deviceData_.app)));
  address.setFromHostPort(deviceData_.host, securePort);

  std::shared_ptr<folly::SSLContext> sslContext =
      contextStore_->getSSLContext();
  auto connectingSecurely = flipperState_->start("Connect securely");
  connectionIsTrusted_ = true;
  client_ =
      rsocket::RSocket::createConnectedClient(
          std::make_unique<rsocket::TcpConnectionFactory>(
              *connectionEventBase_->getEventBase(),
              std::move(address),
              std::move(sslContext)),
          std::move(parameters),
          std::make_shared<Responder>(this),
          std::chrono::seconds(connectionKeepaliveSeconds), // keepaliveInterval
          nullptr, // stats
          std::make_shared<ConnectionEvents>(this))
          .get();
  connectingSecurely->complete();
  failedConnectionAttempts_ = 0;
}

void FlipperConnectionManagerImpl::reconnect() {
  folly::makeFuture()
      .via(flipperEventBase_->getEventBase())
      .delayed(std::chrono::seconds(reconnectIntervalSeconds))
      .thenValue([this](auto&&) { startSync(); });
}

void FlipperConnectionManagerImpl::stop() {
  if (client_) {
    client_->disconnect();
  }
  client_ = nullptr;
}

bool FlipperConnectionManagerImpl::isOpen() const {
  return isOpen_ && connectionIsTrusted_;
}

void FlipperConnectionManagerImpl::setCallbacks(Callbacks* callbacks) {
  callbacks_ = callbacks;
}

void FlipperConnectionManagerImpl::sendMessage(const folly::dynamic& message) {
  flipperEventBase_->add([this, message]() {
    std::string json = folly::toJson(message);
    rsocket::Payload payload = rsocket::Payload(json);
    auto payloadLength = payload.data->computeChainDataLength();

    DCHECK_LE(payloadLength, maxPayloadSize);
    if (payloadLength > maxPayloadSize) {
      auto logMessage =
          std::string(
              "Error: Skipping sending message larger than max rsocket payload: ") +
          json;
      log(logMessage);
      return;
    }
    if (client_) {
      client_->getRequester()
          ->fireAndForget(std::move(payload))
          ->subscribe([]() {});
    }
  });
}

bool FlipperConnectionManagerImpl::isCertificateExchangeNeeded() {
  if (failedConnectionAttempts_ >= 2) {
    return true;
  }

  auto step = flipperState_->start("Check required certificates are present");
  bool hasRequiredFiles = contextStore_->hasRequiredFiles();
  if (hasRequiredFiles) {
    step->complete();
  }
  return !hasRequiredFiles;
}

void FlipperConnectionManagerImpl::requestSignedCertFromFlipper() {
  auto generatingCSR = flipperState_->start("Generate CSR");
  std::string csr = contextStore_->createCertificateSigningRequest();
  generatingCSR->complete();

  folly::dynamic message =
      folly::dynamic::object("method", "signCertificate")("csr", csr.c_str())(
          "destination", contextStore_->getCertificateDirectoryPath().c_str());
  auto gettingCert = flipperState_->start("Getting cert from desktop");

  flipperEventBase_->add([this, message, gettingCert]() {
    client_->getRequester()
        ->requestResponse(rsocket::Payload(folly::toJson(message)))
        ->subscribe(
            [this, gettingCert](rsocket::Payload p) {
              auto response = p.moveDataToString();
              if (!response.empty()) {
                folly::dynamic config = folly::parseJson(response);
                contextStore_->storeConnectionConfig(config);
              }
              gettingCert->complete();
              log("Certificate exchange complete.");
              // Disconnect after message sending is complete.
              // This will trigger a reconnect which should use the secure
              // channel.
              // TODO: Connect immediately, without waiting for reconnect
              client_ = nullptr;
            },
            [this, message](folly::exception_wrapper e) {
              e.handle(
                  [&](rsocket::ErrorWithPayload& errorWithPayload) {
                    std::string errorMessage =
                        errorWithPayload.payload.moveDataToString();

                    if (errorMessage.compare("not implemented")) {
                      log("Desktop failed to provide certificates. Error from flipper desktop:\n" +
                          errorMessage);
                      client_ = nullptr;
                    } else {
                      sendLegacyCertificateRequest(message);
                    }
                  },
                  [e](...) {
                    log(("Error during certificate exchange:" + e.what())
                            .c_str());
                  });
            });
  });
  failedConnectionAttempts_ = 0;
}

void FlipperConnectionManagerImpl::sendLegacyCertificateRequest(
    folly::dynamic message) {
  // Desktop is using an old version of Flipper.
  // Fall back to fireAndForget, instead of requestResponse.
  auto sendingRequest =
      flipperState_->start("Sending fallback certificate request");
  client_->getRequester()
      ->fireAndForget(rsocket::Payload(folly::toJson(message)))
      ->subscribe([this, sendingRequest]() {
        sendingRequest->complete();
        folly::dynamic config = folly::dynamic::object();
        contextStore_->storeConnectionConfig(config);
        client_ = nullptr;
      });
}

bool FlipperConnectionManagerImpl::isRunningInOwnThread() {
  return flipperEventBase_->isInEventBaseThread();
}

} // namespace flipper
} // namespace facebook
<|endoftext|>


<commit_before>#include "callmanager.h"

#include "statisticsinterface.h"

#include "globalsdpstate.h"

#include <QHostAddress>

CallManager::CallManager():
    media_(),
    sip_(),
    window_(nullptr)
{}

void CallManager::init()
{
  window_.init(this);
  window_.show();

  sip_.init(this);

  // register the GUI signals indicating GUI changes to be handled approrietly in a system wide manner
  QObject::connect(&window_, SIGNAL(settingsChanged()), this, SLOT(updateSettings()));
  QObject::connect(&window_, SIGNAL(micStateSwitch()), this, SLOT(micState()));
  QObject::connect(&window_, SIGNAL(cameraStateSwitch()), this, SLOT(cameraState()));
  QObject::connect(&window_, SIGNAL(endCall()), this, SLOT(endTheCall()));
  QObject::connect(&window_, SIGNAL(closed()), this, SLOT(windowClosed()));

  QObject::connect(&window_, &CallWindow::callAccepted, this, &CallManager::userAcceptsCall);
  QObject::connect(&window_, &CallWindow::callRejected, this, &CallManager::userRejectsCall);
  QObject::connect(&window_, &CallWindow::callCancelled, this, &CallManager::userCancelsCall);

  stats_ = window_.createStatsWindow();

  media_.init(window_.getViewFactory(), stats_);

  QObject::connect(&stun_, SIGNAL(addressReceived(QHostAddress)), this, SLOT(stunAddress(QHostAddress)));
  QObject::connect(&stun_, SIGNAL(error()), this, SLOT(noStunAddress()));
  //stun_.wantAddress("stun.l.google.com");
}

void CallManager::stunAddress(QHostAddress address)
{
  qDebug() << "Our stun address:" << address;
}

void CallManager::noStunAddress()
{
  qDebug() << "Could not get STUN address";
}

void CallManager::uninit()
{
  endTheCall();
  sip_.uninit();
  media_.uninit();
}

void CallManager::windowClosed()
{
  uninit();
}

void CallManager::callToParticipant(QString name, QString username, QString ip)
{
  QString ip_str = ip;

  Contact con;
  con.remoteAddress = ip_str;
  con.realName = name;
  con.username = username;
  con.proxyConnection = false;

  QList<Contact> list;
  list.append(con);

  //start negotiations for this connection

  QList<uint32_t> sessionIDs = sip_.startCall(list);

  qDebug() << "Started" << sessionIDs.size() << "calls:" << sessionIDs;

  for(auto sessionID : sessionIDs)
  {
    window_.displayOutgoingCall(sessionID, name);
    if(states_.find(sessionID) == states_.end())
    {
      states_[sessionID] = CALLINGTHEM;
    }
  }
}

void CallManager::chatWithParticipant(QString name, QString username, QString ip)
{
  qDebug() << "Chatting with:" << name << '(' << username << ") at ip:" << ip << ": Chat not implemented yet";
}

bool CallManager::incomingCall(uint32_t sessionID, QString caller)
{
  if(states_.find(sessionID) != states_.end())
  {
    qDebug() << "ERROR: Overwriting and existing session in CallManager!";
  }

  QSettings settings("kvazzup.ini", QSettings::IniFormat);
  int autoAccept = settings.value("local/Auto-Accept").toInt();
  if(autoAccept == 1)
  {
    qDebug() << "Incoming call auto-accpeted!";
    userAcceptsCall(sessionID);
    states_[sessionID] = CALLNEGOTIATING;
    return true;
  }
  else
  {
    window_.displayIncomingCall(sessionID, caller);
    states_[sessionID] = CALLRINGINGWITHUS;
  }
  return false;
}

void CallManager::callRinging(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end() && states_[sessionID] == CALLINGTHEM)
  {
    qDebug() << "Our call is ringing!";
    window_.displayRinging(sessionID);
    states_[sessionID] = CALLRINGINWITHTHEM;
  }
  else
  {
    qDebug() << "PEER ERROR: Got call ringing for nonexisting call:" << sessionID;
  }
}

void CallManager::peerAccepted(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end()
     && states_[sessionID] == CALLRINGINWITHTHEM)
  {
    qDebug() << "They accepted our call!";
    states_[sessionID] = CALLNEGOTIATING;
  }
  else
  {
    qDebug() << "PEER ERROR: Got an accepted call even though we have not yet called them!";
  }
}

void CallManager::peerRejected(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end())
  {
    if(states_[sessionID] == CALLRINGINWITHTHEM)
    {
      qDebug() << "Our call has been rejected!";
      removeSession(sessionID);
    }
    else
    {
      qDebug() << "PEER ERROR: Got reject when we weren't calling them:" << states_[sessionID];
    }
  }
  else
  {
    qDebug() << "PEER ERROR: Got reject for nonexisting call:" << sessionID;
    qDebug() << "Number of ongoing sessions:" << states_.size();
  }
}

void CallManager::callNegotiated(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end() && states_[sessionID] == CALLNEGOTIATING)
  {
    qDebug() << "Call has been agreed upon with peer:" << sessionID;

    window_.addVideoStream(sessionID);

    std::shared_ptr<SDPMessageInfo> localSDP;
    std::shared_ptr<SDPMessageInfo> remoteSDP;

    sip_.getSDPs(sessionID,
                 localSDP,
                 remoteSDP);

    if(localSDP == nullptr || remoteSDP == nullptr)
    {
      return;
    }

    media_.addParticipant(sessionID, remoteSDP, localSDP);
    states_[sessionID] = CALLONGOING;
  }
  else
  {
    qDebug() << "PEER ERROR: Got call succesful negotiation even though we are not there yet!";
  }
}

void CallManager::callNegotiationFailed(uint32_t sessionID)
{
  // TODO: display a proper error for the user
  peerRejected(sessionID);
}

void CallManager::cancelIncomingCall(uint32_t sessionID)
{
  // TODO: display a proper message to the user that peer has cancelled their call
  removeSession(sessionID);
}

void CallManager::endCall(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end()
     && states_[sessionID] == CALLONGOING)
  {
    media_.removeParticipant(sessionID);
  }
  removeSession(sessionID);
}

void CallManager::registeredToServer()
{
  qDebug() << "Got info, that we have been registered to SIP server.";
  // TODO: indicate to user in some small detail
}

void CallManager::registeringFailed()
{
  qDebug() << "Failed to register";
  // TODO: indicate error to user
}

void CallManager::updateSettings()
{
  media_.updateSettings();
  //sip_.updateSettings(); // for blocking list
}

void CallManager::userAcceptsCall(uint32_t sessionID)
{
  qDebug() << "Sending accept";
  sip_.acceptCall(sessionID);
  states_[sessionID] = CALLNEGOTIATING;
}

void CallManager::userRejectsCall(uint32_t sessionID)
{
  qDebug() << "We have rejected their call";
  sip_.rejectCall(sessionID);
  removeSession(sessionID);
}

void CallManager::userCancelsCall(uint32_t sessionID)
{
  qDebug() << "We have cancelled our call";
  sip_.cancelCall(sessionID);
  removeSession(sessionID);
}

void CallManager::endTheCall()
{
  qDebug() << "Ending all calls";
  sip_.endAllCalls();
  media_.endAllCalls();
  window_.clearConferenceView();

  states_.clear();
}

void CallManager::micState()
{
  window_.setMicState(media_.toggleMic());
}

void CallManager::cameraState()
{
  window_.setCameraState(media_.toggleCamera());
}

void CallManager::removeSession(uint32_t sessionID)
{
  window_.removeParticipant(sessionID);

  auto it = states_.find(sessionID);
  if(it != states_.end())
  {
    states_.erase(it);
  }
}
<commit_msg>Disabled some state checking from call manager that caused the program not to work when calling other computers.<commit_after>#include "callmanager.h"

#include "statisticsinterface.h"

#include "globalsdpstate.h"

#include <QHostAddress>

CallManager::CallManager():
    media_(),
    sip_(),
    window_(nullptr)
{}

void CallManager::init()
{
  window_.init(this);
  window_.show();

  sip_.init(this);

  // register the GUI signals indicating GUI changes to be handled approrietly in a system wide manner
  QObject::connect(&window_, SIGNAL(settingsChanged()), this, SLOT(updateSettings()));
  QObject::connect(&window_, SIGNAL(micStateSwitch()), this, SLOT(micState()));
  QObject::connect(&window_, SIGNAL(cameraStateSwitch()), this, SLOT(cameraState()));
  QObject::connect(&window_, SIGNAL(endCall()), this, SLOT(endTheCall()));
  QObject::connect(&window_, SIGNAL(closed()), this, SLOT(windowClosed()));

  QObject::connect(&window_, &CallWindow::callAccepted, this, &CallManager::userAcceptsCall);
  QObject::connect(&window_, &CallWindow::callRejected, this, &CallManager::userRejectsCall);
  QObject::connect(&window_, &CallWindow::callCancelled, this, &CallManager::userCancelsCall);

  stats_ = window_.createStatsWindow();

  media_.init(window_.getViewFactory(), stats_);

  QObject::connect(&stun_, SIGNAL(addressReceived(QHostAddress)), this, SLOT(stunAddress(QHostAddress)));
  QObject::connect(&stun_, SIGNAL(error()), this, SLOT(noStunAddress()));
  //stun_.wantAddress("stun.l.google.com");
}

void CallManager::stunAddress(QHostAddress address)
{
  qDebug() << "Our stun address:" << address;
}

void CallManager::noStunAddress()
{
  qDebug() << "Could not get STUN address";
}

void CallManager::uninit()
{
  endTheCall();
  sip_.uninit();
  media_.uninit();
}

void CallManager::windowClosed()
{
  uninit();
}

void CallManager::callToParticipant(QString name, QString username, QString ip)
{
  QString ip_str = ip;

  Contact con;
  con.remoteAddress = ip_str;
  con.realName = name;
  con.username = username;
  con.proxyConnection = false;

  QList<Contact> list;
  list.append(con);

  //start negotiations for this connection

  QList<uint32_t> sessionIDs = sip_.startCall(list);

  qDebug() << "Started" << sessionIDs.size() << "calls:" << sessionIDs;

  for(auto sessionID : sessionIDs)
  {
    window_.displayOutgoingCall(sessionID, name);
    if(states_.find(sessionID) == states_.end())
    {
      states_[sessionID] = CALLINGTHEM;
    }
  }
}

void CallManager::chatWithParticipant(QString name, QString username, QString ip)
{
  qDebug() << "Chatting with:" << name << '(' << username << ") at ip:" << ip << ": Chat not implemented yet";
}

bool CallManager::incomingCall(uint32_t sessionID, QString caller)
{
  if(states_.find(sessionID) != states_.end())
  {
    qDebug() << "ERROR: Overwriting and existing session in CallManager!";
  }

  QSettings settings("kvazzup.ini", QSettings::IniFormat);
  int autoAccept = settings.value("local/Auto-Accept").toInt();
  if(autoAccept == 1)
  {
    qDebug() << "Incoming call auto-accpeted!";
    userAcceptsCall(sessionID);
    states_[sessionID] = CALLNEGOTIATING;
    return true;
  }
  else
  {
    window_.displayIncomingCall(sessionID, caller);
    states_[sessionID] = CALLRINGINGWITHUS;
  }
  return false;
}

void CallManager::callRinging(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end() && states_[sessionID] == CALLINGTHEM)
  {
    qDebug() << "Our call is ringing!";
    window_.displayRinging(sessionID);
    states_[sessionID] = CALLRINGINWITHTHEM;
  }
  else
  {
    qDebug() << "PEER ERROR: Got call ringing for nonexisting call:" << sessionID;
  }
}

void CallManager::peerAccepted(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end())
  {
    if(states_[sessionID] == CALLRINGINWITHTHEM || true)
    {
      qDebug() << "They accepted our call!";
      states_[sessionID] = CALLNEGOTIATING;
    }
    else
    {
      qDebug() << "PEER ERROR: Got an accepted call even though we have not yet called them!";
    }
  }
  else
  {
    qDebug() << "ERROR: Peer accepted a session which is not in Call manager";
  }
}

void CallManager::peerRejected(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end())
  {
    if(states_[sessionID] == CALLRINGINWITHTHEM)
    {
      qDebug() << "Our call has been rejected!";
      removeSession(sessionID);
    }
    else
    {
      qDebug() << "PEER ERROR: Got reject when we weren't calling them:" << states_[sessionID];
    }
  }
  else
  {
    qDebug() << "PEER ERROR: Got reject for nonexisting call:" << sessionID;
    qDebug() << "Number of ongoing sessions:" << states_.size();
  }
}

void CallManager::callNegotiated(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end())
  {
    if(states_[sessionID] == CALLNEGOTIATING || true)
    {
      qDebug() << "Call has been agreed upon with peer:" << sessionID;

      window_.addVideoStream(sessionID);

      std::shared_ptr<SDPMessageInfo> localSDP;
      std::shared_ptr<SDPMessageInfo> remoteSDP;

      sip_.getSDPs(sessionID,
                   localSDP,
                   remoteSDP);

      if(localSDP == nullptr || remoteSDP == nullptr)
      {
        return;
      }

      media_.addParticipant(sessionID, remoteSDP, localSDP);
      states_[sessionID] = CALLONGOING;
    }
    else
    {
       qDebug() << "PEER ERROR: Got call successful negotiation even though we are not there yet:" << states_[sessionID];
    }
  }
  else
  {
     qDebug() << "ERROR: This session does not exist in Call manager";
  }
}

void CallManager::callNegotiationFailed(uint32_t sessionID)
{
  // TODO: display a proper error for the user
  peerRejected(sessionID);
}

void CallManager::cancelIncomingCall(uint32_t sessionID)
{
  // TODO: display a proper message to the user that peer has cancelled their call
  removeSession(sessionID);
}

void CallManager::endCall(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end()
     && states_[sessionID] == CALLONGOING)
  {
    media_.removeParticipant(sessionID);
  }
  removeSession(sessionID);
}

void CallManager::registeredToServer()
{
  qDebug() << "Got info, that we have been registered to SIP server.";
  // TODO: indicate to user in some small detail
}

void CallManager::registeringFailed()
{
  qDebug() << "Failed to register";
  // TODO: indicate error to user
}

void CallManager::updateSettings()
{
  media_.updateSettings();
  //sip_.updateSettings(); // for blocking list
}

void CallManager::userAcceptsCall(uint32_t sessionID)
{
  qDebug() << "Sending accept";
  sip_.acceptCall(sessionID);
  states_[sessionID] = CALLNEGOTIATING;
}

void CallManager::userRejectsCall(uint32_t sessionID)
{
  qDebug() << "We have rejected their call";
  sip_.rejectCall(sessionID);
  removeSession(sessionID);
}

void CallManager::userCancelsCall(uint32_t sessionID)
{
  qDebug() << "We have cancelled our call";
  sip_.cancelCall(sessionID);
  removeSession(sessionID);
}

void CallManager::endTheCall()
{
  qDebug() << "Ending all calls";
  sip_.endAllCalls();
  media_.endAllCalls();
  window_.clearConferenceView();

  states_.clear();
}

void CallManager::micState()
{
  window_.setMicState(media_.toggleMic());
}

void CallManager::cameraState()
{
  window_.setCameraState(media_.toggleCamera());
}

void CallManager::removeSession(uint32_t sessionID)
{
  window_.removeParticipant(sessionID);

  auto it = states_.find(sessionID);
  if(it != states_.end())
  {
    states_.erase(it);
  }
}
<|endoftext|>


<commit_before>#include "can/canread.h"
#include <stdlib.h>
#include "util/log.h"
#include "util/timer.h"

using openxc::util::bitfield::getBitField;
using openxc::can::lookupMessage;

namespace time = openxc::util::time;

const char openxc::can::read::ID_FIELD_NAME[] = "id";
const char openxc::can::read::DATA_FIELD_NAME[] = "data";
const char openxc::can::read::NAME_FIELD_NAME[] = "name";
const char openxc::can::read::VALUE_FIELD_NAME[] = "value";
const char openxc::can::read::EVENT_FIELD_NAME[] = "event";

/* Private: Serialize the root JSON object to a string (ending with a newline)
 * and send it to the pipeline.
 *
 * root - The JSON object to send.
 * pipeline - The pipeline to send on.
 */
void sendJSON(cJSON* root, Pipeline* pipeline) {
    if(root == NULL) {
        debug("JSON object is NULL -- probably OOM");
    } else {
        char* message = cJSON_PrintUnformatted(root);
        sendMessage(pipeline, (uint8_t*) message, strlen(message));
        cJSON_Delete(root);
        free(message);
    }
}

/* Private: Combine the given name and value into a JSON object (conforming to
 * the OpenXC standard) and send it out to the pipeline.
 *
 * name - The value for the name field of the OpenXC message.
 * value - The numerical, string or booelan for the value field of the OpenXC
 *     message.
 * event - (Optional) The event for the event field of the OpenXC message.
 * pipeline - The pipeline to send on.
 */
void sendJSONMessage(const char* name, cJSON* value, cJSON* event,
        Pipeline* pipeline) {
    using openxc::can::read::NAME_FIELD_NAME;
    using openxc::can::read::VALUE_FIELD_NAME;
    using openxc::can::read::EVENT_FIELD_NAME;

    cJSON *root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, NAME_FIELD_NAME, name);
    cJSON_AddItemToObject(root, VALUE_FIELD_NAME, value);
    if(event != NULL) {
        cJSON_AddItemToObject(root, EVENT_FIELD_NAME, event);
    }
    sendJSON(root, pipeline);
}

float openxc::can::read::preTranslate(CanSignal* signal, uint64_t data, bool* send) {
    float value = decodeSignal(signal, data);

    if(time::shouldTick(&signal->frequencyClock) ||
            (value != signal->lastValue && signal->forceSendChanged)) {
        if(send && (!signal->received || signal->sendSame ||
                    value != signal->lastValue)) {
            signal->received = true;
        } else {
            *send = false;
        }
    } else {
        *send = false;
    }
    return value;
}

void openxc::can::read::postTranslate(CanSignal* signal, float value) {
    signal->lastValue = value;
}

float openxc::can::read::decodeSignal(CanSignal* signal, uint64_t data) {
    uint64_t rawValue = getBitField(data, signal->bitPosition,
            signal->bitSize, true);
    return rawValue * signal->factor + signal->offset;
}

float openxc::can::read::passthroughHandler(CanSignal* signal,
        CanSignal* signals, int signalCount, float value, bool* send) {
    return value;
}

bool openxc::can::read::booleanHandler(CanSignal* signal, CanSignal* signals, int signalCount,
        float value, bool* send) {
    return value == 0.0 ? false : true;
}

float openxc::can::read::ignoreHandler(CanSignal* signal, CanSignal* signals, int signalCount,
        float value, bool* send) {
    *send = false;
    return value;
}

const char* openxc::can::read::stateHandler(CanSignal* signal, CanSignal* signals,
        int signalCount, float value, bool* send) {
    const CanSignalState* signalState = lookupSignalState(value, signal, signals,
            signalCount);
    if(signalState != NULL) {
        return signalState->name;
    }
    *send = false;
    return NULL;
}

void openxc::can::read::sendNumericalMessage(const char* name, float value, Pipeline* pipeline) {
    sendJSONMessage(name, cJSON_CreateNumber(value), NULL, pipeline);
}

void openxc::can::read::sendBooleanMessage(const char* name, bool value, Pipeline* pipeline) {
    sendJSONMessage(name, cJSON_CreateBool(value), NULL, pipeline);
}

void openxc::can::read::sendStringMessage(const char* name, const char* value,
        Pipeline* pipeline) {
    sendJSONMessage(name, cJSON_CreateString(value), NULL, pipeline);
}

void openxc::can::read::sendEventedFloatMessage(const char* name, const char* value, float event,
        Pipeline* pipeline) {
    sendJSONMessage(name, cJSON_CreateString(value), cJSON_CreateNumber(event),
            pipeline);
}

void openxc::can::read::sendEventedBooleanMessage(const char* name, const char* value, bool event,
        Pipeline* pipeline) {
    sendJSONMessage(name, cJSON_CreateString(value), cJSON_CreateBool(event),
            pipeline);
}

void openxc::can::read::sendEventedStringMessage(const char* name, const char* value,
        const char* event, Pipeline* pipeline) {
    sendJSONMessage(name, cJSON_CreateString(value), cJSON_CreateString(event),
            pipeline);
}

void openxc::can::read::passthroughMessage(uint32_t id, uint64_t data,
        CanMessage* messages, int messageCount, Pipeline* pipeline) {
    bool send = false;
    CanMessage* message = NULL;
    if(messageCount > 0 && messages != NULL) {
        message = lookupMessage(id, messages, messageCount);
        if(message != NULL && (time::shouldTick(&message->frequencyClock) ||
                (data != message->lastValue && message->forceSendChanged))) {
            send = true;
        }
    } else {
        send = true;
    }

    if(send) {
        cJSON *root = cJSON_CreateObject();
        cJSON_AddNumberToObject(root, ID_FIELD_NAME, id);

        char encodedData[67];
        union {
            uint64_t whole;
            uint8_t bytes[8];
        } combined;
        combined.whole = data;

        sprintf(encodedData, "0x%02x%02x%02x%02x%02x%02x%02x%02x",
                combined.bytes[0],
                combined.bytes[1],
                combined.bytes[2],
                combined.bytes[3],
                combined.bytes[4],
                combined.bytes[5],
                combined.bytes[6],
                combined.bytes[7]);
        cJSON_AddStringToObject(root, DATA_FIELD_NAME, encodedData);

        sendJSON(root, pipeline);
    }

    if(message != NULL) {
        message->lastValue = data;
    }
}

void openxc::can::read::translateSignal(Pipeline* pipeline, CanSignal* signal,
        uint64_t data,
        float (*handler)(CanSignal*, CanSignal*, int, float, bool*),
        CanSignal* signals, int signalCount) {
    bool send = true;
    float value = preTranslate(signal, data, &send);
    float processedValue = handler(signal, signals, signalCount, value, &send);
    if(send) {
        sendNumericalMessage(signal->genericName, processedValue, pipeline);
    }
    postTranslate(signal, value);
}

void openxc::can::read::translateSignal(Pipeline* pipeline, CanSignal* signal,
        uint64_t data,
        const char* (*handler)(CanSignal*, CanSignal*, int, float, bool*),
        CanSignal* signals, int signalCount) {
    bool send = true;
    float value = preTranslate(signal, data, &send);
    const char* stringValue = handler(signal, signals, signalCount, value,
            &send);
    if(stringValue != NULL && send) {
        sendStringMessage(signal->genericName, stringValue, pipeline);
    }
    postTranslate(signal, value);
}

void openxc::can::read::translateSignal(Pipeline* pipeline, CanSignal* signal,
        uint64_t data,
        bool (*handler)(CanSignal*, CanSignal*, int, float, bool*),
        CanSignal* signals, int signalCount) {
    bool send = true;
    float value = preTranslate(signal, data, &send);
    bool booleanValue = handler(signal, signals, signalCount, value, &send);
    if(send) {
        sendBooleanMessage(signal->genericName, booleanValue, pipeline);
    }
    postTranslate(signal, value);
}

void openxc::can::read::translateSignal(Pipeline* pipeline, CanSignal* signal,
        uint64_t data, CanSignal* signals, int signalCount) {
    translateSignal(pipeline, signal, data, passthroughHandler, signals,
            signalCount);
}
<commit_msg>Check for errors when allocating JSON objects.<commit_after>#include "can/canread.h"
#include <stdlib.h>
#include "util/log.h"
#include "util/timer.h"

using openxc::util::bitfield::getBitField;
using openxc::can::lookupMessage;

namespace time = openxc::util::time;

const char openxc::can::read::ID_FIELD_NAME[] = "id";
const char openxc::can::read::DATA_FIELD_NAME[] = "data";
const char openxc::can::read::NAME_FIELD_NAME[] = "name";
const char openxc::can::read::VALUE_FIELD_NAME[] = "value";
const char openxc::can::read::EVENT_FIELD_NAME[] = "event";

/* Private: Serialize the root JSON object to a string (ending with a newline)
 * and send it to the pipeline.
 *
 * root - The JSON object to send.
 * pipeline - The pipeline to send on.
 */
void sendJSON(cJSON* root, Pipeline* pipeline) {
    if(root == NULL) {
        debug("JSON object is NULL -- probably OOM");
    } else {
        char* message = cJSON_PrintUnformatted(root);
        sendMessage(pipeline, (uint8_t*) message, strlen(message));
        cJSON_Delete(root);
        free(message);
    }
}

/* Private: Combine the given name and value into a JSON object (conforming to
 * the OpenXC standard) and send it out to the pipeline.
 *
 * name - The value for the name field of the OpenXC message.
 * value - The numerical, string or booelan for the value field of the OpenXC
 *     message.
 * event - (Optional) The event for the event field of the OpenXC message.
 * pipeline - The pipeline to send on.
 */
void sendJSONMessage(const char* name, cJSON* value, cJSON* event,
        Pipeline* pipeline) {
    using openxc::can::read::NAME_FIELD_NAME;
    using openxc::can::read::VALUE_FIELD_NAME;
    using openxc::can::read::EVENT_FIELD_NAME;

    cJSON *root = cJSON_CreateObject();
    if(root != NULL) {
        cJSON_AddStringToObject(root, NAME_FIELD_NAME, name);
        cJSON_AddItemToObject(root, VALUE_FIELD_NAME, value);
        if(event != NULL) {
            cJSON_AddItemToObject(root, EVENT_FIELD_NAME, event);
        }
        sendJSON(root, pipeline);
    } else {
        debug("Unable to allocate a cJSON object - probably OOM");
    }
}

float openxc::can::read::preTranslate(CanSignal* signal, uint64_t data, bool* send) {
    float value = decodeSignal(signal, data);

    if(time::shouldTick(&signal->frequencyClock) ||
            (value != signal->lastValue && signal->forceSendChanged)) {
        if(send && (!signal->received || signal->sendSame ||
                    value != signal->lastValue)) {
            signal->received = true;
        } else {
            *send = false;
        }
    } else {
        *send = false;
    }
    return value;
}

void openxc::can::read::postTranslate(CanSignal* signal, float value) {
    signal->lastValue = value;
}

float openxc::can::read::decodeSignal(CanSignal* signal, uint64_t data) {
    uint64_t rawValue = getBitField(data, signal->bitPosition,
            signal->bitSize, true);
    return rawValue * signal->factor + signal->offset;
}

float openxc::can::read::passthroughHandler(CanSignal* signal,
        CanSignal* signals, int signalCount, float value, bool* send) {
    return value;
}

bool openxc::can::read::booleanHandler(CanSignal* signal, CanSignal* signals, int signalCount,
        float value, bool* send) {
    return value == 0.0 ? false : true;
}

float openxc::can::read::ignoreHandler(CanSignal* signal, CanSignal* signals, int signalCount,
        float value, bool* send) {
    *send = false;
    return value;
}

const char* openxc::can::read::stateHandler(CanSignal* signal, CanSignal* signals,
        int signalCount, float value, bool* send) {
    const CanSignalState* signalState = lookupSignalState(value, signal, signals,
            signalCount);
    if(signalState != NULL) {
        return signalState->name;
    }
    *send = false;
    return NULL;
}

void openxc::can::read::sendNumericalMessage(const char* name, float value, Pipeline* pipeline) {
    sendJSONMessage(name, cJSON_CreateNumber(value), NULL, pipeline);
}

void openxc::can::read::sendBooleanMessage(const char* name, bool value, Pipeline* pipeline) {
    sendJSONMessage(name, cJSON_CreateBool(value), NULL, pipeline);
}

void openxc::can::read::sendStringMessage(const char* name, const char* value,
        Pipeline* pipeline) {
    sendJSONMessage(name, cJSON_CreateString(value), NULL, pipeline);
}

void openxc::can::read::sendEventedFloatMessage(const char* name, const char* value, float event,
        Pipeline* pipeline) {
    sendJSONMessage(name, cJSON_CreateString(value), cJSON_CreateNumber(event),
            pipeline);
}

void openxc::can::read::sendEventedBooleanMessage(const char* name, const char* value, bool event,
        Pipeline* pipeline) {
    sendJSONMessage(name, cJSON_CreateString(value), cJSON_CreateBool(event),
            pipeline);
}

void openxc::can::read::sendEventedStringMessage(const char* name, const char* value,
        const char* event, Pipeline* pipeline) {
    sendJSONMessage(name, cJSON_CreateString(value), cJSON_CreateString(event),
            pipeline);
}

void openxc::can::read::passthroughMessage(uint32_t id, uint64_t data,
        CanMessage* messages, int messageCount, Pipeline* pipeline) {
    bool send = false;
    CanMessage* message = NULL;
    if(messageCount > 0 && messages != NULL) {
        message = lookupMessage(id, messages, messageCount);
        if(message != NULL && (time::shouldTick(&message->frequencyClock) ||
                (data != message->lastValue && message->forceSendChanged))) {
            send = true;
        }
    } else {
        send = true;
    }

    if(send) {
        cJSON *root = cJSON_CreateObject();
        cJSON_AddNumberToObject(root, ID_FIELD_NAME, id);

        char encodedData[67];
        union {
            uint64_t whole;
            uint8_t bytes[8];
        } combined;
        combined.whole = data;

        sprintf(encodedData, "0x%02x%02x%02x%02x%02x%02x%02x%02x",
                combined.bytes[0],
                combined.bytes[1],
                combined.bytes[2],
                combined.bytes[3],
                combined.bytes[4],
                combined.bytes[5],
                combined.bytes[6],
                combined.bytes[7]);
        cJSON_AddStringToObject(root, DATA_FIELD_NAME, encodedData);

        sendJSON(root, pipeline);
    }

    if(message != NULL) {
        message->lastValue = data;
    }
}

void openxc::can::read::translateSignal(Pipeline* pipeline, CanSignal* signal,
        uint64_t data,
        float (*handler)(CanSignal*, CanSignal*, int, float, bool*),
        CanSignal* signals, int signalCount) {
    bool send = true;
    float value = preTranslate(signal, data, &send);
    float processedValue = handler(signal, signals, signalCount, value, &send);
    if(send) {
        sendNumericalMessage(signal->genericName, processedValue, pipeline);
    }
    postTranslate(signal, value);
}

void openxc::can::read::translateSignal(Pipeline* pipeline, CanSignal* signal,
        uint64_t data,
        const char* (*handler)(CanSignal*, CanSignal*, int, float, bool*),
        CanSignal* signals, int signalCount) {
    bool send = true;
    float value = preTranslate(signal, data, &send);
    const char* stringValue = handler(signal, signals, signalCount, value,
            &send);
    if(stringValue != NULL && send) {
        sendStringMessage(signal->genericName, stringValue, pipeline);
    }
    postTranslate(signal, value);
}

void openxc::can::read::translateSignal(Pipeline* pipeline, CanSignal* signal,
        uint64_t data,
        bool (*handler)(CanSignal*, CanSignal*, int, float, bool*),
        CanSignal* signals, int signalCount) {
    bool send = true;
    float value = preTranslate(signal, data, &send);
    bool booleanValue = handler(signal, signals, signalCount, value, &send);
    if(send) {
        sendBooleanMessage(signal->genericName, booleanValue, pipeline);
    }
    postTranslate(signal, value);
}

void openxc::can::read::translateSignal(Pipeline* pipeline, CanSignal* signal,
        uint64_t data, CanSignal* signals, int signalCount) {
    translateSignal(pipeline, signal, data, passthroughHandler, signals,
            signalCount);
}
<|endoftext|>


<commit_before><commit_msg>Add BinaryIndexedTree test<commit_after><|endoftext|>


<commit_before><commit_msg>[axl_test] fix utf8 dfa/rdfa tables<commit_after><|endoftext|>


<commit_before><commit_msg>finish `isFulfilled` `isRejected` test cases<commit_after><|endoftext|>


<commit_before>// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "web_to_ccinput_handler_adapter.h"

#include "third_party/WebKit/Source/Platform/chromium/public/WebInputHandlerClient.h"

#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, cc_name) \
    COMPILE_ASSERT(int(WebKit::webkit_name) == int(cc::cc_name), mismatching_enums)

COMPILE_ASSERT_MATCHING_ENUM(WebInputHandlerClient::ScrollStatusOnMainThread, InputHandlerClient::ScrollOnMainThread);
COMPILE_ASSERT_MATCHING_ENUM(WebInputHandlerClient::ScrollStatusStarted, InputHandlerClient::ScrollStarted);
COMPILE_ASSERT_MATCHING_ENUM(WebInputHandlerClient::ScrollStatusIgnored, InputHandlerClient::ScrollIgnored);
COMPILE_ASSERT_MATCHING_ENUM(WebInputHandlerClient::ScrollInputTypeGesture, InputHandlerClient::Gesture);
COMPILE_ASSERT_MATCHING_ENUM(WebInputHandlerClient::ScrollInputTypeWheel, InputHandlerClient::Wheel);

namespace WebKit {

scoped_ptr<WebToCCInputHandlerAdapter> WebToCCInputHandlerAdapter::create(scoped_ptr<WebInputHandler> handler)
{
    return scoped_ptr<WebToCCInputHandlerAdapter>(new WebToCCInputHandlerAdapter(handler.Pass()));
}

WebToCCInputHandlerAdapter::WebToCCInputHandlerAdapter(scoped_ptr<WebInputHandler> handler)
    : m_handler(handler.Pass())
{
}

WebToCCInputHandlerAdapter::~WebToCCInputHandlerAdapter()
{
}

class WebToCCInputHandlerAdapter::ClientAdapter : public WebInputHandlerClient {
public:
    ClientAdapter(cc::InputHandlerClient* client)
        : m_client(client)
    {
    }

    virtual ~ClientAdapter()
    {
    }

    virtual ScrollStatus scrollBegin(WebPoint point, ScrollInputType type) OVERRIDE
    {
        return static_cast<WebInputHandlerClient::ScrollStatus>(m_client->scrollBegin(point, static_cast<cc::InputHandlerClient::ScrollInputType>(type)));
    }

    virtual void scrollBy(WebPoint point, WebSize offset)
    {
        scrollByIfPossible(point, offset);
    }

    virtual bool scrollByIfPossible(WebPoint point, WebSize offset)
    {
      return m_client->scrollBy(point, offset);
    }

    virtual void scrollEnd() OVERRIDE
    {
        m_client->scrollEnd();
    }

    virtual void pinchGestureBegin() OVERRIDE
    {
        m_client->pinchGestureBegin();
    }

    virtual void pinchGestureUpdate(float magnifyDelta, WebPoint anchor) OVERRIDE
    {
        m_client->pinchGestureUpdate(magnifyDelta, anchor);
    }

    virtual void pinchGestureEnd() OVERRIDE
    {
        m_client->pinchGestureEnd();
    }

    virtual void startPageScaleAnimation(WebSize targetPosition,
                                         bool anchorPoint,
                                         float pageScale,
                                         double startTimeSec,
                                         double durationSec) OVERRIDE
    {
        base::TimeTicks startTime = base::TimeTicks::FromInternalValue(startTimeSec * base::Time::kMicrosecondsPerSecond);
        base::TimeDelta duration = base::TimeDelta::FromMicroseconds(durationSec * base::Time::kMicrosecondsPerSecond);
        m_client->startPageScaleAnimation(targetPosition, anchorPoint, pageScale, startTime, duration);
    }

    virtual void scheduleAnimation() OVERRIDE
    {
        m_client->scheduleAnimation();
    }

    virtual bool haveTouchEventHandlersAt(WebPoint point)
    {
        return m_client->haveTouchEventHandlersAt(point);
    }

private:
    cc::InputHandlerClient* m_client;
};

void WebToCCInputHandlerAdapter::bindToClient(cc::InputHandlerClient* client)
{
    m_clientAdapter.reset(new ClientAdapter(client));
    m_handler->bindToClient(m_clientAdapter.get());
}

void WebToCCInputHandlerAdapter::animate(base::TimeTicks time)
{
    double monotonicTimeSeconds = (time - base::TimeTicks()).InSecondsF();
    m_handler->animate(monotonicTimeSeconds);
}

}  // namespace WebKit
<commit_msg>cc: Remove now-obsolete scrollBy and mark scrollByIfPossible as overriding.<commit_after>// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "web_to_ccinput_handler_adapter.h"

#include "third_party/WebKit/Source/Platform/chromium/public/WebInputHandlerClient.h"

#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, cc_name) \
    COMPILE_ASSERT(int(WebKit::webkit_name) == int(cc::cc_name), mismatching_enums)

COMPILE_ASSERT_MATCHING_ENUM(WebInputHandlerClient::ScrollStatusOnMainThread, InputHandlerClient::ScrollOnMainThread);
COMPILE_ASSERT_MATCHING_ENUM(WebInputHandlerClient::ScrollStatusStarted, InputHandlerClient::ScrollStarted);
COMPILE_ASSERT_MATCHING_ENUM(WebInputHandlerClient::ScrollStatusIgnored, InputHandlerClient::ScrollIgnored);
COMPILE_ASSERT_MATCHING_ENUM(WebInputHandlerClient::ScrollInputTypeGesture, InputHandlerClient::Gesture);
COMPILE_ASSERT_MATCHING_ENUM(WebInputHandlerClient::ScrollInputTypeWheel, InputHandlerClient::Wheel);

namespace WebKit {

scoped_ptr<WebToCCInputHandlerAdapter> WebToCCInputHandlerAdapter::create(scoped_ptr<WebInputHandler> handler)
{
    return scoped_ptr<WebToCCInputHandlerAdapter>(new WebToCCInputHandlerAdapter(handler.Pass()));
}

WebToCCInputHandlerAdapter::WebToCCInputHandlerAdapter(scoped_ptr<WebInputHandler> handler)
    : m_handler(handler.Pass())
{
}

WebToCCInputHandlerAdapter::~WebToCCInputHandlerAdapter()
{
}

class WebToCCInputHandlerAdapter::ClientAdapter : public WebInputHandlerClient {
public:
    ClientAdapter(cc::InputHandlerClient* client)
        : m_client(client)
    {
    }

    virtual ~ClientAdapter()
    {
    }

    virtual ScrollStatus scrollBegin(WebPoint point, ScrollInputType type) OVERRIDE
    {
        return static_cast<WebInputHandlerClient::ScrollStatus>(m_client->scrollBegin(point, static_cast<cc::InputHandlerClient::ScrollInputType>(type)));
    }

    virtual bool scrollByIfPossible(WebPoint point, WebSize offset) OVERRIDE
    {
      return m_client->scrollBy(point, offset);
    }

    virtual void scrollEnd() OVERRIDE
    {
        m_client->scrollEnd();
    }

    virtual void pinchGestureBegin() OVERRIDE
    {
        m_client->pinchGestureBegin();
    }

    virtual void pinchGestureUpdate(float magnifyDelta, WebPoint anchor) OVERRIDE
    {
        m_client->pinchGestureUpdate(magnifyDelta, anchor);
    }

    virtual void pinchGestureEnd() OVERRIDE
    {
        m_client->pinchGestureEnd();
    }

    virtual void startPageScaleAnimation(WebSize targetPosition,
                                         bool anchorPoint,
                                         float pageScale,
                                         double startTimeSec,
                                         double durationSec) OVERRIDE
    {
        base::TimeTicks startTime = base::TimeTicks::FromInternalValue(startTimeSec * base::Time::kMicrosecondsPerSecond);
        base::TimeDelta duration = base::TimeDelta::FromMicroseconds(durationSec * base::Time::kMicrosecondsPerSecond);
        m_client->startPageScaleAnimation(targetPosition, anchorPoint, pageScale, startTime, duration);
    }

    virtual void scheduleAnimation() OVERRIDE
    {
        m_client->scheduleAnimation();
    }

    virtual bool haveTouchEventHandlersAt(WebPoint point)
    {
        return m_client->haveTouchEventHandlersAt(point);
    }

private:
    cc::InputHandlerClient* m_client;
};

void WebToCCInputHandlerAdapter::bindToClient(cc::InputHandlerClient* client)
{
    m_clientAdapter.reset(new ClientAdapter(client));
    m_handler->bindToClient(m_clientAdapter.get());
}

void WebToCCInputHandlerAdapter::animate(base::TimeTicks time)
{
    double monotonicTimeSeconds = (time - base::TimeTicks()).InSecondsF();
    m_handler->animate(monotonicTimeSeconds);
}

}  // namespace WebKit
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/audio_coding/neteq4/tools/input_audio_file.h"

namespace webrtc {
namespace test {

InputAudioFile::InputAudioFile(const std::string file_name) {
  fp_ = fopen(file_name.c_str(), "rb");
}

InputAudioFile::~InputAudioFile() { fclose(fp_); }

bool InputAudioFile::Read(size_t samples, int16_t* destination) {
  if (!fp_) {
    return false;
  }
  size_t bytes_read = fread(destination, sizeof(int16_t), samples, fp_);
  if (bytes_read < samples) {
    // Rewind and read the missing sampels.
    rewind(fp_);
    size_t missing_samples = samples - bytes_read;
    if (fread(destination, sizeof(int16_t), missing_samples, fp_) <
        missing_samples) {
      // Could not read enough even after rewinding the file.
      return false;
    }
  }
  return true;
}

void InputAudioFile::DuplicateInterleaved(const int16_t* source, size_t samples,
                                          size_t channels,
                                          int16_t* destination) {
  for (size_t i = 0; i < samples; ++i) {
    for (size_t j = 0; j < channels; ++j) {
      destination[i * channels + j] = source[i];
    }
  }
}

}  // namespace test
}  // namespace webrtc
<commit_msg>Correcting two nits in InputAudioFile<commit_after>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/audio_coding/neteq4/tools/input_audio_file.h"

namespace webrtc {
namespace test {

InputAudioFile::InputAudioFile(const std::string file_name) {
  fp_ = fopen(file_name.c_str(), "rb");
}

InputAudioFile::~InputAudioFile() { fclose(fp_); }

bool InputAudioFile::Read(size_t samples, int16_t* destination) {
  if (!fp_) {
    return false;
  }
  size_t samples_read = fread(destination, sizeof(int16_t), samples, fp_);
  if (samples_read < samples) {
    // Rewind and read the missing samples.
    rewind(fp_);
    size_t missing_samples = samples - samples_read;
    if (fread(destination, sizeof(int16_t), missing_samples, fp_) <
        missing_samples) {
      // Could not read enough even after rewinding the file.
      return false;
    }
  }
  return true;
}

void InputAudioFile::DuplicateInterleaved(const int16_t* source, size_t samples,
                                          size_t channels,
                                          int16_t* destination) {
  for (size_t i = 0; i < samples; ++i) {
    for (size_t j = 0; j < channels; ++j) {
      destination[i * channels + j] = source[i];
    }
  }
}

}  // namespace test
}  // namespace webrtc
<|endoftext|>


<commit_before>//     Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_LEXER_HPP
#define TOML11_LEXER_HPP
#include "combinator.hpp"
#include <stdexcept>
#include <istream>
#include <sstream>
#include <fstream>

namespace toml
{
namespace detail
{

// these scans contents from current location in a container of char
// and extract a region that matches their own pattern.
// to see the implementation of each component, see combinator.hpp.

using lex_wschar  = either<character<' '>, character<'\t'>>;
using lex_ws      = repeat<lex_wschar, at_least<1>>;
using lex_newline = either<character<'\n'>,
                           sequence<character<'\r'>, character<'\n'>>>;
using lex_lower   = in_range<'a', 'z'>;
using lex_upper   = in_range<'A', 'Z'>;
using lex_alpha   = either<lex_lower, lex_upper>;
using lex_digit   = in_range<'0', '9'>;
using lex_nonzero = in_range<'1', '9'>;
using lex_oct_dig = in_range<'0', '7'>;
using lex_bin_dig = in_range<'0', '1'>;
using lex_hex_dig = either<lex_digit, in_range<'A', 'F'>, in_range<'a', 'f'>>;

using lex_hex_prefix = sequence<character<'0'>, character<'x'>>;
using lex_oct_prefix = sequence<character<'0'>, character<'o'>>;
using lex_bin_prefix = sequence<character<'0'>, character<'b'>>;
using lex_underscore = character<'_'>;
using lex_plus       = character<'+'>;
using lex_minus      = character<'-'>;
using lex_sign       = either<lex_plus, lex_minus>;

// digit | nonzero 1*(digit | _ digit)
using lex_unsigned_dec_int = either<sequence<lex_nonzero, repeat<
    either<lex_digit, sequence<lex_underscore, lex_digit>>, at_least<1>>>,
    lex_digit>;
// (+|-)? unsigned_dec_int
using lex_dec_int = sequence<maybe<lex_sign>, lex_unsigned_dec_int>;

// hex_prefix hex_dig *(hex_dig | _ hex_dig)
using lex_hex_int = sequence<lex_hex_prefix, sequence<lex_hex_dig, repeat<
    either<lex_hex_dig, sequence<lex_underscore, lex_hex_dig>>, unlimited>>>;
// oct_prefix oct_dig *(oct_dig | _ oct_dig)
using lex_oct_int = sequence<lex_oct_prefix, sequence<lex_oct_dig, repeat<
    either<lex_oct_dig, sequence<lex_underscore, lex_oct_dig>>, unlimited>>>;
// bin_prefix bin_dig *(bin_dig | _ bin_dig)
using lex_bin_int = sequence<lex_bin_prefix, sequence<lex_bin_dig, repeat<
    either<lex_bin_dig, sequence<lex_underscore, lex_bin_dig>>, unlimited>>>;

// (dec_int | hex_int | oct_int | bin_int)
using lex_integer = either<lex_bin_int, lex_oct_int, lex_hex_int, lex_dec_int>;

// ===========================================================================

using lex_inf = sequence<character<'i'>, character<'n'>, character<'f'>>;
using lex_nan = sequence<character<'n'>, character<'a'>, character<'n'>>;
using lex_special_float = sequence<maybe<lex_sign>, either<lex_inf, lex_nan>>;
using lex_exponent_part = sequence<either<character<'e'>, character<'E'>>, lex_dec_int>;

using lex_zero_prefixable_int = sequence<lex_digit, repeat<either<lex_digit,
      sequence<lex_underscore, lex_digit>>, unlimited>>;
using lex_fractional_part = sequence<character<'.'>, lex_zero_prefixable_int>;

using lex_float = either<lex_special_float,
      sequence<lex_dec_int, either<lex_exponent_part,
      sequence<lex_fractional_part, maybe<lex_exponent_part>>>>>;

// ===========================================================================

using lex_true = sequence<character<'t'>, character<'r'>,
                          character<'u'>, character<'e'>>;
using lex_false = sequence<character<'f'>, character<'a'>, character<'l'>,
                           character<'s'>, character<'e'>>;
using lex_boolean = either<lex_true, lex_false>;

// ===========================================================================

using lex_date_fullyear = repeat<lex_digit, exactly<4>>;
using lex_date_month    = repeat<lex_digit, exactly<2>>;
using lex_date_mday     = repeat<lex_digit, exactly<2>>;
using lex_time_delim    = either<character<'T'>, character<'t'>, character<' '>>;
using lex_time_hour     = repeat<lex_digit, exactly<2>>;
using lex_time_minute   = repeat<lex_digit, exactly<2>>;
using lex_time_second   = repeat<lex_digit, exactly<2>>;
using lex_time_secfrac  = sequence<character<'.'>,
                                   repeat<lex_digit, at_least<1>>>;

using lex_time_numoffset = sequence<either<character<'+'>, character<'-'>>,
                                    sequence<lex_time_hour, character<':'>,
                                             lex_time_minute>>;
using lex_time_offset = either<character<'Z'>, character<'z'>,
                               lex_time_numoffset>;

using lex_partial_time = sequence<lex_time_hour,   character<':'>,
                                  lex_time_minute, character<':'>,
                                  lex_time_second, maybe<lex_time_secfrac>>;
using lex_full_date    = sequence<lex_date_fullyear, character<'-'>,
                                  lex_date_month,    character<'-'>,
                                  lex_date_mday>;
using lex_full_time    = sequence<lex_partial_time, lex_time_offset>;

using lex_offset_date_time = sequence<lex_full_date, lex_time_delim, lex_full_time>;
using lex_local_date_time  = sequence<lex_full_date, lex_time_delim, lex_partial_time>;
using lex_local_date       = lex_full_date;
using lex_local_time       = lex_partial_time;

// ===========================================================================

using lex_quotation_mark  = character<'"'>;
using lex_basic_unescaped = exclude<either<in_range<0x00, 0x1F>,
                                           character<0x22>, character<0x5C>,
                                           character<0x7F>>>;
using lex_escape          = character<'\\'>;
using lex_escape_unicode_short = sequence<character<'u'>,
                                          repeat<lex_hex_dig, exactly<4>>>;
using lex_escape_unicode_long  = sequence<character<'U'>,
                                          repeat<lex_hex_dig, exactly<8>>>;
using lex_escape_seq_char = either<character<'"'>, character<'\\'>,
                                   character<'b'>, character<'f'>,
                                   character<'n'>, character<'r'>,
                                   character<'t'>,
                                   lex_escape_unicode_short,
                                   lex_escape_unicode_long
                                   >;
using lex_escaped      = sequence<lex_escape, lex_escape_seq_char>;
using lex_basic_char   = either<lex_basic_unescaped, lex_escaped>;
using lex_basic_string = sequence<lex_quotation_mark,
                                  repeat<lex_basic_char, unlimited>,
                                  lex_quotation_mark>;

using lex_ml_basic_string_delim = repeat<lex_quotation_mark, exactly<3>>;
using lex_ml_basic_unescaped    = exclude<either<in_range<0x00, 0x1F>,
                                                 character<0x5C>,
                                                 character<0x7F>,
                                                 lex_ml_basic_string_delim>>;

using lex_ml_basic_escaped_newline = sequence<
        lex_escape, maybe<lex_ws>, lex_newline,
        repeat<either<lex_ws, lex_newline>, unlimited>>;

using lex_ml_basic_char = either<lex_ml_basic_unescaped, lex_escaped>;
using lex_ml_basic_body = repeat<either<lex_ml_basic_char, lex_newline,
                                        lex_ml_basic_escaped_newline>,
                                 unlimited>;
using lex_ml_basic_string = sequence<lex_ml_basic_string_delim,
                                     lex_ml_basic_body,
                                     lex_ml_basic_string_delim>;

using lex_literal_char = exclude<either<in_range<0x00, 0x08>,
                                        in_range<0x10, 0x19>, character<0x27>>>;
using lex_apostrophe = character<'\''>;
using lex_literal_string = sequence<lex_apostrophe,
                                    repeat<lex_literal_char, unlimited>,
                                    lex_apostrophe>;

using lex_ml_literal_string_delim = repeat<lex_apostrophe, exactly<3>>;

using lex_ml_literal_char = exclude<either<in_range<0x00, 0x08>,
                                           in_range<0x10, 0x1F>,
                                           character<0x7F>,
                                           lex_ml_literal_string_delim>>;
using lex_ml_literal_body = repeat<either<lex_ml_literal_char, lex_newline>,
                                   unlimited>;
using lex_ml_literal_string = sequence<lex_ml_literal_string_delim,
                                       lex_ml_literal_body,
                                       lex_ml_literal_string_delim>;

using lex_string = either<lex_ml_basic_string,   lex_basic_string,
                          lex_ml_literal_string, lex_literal_string>;

// ===========================================================================

using lex_comment_start_symbol = character<'#'>;
using lex_non_eol = either<character<'\t'>, exclude<in_range<0x00, 0x19>>>;
using lex_comment = sequence<lex_comment_start_symbol,
                             repeat<lex_non_eol, unlimited>>;

using lex_dot_sep = sequence<maybe<lex_ws>, character<'.'>, maybe<lex_ws>>;

using lex_unquoted_key = repeat<either<lex_alpha, lex_digit,
                                       character<'-'>, character<'_'>>,
                                at_least<1>>;
using lex_quoted_key = either<lex_basic_string, lex_literal_string>;
using lex_simple_key = either<lex_unquoted_key, lex_quoted_key>;
using lex_dotted_key = sequence<lex_simple_key,
                                repeat<sequence<lex_dot_sep, lex_simple_key>,
                                       at_least<1>
                                       >
                                >;
using lex_key = either<lex_dotted_key, lex_simple_key>;

using lex_keyval_sep = sequence<maybe<lex_ws>,
                                character<'='>,
                                maybe<lex_ws>>;

using lex_std_table_open  = character<'['>;
using lex_std_table_close = character<']'>;
using lex_std_table       = sequence<lex_std_table_open,
                                     maybe<lex_ws>,
                                     lex_key,
                                     maybe<lex_ws>,
                                     lex_std_table_close>;

using lex_array_table_open  = sequence<lex_std_table_open,  lex_std_table_open>;
using lex_array_table_close = sequence<lex_std_table_close, lex_std_table_close>;
using lex_array_table       = sequence<lex_array_table_open,
                                       maybe<lex_ws>,
                                       lex_key,
                                       maybe<lex_ws>,
                                       lex_array_table_close>;

} // detail
} // toml
#endif // TOML_LEXER_HPP
<commit_msg>feat: allow raw tab characters in basic strings<commit_after>//     Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_LEXER_HPP
#define TOML11_LEXER_HPP
#include "combinator.hpp"
#include <stdexcept>
#include <istream>
#include <sstream>
#include <fstream>

namespace toml
{
namespace detail
{

// these scans contents from current location in a container of char
// and extract a region that matches their own pattern.
// to see the implementation of each component, see combinator.hpp.

using lex_wschar  = either<character<' '>, character<'\t'>>;
using lex_ws      = repeat<lex_wschar, at_least<1>>;
using lex_newline = either<character<'\n'>,
                           sequence<character<'\r'>, character<'\n'>>>;
using lex_lower   = in_range<'a', 'z'>;
using lex_upper   = in_range<'A', 'Z'>;
using lex_alpha   = either<lex_lower, lex_upper>;
using lex_digit   = in_range<'0', '9'>;
using lex_nonzero = in_range<'1', '9'>;
using lex_oct_dig = in_range<'0', '7'>;
using lex_bin_dig = in_range<'0', '1'>;
using lex_hex_dig = either<lex_digit, in_range<'A', 'F'>, in_range<'a', 'f'>>;

using lex_hex_prefix = sequence<character<'0'>, character<'x'>>;
using lex_oct_prefix = sequence<character<'0'>, character<'o'>>;
using lex_bin_prefix = sequence<character<'0'>, character<'b'>>;
using lex_underscore = character<'_'>;
using lex_plus       = character<'+'>;
using lex_minus      = character<'-'>;
using lex_sign       = either<lex_plus, lex_minus>;

// digit | nonzero 1*(digit | _ digit)
using lex_unsigned_dec_int = either<sequence<lex_nonzero, repeat<
    either<lex_digit, sequence<lex_underscore, lex_digit>>, at_least<1>>>,
    lex_digit>;
// (+|-)? unsigned_dec_int
using lex_dec_int = sequence<maybe<lex_sign>, lex_unsigned_dec_int>;

// hex_prefix hex_dig *(hex_dig | _ hex_dig)
using lex_hex_int = sequence<lex_hex_prefix, sequence<lex_hex_dig, repeat<
    either<lex_hex_dig, sequence<lex_underscore, lex_hex_dig>>, unlimited>>>;
// oct_prefix oct_dig *(oct_dig | _ oct_dig)
using lex_oct_int = sequence<lex_oct_prefix, sequence<lex_oct_dig, repeat<
    either<lex_oct_dig, sequence<lex_underscore, lex_oct_dig>>, unlimited>>>;
// bin_prefix bin_dig *(bin_dig | _ bin_dig)
using lex_bin_int = sequence<lex_bin_prefix, sequence<lex_bin_dig, repeat<
    either<lex_bin_dig, sequence<lex_underscore, lex_bin_dig>>, unlimited>>>;

// (dec_int | hex_int | oct_int | bin_int)
using lex_integer = either<lex_bin_int, lex_oct_int, lex_hex_int, lex_dec_int>;

// ===========================================================================

using lex_inf = sequence<character<'i'>, character<'n'>, character<'f'>>;
using lex_nan = sequence<character<'n'>, character<'a'>, character<'n'>>;
using lex_special_float = sequence<maybe<lex_sign>, either<lex_inf, lex_nan>>;
using lex_exponent_part = sequence<either<character<'e'>, character<'E'>>, lex_dec_int>;

using lex_zero_prefixable_int = sequence<lex_digit, repeat<either<lex_digit,
      sequence<lex_underscore, lex_digit>>, unlimited>>;
using lex_fractional_part = sequence<character<'.'>, lex_zero_prefixable_int>;

using lex_float = either<lex_special_float,
      sequence<lex_dec_int, either<lex_exponent_part,
      sequence<lex_fractional_part, maybe<lex_exponent_part>>>>>;

// ===========================================================================

using lex_true = sequence<character<'t'>, character<'r'>,
                          character<'u'>, character<'e'>>;
using lex_false = sequence<character<'f'>, character<'a'>, character<'l'>,
                           character<'s'>, character<'e'>>;
using lex_boolean = either<lex_true, lex_false>;

// ===========================================================================

using lex_date_fullyear = repeat<lex_digit, exactly<4>>;
using lex_date_month    = repeat<lex_digit, exactly<2>>;
using lex_date_mday     = repeat<lex_digit, exactly<2>>;
using lex_time_delim    = either<character<'T'>, character<'t'>, character<' '>>;
using lex_time_hour     = repeat<lex_digit, exactly<2>>;
using lex_time_minute   = repeat<lex_digit, exactly<2>>;
using lex_time_second   = repeat<lex_digit, exactly<2>>;
using lex_time_secfrac  = sequence<character<'.'>,
                                   repeat<lex_digit, at_least<1>>>;

using lex_time_numoffset = sequence<either<character<'+'>, character<'-'>>,
                                    sequence<lex_time_hour, character<':'>,
                                             lex_time_minute>>;
using lex_time_offset = either<character<'Z'>, character<'z'>,
                               lex_time_numoffset>;

using lex_partial_time = sequence<lex_time_hour,   character<':'>,
                                  lex_time_minute, character<':'>,
                                  lex_time_second, maybe<lex_time_secfrac>>;
using lex_full_date    = sequence<lex_date_fullyear, character<'-'>,
                                  lex_date_month,    character<'-'>,
                                  lex_date_mday>;
using lex_full_time    = sequence<lex_partial_time, lex_time_offset>;

using lex_offset_date_time = sequence<lex_full_date, lex_time_delim, lex_full_time>;
using lex_local_date_time  = sequence<lex_full_date, lex_time_delim, lex_partial_time>;
using lex_local_date       = lex_full_date;
using lex_local_time       = lex_partial_time;

// ===========================================================================

using lex_quotation_mark  = character<'"'>;
using lex_basic_unescaped = exclude<either<in_range<0x00, 0x08>, // 0x09 (tab)
                                           in_range<0x0a, 0x1F>, // is allowed
                                           character<0x22>, character<0x5C>,
                                           character<0x7F>>>;
using lex_escape          = character<'\\'>;
using lex_escape_unicode_short = sequence<character<'u'>,
                                          repeat<lex_hex_dig, exactly<4>>>;
using lex_escape_unicode_long  = sequence<character<'U'>,
                                          repeat<lex_hex_dig, exactly<8>>>;
using lex_escape_seq_char = either<character<'"'>, character<'\\'>,
                                   character<'b'>, character<'f'>,
                                   character<'n'>, character<'r'>,
                                   character<'t'>,
                                   lex_escape_unicode_short,
                                   lex_escape_unicode_long
                                   >;
using lex_escaped      = sequence<lex_escape, lex_escape_seq_char>;
using lex_basic_char   = either<lex_basic_unescaped, lex_escaped>;
using lex_basic_string = sequence<lex_quotation_mark,
                                  repeat<lex_basic_char, unlimited>,
                                  lex_quotation_mark>;

using lex_ml_basic_string_delim = repeat<lex_quotation_mark, exactly<3>>;
using lex_ml_basic_unescaped    = exclude<either<in_range<0x00, 0x08>, // 0x09
                                                 in_range<0x0a, 0x1F>, // is tab
                                                 character<0x5C>,
                                                 character<0x7F>,
                                                 lex_ml_basic_string_delim>>;

using lex_ml_basic_escaped_newline = sequence<
        lex_escape, maybe<lex_ws>, lex_newline,
        repeat<either<lex_ws, lex_newline>, unlimited>>;

using lex_ml_basic_char = either<lex_ml_basic_unescaped, lex_escaped>;
using lex_ml_basic_body = repeat<either<lex_ml_basic_char, lex_newline,
                                        lex_ml_basic_escaped_newline>,
                                 unlimited>;
using lex_ml_basic_string = sequence<lex_ml_basic_string_delim,
                                     lex_ml_basic_body,
                                     lex_ml_basic_string_delim>;

using lex_literal_char = exclude<either<in_range<0x00, 0x08>,
                                        in_range<0x10, 0x19>, character<0x27>>>;
using lex_apostrophe = character<'\''>;
using lex_literal_string = sequence<lex_apostrophe,
                                    repeat<lex_literal_char, unlimited>,
                                    lex_apostrophe>;

using lex_ml_literal_string_delim = repeat<lex_apostrophe, exactly<3>>;

using lex_ml_literal_char = exclude<either<in_range<0x00, 0x08>,
                                           in_range<0x10, 0x1F>,
                                           character<0x7F>,
                                           lex_ml_literal_string_delim>>;
using lex_ml_literal_body = repeat<either<lex_ml_literal_char, lex_newline>,
                                   unlimited>;
using lex_ml_literal_string = sequence<lex_ml_literal_string_delim,
                                       lex_ml_literal_body,
                                       lex_ml_literal_string_delim>;

using lex_string = either<lex_ml_basic_string,   lex_basic_string,
                          lex_ml_literal_string, lex_literal_string>;

// ===========================================================================

using lex_comment_start_symbol = character<'#'>;
using lex_non_eol = either<character<'\t'>, exclude<in_range<0x00, 0x19>>>;
using lex_comment = sequence<lex_comment_start_symbol,
                             repeat<lex_non_eol, unlimited>>;

using lex_dot_sep = sequence<maybe<lex_ws>, character<'.'>, maybe<lex_ws>>;

using lex_unquoted_key = repeat<either<lex_alpha, lex_digit,
                                       character<'-'>, character<'_'>>,
                                at_least<1>>;
using lex_quoted_key = either<lex_basic_string, lex_literal_string>;
using lex_simple_key = either<lex_unquoted_key, lex_quoted_key>;
using lex_dotted_key = sequence<lex_simple_key,
                                repeat<sequence<lex_dot_sep, lex_simple_key>,
                                       at_least<1>
                                       >
                                >;
using lex_key = either<lex_dotted_key, lex_simple_key>;

using lex_keyval_sep = sequence<maybe<lex_ws>,
                                character<'='>,
                                maybe<lex_ws>>;

using lex_std_table_open  = character<'['>;
using lex_std_table_close = character<']'>;
using lex_std_table       = sequence<lex_std_table_open,
                                     maybe<lex_ws>,
                                     lex_key,
                                     maybe<lex_ws>,
                                     lex_std_table_close>;

using lex_array_table_open  = sequence<lex_std_table_open,  lex_std_table_open>;
using lex_array_table_close = sequence<lex_std_table_close, lex_std_table_close>;
using lex_array_table       = sequence<lex_array_table_open,
                                       maybe<lex_ws>,
                                       lex_key,
                                       maybe<lex_ws>,
                                       lex_array_table_close>;

} // detail
} // toml
#endif // TOML_LEXER_HPP
<|endoftext|>


<commit_before>#include "kyheader.h"
#include "Objectness.h"
#include "ValStructVec.h"
#include "CmShow.h"

void RunObjectness(CStr &resName, double base, int W, int NSS, int numPerSz);

void illutrateLoG()
{
    for (float delta = 0.5f; delta < 1.1f; delta+=0.1f){
        Mat f = Objectness::aFilter(delta, 8);
        normalize(f, f, 0, 1, NORM_MINMAX);
        CmShow::showTinyMat(format("D=%g", delta), f);
    }
    waitKey(0);
}

int main(int argc, char* argv[])
{
    //CStr wkDir = "D:/WkDir/DetectionProposals/VOC2007/Local/";
    //illutrateLoG();
    //RunObjectness("WinRecall.m", 2, 8, 2, 130);
    //RunObjectness("WinRecall.m", 2, 8, 2, 130);
    RunObjectness("WinRecall.m", 2, 8, 2, 130);
    //RunObjectness("WinRecall.m", 2, 8, 2, 130);
    //RunObjectness("WinRecall.m", 2, 8, 2, 130);

    return 0;
}

void RunObjectness(CStr &resName, double base, int W, int NSS, int numPerSz)
{
    srand((unsigned int)time(NULL));
    //DataSetVOC voc2007("/home/bittnt/BING/BING_beta1/VOC/VOC2007/");
    DataSetVOC voc2007("/home/lin/data/VOCdevkit2007/VOC2007/");
    voc2007.loadAnnotations();
    //voc2007.loadDataGenericOverCls();

    printf("Dataset:`%s' with %d training and %d testing\n", _S(voc2007.wkDir), voc2007.trainNum, voc2007.testNum);
    printf("%s Base = %g, W = %d, NSS = %d, perSz = %d\n", _S(resName), base, W, NSS, numPerSz);

    Objectness objNess(&voc2007, base, W, NSS);

    vector<vector<Vec4i>> boxesTests;
    //objNess.getObjBndBoxesForTests(boxesTests, 250);
    objNess.getObjBndBoxesForTestsFast(boxesTests, numPerSz);
    //objNess.getRandomBoxes(boxesTests);

    //objNess.evaluatePerClassRecall(boxesTests, resName, 1000);
    //objNess.illuTestReults(boxesTests);
    //objNess.evaluatePAMI12();
    //objNess.evaluateIJCV13();
}
<commit_msg>Add tool to predict cusotmer image<commit_after>#include "kyheader.h"
#include "Objectness.h"
#include "ValStructVec.h"
#include "CmShow.h"

void RunObjectness(CStr &resName, double base, int W, int NSS, int numPerSz);

void illutrateLoG()
{
    for (float delta = 0.5f; delta < 1.1f; delta+=0.1f){
        Mat f = Objectness::aFilter(delta, 8);
        normalize(f, f, 0, 1, NORM_MINMAX);
        CmShow::showTinyMat(format("D=%g", delta), f);
    }
    waitKey(0);
}

inline bool check_exists(const std::string & name) {
    struct stat buffer;
    return (stat (name.c_str() , &buffer) == 0);
}

void writeBoxesToFile(std::string const& textFileName, ValStructVec<float, Vec4i> const& bboxes)
{
    std::ofstream f(textFileName.c_str());
    if (f.is_open() == false) {
        std::cerr << "Error: failed to open " << textFileName << std::endl;
    }
    f << bboxes.size() << std::endl;
    for (int j = 0; j < bboxes.size(); j++) {
        f << bboxes[j][0] << " " << bboxes[j][1] << " " << bboxes[j][2] << " " << bboxes[j][3] << std::endl;
    }
    f.close();
}

void print_help(const string &program_name)
{
    printf("Usage: %s baseImageDir -f imageNameList -w\n", program_name.c_str());
    exit(1);
}

void RunCustomerImages(int argc, char* argv[])
{
    string baseImageDir;
    string imageNameListFullPath;
    bool overwrite = false;
    if (argc < 2 || argc > 5) {
        print_help(argv[0]);
    } else {
        baseImageDir = argv[1];
        for (int i = 2; i < argc; i++) {
            if (strcmp(argv[i], "-f") == 0) {
                if (i + 1 != argc) {
                    imageNameListFullPath = argv[i + 1];
                } else {
                    print_help(argv[0]);
                }
            } else if (strcmp(argv[i], "-w") == 0) {
                overwrite = true;
            }
        }
    }

    if (imageNameListFullPath.size() == 0) {
        imageNameListFullPath = baseImageDir + "/" + "imageNameList.txt";
    }

    cout << "baseImageDir = " << baseImageDir << endl;
    cout << "imageNameListFullPath = " << imageNameListFullPath << endl;
    cout << "overwrite = " << overwrite << endl;

    srand((unsigned int)time(NULL));
    DataSetVOC voc2007("/home/lin/data/VOCdevkit2007/VOC2007/");
    voc2007.loadAnnotations();
    double base = 2;
    int W = 8;
    int NSS = 2;
    int numPerSz = 100;
    printf("Dataset:`%s' with %d training and %d testing\n", _S(voc2007.wkDir), voc2007.trainNum, voc2007.testNum);
    printf("Base = %g, W = %d, NSS = %d, perSz = %d\n", base, W, NSS, numPerSz);
    Objectness objNess(&voc2007, base, W, NSS);
    //objNess.trainObjectness(numPerSz);
    objNess.loadTrainedModel();

    CmTimer tm("single");
    float total = 0.;
    vecS imageFileNames = CmFile::loadStrList(imageNameListFullPath);
    for (int i = 0; i < imageFileNames.size(); i++) {
        CStr fileNameFullPath = baseImageDir + "/" + imageFileNames[i];
        unsigned int fileNameEndLoc = fileNameFullPath.find_last_of('.');
        string outFileName = fileNameFullPath.substr(0, fileNameEndLoc) + "_bing_voc.txt";
        if (check_exists(outFileName) && ! overwrite) {
            continue;
        }
        //Mat img = imread("/workplace/linche/Logo/data/CamFind-Logo/converse/6_6895_6895645_image.jpg");
        Mat img = imread(fileNameFullPath);
        ValStructVec<float, Vec4i> bboxes;
        tm.Start();
        objNess.getObjBndBoxes(img, bboxes, numPerSz);
        tm.Stop();
        total += tm.TimeInSeconds();
        clock_t end_time = clock();
        cout << "[" << i << "/" << imageFileNames.size() << "]" << fileNameFullPath << ":" << bboxes.size() << " regions detected using " << tm.TimeInSeconds() << "s" << endl;
        writeBoxesToFile(outFileName, bboxes);
        /*
        for (int j = 0; j < bboxes.size(); j++) {
            Rect current(Point2i(bboxes[j][0], bboxes[j][1]), Point2i(bboxes[j][2], bboxes[j][3]));
            rectangle(img, current, Scalar(255, 0, 0), 1);
            imshow("query", img);
            waitKey(0);
        }
        */
    }
    cout << "average time per image = " << total / imageFileNames.size() << "s" << endl;
}

int main(int argc, char* argv[])
{
    //CStr wkDir = "D:/WkDir/DetectionProposals/VOC2007/Local/";
    //illutrateLoG();
    //RunObjectness("WinRecall.m", 2, 8, 2, 130);
    RunCustomerImages(argc, argv);
    return 0;
}

void RunObjectness(CStr &resName, double base, int W, int NSS, int numPerSz)
{
    srand((unsigned int)time(NULL));
    //DataSetVOC voc2007("/home/bittnt/BING/BING_beta1/VOC/VOC2007/");
    DataSetVOC voc2007("/home/lin/data/VOCdevkit2007/VOC2007/");
    voc2007.loadAnnotations();
    //voc2007.loadDataGenericOverCls();

    printf("Dataset:`%s' with %d training and %d testing\n", _S(voc2007.wkDir), voc2007.trainNum, voc2007.testNum);
    printf("%s Base = %g, W = %d, NSS = %d, perSz = %d\n", _S(resName), base, W, NSS, numPerSz);

    Objectness objNess(&voc2007, base, W, NSS);

    vector<vector<Vec4i> > boxesTests;
    //objNess.getObjBndBoxesForTests(boxesTests, 250);
    objNess.getObjBndBoxesForTestsFast(boxesTests, numPerSz);
    //objNess.getRandomBoxes(boxesTests);

    //objNess.evaluatePerClassRecall(boxesTests, resName, 1000);
    //objNess.illuTestReults(boxesTests);
    //objNess.evaluatePAMI12();
    //objNess.evaluateIJCV13();
}
<|endoftext|>