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