Socket connect no longer synchronous and blocking
Summary: Never really liked this code. Before this change, calls to connect were blocking. Because of this, we had to make use of promises and a bit of really not that good-looking code. So, this change makes connect non-blocking meaning that we make full use of our event handler. These changes contain: - CSR is not getting generated after each failed attempt. - Connect is no longer blocking. - Do not report events via the handler when explicitly disconnecting. Reviewed By: jknoxville Differential Revision: D46853228 fbshipit-source-id: 00e6a9c7c039a756175fe14982959e078d92bacb
This commit is contained in:
committed by
Facebook GitHub Bot
parent
65e515bdaa
commit
e42db220ee
@@ -276,9 +276,9 @@ class JFlipperWebSocket : public facebook::flipper::FlipperSocket {
|
|||||||
messageHandler_ = std::move(messageHandler);
|
messageHandler_ = std::move(messageHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool connect(FlipperConnectionManager* manager) override {
|
virtual void connect(FlipperConnectionManager* manager) override {
|
||||||
if (socket_ != nullptr) {
|
if (socket_ != nullptr) {
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string connectionURL = endpoint_.secure ? "wss://" : "ws://";
|
std::string connectionURL = endpoint_.secure ? "wss://" : "ws://";
|
||||||
@@ -297,38 +297,9 @@ class JFlipperWebSocket : public facebook::flipper::FlipperSocket {
|
|||||||
|
|
||||||
auto secure = endpoint_.secure;
|
auto secure = endpoint_.secure;
|
||||||
|
|
||||||
std::promise<bool> promise;
|
|
||||||
auto connected = promise.get_future();
|
|
||||||
|
|
||||||
connecting_ = true;
|
|
||||||
|
|
||||||
socket_ = make_global(JFlipperSocketImpl::create(connectionURL));
|
socket_ = make_global(JFlipperSocketImpl::create(connectionURL));
|
||||||
socket_->setEventHandler(JFlipperSocketEventHandlerImpl::newObjectCxxArgs(
|
socket_->setEventHandler(JFlipperSocketEventHandlerImpl::newObjectCxxArgs(
|
||||||
[this, &promise, eventHandler = eventHandler_](SocketEvent event) {
|
[eventHandler = eventHandler_](SocketEvent event) {
|
||||||
/**
|
|
||||||
Only fulfill the promise the first time the event handler is used.
|
|
||||||
If the open event is received, then set the promise value to true.
|
|
||||||
For any other event, consider a failure and set to false.
|
|
||||||
*/
|
|
||||||
if (this->connecting_) {
|
|
||||||
this->connecting_ = false;
|
|
||||||
if (event == SocketEvent::OPEN) {
|
|
||||||
promise.set_value(true);
|
|
||||||
} else if (event == SocketEvent::SSL_ERROR) {
|
|
||||||
try {
|
|
||||||
promise.set_exception(
|
|
||||||
std::make_exception_ptr(folly::AsyncSocketException(
|
|
||||||
folly::AsyncSocketException::SSL_ERROR,
|
|
||||||
"SSL handshake failed")));
|
|
||||||
} catch (...) {
|
|
||||||
// set_exception() may throw an exception
|
|
||||||
// In that case, just set the value to false.
|
|
||||||
promise.set_value(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
promise.set_value(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
eventHandler(event);
|
eventHandler(event);
|
||||||
},
|
},
|
||||||
[messageHandler = messageHandler_](const std::string& message) {
|
[messageHandler = messageHandler_](const std::string& message) {
|
||||||
@@ -348,8 +319,6 @@ class JFlipperWebSocket : public facebook::flipper::FlipperSocket {
|
|||||||
return JFlipperObject::create(std::move(object_));
|
return JFlipperObject::create(std::move(object_));
|
||||||
}));
|
}));
|
||||||
socket_->connect();
|
socket_->connect();
|
||||||
|
|
||||||
return connected.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void disconnect() override {
|
virtual void disconnect() override {
|
||||||
@@ -409,7 +378,6 @@ class JFlipperWebSocket : public facebook::flipper::FlipperSocket {
|
|||||||
facebook::flipper::SocketMessageHandler messageHandler_;
|
facebook::flipper::SocketMessageHandler messageHandler_;
|
||||||
|
|
||||||
jni::global_ref<JFlipperSocketImpl> socket_;
|
jni::global_ref<JFlipperSocketImpl> socket_;
|
||||||
bool connecting_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class JFlipperSocketProvider : public facebook::flipper::FlipperSocketProvider {
|
class JFlipperSocketProvider : public facebook::flipper::FlipperSocketProvider {
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ class FlipperSocketImpl extends WebSocketClient implements FlipperSocket {
|
|||||||
|
|
||||||
this.connect();
|
this.connect();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e("Flipper", "Failed to initialize the socket before connect. " + e.getMessage());
|
Log.e("flipper", "Failed to initialize the socket before connect. Error: " + e.getMessage());
|
||||||
this.mEventHandler.onConnectionEvent(FlipperSocketEventHandler.SocketEvent.ERROR);
|
this.mEventHandler.onConnectionEvent(FlipperSocketEventHandler.SocketEvent.ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,6 +139,13 @@ class FlipperSocketImpl extends WebSocketClient implements FlipperSocket {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClose(int code, String reason, boolean remote) {
|
public void onClose(int code, String reason, boolean remote) {
|
||||||
|
/**
|
||||||
|
* If the socket is not yet open, don't report the close event. Usually, onError is invoked
|
||||||
|
* instead which is the one that needs reporting.
|
||||||
|
*/
|
||||||
|
if (!this.isOpen()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.mEventHandler.onConnectionEvent(FlipperSocketEventHandler.SocketEvent.CLOSE);
|
this.mEventHandler.onConnectionEvent(FlipperSocketEventHandler.SocketEvent.CLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +169,6 @@ class FlipperSocketImpl extends WebSocketClient implements FlipperSocket {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void flipperDisconnect() {
|
public void flipperDisconnect() {
|
||||||
this.mEventHandler.onConnectionEvent(FlipperSocketEventHandler.SocketEvent.CLOSE);
|
|
||||||
this.mEventHandler =
|
this.mEventHandler =
|
||||||
new FlipperSocketEventHandler() {
|
new FlipperSocketEventHandler() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -181,11 +181,6 @@ static constexpr int connectionKeepaliveSeconds = 10;
|
|||||||
|
|
||||||
[_dispatchQueue cancelAllOperations];
|
[_dispatchQueue cancelAllOperations];
|
||||||
[_dispatchQueue waitUntilAllOperationsAreFinished];
|
[_dispatchQueue waitUntilAllOperationsAreFinished];
|
||||||
|
|
||||||
// Manually trigger a 'close' event as SocketRocket close method will
|
|
||||||
// not notify the delegate. SocketRocket only triggers the close event
|
|
||||||
// when the connection is closed from the server.
|
|
||||||
_eventHandler(facebook::flipper::SocketEvent::CLOSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)send:(NSString*)message
|
- (void)send:(NSString*)message
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class FlipperWebSocket : public FlipperSocket {
|
|||||||
virtual void setEventHandler(SocketEventHandler eventHandler) override;
|
virtual void setEventHandler(SocketEventHandler eventHandler) override;
|
||||||
virtual void setMessageHandler(SocketMessageHandler messageHandler) override;
|
virtual void setMessageHandler(SocketMessageHandler messageHandler) override;
|
||||||
|
|
||||||
virtual bool connect(FlipperConnectionManager* manager) override;
|
virtual void connect(FlipperConnectionManager* manager) override;
|
||||||
virtual void disconnect() override;
|
virtual void disconnect() override;
|
||||||
|
|
||||||
virtual void send(const folly::dynamic& message, SocketSendHandler completion)
|
virtual void send(const folly::dynamic& message, SocketSendHandler completion)
|
||||||
|
|||||||
@@ -53,9 +53,9 @@ void FlipperWebSocket::setMessageHandler(SocketMessageHandler messageHandler) {
|
|||||||
messageHandler_ = std::move(messageHandler);
|
messageHandler_ = std::move(messageHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlipperWebSocket::connect(FlipperConnectionManager* manager) {
|
void FlipperWebSocket::connect(FlipperConnectionManager* manager) {
|
||||||
if (socket_ != NULL) {
|
if (socket_ != NULL) {
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string connectionURL = endpoint_.secure ? "wss://" : "ws://";
|
std::string connectionURL = endpoint_.secure ? "wss://" : "ws://";
|
||||||
@@ -72,43 +72,16 @@ bool FlipperWebSocket::connect(FlipperConnectionManager* manager) {
|
|||||||
connectionURL += payload;
|
connectionURL += payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
__block bool fullfilled = false;
|
|
||||||
__block std::promise<bool> promise;
|
|
||||||
auto connected = promise.get_future();
|
|
||||||
|
|
||||||
NSURL* urlObjc = [NSURL
|
NSURL* urlObjc = [NSURL
|
||||||
URLWithString:[NSString stringWithUTF8String:connectionURL.c_str()]];
|
URLWithString:[NSString stringWithUTF8String:connectionURL.c_str()]];
|
||||||
|
|
||||||
auto eventHandler = eventHandler_;
|
|
||||||
socket_ = [[FlipperPlatformWebSocket alloc] initWithURL:urlObjc];
|
socket_ = [[FlipperPlatformWebSocket alloc] initWithURL:urlObjc];
|
||||||
socket_.eventHandler = ^(SocketEvent event) {
|
socket_.eventHandler = ^(SocketEvent event) {
|
||||||
/**
|
eventHandler_(event);
|
||||||
Only fulfill the promise the first time the event handler is used. If the
|
|
||||||
open event is received, then set the promise value to true. For any other
|
|
||||||
event, consider a failure and set to false.
|
|
||||||
*/
|
|
||||||
if (!fullfilled) {
|
|
||||||
fullfilled = true;
|
|
||||||
if (event == SocketEvent::OPEN) {
|
|
||||||
promise.set_value(true);
|
|
||||||
} else if (event == SocketEvent::SSL_ERROR) {
|
|
||||||
try {
|
|
||||||
promise.set_exception(
|
|
||||||
std::make_exception_ptr(SSLException("SSL handshake failed")));
|
|
||||||
} catch (...) {
|
|
||||||
// set_exception() may throw an exception
|
|
||||||
// In that case, just set the value to false.
|
|
||||||
promise.set_value(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
promise.set_value(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
eventHandler(event);
|
|
||||||
};
|
};
|
||||||
auto messageHandler = messageHandler_;
|
|
||||||
socket_.messageHandler = ^(const std::string& message) {
|
socket_.messageHandler = ^(const std::string& message) {
|
||||||
messageHandler(message);
|
messageHandler_(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (endpoint_.secure) {
|
if (endpoint_.secure) {
|
||||||
@@ -124,8 +97,6 @@ bool FlipperWebSocket::connect(FlipperConnectionManager* manager) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[socket_ connect];
|
[socket_ connect];
|
||||||
|
|
||||||
return connected.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperWebSocket::disconnect() {
|
void FlipperWebSocket::disconnect() {
|
||||||
@@ -157,9 +128,9 @@ void FlipperWebSocket::send(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Only ever used for insecure connections to receive the device_id from a
|
* Only ever used for insecure connections to receive the device_id from a
|
||||||
signCertificate request. If the intended usage ever changes, then a better
|
* signCertificate request. If the intended usage ever changes, then a better
|
||||||
approach needs to be put in place.
|
* approach needs to be put in place.
|
||||||
*/
|
*/
|
||||||
void FlipperWebSocket::sendExpectResponse(
|
void FlipperWebSocket::sendExpectResponse(
|
||||||
const std::string& message,
|
const std::string& message,
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class FlipperReactBaseSocket {
|
|||||||
messageHandler_ = std::move(messageHandler);
|
messageHandler_ = std::move(messageHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool connect(FlipperConnectionManager* manager) = 0;
|
virtual void connect(FlipperConnectionManager* manager) = 0;
|
||||||
virtual void disconnect() = 0;
|
virtual void disconnect() = 0;
|
||||||
|
|
||||||
virtual void send(
|
virtual void send(
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ void FlipperReactSocket::setMessageHandler(
|
|||||||
socket_->setMessageHandler(messageHandler);
|
socket_->setMessageHandler(messageHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlipperReactSocket::connect(FlipperConnectionManager* manager) {
|
void FlipperReactSocket::connect(FlipperConnectionManager* manager) {
|
||||||
return socket_->connect(manager);
|
socket_->connect(manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperReactSocket::disconnect() {
|
void FlipperReactSocket::disconnect() {
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class FlipperReactSocket : public FlipperSocket {
|
|||||||
virtual void setEventHandler(SocketEventHandler eventHandler) override;
|
virtual void setEventHandler(SocketEventHandler eventHandler) override;
|
||||||
virtual void setMessageHandler(SocketMessageHandler messageHandler) override;
|
virtual void setMessageHandler(SocketMessageHandler messageHandler) override;
|
||||||
|
|
||||||
virtual bool connect(FlipperConnectionManager* manager) override;
|
virtual void connect(FlipperConnectionManager* manager) override;
|
||||||
virtual void disconnect() override;
|
virtual void disconnect() override;
|
||||||
|
|
||||||
virtual void send(const folly::dynamic& message, SocketSendHandler completion)
|
virtual void send(const folly::dynamic& message, SocketSendHandler completion)
|
||||||
|
|||||||
@@ -134,9 +134,9 @@ FlipperReactSocketClient::getClientCertificate() {
|
|||||||
return installClientCertificate();
|
return installClientCertificate();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlipperReactSocketClient::connect(FlipperConnectionManager* manager) {
|
void FlipperReactSocketClient::connect(FlipperConnectionManager* manager) {
|
||||||
if (status_ != Status::Unconnected) {
|
if (status_ != Status::Unconnected) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_ = Status::Connecting;
|
status_ = Status::Connecting;
|
||||||
@@ -176,30 +176,34 @@ bool FlipperReactSocketClient::connect(FlipperConnectionManager* manager) {
|
|||||||
socket_.Closed({this, &FlipperReactSocketClient::OnWebSocketClosed});
|
socket_.Closed({this, &FlipperReactSocketClient::OnWebSocketClosed});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this->socket_.ConnectAsync(winrt::Windows::Foundation::Uri(uri))
|
|
||||||
.wait_for(std::chrono::seconds(10));
|
|
||||||
|
|
||||||
status_ = Status::Initializing;
|
status_ = Status::Initializing;
|
||||||
scheduler_->schedule(
|
|
||||||
[eventHandler = eventHandler_]() { eventHandler(SocketEvent::OPEN); });
|
|
||||||
|
|
||||||
return true;
|
Windows::Foundation::IAsyncAction ^ connectAction;
|
||||||
|
connectAction =
|
||||||
|
this->socket_.ConnectAsync(winrt::Windows::Foundation::Uri(uri));
|
||||||
|
connectAction->Completed = ref new AsyncActionCompletedHandler(
|
||||||
|
[eventHandler = eventHandler_](
|
||||||
|
Windows::Foundation::IAsyncAction ^ asyncAction,
|
||||||
|
Windows::Foundation::AsyncStatus asyncStatus) {
|
||||||
|
if (asyncStatus == Windows::Foundation::AsyncStatus::Completed) {
|
||||||
|
eventHandler(SocketEvent::OPEN);
|
||||||
|
} else {
|
||||||
|
eventHandler(SocketEvent::ERROR);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
} catch (winrt::hresult_error const& ex) {
|
} catch (winrt::hresult_error const& ex) {
|
||||||
winrt::Windows::Web::WebErrorStatus webErrorStatus{
|
winrt::Windows::Web::WebErrorStatus webErrorStatus{
|
||||||
winrt::Windows::Networking::Sockets::WebSocketError::GetStatus(
|
winrt::Windows::Networking::Sockets::WebSocketError::GetStatus(
|
||||||
ex.to_abi())};
|
ex.to_abi())};
|
||||||
|
socket_ = nullptr;
|
||||||
|
status_ = Status::Unconnected;
|
||||||
|
eventHandler(SocketEvent::ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperReactSocketClient::disconnect() {
|
void FlipperReactSocketClient::disconnect() {
|
||||||
status_ = Status::Closed;
|
status_ = Status::Closed;
|
||||||
scheduler_->schedule(
|
|
||||||
[eventHandler = eventHandler_]() { eventHandler(SocketEvent::CLOSE); });
|
|
||||||
// socket_.Close();
|
|
||||||
socket_ = nullptr;
|
socket_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,14 +273,10 @@ void FlipperReactSocketClient::OnWebSocketMessageReceived(
|
|||||||
const std::string payload = winrt::to_string(message);
|
const std::string payload = winrt::to_string(message);
|
||||||
|
|
||||||
if (overrideHandler_ != nullptr) {
|
if (overrideHandler_ != nullptr) {
|
||||||
scheduler_->schedule([payload, messageHandler = *overrideHandler_]() {
|
|
||||||
messageHandler(payload, false);
|
messageHandler(payload, false);
|
||||||
});
|
|
||||||
overrideHandler_ = nullptr;
|
overrideHandler_ = nullptr;
|
||||||
} else if (messageHandler_) {
|
} else if (messageHandler_) {
|
||||||
scheduler_->schedule([payload, messageHandler = messageHandler_]() {
|
|
||||||
messageHandler(payload);
|
messageHandler(payload);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} catch (winrt::hresult_error const& ex) {
|
} catch (winrt::hresult_error const& ex) {
|
||||||
// winrt::Windows::Web::WebErrorStatus webErrorStatus{
|
// winrt::Windows::Web::WebErrorStatus webErrorStatus{
|
||||||
@@ -291,8 +291,7 @@ void FlipperReactSocketClient::OnWebSocketClosed(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
status_ = Status::Closed;
|
status_ = Status::Closed;
|
||||||
scheduler_->schedule(
|
eventHandler(SocketEvent::CLOSE);
|
||||||
[eventHandler = eventHandler_]() { eventHandler(SocketEvent::CLOSE); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace flipper
|
} // namespace flipper
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class FlipperReactSocketClient : public FlipperReactBaseSocket {
|
|||||||
|
|
||||||
virtual ~FlipperReactSocketClient();
|
virtual ~FlipperReactSocketClient();
|
||||||
|
|
||||||
virtual bool connect(FlipperConnectionManager* manager) override;
|
virtual void connect(FlipperConnectionManager* manager) override;
|
||||||
virtual void disconnect() override;
|
virtual void disconnect() override;
|
||||||
|
|
||||||
virtual void send(const folly::dynamic& message, SocketSendHandler completion)
|
virtual void send(const folly::dynamic& message, SocketSendHandler completion)
|
||||||
@@ -61,7 +61,6 @@ class FlipperReactSocketClient : public FlipperReactBaseSocket {
|
|||||||
args);
|
args);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::promise<bool> connected_;
|
|
||||||
winrt::Windows::Networking::Sockets::MessageWebSocket socket_;
|
winrt::Windows::Networking::Sockets::MessageWebSocket socket_;
|
||||||
winrt::event_token messageReceivedEventToken_;
|
winrt::event_token messageReceivedEventToken_;
|
||||||
winrt::event_token closedEventToken_;
|
winrt::event_token closedEventToken_;
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ bool ConnectionContextStore::hasRequiredFiles() {
|
|||||||
std::string config =
|
std::string config =
|
||||||
loadStringFromFile(absoluteFilePath(CONNECTION_CONFIG_FILE));
|
loadStringFromFile(absoluteFilePath(CONNECTION_CONFIG_FILE));
|
||||||
|
|
||||||
if (caCert == "" || clientCert == "" || privateKey == "" || config == "") {
|
if (caCert.empty() || clientCert.empty() || privateKey.empty() ||
|
||||||
|
config.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -56,14 +57,14 @@ bool ConnectionContextStore::hasRequiredFiles() {
|
|||||||
|
|
||||||
std::string ConnectionContextStore::getCertificateSigningRequest() {
|
std::string ConnectionContextStore::getCertificateSigningRequest() {
|
||||||
// Use in-memory CSR if already loaded
|
// Use in-memory CSR if already loaded
|
||||||
if (csr != "") {
|
if (!csr_.empty()) {
|
||||||
return csr;
|
return csr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to load existing CSR from previous run of the app
|
// Attempt to load existing CSR from previous run of the app
|
||||||
csr = loadStringFromFile(absoluteFilePath(CSR_FILE_NAME));
|
csr_ = loadStringFromFile(absoluteFilePath(CSR_FILE_NAME));
|
||||||
if (csr != "") {
|
if (!csr_.empty()) {
|
||||||
return csr;
|
return csr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean all state and generate a new one
|
// Clean all state and generate a new one
|
||||||
@@ -75,9 +76,9 @@ std::string ConnectionContextStore::getCertificateSigningRequest() {
|
|||||||
if (!success) {
|
if (!success) {
|
||||||
throw new std::runtime_error("Failed to generate CSR");
|
throw new std::runtime_error("Failed to generate CSR");
|
||||||
}
|
}
|
||||||
csr = loadStringFromFile(absoluteFilePath(CSR_FILE_NAME));
|
csr_ = loadStringFromFile(absoluteFilePath(CSR_FILE_NAME));
|
||||||
|
|
||||||
return csr;
|
return csr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ConnectionContextStore::getDeviceId() {
|
std::string ConnectionContextStore::getDeviceId() {
|
||||||
@@ -124,7 +125,8 @@ void ConnectionContextStore::storeConnectionConfig(folly::dynamic& config) {
|
|||||||
writeStringToFile(json, absoluteFilePath(CONNECTION_CONFIG_FILE));
|
writeStringToFile(json, absoluteFilePath(CONNECTION_CONFIG_FILE));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ConnectionContextStore::absoluteFilePath(const char* filename) {
|
std::string ConnectionContextStore::absoluteFilePath(
|
||||||
|
const char* filename) const {
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
return std::string(deviceData_.privateAppDirectory + "/sonar/" + filename);
|
return std::string(deviceData_.privateAppDirectory + "/sonar/" + filename);
|
||||||
#else
|
#else
|
||||||
@@ -159,7 +161,7 @@ std::string ConnectionContextStore::getPath(StoreItem storeItem) {
|
|||||||
|
|
||||||
bool ConnectionContextStore::resetState() {
|
bool ConnectionContextStore::resetState() {
|
||||||
// Clear in-memory state
|
// Clear in-memory state
|
||||||
csr = "";
|
csr_ = "";
|
||||||
|
|
||||||
// Delete state from disk
|
// Delete state from disk
|
||||||
std::string dirPath = absoluteFilePath("");
|
std::string dirPath = absoluteFilePath("");
|
||||||
@@ -208,6 +210,18 @@ std::pair<std::string, std::string> ConnectionContextStore::getCertificate() {
|
|||||||
return std::make_pair(certificate_path, std::string(CERTIFICATE_PASSWORD));
|
return std::make_pair(certificate_path, std::string(CERTIFICATE_PASSWORD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ConnectionContextStore::hasCertificateSigningRequest() const {
|
||||||
|
std::string csr = loadStringFromFile(absoluteFilePath(CSR_FILE_NAME));
|
||||||
|
return !csr.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConnectionContextStore::hasClientCertificate() const {
|
||||||
|
std::string clientCertificate =
|
||||||
|
loadStringFromFile(absoluteFilePath(CLIENT_CERT_FILE_NAME));
|
||||||
|
|
||||||
|
return !clientCertificate.empty();
|
||||||
|
}
|
||||||
|
|
||||||
std::string loadStringFromFile(std::string fileName) {
|
std::string loadStringFromFile(std::string fileName) {
|
||||||
if (!fileExists(fileName)) {
|
if (!fileExists(fileName)) {
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
@@ -57,11 +57,18 @@ class ConnectionContextStore {
|
|||||||
*/
|
*/
|
||||||
std::pair<std::string, std::string> getCertificate();
|
std::pair<std::string, std::string> getCertificate();
|
||||||
|
|
||||||
|
/** Is there a CSR present.
|
||||||
|
*/
|
||||||
|
bool hasCertificateSigningRequest() const;
|
||||||
|
/** Is there a client certificate present.
|
||||||
|
*/
|
||||||
|
bool hasClientCertificate() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeviceData deviceData_;
|
DeviceData deviceData_;
|
||||||
std::string csr = "";
|
std::string csr_ = "";
|
||||||
|
|
||||||
std::string absoluteFilePath(const char* filename);
|
std::string absoluteFilePath(const char* filename) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace flipper
|
} // namespace flipper
|
||||||
|
|||||||
@@ -20,12 +20,12 @@
|
|||||||
#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."
|
||||||
|
|
||||||
static constexpr int reconnectIntervalSeconds = 2;
|
static constexpr int RECONNECT_INTERVAL_SECONDS = 3;
|
||||||
|
|
||||||
// Not a public-facing version number.
|
// Not a public-facing version number.
|
||||||
// Used for compatibility checking with desktop flipper.
|
// Used for compatibility checking with desktop flipper.
|
||||||
// To be bumped for every core platform interface change.
|
// To be bumped for every core platform interface change.
|
||||||
static constexpr int sdkVersion = 4;
|
static constexpr int SDK_VERSION = 4;
|
||||||
|
|
||||||
using namespace folly;
|
using namespace folly;
|
||||||
|
|
||||||
@@ -66,14 +66,14 @@ FlipperConnectionManagerImpl::FlipperConnectionManagerImpl(
|
|||||||
std::shared_ptr<FlipperState> state,
|
std::shared_ptr<FlipperState> state,
|
||||||
std::shared_ptr<ConnectionContextStore> contextStore)
|
std::shared_ptr<ConnectionContextStore> contextStore)
|
||||||
: deviceData_(config.deviceData),
|
: deviceData_(config.deviceData),
|
||||||
flipperState_(state),
|
state_(state),
|
||||||
insecurePort(config.insecurePort),
|
insecurePort(config.insecurePort),
|
||||||
securePort(config.securePort),
|
securePort(config.securePort),
|
||||||
altInsecurePort(config.altInsecurePort),
|
altInsecurePort(config.altInsecurePort),
|
||||||
altSecurePort(config.altSecurePort),
|
altSecurePort(config.altSecurePort),
|
||||||
flipperScheduler_(config.callbackWorker),
|
scheduler_(config.callbackWorker),
|
||||||
connectionScheduler_(config.connectionWorker),
|
connectionScheduler_(config.connectionWorker),
|
||||||
contextStore_(contextStore),
|
store_(contextStore),
|
||||||
implWrapper_(std::make_shared<FlipperConnectionManagerWrapper>(this)) {
|
implWrapper_(std::make_shared<FlipperConnectionManagerWrapper>(this)) {
|
||||||
CHECK_THROW(config.callbackWorker, std::invalid_argument);
|
CHECK_THROW(config.callbackWorker, std::invalid_argument);
|
||||||
CHECK_THROW(config.connectionWorker, std::invalid_argument);
|
CHECK_THROW(config.connectionWorker, std::invalid_argument);
|
||||||
@@ -85,39 +85,52 @@ FlipperConnectionManagerImpl::~FlipperConnectionManagerImpl() {
|
|||||||
|
|
||||||
void FlipperConnectionManagerImpl::setCertificateProvider(
|
void FlipperConnectionManagerImpl::setCertificateProvider(
|
||||||
const std::shared_ptr<FlipperCertificateProvider> provider) {
|
const std::shared_ptr<FlipperCertificateProvider> provider) {
|
||||||
certProvider_ = provider;
|
certificateProvider_ = provider;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<FlipperCertificateProvider>
|
std::shared_ptr<FlipperCertificateProvider>
|
||||||
FlipperConnectionManagerImpl::getCertificateProvider() {
|
FlipperConnectionManagerImpl::getCertificateProvider() {
|
||||||
return certProvider_;
|
return certificateProvider_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperConnectionManagerImpl::handleSocketEvent(SocketEvent event) {
|
void FlipperConnectionManagerImpl::handleSocketEvent(SocketEvent event) {
|
||||||
|
// Ensure that the event is handled on the correct thread i.e. scheduler.
|
||||||
|
scheduler_->schedule([this, event]() {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case SocketEvent::OPEN:
|
case SocketEvent::OPEN:
|
||||||
isConnected_ = true;
|
isConnected_ = true;
|
||||||
if (connectionIsTrusted_) {
|
if (isConnectionTrusted_) {
|
||||||
|
failedConnectionAttempts_ = 0;
|
||||||
callbacks_->onConnected();
|
callbacks_->onConnected();
|
||||||
|
} else {
|
||||||
|
requestSignedCertificate();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SocketEvent::SSL_ERROR:
|
case SocketEvent::SSL_ERROR:
|
||||||
// SSL errors are not handled as a connection event
|
log("[conn] handleSocketEvent(SSL_ERROR)");
|
||||||
// on this handler.
|
failedConnectionAttempts_++;
|
||||||
|
reconnect();
|
||||||
break;
|
break;
|
||||||
case SocketEvent::CLOSE:
|
case SocketEvent::CLOSE:
|
||||||
case SocketEvent::ERROR:
|
case SocketEvent::ERROR:
|
||||||
|
log("[conn] handleSocketEvent(CLOSE_ERROR)");
|
||||||
if (!isConnected_) {
|
if (!isConnected_) {
|
||||||
|
reconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
failedConnectionAttempts_++;
|
||||||
isConnected_ = false;
|
isConnected_ = false;
|
||||||
if (connectionIsTrusted_) {
|
|
||||||
connectionIsTrusted_ = false;
|
if (isConnectionTrusted_) {
|
||||||
|
isConnectionTrusted_ = false;
|
||||||
callbacks_->onDisconnected();
|
callbacks_->onDisconnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
reconnect();
|
reconnect();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperConnectionManagerImpl::start() {
|
void FlipperConnectionManagerImpl::start() {
|
||||||
@@ -126,22 +139,22 @@ void FlipperConnectionManagerImpl::start() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isStarted_) {
|
if (started_) {
|
||||||
log("Already started");
|
log("Already started");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isStarted_ = true;
|
started_ = true;
|
||||||
|
|
||||||
auto step = flipperState_->start("Start connection thread");
|
auto step = state_->start("Start connection thread");
|
||||||
|
|
||||||
flipperScheduler_->schedule([this, step]() {
|
scheduler_->schedule([this, step]() {
|
||||||
step->complete();
|
step->complete();
|
||||||
startSync();
|
startSync();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperConnectionManagerImpl::startSync() {
|
void FlipperConnectionManagerImpl::startSync() {
|
||||||
if (!isStarted_) {
|
if (!started_) {
|
||||||
log("Not started");
|
log("Not started");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -153,52 +166,28 @@ void FlipperConnectionManagerImpl::startSync() {
|
|||||||
log("Already connected");
|
log("Already connected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
socket_ = nullptr;
|
||||||
|
|
||||||
bool isClientSetupStep = isCertificateExchangeNeeded();
|
bool isClientSetupStep = isCertificateExchangeNeeded();
|
||||||
auto step = flipperState_->start(
|
auto step = state_->start(
|
||||||
isClientSetupStep ? "Establish pre-setup connection"
|
isClientSetupStep ? "Establish certificate exchange connection"
|
||||||
: "Establish main connection");
|
: "Establish main connection");
|
||||||
try {
|
|
||||||
if (isClientSetupStep) {
|
if (isClientSetupStep) {
|
||||||
bool success = connectAndExchangeCertificate();
|
connectAndExchangeCertificate();
|
||||||
if (!success) {
|
|
||||||
reconnect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!connectSecurely()) {
|
connectSecurely();
|
||||||
// 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...");
|
|
||||||
reconnect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
step->complete();
|
step->complete();
|
||||||
} catch (const SSLException& e) {
|
|
||||||
auto message = std::string(e.what()) +
|
|
||||||
"\nMake sure the date and time of your device is up to date.";
|
|
||||||
log(message);
|
|
||||||
step->fail(message);
|
|
||||||
failedConnectionAttempts_++;
|
|
||||||
reconnect();
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
log(e.what());
|
|
||||||
step->fail(e.what());
|
|
||||||
failedConnectionAttempts_++;
|
|
||||||
reconnect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlipperConnectionManagerImpl::connectAndExchangeCertificate() {
|
void FlipperConnectionManagerImpl::connectAndExchangeCertificate() {
|
||||||
|
log("[conn] connectAndExchangeCertificate()");
|
||||||
auto port = insecurePort;
|
auto port = insecurePort;
|
||||||
auto endpoint = FlipperConnectionEndpoint(deviceData_.host, port, false);
|
auto endpoint = FlipperConnectionEndpoint(deviceData_.host, port, false);
|
||||||
|
|
||||||
int medium = certProvider_ != nullptr
|
int medium = certificateProvider_ != nullptr
|
||||||
? certProvider_->getCertificateExchangeMedium()
|
? certificateProvider_->getCertificateExchangeMedium()
|
||||||
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
||||||
|
|
||||||
auto payload = std::make_unique<FlipperSocketBasePayload>();
|
auto payload = std::make_unique<FlipperSocketBasePayload>();
|
||||||
@@ -206,47 +195,31 @@ bool FlipperConnectionManagerImpl::connectAndExchangeCertificate() {
|
|||||||
payload->device = deviceData_.device;
|
payload->device = deviceData_.device;
|
||||||
payload->device_id = "unknown";
|
payload->device_id = "unknown";
|
||||||
payload->app = deviceData_.app;
|
payload->app = deviceData_.app;
|
||||||
payload->sdk_version = sdkVersion;
|
payload->sdk_version = SDK_VERSION;
|
||||||
payload->medium = medium;
|
payload->medium = medium;
|
||||||
|
|
||||||
client_ = FlipperSocketProvider::socketCreate(
|
socket_ = FlipperSocketProvider::socketCreate(
|
||||||
endpoint, std::move(payload), flipperScheduler_);
|
endpoint, std::move(payload), scheduler_);
|
||||||
client_->setEventHandler(ConnectionEvents(implWrapper_));
|
socket_->setEventHandler(ConnectionEvents(implWrapper_));
|
||||||
|
|
||||||
connectionIsTrusted_ = false;
|
isConnectionTrusted_ = false;
|
||||||
|
|
||||||
auto step =
|
|
||||||
flipperState_->start("Attempt to connect for certificate exchange");
|
|
||||||
|
|
||||||
|
auto step = state_->start("Attempt to connect for certificate exchange");
|
||||||
step->complete();
|
step->complete();
|
||||||
|
|
||||||
// NON-TLS:
|
socket_->connect(this);
|
||||||
// On failure: clear the client.
|
|
||||||
// On success: proceed to request the client certificate.
|
|
||||||
|
|
||||||
// Connect is just handled here, move this elsewhere.
|
|
||||||
if (!client_->connect(this)) {
|
|
||||||
client_ = nullptr;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
requestSignedCertificate();
|
void FlipperConnectionManagerImpl::connectSecurely() {
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FlipperConnectionManagerImpl::connectSecurely() {
|
|
||||||
client_ = nullptr;
|
|
||||||
|
|
||||||
auto port = securePort;
|
auto port = securePort;
|
||||||
auto endpoint = FlipperConnectionEndpoint(deviceData_.host, port, true);
|
auto endpoint = FlipperConnectionEndpoint(deviceData_.host, port, true);
|
||||||
|
|
||||||
int medium = certProvider_ != nullptr
|
int medium = certificateProvider_ != nullptr
|
||||||
? certProvider_->getCertificateExchangeMedium()
|
? certificateProvider_->getCertificateExchangeMedium()
|
||||||
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
||||||
|
|
||||||
auto loadingDeviceId = flipperState_->start("Load Device Id");
|
auto loadingDeviceId = state_->start("Load Device Id");
|
||||||
auto deviceId = contextStore_->getDeviceId();
|
auto deviceId = store_->getDeviceId();
|
||||||
if (deviceId.compare("unknown")) {
|
if (deviceId.compare("unknown")) {
|
||||||
loadingDeviceId->complete();
|
loadingDeviceId->complete();
|
||||||
}
|
}
|
||||||
@@ -256,15 +229,15 @@ bool FlipperConnectionManagerImpl::connectSecurely() {
|
|||||||
payload->device = deviceData_.device;
|
payload->device = deviceData_.device;
|
||||||
payload->device_id = deviceId;
|
payload->device_id = deviceId;
|
||||||
payload->app = deviceData_.app;
|
payload->app = deviceData_.app;
|
||||||
payload->sdk_version = sdkVersion;
|
payload->sdk_version = SDK_VERSION;
|
||||||
payload->medium = medium;
|
payload->medium = medium;
|
||||||
payload->csr = contextStore_->getCertificateSigningRequest().c_str();
|
payload->csr = store_->getCertificateSigningRequest().c_str();
|
||||||
payload->csr_path = contextStore_->getCertificateDirectoryPath().c_str();
|
payload->csr_path = store_->getCertificateDirectoryPath().c_str();
|
||||||
|
|
||||||
client_ = FlipperSocketProvider::socketCreate(
|
socket_ = FlipperSocketProvider::socketCreate(
|
||||||
endpoint, std::move(payload), connectionScheduler_, contextStore_.get());
|
endpoint, std::move(payload), connectionScheduler_, store_.get());
|
||||||
client_->setEventHandler(ConnectionEvents(implWrapper_));
|
socket_->setEventHandler(ConnectionEvents(implWrapper_));
|
||||||
client_->setMessageHandler([this](const std::string& msg) {
|
socket_->setMessageHandler([this](const std::string& msg) {
|
||||||
std::unique_ptr<FireAndForgetBasedFlipperResponder> responder;
|
std::unique_ptr<FireAndForgetBasedFlipperResponder> responder;
|
||||||
auto message = folly::parseJson(msg);
|
auto message = folly::parseJson(msg);
|
||||||
auto idItr = message.find("id");
|
auto idItr = message.find("id");
|
||||||
@@ -278,54 +251,41 @@ bool FlipperConnectionManagerImpl::connectSecurely() {
|
|||||||
this->onMessageReceived(folly::parseJson(msg), std::move(responder));
|
this->onMessageReceived(folly::parseJson(msg), std::move(responder));
|
||||||
});
|
});
|
||||||
|
|
||||||
connectionIsTrusted_ = true;
|
isConnectionTrusted_ = true;
|
||||||
|
|
||||||
auto step = flipperState_->start(
|
|
||||||
"Attempt to connect with existing client certificate");
|
|
||||||
|
|
||||||
|
auto step =
|
||||||
|
state_->start("Attempt to connect with existing client certificate");
|
||||||
step->complete();
|
step->complete();
|
||||||
|
|
||||||
// TLS:
|
socket_->connect(this);
|
||||||
// On failure: clear the client.
|
|
||||||
// On success: clear number of failed attempts.
|
|
||||||
|
|
||||||
// Connect is just handled here, move this elsewhere.
|
|
||||||
if (!client_->connect(this)) {
|
|
||||||
client_ = nullptr;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
failedConnectionAttempts_ = 0;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperConnectionManagerImpl::reconnect() {
|
void FlipperConnectionManagerImpl::reconnect() {
|
||||||
if (!isStarted_) {
|
if (!started_) {
|
||||||
log("Not started");
|
log("Not started");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
flipperScheduler_->scheduleAfter(
|
log("[conn] reconnect()");
|
||||||
[this]() { startSync(); }, reconnectIntervalSeconds * 1000.0f);
|
scheduler_->scheduleAfter(
|
||||||
|
[this]() { startSync(); }, RECONNECT_INTERVAL_SECONDS * 1000.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperConnectionManagerImpl::stop() {
|
void FlipperConnectionManagerImpl::stop() {
|
||||||
if (certProvider_ && certProvider_->shouldResetCertificateFolder()) {
|
if (certificateProvider_ &&
|
||||||
contextStore_->resetState();
|
certificateProvider_->shouldResetCertificateFolder()) {
|
||||||
|
store_->resetState();
|
||||||
}
|
}
|
||||||
if (!isStarted_) {
|
if (!started_) {
|
||||||
log("Not started");
|
log("Not started");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isStarted_ = false;
|
started_ = false;
|
||||||
|
|
||||||
std::shared_ptr<std::promise<void>> joinPromise =
|
std::shared_ptr<std::promise<void>> joinPromise =
|
||||||
std::make_shared<std::promise<void>>();
|
std::make_shared<std::promise<void>>();
|
||||||
std::future<void> join = joinPromise->get_future();
|
std::future<void> join = joinPromise->get_future();
|
||||||
flipperScheduler_->schedule([this, joinPromise]() {
|
scheduler_->schedule([this, joinPromise]() {
|
||||||
if (client_) {
|
socket_ = nullptr;
|
||||||
client_->disconnect();
|
|
||||||
}
|
|
||||||
client_ = nullptr;
|
|
||||||
joinPromise->set_value();
|
joinPromise->set_value();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -333,7 +293,7 @@ void FlipperConnectionManagerImpl::stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool FlipperConnectionManagerImpl::isConnected() const {
|
bool FlipperConnectionManagerImpl::isConnected() const {
|
||||||
return isConnected_ && connectionIsTrusted_;
|
return isConnected_ && isConnectionTrusted_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperConnectionManagerImpl::setCallbacks(Callbacks* callbacks) {
|
void FlipperConnectionManagerImpl::setCallbacks(Callbacks* callbacks) {
|
||||||
@@ -341,10 +301,10 @@ void FlipperConnectionManagerImpl::setCallbacks(Callbacks* callbacks) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FlipperConnectionManagerImpl::sendMessage(const folly::dynamic& message) {
|
void FlipperConnectionManagerImpl::sendMessage(const folly::dynamic& message) {
|
||||||
flipperScheduler_->schedule([this, message]() {
|
scheduler_->schedule([this, message]() {
|
||||||
try {
|
try {
|
||||||
if (client_) {
|
if (socket_) {
|
||||||
client_->send(message, []() {});
|
socket_->send(message, []() {});
|
||||||
}
|
}
|
||||||
} catch (std::length_error& e) {
|
} catch (std::length_error& e) {
|
||||||
// Skip sending messages that are too large.
|
// Skip sending messages that are too large.
|
||||||
@@ -355,10 +315,10 @@ void FlipperConnectionManagerImpl::sendMessage(const folly::dynamic& message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FlipperConnectionManagerImpl::sendMessageRaw(const std::string& message) {
|
void FlipperConnectionManagerImpl::sendMessageRaw(const std::string& message) {
|
||||||
flipperScheduler_->schedule([this, message]() {
|
scheduler_->schedule([this, message]() {
|
||||||
try {
|
try {
|
||||||
if (client_) {
|
if (socket_) {
|
||||||
client_->send(message, []() {});
|
socket_->send(message, []() {});
|
||||||
}
|
}
|
||||||
} catch (std::length_error& e) {
|
} catch (std::length_error& e) {
|
||||||
// Skip sending messages that are too large.
|
// Skip sending messages that are too large.
|
||||||
@@ -379,7 +339,7 @@ bool FlipperConnectionManagerImpl::isCertificateExchangeNeeded() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto last_known_medium = contextStore_->getLastKnownMedium();
|
auto last_known_medium = store_->getLastKnownMedium();
|
||||||
if (!last_known_medium) {
|
if (!last_known_medium) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -387,15 +347,15 @@ bool FlipperConnectionManagerImpl::isCertificateExchangeNeeded() {
|
|||||||
// When we exchange certs over WWW, we use a fake generated serial number and
|
// When we exchange certs over WWW, we use a fake generated serial number and
|
||||||
// a virtual device. If medium changes to FS_ACCESS at some point, we should
|
// a virtual device. If medium changes to FS_ACCESS at some point, we should
|
||||||
// restart the exchange process to get the device ID of the real device.
|
// restart the exchange process to get the device ID of the real device.
|
||||||
int medium = certProvider_ != nullptr
|
int medium = certificateProvider_ != nullptr
|
||||||
? certProvider_->getCertificateExchangeMedium()
|
? certificateProvider_->getCertificateExchangeMedium()
|
||||||
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
||||||
if (last_known_medium != medium) {
|
if (last_known_medium != medium) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto step = flipperState_->start("Check required certificates are present");
|
auto step = state_->start("Check required certificates are present");
|
||||||
bool hasRequiredFiles = contextStore_->hasRequiredFiles();
|
bool hasRequiredFiles = store_->hasRequiredFiles();
|
||||||
if (hasRequiredFiles) {
|
if (hasRequiredFiles) {
|
||||||
step->complete();
|
step->complete();
|
||||||
}
|
}
|
||||||
@@ -406,40 +366,27 @@ void FlipperConnectionManagerImpl::processSignedCertificateResponse(
|
|||||||
std::shared_ptr<FlipperStep> gettingCert,
|
std::shared_ptr<FlipperStep> gettingCert,
|
||||||
std::string response,
|
std::string response,
|
||||||
bool isError) {
|
bool isError) {
|
||||||
/**
|
|
||||||
Need to keep track of whether the response has been
|
|
||||||
handled. On success, the completion handler deallocates the socket which in
|
|
||||||
turn triggers a disconnect. A disconnect is called within
|
|
||||||
the context of a subscription handler. This means that the completion
|
|
||||||
handler can be called again to notify that the stream has
|
|
||||||
been interrupted because we are effectively still handing the response
|
|
||||||
read. So, if already handled, ignore and return;
|
|
||||||
*/
|
|
||||||
if (certificateExchangeCompleted_)
|
|
||||||
return;
|
|
||||||
certificateExchangeCompleted_ = true;
|
|
||||||
if (isError) {
|
if (isError) {
|
||||||
auto error =
|
auto error =
|
||||||
"Desktop failed to provide certificates. Error from flipper desktop:\n" +
|
"Flipper failed to provide certificates. Error from Flipper Desktop:\n" +
|
||||||
response;
|
response;
|
||||||
log(error);
|
log(error);
|
||||||
gettingCert->fail(error);
|
gettingCert->fail(error);
|
||||||
client_ = nullptr;
|
|
||||||
return;
|
} else {
|
||||||
}
|
int medium = certificateProvider_ != nullptr
|
||||||
int medium = certProvider_ != nullptr
|
? certificateProvider_->getCertificateExchangeMedium()
|
||||||
? certProvider_->getCertificateExchangeMedium()
|
|
||||||
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
||||||
|
|
||||||
if (!response.empty()) {
|
if (!response.empty()) {
|
||||||
folly::dynamic config = folly::parseJson(response);
|
folly::dynamic config = folly::parseJson(response);
|
||||||
config["medium"] = medium;
|
config["medium"] = medium;
|
||||||
contextStore_->storeConnectionConfig(config);
|
store_->storeConnectionConfig(config);
|
||||||
}
|
}
|
||||||
if (certProvider_) {
|
if (certificateProvider_) {
|
||||||
certProvider_->setFlipperState(flipperState_);
|
certificateProvider_->setFlipperState(state_);
|
||||||
auto gettingCertFromProvider =
|
auto gettingCertFromProvider =
|
||||||
flipperState_->start("Getting cert from Cert Provider");
|
state_->start("Getting client certificate from Certificate Provider");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Certificates should be present in app's sandbox after it is
|
// Certificates should be present in app's sandbox after it is
|
||||||
@@ -449,66 +396,58 @@ void FlipperConnectionManagerImpl::processSignedCertificateResponse(
|
|||||||
// and recreates the app.csr. By the time completion block is
|
// and recreates the app.csr. By the time completion block is
|
||||||
// called the DeviceCA cert doesn't match app's csr and it
|
// called the DeviceCA cert doesn't match app's csr and it
|
||||||
// throws an SSL error.
|
// throws an SSL error.
|
||||||
certProvider_->getCertificates(
|
certificateProvider_->getCertificates(
|
||||||
contextStore_->getCertificateDirectoryPath(),
|
store_->getCertificateDirectoryPath(), store_->getDeviceId());
|
||||||
contextStore_->getDeviceId());
|
|
||||||
gettingCertFromProvider->complete();
|
gettingCertFromProvider->complete();
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
gettingCertFromProvider->fail(e.what());
|
gettingCertFromProvider->fail(e.what());
|
||||||
gettingCert->fail(e.what());
|
gettingCert->fail(e.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
gettingCertFromProvider->fail("Exception from certProvider");
|
gettingCertFromProvider->fail(
|
||||||
gettingCert->fail("Exception from certProvider");
|
"Exception thrown from Certificate Provider");
|
||||||
|
gettingCert->fail("Exception thrown from Certificate Provider");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log("Certificate exchange complete.");
|
log("Certificate exchange complete.");
|
||||||
gettingCert->complete();
|
gettingCert->complete();
|
||||||
|
}
|
||||||
|
|
||||||
// Disconnect after message sending is complete.
|
socket_ = nullptr;
|
||||||
// The client destructor will send a disconnected event
|
reconnect();
|
||||||
// which will be handled by Flipper which will initiate
|
|
||||||
// a reconnect sequence.
|
|
||||||
client_ = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperConnectionManagerImpl::requestSignedCertificate() {
|
void FlipperConnectionManagerImpl::requestSignedCertificate() {
|
||||||
auto resettingState = flipperState_->start("Reset connection store state");
|
auto resettingState = state_->start("Reset connection store state");
|
||||||
contextStore_->resetState();
|
store_->resetState();
|
||||||
resettingState->complete();
|
resettingState->complete();
|
||||||
|
|
||||||
auto generatingCSR = flipperState_->start("Generate CSR");
|
auto generatingCSR = state_->start("Generate CSR");
|
||||||
std::string csr = contextStore_->getCertificateSigningRequest();
|
std::string csr = store_->getCertificateSigningRequest();
|
||||||
generatingCSR->complete();
|
generatingCSR->complete();
|
||||||
|
|
||||||
int medium = certProvider_ != nullptr
|
int medium = certificateProvider_ != nullptr
|
||||||
? certProvider_->getCertificateExchangeMedium()
|
? certificateProvider_->getCertificateExchangeMedium()
|
||||||
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
||||||
folly::dynamic message = folly::dynamic::object("method", "signCertificate")(
|
folly::dynamic message =
|
||||||
"csr", csr.c_str())(
|
folly::dynamic::object("method", "signCertificate")("csr", csr.c_str())(
|
||||||
"destination",
|
"destination",
|
||||||
contextStore_->getCertificateDirectoryPath().c_str())("medium", medium);
|
store_->getCertificateDirectoryPath().c_str())("medium", medium);
|
||||||
|
|
||||||
auto gettingCert = flipperState_->start("Getting cert from desktop");
|
auto gettingCert = state_->start("Getting cert from desktop");
|
||||||
|
|
||||||
certificateExchangeCompleted_ = false;
|
socket_->sendExpectResponse(
|
||||||
flipperScheduler_->schedule([this, message, gettingCert]() {
|
|
||||||
if (!client_) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
client_->sendExpectResponse(
|
|
||||||
folly::toJson(message),
|
folly::toJson(message),
|
||||||
[this, gettingCert](const std::string& response, bool isError) {
|
[this, gettingCert](const std::string& response, bool isError) {
|
||||||
flipperScheduler_->schedule([this, gettingCert, response, isError]() {
|
scheduler_->schedule([this, gettingCert, response, isError]() {
|
||||||
this->processSignedCertificateResponse(
|
this->processSignedCertificateResponse(
|
||||||
gettingCert, response, isError);
|
gettingCert, response, isError);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
failedConnectionAttempts_ = 0;
|
failedConnectionAttempts_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlipperConnectionManagerImpl::isRunningInOwnThread() {
|
bool FlipperConnectionManagerImpl::isRunningInOwnThread() {
|
||||||
return flipperScheduler_->isRunningInOwnThread();
|
return scheduler_->isRunningInOwnThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace flipper
|
} // namespace flipper
|
||||||
|
|||||||
@@ -55,33 +55,35 @@ class FlipperConnectionManagerImpl : public FlipperConnectionManager {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool isConnected_ = false;
|
bool isConnected_ = false;
|
||||||
bool isStarted_ = false;
|
bool started_ = false;
|
||||||
std::shared_ptr<FlipperCertificateProvider> certProvider_ = nullptr;
|
bool isConnectionTrusted_ = false;
|
||||||
|
|
||||||
|
std::shared_ptr<FlipperCertificateProvider> certificateProvider_ = nullptr;
|
||||||
|
|
||||||
Callbacks* callbacks_;
|
Callbacks* callbacks_;
|
||||||
|
|
||||||
DeviceData deviceData_;
|
DeviceData deviceData_;
|
||||||
std::shared_ptr<FlipperState> flipperState_;
|
|
||||||
|
std::shared_ptr<FlipperState> state_;
|
||||||
|
|
||||||
int insecurePort;
|
int insecurePort;
|
||||||
int securePort;
|
int securePort;
|
||||||
int altInsecurePort;
|
int altInsecurePort;
|
||||||
int altSecurePort;
|
int altSecurePort;
|
||||||
|
|
||||||
Scheduler* flipperScheduler_;
|
Scheduler* scheduler_;
|
||||||
Scheduler* connectionScheduler_;
|
Scheduler* connectionScheduler_;
|
||||||
|
|
||||||
std::unique_ptr<FlipperSocket> client_;
|
std::unique_ptr<FlipperSocket> socket_;
|
||||||
|
|
||||||
bool connectionIsTrusted_;
|
|
||||||
bool certificateExchangeCompleted_ = false;
|
|
||||||
|
|
||||||
int failedConnectionAttempts_ = 0;
|
int failedConnectionAttempts_ = 0;
|
||||||
int failedSocketConnectionAttempts = 0;
|
|
||||||
|
|
||||||
std::shared_ptr<ConnectionContextStore> contextStore_;
|
std::shared_ptr<ConnectionContextStore> store_;
|
||||||
std::shared_ptr<FlipperConnectionManagerWrapper> implWrapper_;
|
std::shared_ptr<FlipperConnectionManagerWrapper> implWrapper_;
|
||||||
|
|
||||||
void startSync();
|
void startSync();
|
||||||
bool connectAndExchangeCertificate();
|
void connectAndExchangeCertificate();
|
||||||
bool connectSecurely();
|
void connectSecurely();
|
||||||
void handleSocketEvent(const SocketEvent event);
|
void handleSocketEvent(const SocketEvent event);
|
||||||
bool isCertificateExchangeNeeded();
|
bool isCertificateExchangeNeeded();
|
||||||
void requestSignedCertificate();
|
void requestSignedCertificate();
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class FlipperSocket {
|
|||||||
used or error.
|
used or error.
|
||||||
@param manager An instance of FlipperConnectionManager.
|
@param manager An instance of FlipperConnectionManager.
|
||||||
*/
|
*/
|
||||||
virtual bool connect(FlipperConnectionManager* manager) = 0;
|
virtual void connect(FlipperConnectionManager* manager) = 0;
|
||||||
/**
|
/**
|
||||||
Disconnect from the endpoint.
|
Disconnect from the endpoint.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ class BaseClient {
|
|||||||
messageHandler_ = std::move(messageHandler);
|
messageHandler_ = std::move(messageHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool connect(FlipperConnectionManager* manager) = 0;
|
virtual void connect(FlipperConnectionManager* manager) = 0;
|
||||||
virtual void disconnect() = 0;
|
virtual void disconnect() = 0;
|
||||||
|
|
||||||
virtual void send(
|
virtual void send(
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ void FlipperWebSocket::setMessageHandler(SocketMessageHandler messageHandler) {
|
|||||||
socket_->setMessageHandler(messageHandler);
|
socket_->setMessageHandler(messageHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlipperWebSocket::connect(FlipperConnectionManager* manager) {
|
void FlipperWebSocket::connect(FlipperConnectionManager* manager) {
|
||||||
return socket_->connect(manager);
|
socket_->connect(manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipperWebSocket::disconnect() {
|
void FlipperWebSocket::disconnect() {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class FlipperWebSocket : public FlipperSocket {
|
|||||||
virtual void setEventHandler(SocketEventHandler eventHandler) override;
|
virtual void setEventHandler(SocketEventHandler eventHandler) override;
|
||||||
virtual void setMessageHandler(SocketMessageHandler messageHandler) override;
|
virtual void setMessageHandler(SocketMessageHandler messageHandler) override;
|
||||||
|
|
||||||
virtual bool connect(FlipperConnectionManager* manager) override;
|
virtual void connect(FlipperConnectionManager* manager) override;
|
||||||
virtual void disconnect() override;
|
virtual void disconnect() override;
|
||||||
|
|
||||||
virtual void send(const folly::dynamic& message, SocketSendHandler completion)
|
virtual void send(const folly::dynamic& message, SocketSendHandler completion)
|
||||||
|
|||||||
@@ -62,9 +62,9 @@ WebSocketClient::~WebSocketClient() {
|
|||||||
disconnect();
|
disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocketClient::connect(FlipperConnectionManager* manager) {
|
void WebSocketClient::connect(FlipperConnectionManager*) {
|
||||||
if (status_ != Status::Unconnected) {
|
if (status_ != Status::Unconnected) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_ = Status::Connecting;
|
status_ = Status::Connecting;
|
||||||
@@ -89,7 +89,8 @@ bool WebSocketClient::connect(FlipperConnectionManager* manager) {
|
|||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
status_ = Status::Failed;
|
status_ = Status::Failed;
|
||||||
return false;
|
eventHandler_(SocketEvent::ERROR);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_ = connection_->get_handle();
|
handle_ = connection_->get_handle();
|
||||||
@@ -119,18 +120,7 @@ bool WebSocketClient::connect(FlipperConnectionManager* manager) {
|
|||||||
&socket_,
|
&socket_,
|
||||||
websocketpp::lib::placeholders::_1));
|
websocketpp::lib::placeholders::_1));
|
||||||
|
|
||||||
auto connected = connected_.get_future();
|
|
||||||
|
|
||||||
socket_.connect(connection_);
|
socket_.connect(connection_);
|
||||||
|
|
||||||
auto state = connected.wait_for(std::chrono::seconds(10));
|
|
||||||
if (state == std::future_status::ready) {
|
|
||||||
return connected.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
disconnect();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketClient::disconnect() {
|
void WebSocketClient::disconnect() {
|
||||||
@@ -147,8 +137,6 @@ void WebSocketClient::disconnect() {
|
|||||||
thread_->join();
|
thread_->join();
|
||||||
}
|
}
|
||||||
thread_ = nullptr;
|
thread_ = nullptr;
|
||||||
scheduler_->schedule(
|
|
||||||
[eventHandler = eventHandler_]() { eventHandler(SocketEvent::CLOSE); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketClient::send(
|
void WebSocketClient::send(
|
||||||
@@ -204,8 +192,7 @@ void WebSocketClient::onOpen(SocketClient* c, websocketpp::connection_hdl hdl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_ = Status::Initializing;
|
status_ = Status::Initializing;
|
||||||
scheduler_->schedule(
|
eventHandler_(SocketEvent::OPEN);
|
||||||
[eventHandler = eventHandler_]() { eventHandler(SocketEvent::OPEN); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketClient::onMessage(
|
void WebSocketClient::onMessage(
|
||||||
@@ -229,16 +216,14 @@ void WebSocketClient::onFail(SocketClient* c, websocketpp::connection_hdl hdl) {
|
|||||||
connected_.set_value(false);
|
connected_.set_value(false);
|
||||||
}
|
}
|
||||||
status_ = Status::Failed;
|
status_ = Status::Failed;
|
||||||
scheduler_->schedule(
|
eventHandler_(SocketEvent::ERROR);
|
||||||
[eventHandler = eventHandler_]() { eventHandler(SocketEvent::ERROR); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketClient::onClose(
|
void WebSocketClient::onClose(
|
||||||
SocketClient* c,
|
SocketClient* c,
|
||||||
websocketpp::connection_hdl hdl) {
|
websocketpp::connection_hdl hdl) {
|
||||||
status_ = Status::Closed;
|
status_ = Status::Closed;
|
||||||
scheduler_->schedule(
|
eventHandler_(SocketEvent::CLOSE);
|
||||||
[eventHandler = eventHandler_]() { eventHandler(SocketEvent::CLOSE); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace flipper
|
} // namespace flipper
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class WebSocketClient : public BaseClient {
|
|||||||
|
|
||||||
virtual ~WebSocketClient();
|
virtual ~WebSocketClient();
|
||||||
|
|
||||||
virtual bool connect(FlipperConnectionManager* manager) override;
|
virtual void connect(FlipperConnectionManager* manager) override;
|
||||||
virtual void disconnect() override;
|
virtual void disconnect() override;
|
||||||
|
|
||||||
virtual void send(const folly::dynamic& message, SocketSendHandler completion)
|
virtual void send(const folly::dynamic& message, SocketSendHandler completion)
|
||||||
|
|||||||
@@ -65,9 +65,9 @@ WebSocketTLSClient::~WebSocketTLSClient() {
|
|||||||
disconnect();
|
disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocketTLSClient::connect(FlipperConnectionManager* manager) {
|
void WebSocketTLSClient::connect(FlipperConnectionManager*) {
|
||||||
if (status_ != Status::Unconnected) {
|
if (status_ != Status::Unconnected) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_ = Status::Connecting;
|
status_ = Status::Connecting;
|
||||||
@@ -98,7 +98,8 @@ bool WebSocketTLSClient::connect(FlipperConnectionManager* manager) {
|
|||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
status_ = Status::Failed;
|
status_ = Status::Failed;
|
||||||
return false;
|
eventHandler_(SocketEvent::ERROR);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_ = connection_->get_handle();
|
handle_ = connection_->get_handle();
|
||||||
@@ -128,18 +129,7 @@ bool WebSocketTLSClient::connect(FlipperConnectionManager* manager) {
|
|||||||
&socket_,
|
&socket_,
|
||||||
websocketpp::lib::placeholders::_1));
|
websocketpp::lib::placeholders::_1));
|
||||||
|
|
||||||
auto connected = connected_.get_future();
|
|
||||||
|
|
||||||
socket_.connect(connection_);
|
socket_.connect(connection_);
|
||||||
|
|
||||||
auto state = connected.wait_for(std::chrono::seconds(10));
|
|
||||||
if (state == std::future_status::ready) {
|
|
||||||
return connected.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
disconnect();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketTLSClient::disconnect() {
|
void WebSocketTLSClient::disconnect() {
|
||||||
@@ -157,8 +147,6 @@ void WebSocketTLSClient::disconnect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
thread_ = nullptr;
|
thread_ = nullptr;
|
||||||
scheduler_->schedule(
|
|
||||||
[eventHandler = eventHandler_]() { eventHandler(SocketEvent::CLOSE); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketTLSClient::send(
|
void WebSocketTLSClient::send(
|
||||||
@@ -211,13 +199,8 @@ void WebSocketTLSClient::sendExpectResponse(
|
|||||||
void WebSocketTLSClient::onOpen(
|
void WebSocketTLSClient::onOpen(
|
||||||
SocketTLSClient* c,
|
SocketTLSClient* c,
|
||||||
websocketpp::connection_hdl hdl) {
|
websocketpp::connection_hdl hdl) {
|
||||||
if (status_ == Status::Connecting) {
|
|
||||||
connected_.set_value(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
status_ = Status::Initializing;
|
status_ = Status::Initializing;
|
||||||
scheduler_->schedule(
|
eventHandler_(SocketEvent::OPEN);
|
||||||
[eventHandler = eventHandler_]() { eventHandler(SocketEvent::OPEN); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketTLSClient::onMessage(
|
void WebSocketTLSClient::onMessage(
|
||||||
@@ -242,36 +225,19 @@ void WebSocketTLSClient::onFail(
|
|||||||
(reason.find("TLS handshake failed") != std::string::npos ||
|
(reason.find("TLS handshake failed") != std::string::npos ||
|
||||||
reason.find("Generic TLS related error") != std::string::npos);
|
reason.find("Generic TLS related error") != std::string::npos);
|
||||||
|
|
||||||
if (status_ == Status::Connecting) {
|
|
||||||
if (sslError) {
|
|
||||||
try {
|
|
||||||
connected_.set_exception(
|
|
||||||
std::make_exception_ptr(SSLException("SSL handshake failed")));
|
|
||||||
} catch (...) {
|
|
||||||
// set_exception() may throw an exception
|
|
||||||
// In that case, just set the value to false.
|
|
||||||
connected_.set_value(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
connected_.set_value(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
status_ = Status::Failed;
|
status_ = Status::Failed;
|
||||||
scheduler_->schedule([eventHandler = eventHandler_, sslError]() {
|
|
||||||
if (sslError) {
|
if (sslError) {
|
||||||
eventHandler(SocketEvent::SSL_ERROR);
|
eventHandler_(SocketEvent::SSL_ERROR);
|
||||||
} else {
|
} else {
|
||||||
eventHandler(SocketEvent::ERROR);
|
eventHandler_(SocketEvent::ERROR);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketTLSClient::onClose(
|
void WebSocketTLSClient::onClose(
|
||||||
SocketTLSClient* c,
|
SocketTLSClient* c,
|
||||||
websocketpp::connection_hdl hdl) {
|
websocketpp::connection_hdl hdl) {
|
||||||
status_ = Status::Closed;
|
status_ = Status::Closed;
|
||||||
scheduler_->schedule(
|
eventHandler_(SocketEvent::CLOSE);
|
||||||
[eventHandler = eventHandler_]() { eventHandler(SocketEvent::CLOSE); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketTLSContext WebSocketTLSClient::onTLSInit(
|
SocketTLSContext WebSocketTLSClient::onTLSInit(
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class WebSocketTLSClient : public BaseClient {
|
|||||||
|
|
||||||
virtual ~WebSocketTLSClient();
|
virtual ~WebSocketTLSClient();
|
||||||
|
|
||||||
virtual bool connect(FlipperConnectionManager* manager) override;
|
virtual void connect(FlipperConnectionManager* manager) override;
|
||||||
virtual void disconnect() override;
|
virtual void disconnect() override;
|
||||||
|
|
||||||
virtual void send(const folly::dynamic& message, SocketSendHandler completion)
|
virtual void send(const folly::dynamic& message, SocketSendHandler completion)
|
||||||
@@ -76,7 +76,6 @@ class WebSocketTLSClient : public BaseClient {
|
|||||||
|
|
||||||
SocketTLSThread thread_;
|
SocketTLSThread thread_;
|
||||||
websocketpp::connection_hdl handle_;
|
websocketpp::connection_hdl handle_;
|
||||||
std::promise<bool> connected_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace flipper
|
} // namespace flipper
|
||||||
|
|||||||
Reference in New Issue
Block a user