folly::Optional ReadRecordLayer::decodeHandshakeMessage()

in fizz/record/RecordLayer.cpp [130:186]


folly::Optional<Param> ReadRecordLayer::decodeHandshakeMessage(
    folly::IOBufQueue& buf) {
  folly::io::Cursor cursor(buf.front());

  if (!cursor.canAdvance(kHandshakeHeaderSize)) {
    return folly::none;
  }

  auto handshakeType =
      static_cast<HandshakeType>(cursor.readBE<HandshakeTypeType>());
  auto length = detail::readBits24(cursor);

  if (length > kMaxHandshakeSize) {
    throw std::runtime_error("handshake record too big");
  }
  if (buf.chainLength() < (cursor - buf.front()) + length) {
    return folly::none;
  }

  Buf handshakeMsg;
  cursor.clone(handshakeMsg, length);
  auto original = buf.split(kHandshakeHeaderSize + length);

  switch (handshakeType) {
    case HandshakeType::client_hello:
      return parse<ClientHello>(std::move(handshakeMsg), std::move(original));
    case HandshakeType::server_hello:
      return parse<ServerHello>(std::move(handshakeMsg), std::move(original));
    case HandshakeType::end_of_early_data:
      return parse<EndOfEarlyData>(
          std::move(handshakeMsg), std::move(original));
    case HandshakeType::new_session_ticket:
      return parse<NewSessionTicket>(
          std::move(handshakeMsg), std::move(original));
    case HandshakeType::encrypted_extensions:
      return parse<EncryptedExtensions>(
          std::move(handshakeMsg), std::move(original));
    case HandshakeType::certificate:
      return parse<CertificateMsg>(
          std::move(handshakeMsg), std::move(original));
    case HandshakeType::compressed_certificate:
      return parse<CompressedCertificate>(
          std::move(handshakeMsg), std::move(original));
    case HandshakeType::certificate_request:
      return parse<CertificateRequest>(
          std::move(handshakeMsg), std::move(original));
    case HandshakeType::certificate_verify:
      return parse<CertificateVerify>(
          std::move(handshakeMsg), std::move(original));
    case HandshakeType::finished:
      return parse<Finished>(std::move(handshakeMsg), std::move(original));
    case HandshakeType::key_update:
      return parse<KeyUpdate>(std::move(handshakeMsg), std::move(original));
    default:
      throw std::runtime_error("unknown handshake type");
  };
}