static ClientHello getClientHello()

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;
}