Wrap flipper client methods to avoid crash
Summary: Wraps flipper client methods to avoid crash. Also added a tests which makes sure that malcious plugin cannot cause a crash Reviewed By: jknoxville Differential Revision: D13153277 fbshipit-source-id: ac21731fa3c4eb447f189e61f61b9e83aad91e13
This commit is contained in:
committed by
Facebook Github Bot
parent
37c973d0c9
commit
bf3be3e16c
@@ -1,23 +1,22 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-present, Facebook, Inc.
|
* Copyright (c) Facebook, Inc.
|
||||||
*
|
*
|
||||||
* This source code is licensed under the MIT license found in the LICENSE
|
* This source code is licensed under the MIT license found in the LICENSE
|
||||||
* file in the root directory of this source tree.
|
* file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "FlipperClient.h"
|
#include "FlipperClient.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
#include "ConnectionContextStore.h"
|
||||||
#include "FlipperConnectionImpl.h"
|
#include "FlipperConnectionImpl.h"
|
||||||
|
#include "FlipperConnectionManagerImpl.h"
|
||||||
#include "FlipperResponderImpl.h"
|
#include "FlipperResponderImpl.h"
|
||||||
#include "FlipperState.h"
|
#include "FlipperState.h"
|
||||||
#include "FlipperStep.h"
|
#include "FlipperStep.h"
|
||||||
#include "FlipperConnectionManagerImpl.h"
|
|
||||||
#include "ConnectionContextStore.h"
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include <vector>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#if FB_SONARKIT_ENABLED
|
#if FB_SONARKIT_ENABLED
|
||||||
|
|
||||||
@@ -31,8 +30,10 @@ using folly::dynamic;
|
|||||||
void FlipperClient::init(FlipperInitConfig config) {
|
void FlipperClient::init(FlipperInitConfig config) {
|
||||||
auto state = std::make_shared<FlipperState>();
|
auto state = std::make_shared<FlipperState>();
|
||||||
auto context = std::make_shared<ConnectionContextStore>(config.deviceData);
|
auto context = std::make_shared<ConnectionContextStore>(config.deviceData);
|
||||||
kInstance =
|
kInstance = new FlipperClient(
|
||||||
new FlipperClient(std::make_unique<FlipperConnectionManagerImpl>(std::move(config), state, context), state);
|
std::make_unique<FlipperConnectionManagerImpl>(
|
||||||
|
std::move(config), state, context),
|
||||||
|
state);
|
||||||
}
|
}
|
||||||
|
|
||||||
FlipperClient* FlipperClient::instance() {
|
FlipperClient* FlipperClient::instance() {
|
||||||
@@ -41,16 +42,18 @@ FlipperClient* FlipperClient::instance() {
|
|||||||
|
|
||||||
void FlipperClient::setStateListener(
|
void FlipperClient::setStateListener(
|
||||||
std::shared_ptr<FlipperStateUpdateListener> stateListener) {
|
std::shared_ptr<FlipperStateUpdateListener> stateListener) {
|
||||||
log("Setting state listener");
|
performAndReportError([this, &stateListener]() {
|
||||||
flipperState_->setUpdateListener(stateListener);
|
log("Setting state listener");
|
||||||
|
flipperState_->setUpdateListener(stateListener);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperClient::addPlugin(std::shared_ptr<FlipperPlugin> plugin) {
|
void FlipperClient::addPlugin(std::shared_ptr<FlipperPlugin> plugin) {
|
||||||
log("FlipperClient::addPlugin " + plugin->identifier());
|
performAndReportError([this, plugin]() {
|
||||||
auto step = flipperState_->start("Add plugin " + plugin->identifier());
|
log("FlipperClient::addPlugin " + plugin->identifier());
|
||||||
|
auto step = flipperState_->start("Add plugin " + plugin->identifier());
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
performAndReportError([this, plugin, step]() {
|
|
||||||
if (plugins_.find(plugin->identifier()) != plugins_.end()) {
|
if (plugins_.find(plugin->identifier()) != plugins_.end()) {
|
||||||
throw std::out_of_range(
|
throw std::out_of_range(
|
||||||
"plugin " + plugin->identifier() + " already added.");
|
"plugin " + plugin->identifier() + " already added.");
|
||||||
@@ -64,10 +67,10 @@ void FlipperClient::addPlugin(std::shared_ptr<FlipperPlugin> plugin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FlipperClient::removePlugin(std::shared_ptr<FlipperPlugin> plugin) {
|
void FlipperClient::removePlugin(std::shared_ptr<FlipperPlugin> plugin) {
|
||||||
log("FlipperClient::removePlugin " + plugin->identifier());
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
|
||||||
performAndReportError([this, plugin]() {
|
performAndReportError([this, plugin]() {
|
||||||
|
log("FlipperClient::removePlugin " + plugin->identifier());
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
if (plugins_.find(plugin->identifier()) == plugins_.end()) {
|
if (plugins_.find(plugin->identifier()) == plugins_.end()) {
|
||||||
throw std::out_of_range("plugin " + plugin->identifier() + " not added.");
|
throw std::out_of_range("plugin " + plugin->identifier() + " not added.");
|
||||||
}
|
}
|
||||||
@@ -79,18 +82,20 @@ void FlipperClient::removePlugin(std::shared_ptr<FlipperPlugin> plugin) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperClient::startBackgroundPlugins() {
|
void FlipperClient::startBackgroundPlugins() {
|
||||||
std::cout << "Activating Background Plugins..." << std::endl;
|
std::cout << "Activating Background Plugins..." << std::endl;
|
||||||
for (std::map<std::string, std::shared_ptr<FlipperPlugin>>::iterator it=plugins_.begin(); it!=plugins_.end(); ++it) {
|
for (std::map<std::string, std::shared_ptr<FlipperPlugin>>::iterator it =
|
||||||
std::cout << it->first << std::endl;
|
plugins_.begin();
|
||||||
if (it->second.get()->runInBackground()) {
|
it != plugins_.end();
|
||||||
auto& conn = connections_[it->first];
|
++it) {
|
||||||
conn = std::make_shared<FlipperConnectionImpl>(socket_.get(),it->first);
|
std::cout << it->first << std::endl;
|
||||||
it->second.get()->didConnect(conn);
|
if (it->second.get()->runInBackground()) {
|
||||||
}
|
auto& conn = connections_[it->first];
|
||||||
|
conn = std::make_shared<FlipperConnectionImpl>(socket_.get(), it->first);
|
||||||
|
it->second.get()->didConnect(conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<FlipperPlugin> FlipperClient::getPlugin(
|
std::shared_ptr<FlipperPlugin> FlipperClient::getPlugin(
|
||||||
const std::string& identifier) {
|
const std::string& identifier) {
|
||||||
@@ -115,26 +120,28 @@ void FlipperClient::disconnect(std::shared_ptr<FlipperPlugin> plugin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FlipperClient::refreshPlugins() {
|
void FlipperClient::refreshPlugins() {
|
||||||
performAndReportError([this]() {
|
performAndReportError([this]() {
|
||||||
dynamic message = dynamic::object("method", "refreshPlugins");
|
dynamic message = dynamic::object("method", "refreshPlugins");
|
||||||
socket_->sendMessage(message);
|
socket_->sendMessage(message);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperClient::onConnected() {
|
void FlipperClient::onConnected() {
|
||||||
log("FlipperClient::onConnected");
|
performAndReportError([this]() {
|
||||||
|
log("FlipperClient::onConnected");
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
connected_ = true;
|
connected_ = true;
|
||||||
startBackgroundPlugins();
|
startBackgroundPlugins();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperClient::onDisconnected() {
|
void FlipperClient::onDisconnected() {
|
||||||
log("FlipperClient::onDisconnected");
|
performAndReportError([this]() {
|
||||||
auto step = flipperState_->start("Trigger onDisconnected callbacks");
|
log("FlipperClient::onDisconnected");
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
auto step = flipperState_->start("Trigger onDisconnected callbacks");
|
||||||
connected_ = false;
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
performAndReportError([this, step]() {
|
connected_ = false;
|
||||||
for (const auto& iter : plugins_) {
|
for (const auto& iter : plugins_) {
|
||||||
disconnect(iter.second);
|
disconnect(iter.second);
|
||||||
}
|
}
|
||||||
@@ -143,8 +150,8 @@ void FlipperClient::onDisconnected() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FlipperClient::onMessageReceived(const dynamic& message) {
|
void FlipperClient::onMessageReceived(const dynamic& message) {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
|
||||||
performAndReportError([this, &message]() {
|
performAndReportError([this, &message]() {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
const auto& method = message["method"];
|
const auto& method = message["method"];
|
||||||
const auto& params = message.getDefault("params");
|
const auto& params = message.getDefault("params");
|
||||||
|
|
||||||
@@ -174,7 +181,8 @@ void FlipperClient::onMessageReceived(const dynamic& message) {
|
|||||||
const auto plugin = plugins_.at(identifier);
|
const auto plugin = plugins_.at(identifier);
|
||||||
if (!plugin.get()->runInBackground()) {
|
if (!plugin.get()->runInBackground()) {
|
||||||
auto& conn = connections_[plugin->identifier()];
|
auto& conn = connections_[plugin->identifier()];
|
||||||
conn = std::make_shared<FlipperConnectionImpl>(socket_.get(), plugin->identifier());
|
conn = std::make_shared<FlipperConnectionImpl>(
|
||||||
|
socket_.get(), plugin->identifier());
|
||||||
plugin->didConnect(conn);
|
plugin->didConnect(conn);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -214,20 +222,28 @@ void FlipperClient::onMessageReceived(const dynamic& message) {
|
|||||||
responder->error(response);
|
responder->error(response);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperClient::performAndReportError(const std::function<void()>& func) {
|
void FlipperClient::performAndReportError(const std::function<void()>& func) {
|
||||||
|
#if FLIPPER_ENABLE_CRASH
|
||||||
|
// To debug the stack trace and an exception turn on the compiler flag
|
||||||
|
// FLIPPER_ENABLE_CRASH
|
||||||
|
func();
|
||||||
|
#else
|
||||||
try {
|
try {
|
||||||
func();
|
func();
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
dynamic message = dynamic::object(
|
dynamic message = dynamic::object(
|
||||||
"error",
|
"error", dynamic::object("message", e.what())("stacktrace", "<none>"));
|
||||||
dynamic::object("message", e.what())("stacktrace", "<none>"));
|
|
||||||
if (connected_) {
|
if (connected_) {
|
||||||
socket_->sendMessage(message);
|
socket_->sendMessage(message);
|
||||||
} else {
|
} else {
|
||||||
log("Error: " + std::string(e.what()));
|
log("Error: " + std::string(e.what()));
|
||||||
}
|
}
|
||||||
|
} catch (...) {
|
||||||
|
// Generic catch block for the exception of type not belonging to
|
||||||
|
// std::exception
|
||||||
|
log("Unknown error suppressed in FlipperClient");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FlipperClient::getState() {
|
std::string FlipperClient::getState() {
|
||||||
|
|||||||
@@ -1,22 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-present, Facebook, Inc.
|
* Copyright (c) Facebook, Inc.
|
||||||
*
|
*
|
||||||
* This source code is licensed under the MIT license found in the LICENSE
|
* This source code is licensed under the MIT license found in the LICENSE
|
||||||
* file in the root directory of this source tree.
|
* file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
#include "FlipperConnectionImpl.h"
|
#include "FlipperConnectionImpl.h"
|
||||||
|
#include "FlipperConnectionManager.h"
|
||||||
#include "FlipperInitConfig.h"
|
#include "FlipperInitConfig.h"
|
||||||
#include "FlipperPlugin.h"
|
#include "FlipperPlugin.h"
|
||||||
#include "FlipperState.h"
|
#include "FlipperState.h"
|
||||||
#include "FlipperConnectionManager.h"
|
|
||||||
#include <map>
|
|
||||||
#include <mutex>
|
|
||||||
#include "FlipperStep.h"
|
#include "FlipperStep.h"
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace facebook {
|
namespace facebook {
|
||||||
namespace flipper {
|
namespace flipper {
|
||||||
@@ -24,23 +23,26 @@ namespace flipper {
|
|||||||
class FlipperClient : public FlipperConnectionManager::Callbacks {
|
class FlipperClient : public FlipperConnectionManager::Callbacks {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Call before accessing instance with FlipperClient::instance(). This will set up
|
Call before accessing instance with FlipperClient::instance(). This will set
|
||||||
all the state needed to establish a Flipper connection.
|
up all the state needed to establish a Flipper connection.
|
||||||
*/
|
*/
|
||||||
static void init(FlipperInitConfig config);
|
static void init(FlipperInitConfig config);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Standard accessor for the shared FlipperClient instance. This returns a
|
Standard accessor for the shared FlipperClient instance. This returns a
|
||||||
singleton instance to a shared FlipperClient. First call to this function will
|
singleton instance to a shared FlipperClient. First call to this function
|
||||||
create the shared FlipperClient. Must call FlipperClient::initDeviceData() before
|
will create the shared FlipperClient. Must call
|
||||||
first call to FlipperClient::instance().
|
FlipperClient::initDeviceData() before first call to
|
||||||
|
FlipperClient::instance().
|
||||||
*/
|
*/
|
||||||
static FlipperClient* instance();
|
static FlipperClient* instance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Only public for testing
|
Only public for testing
|
||||||
*/
|
*/
|
||||||
FlipperClient(std::unique_ptr<FlipperConnectionManager> socket, std::shared_ptr<FlipperState> state)
|
FlipperClient(
|
||||||
|
std::unique_ptr<FlipperConnectionManager> socket,
|
||||||
|
std::shared_ptr<FlipperState> state)
|
||||||
: socket_(std::move(socket)), flipperState_(state) {
|
: socket_(std::move(socket)), flipperState_(state) {
|
||||||
auto step = flipperState_->start("Create client");
|
auto step = flipperState_->start("Create client");
|
||||||
socket_->setCallbacks(this);
|
socket_->setCallbacks(this);
|
||||||
@@ -48,15 +50,19 @@ class FlipperClient : public FlipperConnectionManager::Callbacks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
auto step = flipperState_->start("Start client");
|
performAndReportError([this]() {
|
||||||
socket_->start();
|
auto step = flipperState_->start("Start client");
|
||||||
step->complete();
|
socket_->start();
|
||||||
|
step->complete();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop() {
|
void stop() {
|
||||||
auto step = flipperState_->start("Stop client");
|
performAndReportError([this]() {
|
||||||
socket_->stop();
|
auto step = flipperState_->start("Stop client");
|
||||||
step->complete();
|
socket_->stop();
|
||||||
|
step->complete();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void onConnected() override;
|
void onConnected() override;
|
||||||
@@ -86,6 +92,7 @@ class FlipperClient : public FlipperConnectionManager::Callbacks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool hasPlugin(const std::string& identifier);
|
bool hasPlugin(const std::string& identifier);
|
||||||
|
void performAndReportError(const std::function<void()>& func);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static FlipperClient* instance_;
|
static FlipperClient* instance_;
|
||||||
@@ -96,7 +103,6 @@ class FlipperClient : public FlipperConnectionManager::Callbacks {
|
|||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
std::shared_ptr<FlipperState> flipperState_;
|
std::shared_ptr<FlipperState> flipperState_;
|
||||||
|
|
||||||
void performAndReportError(const std::function<void()>& func);
|
|
||||||
void disconnect(std::shared_ptr<FlipperPlugin> plugin);
|
void disconnect(std::shared_ptr<FlipperPlugin> plugin);
|
||||||
void startBackgroundPlugins();
|
void startBackgroundPlugins();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,25 +1,24 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-present, Facebook, Inc.
|
* Copyright (c) Facebook, Inc.
|
||||||
*
|
*
|
||||||
* This source code is licensed under the MIT license found in the LICENSE
|
* This source code is licensed under the MIT license found in the LICENSE
|
||||||
* file in the root directory of this source tree.
|
* file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "FlipperConnectionManagerImpl.h"
|
#include "FlipperConnectionManagerImpl.h"
|
||||||
#include "FlipperStep.h"
|
|
||||||
#include "ConnectionContextStore.h"
|
|
||||||
#include "Log.h"
|
|
||||||
#include <folly/String.h>
|
#include <folly/String.h>
|
||||||
#include <folly/futures/Future.h>
|
#include <folly/futures/Future.h>
|
||||||
|
#include <folly/io/async/AsyncSocketException.h>
|
||||||
#include <folly/io/async/SSLContext.h>
|
#include <folly/io/async/SSLContext.h>
|
||||||
#include <folly/json.h>
|
#include <folly/json.h>
|
||||||
#include <rsocket/Payload.h>
|
#include <rsocket/Payload.h>
|
||||||
#include <rsocket/RSocket.h>
|
#include <rsocket/RSocket.h>
|
||||||
#include <rsocket/transports/tcp/TcpConnectionFactory.h>
|
#include <rsocket/transports/tcp/TcpConnectionFactory.h>
|
||||||
#include <thread>
|
|
||||||
#include <folly/io/async/AsyncSocketException.h>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <thread>
|
||||||
|
#include "ConnectionContextStore.h"
|
||||||
|
#include "FlipperStep.h"
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
#define WRONG_THREAD_EXIT_MSG \
|
#define WRONG_THREAD_EXIT_MSG \
|
||||||
"ERROR: Aborting flipper initialization because it's not running in the flipper thread."
|
"ERROR: Aborting flipper initialization because it's not running in the flipper thread."
|
||||||
@@ -39,7 +38,8 @@ class ConnectionEvents : public rsocket::RSocketConnectionEvents {
|
|||||||
FlipperConnectionManagerImpl* websocket_;
|
FlipperConnectionManagerImpl* websocket_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConnectionEvents(FlipperConnectionManagerImpl* websocket) : websocket_(websocket) {}
|
ConnectionEvents(FlipperConnectionManagerImpl* websocket)
|
||||||
|
: websocket_(websocket) {}
|
||||||
|
|
||||||
void onConnected() {
|
void onConnected() {
|
||||||
websocket_->isOpen_ = true;
|
websocket_->isOpen_ = true;
|
||||||
@@ -79,11 +79,18 @@ class Responder : public rsocket::RSocketResponder {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
FlipperConnectionManagerImpl::FlipperConnectionManagerImpl(FlipperInitConfig config, std::shared_ptr<FlipperState> state, std::shared_ptr<ConnectionContextStore> contextStore)
|
FlipperConnectionManagerImpl::FlipperConnectionManagerImpl(
|
||||||
: deviceData_(config.deviceData), flipperState_(state), flipperEventBase_(config.callbackWorker), connectionEventBase_(config.connectionWorker), contextStore_(contextStore) {
|
FlipperInitConfig config,
|
||||||
CHECK_THROW(config.callbackWorker, std::invalid_argument);
|
std::shared_ptr<FlipperState> state,
|
||||||
CHECK_THROW(config.connectionWorker, std::invalid_argument);
|
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() {
|
FlipperConnectionManagerImpl::~FlipperConnectionManagerImpl() {
|
||||||
stop();
|
stop();
|
||||||
@@ -91,10 +98,14 @@ FlipperConnectionManagerImpl::~FlipperConnectionManagerImpl() {
|
|||||||
|
|
||||||
void FlipperConnectionManagerImpl::start() {
|
void FlipperConnectionManagerImpl::start() {
|
||||||
auto step = flipperState_->start("Start connection thread");
|
auto step = flipperState_->start("Start connection thread");
|
||||||
|
|
||||||
folly::makeFuture()
|
folly::makeFuture()
|
||||||
.via(flipperEventBase_->getEventBase())
|
.via(flipperEventBase_->getEventBase())
|
||||||
.delayed(std::chrono::milliseconds(0))
|
.delayed(std::chrono::milliseconds(0))
|
||||||
.thenValue([this, step](auto&&){ step->complete(); startSync();});
|
.thenValue([this, step](auto&&) {
|
||||||
|
step->complete();
|
||||||
|
startSync();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperConnectionManagerImpl::startSync() {
|
void FlipperConnectionManagerImpl::startSync() {
|
||||||
@@ -135,7 +146,6 @@ void FlipperConnectionManagerImpl::startSync() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FlipperConnectionManagerImpl::doCertificateExchange() {
|
void FlipperConnectionManagerImpl::doCertificateExchange() {
|
||||||
|
|
||||||
rsocket::SetupParameters parameters;
|
rsocket::SetupParameters parameters;
|
||||||
folly::SocketAddress address;
|
folly::SocketAddress address;
|
||||||
|
|
||||||
@@ -175,7 +185,8 @@ void FlipperConnectionManagerImpl::connectSecurely() {
|
|||||||
"device_id", deviceId)("app", deviceData_.app)));
|
"device_id", deviceId)("app", deviceData_.app)));
|
||||||
address.setFromHostPort(deviceData_.host, securePort);
|
address.setFromHostPort(deviceData_.host, securePort);
|
||||||
|
|
||||||
std::shared_ptr<folly::SSLContext> sslContext = contextStore_->getSSLContext();
|
std::shared_ptr<folly::SSLContext> sslContext =
|
||||||
|
contextStore_->getSSLContext();
|
||||||
auto connectingSecurely = flipperState_->start("Connect securely");
|
auto connectingSecurely = flipperState_->start("Connect securely");
|
||||||
connectionIsTrusted_ = true;
|
connectionIsTrusted_ = true;
|
||||||
client_ =
|
client_ =
|
||||||
@@ -198,7 +209,7 @@ void FlipperConnectionManagerImpl::reconnect() {
|
|||||||
folly::makeFuture()
|
folly::makeFuture()
|
||||||
.via(flipperEventBase_->getEventBase())
|
.via(flipperEventBase_->getEventBase())
|
||||||
.delayed(std::chrono::seconds(reconnectIntervalSeconds))
|
.delayed(std::chrono::seconds(reconnectIntervalSeconds))
|
||||||
.thenValue([this](auto&&){ startSync(); });
|
.thenValue([this](auto&&) { startSync(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperConnectionManagerImpl::stop() {
|
void FlipperConnectionManagerImpl::stop() {
|
||||||
@@ -240,7 +251,6 @@ void FlipperConnectionManagerImpl::sendMessage(const folly::dynamic& message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool FlipperConnectionManagerImpl::isCertificateExchangeNeeded() {
|
bool FlipperConnectionManagerImpl::isCertificateExchangeNeeded() {
|
||||||
|
|
||||||
if (failedConnectionAttempts_ >= 2) {
|
if (failedConnectionAttempts_ >= 2) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -258,59 +268,66 @@ void FlipperConnectionManagerImpl::requestSignedCertFromFlipper() {
|
|||||||
std::string csr = contextStore_->createCertificateSigningRequest();
|
std::string csr = contextStore_->createCertificateSigningRequest();
|
||||||
generatingCSR->complete();
|
generatingCSR->complete();
|
||||||
|
|
||||||
folly::dynamic message = folly::dynamic::object("method", "signCertificate")(
|
folly::dynamic message =
|
||||||
"csr", csr.c_str())("destination", contextStore_->getCertificateDirectoryPath().c_str());
|
folly::dynamic::object("method", "signCertificate")("csr", csr.c_str())(
|
||||||
|
"destination", contextStore_->getCertificateDirectoryPath().c_str());
|
||||||
auto gettingCert = flipperState_->start("Getting cert from desktop");
|
auto gettingCert = flipperState_->start("Getting cert from desktop");
|
||||||
|
|
||||||
flipperEventBase_->add([this, message, gettingCert]() {
|
flipperEventBase_->add([this, message, gettingCert]() {
|
||||||
client_->getRequester()
|
client_->getRequester()
|
||||||
->requestResponse(rsocket::Payload(folly::toJson(message)))
|
->requestResponse(rsocket::Payload(folly::toJson(message)))
|
||||||
->subscribe([this, gettingCert](rsocket::Payload p) {
|
->subscribe(
|
||||||
auto response = p.moveDataToString();
|
[this, gettingCert](rsocket::Payload p) {
|
||||||
if (!response.empty()) {
|
auto response = p.moveDataToString();
|
||||||
folly::dynamic config = folly::parseJson(response);
|
if (!response.empty()) {
|
||||||
contextStore_->storeConnectionConfig(config);
|
folly::dynamic config = folly::parseJson(response);
|
||||||
}
|
contextStore_->storeConnectionConfig(config);
|
||||||
gettingCert->complete();
|
}
|
||||||
log("Certificate exchange complete.");
|
gettingCert->complete();
|
||||||
// Disconnect after message sending is complete.
|
log("Certificate exchange complete.");
|
||||||
// This will trigger a reconnect which should use the secure channel.
|
// Disconnect after message sending is complete.
|
||||||
// TODO: Connect immediately, without waiting for reconnect
|
// This will trigger a reconnect which should use the secure
|
||||||
client_ = nullptr;
|
// channel.
|
||||||
},
|
// TODO: Connect immediately, without waiting for reconnect
|
||||||
[this, message](folly::exception_wrapper e) {
|
client_ = nullptr;
|
||||||
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](...) {
|
[this, message](folly::exception_wrapper e) {
|
||||||
log(("Error during certificate exchange:" + e.what()).c_str());
|
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;
|
failedConnectionAttempts_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperConnectionManagerImpl::sendLegacyCertificateRequest(folly::dynamic message) {
|
void FlipperConnectionManagerImpl::sendLegacyCertificateRequest(
|
||||||
|
folly::dynamic message) {
|
||||||
// Desktop is using an old version of Flipper.
|
// Desktop is using an old version of Flipper.
|
||||||
// Fall back to fireAndForget, instead of requestResponse.
|
// Fall back to fireAndForget, instead of requestResponse.
|
||||||
auto sendingRequest = flipperState_->start("Sending fallback certificate request");
|
auto sendingRequest =
|
||||||
|
flipperState_->start("Sending fallback certificate request");
|
||||||
client_->getRequester()
|
client_->getRequester()
|
||||||
->fireAndForget(rsocket::Payload(folly::toJson(message)))
|
->fireAndForget(rsocket::Payload(folly::toJson(message)))
|
||||||
->subscribe([this, sendingRequest]() {
|
->subscribe([this, sendingRequest]() {
|
||||||
sendingRequest->complete();
|
sendingRequest->complete();
|
||||||
folly::dynamic config = folly::dynamic::object();
|
folly::dynamic config = folly::dynamic::object();
|
||||||
contextStore_->storeConnectionConfig(config);
|
contextStore_->storeConnectionConfig(config);
|
||||||
client_ = nullptr;
|
client_ = nullptr;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlipperConnectionManagerImpl::isRunningInOwnThread() {
|
bool FlipperConnectionManagerImpl::isRunningInOwnThread() {
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <Flipper/FlipperClient.h>
|
#include <Flipper/FlipperClient.h>
|
||||||
#include <FlipperTestLib/FlipperPluginMock.h>
|
|
||||||
#include <FlipperTestLib/FlipperConnectionManagerMock.h>
|
#include <FlipperTestLib/FlipperConnectionManagerMock.h>
|
||||||
|
#include <FlipperTestLib/FlipperPluginMock.h>
|
||||||
|
|
||||||
#include <folly/json.h>
|
#include <folly/json.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
@@ -33,7 +33,8 @@ TEST(FlipperClientTests, testSaneMocks) {
|
|||||||
|
|
||||||
TEST(FlipperClientTests, testGetPlugins) {
|
TEST(FlipperClientTests, testGetPlugins) {
|
||||||
auto socket = new FlipperConnectionManagerMock;
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
FlipperClient client(std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
client.start();
|
client.start();
|
||||||
|
|
||||||
client.addPlugin(std::make_shared<FlipperPluginMock>("Cat"));
|
client.addPlugin(std::make_shared<FlipperPluginMock>("Cat"));
|
||||||
@@ -49,7 +50,8 @@ TEST(FlipperClientTests, testGetPlugins) {
|
|||||||
|
|
||||||
TEST(FlipperClientTests, testGetPlugin) {
|
TEST(FlipperClientTests, testGetPlugin) {
|
||||||
auto socket = new FlipperConnectionManagerMock;
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
FlipperClient client(std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
|
|
||||||
const auto catPlugin = std::make_shared<FlipperPluginMock>("Cat");
|
const auto catPlugin = std::make_shared<FlipperPluginMock>("Cat");
|
||||||
client.addPlugin(catPlugin);
|
client.addPlugin(catPlugin);
|
||||||
@@ -62,7 +64,8 @@ TEST(FlipperClientTests, testGetPlugin) {
|
|||||||
|
|
||||||
TEST(FlipperClientTests, testGetPluginWithDowncast) {
|
TEST(FlipperClientTests, testGetPluginWithDowncast) {
|
||||||
auto socket = new FlipperConnectionManagerMock;
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
FlipperClient client(std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
|
|
||||||
const auto catPlugin = std::make_shared<FlipperPluginMock>("Cat");
|
const auto catPlugin = std::make_shared<FlipperPluginMock>("Cat");
|
||||||
client.addPlugin(catPlugin);
|
client.addPlugin(catPlugin);
|
||||||
@@ -71,7 +74,8 @@ TEST(FlipperClientTests, testGetPluginWithDowncast) {
|
|||||||
|
|
||||||
TEST(FlipperClientTests, testRemovePlugin) {
|
TEST(FlipperClientTests, testRemovePlugin) {
|
||||||
auto socket = new FlipperConnectionManagerMock;
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
FlipperClient client(std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
client.start();
|
client.start();
|
||||||
|
|
||||||
auto plugin = std::make_shared<FlipperPluginMock>("Test");
|
auto plugin = std::make_shared<FlipperPluginMock>("Test");
|
||||||
@@ -88,7 +92,8 @@ TEST(FlipperClientTests, testRemovePlugin) {
|
|||||||
|
|
||||||
TEST(FlipperClientTests, testStartStop) {
|
TEST(FlipperClientTests, testStartStop) {
|
||||||
auto socket = new FlipperConnectionManagerMock;
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
FlipperClient client(std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
|
|
||||||
client.start();
|
client.start();
|
||||||
EXPECT_TRUE(socket->isOpen());
|
EXPECT_TRUE(socket->isOpen());
|
||||||
@@ -99,15 +104,16 @@ TEST(FlipperClientTests, testStartStop) {
|
|||||||
|
|
||||||
TEST(FlipperClientTests, testConnectDisconnect) {
|
TEST(FlipperClientTests, testConnectDisconnect) {
|
||||||
auto socket = new FlipperConnectionManagerMock;
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
FlipperClient client(std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
|
|
||||||
bool pluginConnected = false;
|
bool pluginConnected = false;
|
||||||
const auto connectionCallback = [&](std::shared_ptr<FlipperConnection> conn) {
|
const auto connectionCallback = [&](std::shared_ptr<FlipperConnection> conn) {
|
||||||
pluginConnected = true;
|
pluginConnected = true;
|
||||||
};
|
};
|
||||||
const auto disconnectionCallback = [&]() { pluginConnected = false; };
|
const auto disconnectionCallback = [&]() { pluginConnected = false; };
|
||||||
auto plugin = std::make_shared<FlipperPluginMock>("Test", connectionCallback,
|
auto plugin = std::make_shared<FlipperPluginMock>(
|
||||||
disconnectionCallback);
|
"Test", connectionCallback, disconnectionCallback);
|
||||||
client.addPlugin(plugin);
|
client.addPlugin(plugin);
|
||||||
|
|
||||||
client.start();
|
client.start();
|
||||||
@@ -122,15 +128,16 @@ TEST(FlipperClientTests, testConnectDisconnect) {
|
|||||||
|
|
||||||
TEST(FlipperClientTests, testInitDeinit) {
|
TEST(FlipperClientTests, testInitDeinit) {
|
||||||
auto socket = new FlipperConnectionManagerMock;
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
FlipperClient client(std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
|
|
||||||
bool pluginConnected = false;
|
bool pluginConnected = false;
|
||||||
const auto connectionCallback = [&](std::shared_ptr<FlipperConnection> conn) {
|
const auto connectionCallback = [&](std::shared_ptr<FlipperConnection> conn) {
|
||||||
pluginConnected = true;
|
pluginConnected = true;
|
||||||
};
|
};
|
||||||
const auto disconnectionCallback = [&]() { pluginConnected = false; };
|
const auto disconnectionCallback = [&]() { pluginConnected = false; };
|
||||||
auto plugin = std::make_shared<FlipperPluginMock>("Test", connectionCallback,
|
auto plugin = std::make_shared<FlipperPluginMock>(
|
||||||
disconnectionCallback);
|
"Test", connectionCallback, disconnectionCallback);
|
||||||
|
|
||||||
client.start();
|
client.start();
|
||||||
client.addPlugin(plugin);
|
client.addPlugin(plugin);
|
||||||
@@ -160,15 +167,16 @@ TEST(FlipperClientTests, testInitDeinit) {
|
|||||||
|
|
||||||
TEST(FlipperClientTests, testRemovePluginWhenConnected) {
|
TEST(FlipperClientTests, testRemovePluginWhenConnected) {
|
||||||
auto socket = new FlipperConnectionManagerMock;
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
FlipperClient client(std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
|
|
||||||
bool pluginConnected = false;
|
bool pluginConnected = false;
|
||||||
const auto connectionCallback = [&](std::shared_ptr<FlipperConnection> conn) {
|
const auto connectionCallback = [&](std::shared_ptr<FlipperConnection> conn) {
|
||||||
pluginConnected = true;
|
pluginConnected = true;
|
||||||
};
|
};
|
||||||
const auto disconnectionCallback = [&]() { pluginConnected = false; };
|
const auto disconnectionCallback = [&]() { pluginConnected = false; };
|
||||||
auto plugin = std::make_shared<FlipperPluginMock>("Test", connectionCallback,
|
auto plugin = std::make_shared<FlipperPluginMock>(
|
||||||
disconnectionCallback);
|
"Test", connectionCallback, disconnectionCallback);
|
||||||
|
|
||||||
client.addPlugin(plugin);
|
client.addPlugin(plugin);
|
||||||
client.start();
|
client.start();
|
||||||
@@ -181,7 +189,8 @@ TEST(FlipperClientTests, testRemovePluginWhenConnected) {
|
|||||||
|
|
||||||
TEST(FlipperClientTests, testUnhandleableMethod) {
|
TEST(FlipperClientTests, testUnhandleableMethod) {
|
||||||
auto socket = new FlipperConnectionManagerMock;
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
FlipperClient client(std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
|
|
||||||
auto plugin = std::make_shared<FlipperPluginMock>("Test");
|
auto plugin = std::make_shared<FlipperPluginMock>("Test");
|
||||||
client.addPlugin(plugin);
|
client.addPlugin(plugin);
|
||||||
@@ -201,11 +210,12 @@ TEST(FlipperClientTests, testUnhandleableMethod) {
|
|||||||
|
|
||||||
TEST(FlipperClientTests, testExecute) {
|
TEST(FlipperClientTests, testExecute) {
|
||||||
auto socket = new FlipperConnectionManagerMock;
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
FlipperClient client(std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
client.start();
|
client.start();
|
||||||
|
|
||||||
const auto connectionCallback = [](std::shared_ptr<FlipperConnection> conn) {
|
const auto connectionCallback = [](std::shared_ptr<FlipperConnection> conn) {
|
||||||
const auto receiver = [](const dynamic ¶ms,
|
const auto receiver = [](const dynamic& params,
|
||||||
std::unique_ptr<FlipperResponder> responder) {
|
std::unique_ptr<FlipperResponder> responder) {
|
||||||
dynamic payload = dynamic::object("message", "yes_i_hear_u");
|
dynamic payload = dynamic::object("message", "yes_i_hear_u");
|
||||||
responder->success(payload);
|
responder->success(payload);
|
||||||
@@ -231,13 +241,14 @@ TEST(FlipperClientTests, testExecute) {
|
|||||||
|
|
||||||
TEST(FlipperClientTests, testExecuteWithParams) {
|
TEST(FlipperClientTests, testExecuteWithParams) {
|
||||||
auto socket = new FlipperConnectionManagerMock;
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
FlipperClient client(std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
|
|
||||||
const auto connectionCallback = [&](std::shared_ptr<FlipperConnection> conn) {
|
const auto connectionCallback = [&](std::shared_ptr<FlipperConnection> conn) {
|
||||||
const auto receiver = [](const dynamic ¶ms,
|
const auto receiver = [](const dynamic& params,
|
||||||
std::unique_ptr<FlipperResponder> responder) {
|
std::unique_ptr<FlipperResponder> responder) {
|
||||||
const auto &first = params["first"].asString();
|
const auto& first = params["first"].asString();
|
||||||
const auto &second = params["second"].asString();
|
const auto& second = params["second"].asString();
|
||||||
std::map<std::string, std::string> m{{"dog", "woof"}, {"cat", "meow"}};
|
std::map<std::string, std::string> m{{"dog", "woof"}, {"cat", "meow"}};
|
||||||
dynamic payload = dynamic::object(first, m[first])(second, m[second]);
|
dynamic payload = dynamic::object(first, m[first])(second, m[second]);
|
||||||
responder->success(payload);
|
responder->success(payload);
|
||||||
@@ -264,28 +275,32 @@ TEST(FlipperClientTests, testExecuteWithParams) {
|
|||||||
|
|
||||||
TEST(FlipperClientTests, testExceptionUnknownPlugin) {
|
TEST(FlipperClientTests, testExceptionUnknownPlugin) {
|
||||||
auto socket = new FlipperConnectionManagerMock;
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
FlipperClient client(std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
client.start();
|
client.start();
|
||||||
|
|
||||||
dynamic messageInit = dynamic::object("method", "init")(
|
dynamic messageInit = dynamic::object("method", "init")(
|
||||||
"params", dynamic::object("plugin", "Unknown"));
|
"params", dynamic::object("plugin", "Unknown"));
|
||||||
socket->callbacks->onMessageReceived(messageInit);
|
socket->callbacks->onMessageReceived(messageInit);
|
||||||
|
|
||||||
EXPECT_EQ(socket->messages.back()["error"]["message"],
|
EXPECT_EQ(
|
||||||
"plugin Unknown not found for method init");
|
socket->messages.back()["error"]["message"],
|
||||||
|
"plugin Unknown not found for method init");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlipperClientTests, testExceptionUnknownApi) {
|
TEST(FlipperClientTests, testExceptionUnknownApi) {
|
||||||
auto socket = new FlipperConnectionManagerMock;
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
FlipperClient client(std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
client.start();
|
client.start();
|
||||||
|
|
||||||
dynamic messageInit = dynamic::object("method", "execute")(
|
dynamic messageInit = dynamic::object("method", "execute")(
|
||||||
"params", dynamic::object("api", "Unknown"));
|
"params", dynamic::object("api", "Unknown"));
|
||||||
socket->callbacks->onMessageReceived(messageInit);
|
socket->callbacks->onMessageReceived(messageInit);
|
||||||
|
|
||||||
EXPECT_EQ(socket->messages.back()["error"]["message"],
|
EXPECT_EQ(
|
||||||
"connection Unknown not found for method execute");
|
socket->messages.back()["error"]["message"],
|
||||||
|
"connection Unknown not found for method execute");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FlipperClientTests, testBackgroundPluginActivated) {
|
TEST(FlipperClientTests, testBackgroundPluginActivated) {
|
||||||
@@ -328,6 +343,46 @@ TEST(FlipperClientTests, testNonBackgroundPluginNotActivated) {
|
|||||||
EXPECT_FALSE(pluginConnected);
|
EXPECT_FALSE(pluginConnected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(FlipperClientTests, testCrashInDidConnectDisConnectIsSuppressed) {
|
||||||
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
|
|
||||||
|
const auto connectionCallback = [&](std::shared_ptr<FlipperConnection> conn) {
|
||||||
|
throw std::runtime_error("Runtime Error in test");
|
||||||
|
};
|
||||||
|
const auto disconnectionCallback = [&]() {
|
||||||
|
throw std::runtime_error("Runtime Error in test");
|
||||||
|
};
|
||||||
|
auto plugin = std::make_shared<FlipperPluginMock>(
|
||||||
|
"Test", connectionCallback, disconnectionCallback, true);
|
||||||
|
|
||||||
|
client.addPlugin(plugin);
|
||||||
|
|
||||||
|
EXPECT_NO_FATAL_FAILURE(client.start());
|
||||||
|
EXPECT_NO_FATAL_FAILURE(client.stop());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(
|
||||||
|
FlipperClientTests,
|
||||||
|
testNonStandardCrashInDidConnectDisConnectIsSuppressed) {
|
||||||
|
auto socket = new FlipperConnectionManagerMock;
|
||||||
|
FlipperClient client(
|
||||||
|
std::unique_ptr<FlipperConnectionManagerMock>{socket}, state);
|
||||||
|
|
||||||
|
const auto connectionCallback = [&](std::shared_ptr<FlipperConnection> conn) {
|
||||||
|
throw "Non standard exception";
|
||||||
|
};
|
||||||
|
const auto disconnectionCallback = [&]() { throw "Non standard exception"; };
|
||||||
|
auto plugin = std::make_shared<FlipperPluginMock>(
|
||||||
|
"Test", connectionCallback, disconnectionCallback, true);
|
||||||
|
|
||||||
|
client.addPlugin(plugin);
|
||||||
|
|
||||||
|
EXPECT_NO_FATAL_FAILURE(client.start());
|
||||||
|
EXPECT_NO_FATAL_FAILURE(client.stop());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace test
|
} // namespace test
|
||||||
} // namespace flipper
|
} // namespace flipper
|
||||||
} // namespace facebook
|
} // namespace facebook
|
||||||
|
|||||||
Reference in New Issue
Block a user