package io.vertx.pgclient.impl.codec;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import io.netty.buffer.ByteBuf;
import io.vertx.pgclient.impl.PgDatabaseMetadata;
import io.vertx.pgclient.impl.PgSocketConnection;
import io.vertx.pgclient.impl.util.ScramAuthentication;
import io.vertx.sqlclient.impl.Connection;
import io.vertx.sqlclient.impl.command.CommandResponse;
import io.vertx.sqlclient.impl.command.InitCommand;
class InitCommandCodec extends PgCommandCodec<Connection, InitCommand> {
private PgEncoder encoder;
private String encoding;
private ScramAuthentication scramAuthentication;
InitCommandCodec(InitCommand cmd) {
super(cmd);
}
@Override
void encode(PgEncoder encoder) {
this.encoder = encoder;
encoder.writeStartupMessage(new StartupMessage(cmd.username(), cmd.database(), cmd.properties()));
}
@Override
public void handleAuthenticationMD5Password(byte[] salt) {
encoder.writePasswordMessage(new PasswordMessage(cmd.username(), cmd.password(), salt));
encoder.flush();
}
@Override
public void handleAuthenticationClearTextPassword() {
encoder.writePasswordMessage(new PasswordMessage(cmd.username(), cmd.password(), null));
encoder.flush();
}
@Override
void handleAuthenticationSasl(ByteBuf in) {
scramAuthentication = new ScramAuthentication(cmd.username(), cmd.password());
encoder.writeScramClientInitialMessage(scramAuthentication.createInitialSaslMessage(in));
encoder.flush();
}
@Override
void handleAuthenticationSaslContinue(ByteBuf in) {
encoder.writeScramClientFinalMessage(new ScramClientFinalMessage(scramAuthentication.receiveServerFirstMessage(in)));
encoder.flush();
}
@Override
void handleAuthenticationSaslFinal(ByteBuf in) {
scramAuthentication.checkServerFinalMessage(in);
}
@Override
public void handleAuthenticationOk() {
}
@Override
public void handleParameterStatus(String key, String value) {
if(key.equals("client_encoding")) {
encoding = value;
}
if(key.equals("server_version")) {
((PgSocketConnection)cmd.connection()).dbMetaData = new PgDatabaseMetadata(value);
}
}
@Override
public void handleBackendKeyData(int processId, int secretKey) {
((PgSocketConnection)cmd.connection()).processId = processId;
((PgSocketConnection)cmd.connection()).secretKey = secretKey;
}
@Override
public void handleErrorResponse(ErrorResponse errorResponse) {
CommandResponse<Connection> resp = CommandResponse.failure(errorResponse.toException());
completionHandler.handle(resp);
}
@Override
public void handleReadyForQuery() {
Charset cs = null;
try {
cs = Charset.forName(encoding);
} catch (Exception ignore) {
}
CommandResponse<Connection> fut;
if(cs == null || !cs.equals(StandardCharsets.UTF_8)) {
fut = CommandResponse.failure(encoding + " is not supported in the client only UTF8");
} else {
fut = CommandResponse.success(cmd.connection());
}
completionHandler.handle(fut);
}
}