in fizz/client/ClientProtocol.cpp [414:511]
static ClientHello getClientHello(
const Factory& /*factory*/,
const Random& random,
const std::vector<CipherSuite>& supportedCiphers,
const std::vector<ProtocolVersion>& supportedVersions,
const std::vector<NamedGroup>& supportedGroups,
const std::map<NamedGroup, std::unique_ptr<KeyExchange>>& shares,
const std::vector<SignatureScheme>& supportedSigSchemes,
const std::vector<PskKeyExchangeMode>& supportedPskModes,
const folly::Optional<std::string>& hostname,
const std::vector<std::string>& supportedAlpns,
const std::vector<CertificateCompressionAlgorithm>& compressionAlgos,
const Optional<EarlyDataParams>& earlyDataParams,
const Buf& legacySessionId,
ClientExtensions* extensions,
Optional<Extension> encodedECHExtension,
Buf cookie = nullptr) {
ClientHello chlo;
chlo.legacy_version = ProtocolVersion::tls_1_2;
chlo.random = random;
chlo.legacy_session_id = legacySessionId->clone();
chlo.cipher_suites = supportedCiphers;
chlo.legacy_compression_methods.push_back(0x00);
SupportedVersions versions;
versions.versions = supportedVersions;
chlo.extensions.push_back(encodeExtension(std::move(versions)));
SupportedGroups groups;
groups.named_group_list = supportedGroups;
chlo.extensions.push_back(encodeExtension(std::move(groups)));
ClientKeyShare keyShare;
for (const auto& share : shares) {
KeyShareEntry entry;
entry.group = share.first;
entry.key_exchange = share.second->getKeyShare();
keyShare.client_shares.push_back(std::move(entry));
}
chlo.extensions.push_back(encodeExtension(std::move(keyShare)));
SignatureAlgorithms sigAlgs;
sigAlgs.supported_signature_algorithms = supportedSigSchemes;
chlo.extensions.push_back(encodeExtension(std::move(sigAlgs)));
if (hostname) {
ServerNameList sni;
ServerName sn;
sn.hostname = folly::IOBuf::copyBuffer(*hostname);
sni.server_name_list.push_back(std::move(sn));
chlo.extensions.push_back(encodeExtension(std::move(sni)));
}
if (!supportedAlpns.empty()) {
ProtocolNameList alpn;
for (const auto& protoName : supportedAlpns) {
ProtocolName proto;
proto.name = folly::IOBuf::copyBuffer(protoName);
alpn.protocol_name_list.push_back(std::move(proto));
}
chlo.extensions.push_back(encodeExtension(std::move(alpn)));
}
if (!supportedPskModes.empty()) {
PskKeyExchangeModes modes;
modes.modes = supportedPskModes;
chlo.extensions.push_back(encodeExtension(std::move(modes)));
}
if (earlyDataParams) {
chlo.extensions.push_back(encodeExtension(ClientEarlyData()));
}
if (cookie) {
Cookie monster;
monster.cookie = std::move(cookie);
chlo.extensions.push_back(encodeExtension(std::move(monster)));
}
if (!compressionAlgos.empty()) {
CertificateCompressionAlgorithms algos;
algos.algorithms = compressionAlgos;
chlo.extensions.push_back(encodeExtension(std::move(algos)));
}
if (extensions) {
auto additionalExtensions = extensions->getClientHelloExtensions();
for (auto& ext : additionalExtensions) {
chlo.extensions.push_back(std::move(ext));
}
}
if (encodedECHExtension.has_value()) {
chlo.extensions.push_back(std::move(encodedECHExtension.value()));
}
return chlo;
}