void onResponse()

in core/src/main/java/com/datastax/oss/driver/internal/core/channel/ProtocolInitHandler.java [199:353]


    void onResponse(Message response) {
      LOG.debug(
          "[{}] step {} received response opcode={}",
          logPrefix,
          step,
          ProtocolUtils.opcodeString(response.opcode));
      try {
        if (step == Step.OPTIONS && response instanceof Supported) {
          channel.attr(DriverChannel.OPTIONS_KEY).set(((Supported) response).options);
          step = Step.STARTUP;
          send();
        } else if (step == Step.STARTUP && response instanceof Ready) {
          maybeSwitchToModernFraming();
          context.getAuthProvider().ifPresent(provider -> provider.onMissingChallenge(endPoint));
          step = Step.GET_CLUSTER_NAME;
          send();
        } else if (step == Step.STARTUP && response instanceof Authenticate) {
          maybeSwitchToModernFraming();
          Authenticate authenticate = (Authenticate) response;
          authenticator = buildAuthenticator(endPoint, authenticate.authenticator);
          authenticator
              .initialResponse()
              .whenCompleteAsync(
                  (token, error) -> {
                    if (error != null) {
                      fail(
                          new AuthenticationException(
                              endPoint,
                              String.format(
                                  "Authenticator.initialResponse(): stage completed exceptionally (%s)",
                                  error),
                              error));
                    } else {
                      step = Step.AUTH_RESPONSE;
                      authResponseToken = token;
                      send();
                    }
                  },
                  channel.eventLoop())
              .exceptionally(UncaughtExceptions::log);
        } else if (step == Step.AUTH_RESPONSE && response instanceof AuthChallenge) {
          ByteBuffer challenge = ((AuthChallenge) response).token;
          authenticator
              .evaluateChallenge(challenge)
              .whenCompleteAsync(
                  (token, error) -> {
                    if (error != null) {
                      fail(
                          new AuthenticationException(
                              endPoint,
                              String.format(
                                  "Authenticator.evaluateChallenge(): stage completed exceptionally (%s)",
                                  error),
                              error));
                    } else {
                      step = Step.AUTH_RESPONSE;
                      authResponseToken = token;
                      send();
                    }
                  },
                  channel.eventLoop())
              .exceptionally(UncaughtExceptions::log);
        } else if (step == Step.AUTH_RESPONSE && response instanceof AuthSuccess) {
          ByteBuffer token = ((AuthSuccess) response).token;
          authenticator
              .onAuthenticationSuccess(token)
              .whenCompleteAsync(
                  (ignored, error) -> {
                    if (error != null) {
                      fail(
                          new AuthenticationException(
                              endPoint,
                              String.format(
                                  "Authenticator.onAuthenticationSuccess(): stage completed exceptionally (%s)",
                                  error),
                              error));
                    } else {
                      step = Step.GET_CLUSTER_NAME;
                      send();
                    }
                  },
                  channel.eventLoop())
              .exceptionally(UncaughtExceptions::log);
        } else if (step == Step.AUTH_RESPONSE
            && response instanceof Error
            && ((Error) response).code == ProtocolConstants.ErrorCode.AUTH_ERROR) {
          fail(
              new AuthenticationException(
                  endPoint,
                  String.format(
                      "server replied with '%s' to AuthResponse request",
                      ((Error) response).message)));
        } else if (step == Step.GET_CLUSTER_NAME && response instanceof Rows) {
          Rows rows = (Rows) response;
          List<ByteBuffer> row = Objects.requireNonNull(rows.getData().poll());
          String actualClusterName = getString(row, 0);
          if (expectedClusterName != null && !expectedClusterName.equals(actualClusterName)) {
            fail(
                new ClusterNameMismatchException(endPoint, actualClusterName, expectedClusterName));
          } else {
            if (expectedClusterName == null) {
              // Store the actual name so that it can be retrieved from the factory
              channel.attr(DriverChannel.CLUSTER_NAME_KEY).set(actualClusterName);
            }
            if (options.keyspace != null) {
              step = Step.SET_KEYSPACE;
              send();
            } else if (!options.eventTypes.isEmpty()) {
              step = Step.REGISTER;
              send();
            } else {
              setConnectSuccess();
            }
          }
        } else if (step == Step.SET_KEYSPACE && response instanceof SetKeyspace) {
          if (!options.eventTypes.isEmpty()) {
            step = Step.REGISTER;
            send();
          } else {
            setConnectSuccess();
          }
        } else if (step == Step.REGISTER && response instanceof Ready) {
          setConnectSuccess();
        } else if (response instanceof Error) {
          Error error = (Error) response;
          // Testing for a specific string is a tad fragile but Cassandra doesn't give us a more
          // precise error code.
          // C* 2.1 reports a server error instead of protocol error, see CASSANDRA-9451.
          boolean firstRequest =
              (step == Step.OPTIONS && querySupportedOptions) || step == Step.STARTUP;
          boolean serverOrProtocolError =
              error.code == ErrorCode.PROTOCOL_ERROR || error.code == ErrorCode.SERVER_ERROR;
          boolean badProtocolVersionMessage =
              error.message.contains("Invalid or unsupported protocol version")
                  // JAVA-2925: server is behind driver and considers the proposed version as beta
                  || error.message.contains("Beta version of the protocol used");
          if (firstRequest && serverOrProtocolError && badProtocolVersionMessage) {
            fail(
                UnsupportedProtocolVersionException.forSingleAttempt(
                    endPoint, initialProtocolVersion));
          } else if (step == Step.SET_KEYSPACE
              && error.code == ProtocolConstants.ErrorCode.INVALID) {
            fail(new InvalidKeyspaceException(error.message));
          } else {
            failOnUnexpected(error);
          }
        } else {
          failOnUnexpected(response);
        }
      } catch (AuthenticationException e) {
        fail(e);
      } catch (Throwable t) {
        fail(String.format("%s: unexpected exception (%s)", describe(), t), t);
      }
    }