1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-04-18 17:24:03 +03:00
mvfst/quic/client/connector/QuicConnector.cpp
Hani Damlaj 00e67c1bf9 mvfst License Header Update
Reviewed By: lnicco

Differential Revision: D33587012

fbshipit-source-id: 972eb440f0156c9c04aa6e8787561b18295c1a97
2022-01-18 13:56:12 -08:00

136 lines
4.3 KiB
C++

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <quic/client/connector/QuicConnector.h>
#include <folly/io/SocketOptionMap.h>
#include <folly/io/async/AsyncSSLSocket.h>
#include <quic/api/QuicSocket.h>
#include <quic/congestion_control/CongestionControllerFactory.h>
#include <quic/fizz/client/handshake/FizzClientQuicHandshakeContext.h>
using namespace std;
namespace quic {
QuicConnector::QuicConnector(Callback* cb) : cb_(CHECK_NOTNULL(cb)) {}
void QuicConnector::onConnectionSetupError(
std::pair<quic::QuicErrorCode, std::string> code) noexcept {
if (cb_) {
cb_->onConnectError(std::move(code));
}
cleanUp();
}
void QuicConnector::onReplaySafe() noexcept {
if (cb_) {
cb_->onConnectSuccess();
}
cleanUpAndCloseSocket();
}
void QuicConnector::connect(
folly::EventBase* eventBase,
folly::Optional<folly::SocketAddress> localAddr,
const folly::SocketAddress& connectAddr,
std::shared_ptr<const fizz::client::FizzClientContext> fizzContext,
std::shared_ptr<const fizz::CertificateVerifier> verifier,
std::shared_ptr<quic::QuicPskCache> quicPskCache,
quic::TransportSettings transportSettings,
const std::vector<QuicVersion>& supportedQuicVersions,
std::chrono::milliseconds connectTimeout,
const folly::SocketOptionMap& socketOptions,
const folly::Optional<std::string>& sni,
std::shared_ptr<quic::QLogger> qLogger,
std::shared_ptr<quic::LoopDetectorCallback> quicLoopDetectorCallback,
std::shared_ptr<quic::QuicTransportStatsCallback>
quicTransportStatsCallback) {
if (isBusy()) {
LOG(ERROR) << "Already connecting...";
return;
}
auto sock = std::make_unique<folly::AsyncUDPSocket>(eventBase);
quicClient_ = quic::QuicClientTransport::newClient(
eventBase,
std::move(sock),
quic::FizzClientQuicHandshakeContext::Builder()
.setFizzClientContext(std::move(fizzContext))
.setCertificateVerifier(std::move(verifier))
.setPskCache(std::move(quicPskCache))
.build(),
0, /* connectionIdSize */
true /* useSplitConnectionCallbacks */);
quicClient_->setHostname(sni.value_or(connectAddr.getAddressStr()));
quicClient_->addNewPeerAddress(connectAddr);
if (localAddr.hasValue()) {
quicClient_->setLocalAddress(*localAddr);
}
quicClient_->setCongestionControllerFactory(
std::make_shared<quic::DefaultCongestionControllerFactory>());
quicClient_->setTransportStatsCallback(std::move(quicTransportStatsCallback));
quicClient_->setTransportSettings(std::move(transportSettings));
quicClient_->setQLogger(std::move(qLogger));
quicClient_->setLoopDetectorCallback(std::move(quicLoopDetectorCallback));
quicClient_->setSocketOptions(socketOptions);
quicClient_->setSupportedVersions(supportedQuicVersions);
VLOG(4) << "connecting to " << connectAddr.describe();
doConnect(connectTimeout);
}
void QuicConnector::connect(
std::shared_ptr<quic::QuicClientTransport> quicClient,
std::chrono::milliseconds connectTimeout) {
quicClient_ = std::move(quicClient);
doConnect(connectTimeout);
}
void QuicConnector::doConnect(std::chrono::milliseconds connectTimeout) {
connectStart_ = std::chrono::steady_clock::now();
quicClient_->getEventBase()->timer().scheduleTimeout(this, connectTimeout);
quicClient_->start(this, nullptr);
}
void QuicConnector::reset() {
cleanUpAndCloseSocket();
}
void QuicConnector::cleanUp() {
quicClient_.reset();
connectStart_ = TimePoint{};
}
void QuicConnector::cleanUpAndCloseSocket() {
if (quicClient_) {
auto error = std::make_pair(
quic::QuicErrorCode(quic::LocalErrorCode::SHUTTING_DOWN),
std::string("shutting down"));
quicClient_->close(std::move(error));
}
cleanUp();
}
std::chrono::milliseconds QuicConnector::timeElapsed() {
return timePointInitialized(connectStart_) ? millisecondsSince(connectStart_)
: std::chrono::milliseconds(0);
}
void QuicConnector::timeoutExpired() noexcept {
auto error = std::make_pair(
quic::QuicErrorCode(quic::LocalErrorCode::CONNECT_FAILED),
std::string("connect operation timed out"));
if (quicClient_) {
quicClient_->close(error);
}
onConnectionSetupError(std::move(error));
}
} // namespace quic