Process certificate signing request in the right event loop
Summary: To ensure that no deadlocks take place, it is important that there are no re-entrant calls from within the callbacks or event handlers. For the most part, this was already the case. Event and message handlers run critical sections into a Folly event scheduler. The only exception was the sendExpectResponse used during the certificate exchange. Once the response was received, the non-secure socket was disconnected. The solution was to put that operation in the Folly event scheduler as it should've been from the beginning. changelog: Certificate signing request response to be processed on the right event loop. Reviewed By: fabiomassimo Differential Revision: D35548148 fbshipit-source-id: cea2476ad66137f376acda66cdbc27801c0c47e1
This commit is contained in:
committed by
Facebook GitHub Bot
parent
30a1d09a83
commit
2bafe32f2a
@@ -233,7 +233,7 @@ bool FlipperConnectionManagerImpl::connectAndExchangeCertificate() {
|
||||
contextStore_->resetState();
|
||||
resettingState->complete();
|
||||
|
||||
requestSignedCertFromFlipper();
|
||||
requestSignedCertificate();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -377,33 +377,17 @@ bool FlipperConnectionManagerImpl::isCertificateExchangeNeeded() {
|
||||
return !hasRequiredFiles;
|
||||
}
|
||||
|
||||
void FlipperConnectionManagerImpl::requestSignedCertFromFlipper() {
|
||||
auto generatingCSR = flipperState_->start("Generate CSR");
|
||||
std::string csr = contextStore_->getCertificateSigningRequest();
|
||||
generatingCSR->complete();
|
||||
int medium = certProvider_ != nullptr
|
||||
? certProvider_->getCertificateExchangeMedium()
|
||||
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
||||
folly::dynamic message = folly::dynamic::object("method", "signCertificate")(
|
||||
"csr", csr.c_str())(
|
||||
"destination",
|
||||
contextStore_->getCertificateDirectoryPath().c_str())("medium", medium);
|
||||
auto gettingCert = flipperState_->start("Getting cert from desktop");
|
||||
|
||||
certificateExchangeCompleted_ = false;
|
||||
|
||||
flipperEventBase_->add([this, message, gettingCert, medium]() {
|
||||
client_->sendExpectResponse(
|
||||
folly::toJson(message),
|
||||
[this, message, gettingCert, medium](
|
||||
const std::string& response, bool isError) {
|
||||
void FlipperConnectionManagerImpl::processSignedCertificateResponse(
|
||||
std::shared_ptr<FlipperStep> gettingCert,
|
||||
std::string response,
|
||||
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
|
||||
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_)
|
||||
@@ -418,6 +402,10 @@ void FlipperConnectionManagerImpl::requestSignedCertFromFlipper() {
|
||||
client_ = nullptr;
|
||||
return;
|
||||
}
|
||||
int medium = certProvider_ != nullptr
|
||||
? certProvider_->getCertificateExchangeMedium()
|
||||
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
||||
|
||||
if (!response.empty()) {
|
||||
folly::dynamic config = folly::parseJson(response);
|
||||
config["medium"] = medium;
|
||||
@@ -456,6 +444,32 @@ void FlipperConnectionManagerImpl::requestSignedCertFromFlipper() {
|
||||
// which will be handled by Flipper which will initiate
|
||||
// a reconnect sequence.
|
||||
client_ = nullptr;
|
||||
}
|
||||
|
||||
void FlipperConnectionManagerImpl::requestSignedCertificate() {
|
||||
auto generatingCSR = flipperState_->start("Generate CSR");
|
||||
std::string csr = contextStore_->getCertificateSigningRequest();
|
||||
generatingCSR->complete();
|
||||
|
||||
int medium = certProvider_ != nullptr
|
||||
? certProvider_->getCertificateExchangeMedium()
|
||||
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
||||
folly::dynamic message = folly::dynamic::object("method", "signCertificate")(
|
||||
"csr", csr.c_str())(
|
||||
"destination",
|
||||
contextStore_->getCertificateDirectoryPath().c_str())("medium", medium);
|
||||
|
||||
auto gettingCert = flipperState_->start("Getting cert from desktop");
|
||||
|
||||
certificateExchangeCompleted_ = false;
|
||||
flipperEventBase_->add([this, message, gettingCert]() {
|
||||
client_->sendExpectResponse(
|
||||
folly::toJson(message),
|
||||
[this, gettingCert](const std::string& response, bool isError) {
|
||||
flipperEventBase_->add([this, gettingCert, response, isError]() {
|
||||
this->processSignedCertificateResponse(
|
||||
gettingCert, response, isError);
|
||||
});
|
||||
});
|
||||
});
|
||||
failedConnectionAttempts_ = 0;
|
||||
|
||||
@@ -82,7 +82,11 @@ class FlipperConnectionManagerImpl : public FlipperConnectionManager {
|
||||
bool connectAndExchangeCertificate();
|
||||
bool connectSecurely();
|
||||
bool isCertificateExchangeNeeded();
|
||||
void requestSignedCertFromFlipper();
|
||||
void requestSignedCertificate();
|
||||
void processSignedCertificateResponse(
|
||||
std::shared_ptr<FlipperStep> gettingCertificateStep,
|
||||
std::string response,
|
||||
bool isError);
|
||||
bool isRunningInOwnThread();
|
||||
void reevaluateSocketProvider();
|
||||
std::string getDeviceId();
|
||||
|
||||
Reference in New Issue
Block a user