bool DefaultAppTokenValidator::validate()

in quic/server/handshake/DefaultAppTokenValidator.cpp [34:165]


bool DefaultAppTokenValidator::validate(
    const fizz::server::ResumptionState& resumptionState) const {
  conn_->transportParamsMatching = false;
  conn_->sourceTokenMatching = false;
  bool validated = true;

  SCOPE_EXIT {
    if (validated) {
      QUIC_STATS(conn_->statsCallback, onZeroRttAccepted);
    } else {
      QUIC_STATS(conn_->statsCallback, onZeroRttRejected);
    }
  };

  if (!resumptionState.appToken) {
    VLOG(10) << "App token does not exist";
    return validated = false;
  }

  auto appToken = decodeAppToken(*resumptionState.appToken);
  if (!appToken) {
    VLOG(10) << "Failed to decode app token";
    return validated = false;
  }

  auto& params = appToken->transportParams.parameters;

  // TODO T33454954 Simplify ticket transport params. see comments in D9324131
  // Currenly only initialMaxData, initialMaxStreamData, ackDelayExponent, and
  // maxRecvPacketSize are written into the ticket. In case new parameters
  // are added for making early data decision (although not likely), this
  // validator fails the check if number of parameters is not
  // kExpectedNumOfParamsInTheTicket.
  if (params.size() != kExpectedNumOfParamsInTheTicket) {
    VLOG(10) << "Unexpected number of parameters in the ticket";
    return validated = false;
  }

  auto ticketIdleTimeout =
      getIntegerParameter(TransportParameterId::idle_timeout, params);
  if (!ticketIdleTimeout ||
      conn_->transportSettings.idleTimeout !=
          std::chrono::milliseconds(*ticketIdleTimeout)) {
    VLOG(10) << "Changed idle timeout";
    return validated = false;
  }

  auto ticketPacketSize =
      getIntegerParameter(TransportParameterId::max_packet_size, params);
  if (!ticketPacketSize ||
      conn_->transportSettings.maxRecvPacketSize < *ticketPacketSize) {
    VLOG(10) << "Decreased max receive packet size";
    return validated = false;
  }

  // if the current max data is less than the one advertised previously we
  // reject the early data
  auto ticketMaxData =
      getIntegerParameter(TransportParameterId::initial_max_data, params);
  if (!ticketMaxData ||
      conn_->transportSettings.advertisedInitialConnectionWindowSize <
          *ticketMaxData) {
    VLOG(10) << "Decreased max data";
    return validated = false;
  }

  auto ticketMaxStreamDataBidiLocal = getIntegerParameter(
      TransportParameterId::initial_max_stream_data_bidi_local, params);
  auto ticketMaxStreamDataBidiRemote = getIntegerParameter(
      TransportParameterId::initial_max_stream_data_bidi_remote, params);
  auto ticketMaxStreamDataUni = getIntegerParameter(
      TransportParameterId::initial_max_stream_data_uni, params);
  if (!ticketMaxStreamDataBidiLocal ||
      conn_->transportSettings.advertisedInitialBidiLocalStreamWindowSize <
          *ticketMaxStreamDataBidiLocal ||
      !ticketMaxStreamDataBidiRemote ||
      conn_->transportSettings.advertisedInitialBidiRemoteStreamWindowSize <
          *ticketMaxStreamDataBidiRemote ||
      !ticketMaxStreamDataUni ||
      conn_->transportSettings.advertisedInitialUniStreamWindowSize <
          *ticketMaxStreamDataUni) {
    VLOG(10) << "Decreased max stream data";
    return validated = false;
  }

  auto ticketMaxStreamsBidi = getIntegerParameter(
      TransportParameterId::initial_max_streams_bidi, params);
  auto ticketMaxStreamsUni = getIntegerParameter(
      TransportParameterId::initial_max_streams_uni, params);
  if (!ticketMaxStreamsBidi ||
      conn_->transportSettings.advertisedInitialMaxStreamsBidi <
          *ticketMaxStreamsBidi ||
      !ticketMaxStreamsUni ||
      conn_->transportSettings.advertisedInitialMaxStreamsUni <
          *ticketMaxStreamsUni) {
    VLOG(10) << "Decreased max streams";
    return validated = false;
  }

  // TODO max ack delay, is this really necessary?
  // spec says disable_migration should also be in the ticket. It shouldn't.

  conn_->transportParamsMatching = true;

  if (!validateAndUpdateSourceToken(
          *conn_, std::move(appToken->sourceAddresses))) {
    VLOG(10) << "No exact match from source address token";
    return validated = false;
  }

  // If application has set validator and the token is invalid, reject 0-RTT.
  // If application did not set validator, it's valid.
  if (conn_->earlyDataAppParamsValidator &&
      !conn_->earlyDataAppParamsValidator(
          resumptionState.alpn, appToken->appParams)) {
    VLOG(10) << "Invalid app params";
    return validated = false;
  }

  updateTransportParamsFromTicket(
      *conn_,
      *ticketIdleTimeout,
      *ticketPacketSize,
      *ticketMaxData,
      *ticketMaxStreamDataBidiLocal,
      *ticketMaxStreamDataBidiRemote,
      *ticketMaxStreamDataUni,
      *ticketMaxStreamsBidi,
      *ticketMaxStreamsUni);

  return validated;
}