Package org.mariadb.jdbc.client.impl
Class StandardClient
- java.lang.Object
-
- org.mariadb.jdbc.client.impl.StandardClient
-
- All Implemented Interfaces:
java.lang.AutoCloseable,Client
- Direct Known Subclasses:
ReplayClient
public class StandardClient extends java.lang.Object implements Client, java.lang.AutoCloseable
Connection client
-
-
Field Summary
Fields Modifier and Type Field Description private AuthenticationPluginauthPluginprivate byte[]certFingerprintprivate booleanclosedprivate MutableBytecompressionSequenceprivate Configurationconfprivate longconnectDeadlineNsprotected Contextcontextconnection contextprivate booleandisablePipelineprotected ExceptionFactoryexceptionFactoryconnection exception factoryprivate HostAddresshostAddressprivate ClosableLocklockprivate static Loggerloggerprivate static intMAX_AUTHENTICATION_SWITCHmaximum number of authentication switch requests a server may send during connectionprivate Readerreaderprivate static java.util.regex.PatternREDIRECT_PATTERNprivate java.util.function.Consumer<java.lang.String>redirectConsumerprivate MutableBytesequenceprivate java.net.Socketsocketconnection socket: the TLS socket once TLS is negotiated, the transport socket beforeprivate intsocketTimeoutprivate ClientMessagestreamMsgprivate StatementstreamStmtprivate booleanunixSocketTransportwhether the transport is a unix domain socket (a MitM-proof connection method)protected Writerwriterpacket writer
-
Constructor Summary
Constructors Constructor Description StandardClient(Configuration conf, HostAddress hostAddress, ClosableLock lock, boolean skipPostCommands)Constructor
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description voidabort(java.util.concurrent.Executor executor)Abort current connectionprivate voidaddAutoCommitCommand(Context context, java.util.List<java.lang.String> commands)private voidaddCharsetCommand(Context context, java.util.List<java.lang.String> commands)private voidaddCustomSessionVariables(java.util.List<java.lang.String> commands)private voidaddFixedOffsetTimeZone(java.time.ZoneId connectionZoneId, java.util.List<java.lang.String> commands)private voidaddReadOnlyCommand(Context context, java.util.List<java.lang.String> commands)private voidaddSessionTrackingCommand(Context context, java.util.List<java.lang.String> commands)private voidaddTimeZoneCommand(Context context, java.util.List<java.lang.String> commands)private voidaddTransactionIsolationCommand(Context context, java.util.List<java.lang.String> commands)private voidaddTruncationCommand(java.util.List<java.lang.String> commands)private voidassignStream(java.io.OutputStream out, java.io.InputStream in, Configuration conf, java.lang.Long threadId)voidauthenticationHandler(Credential credential, HostAddress hostAddress)private java.lang.StringbuildFinalQuery(java.util.List<java.lang.String> commands)protected voidcheckNotClosed()Throw an exception if client is closedvoidclose()Close clientvoidclosePrepare(Prepare prepare)Close prepare commandprivate voidcloseSocket()private voidconfigureSslSocket(javax.net.ssl.SSLSocket sslSocket, Configuration conf)private voidconfigureTimeout()(package private) static booleanconnectDeadlineReached(long deadlineNs, int connectTimeout)Indicate if the connection phase has exhausted the connectTimeout budget.java.lang.StringcreateSessionVariableQuery(Context context)Creates a query string for setting session variables based on context and configuration.private javax.net.ssl.SSLSocketcreateSslSocket(Configuration conf, TlsSocketPlugin socketPlugin, javax.net.ssl.TrustManager[] trustManagers)protected voiddestroySocket()Closing socket in case of Connection error after socket creation.private java.lang.StringdetermineAuthType(InitialHandshakePacket handshake)private SslModedetermineSslMode(Configuration conf)java.util.List<Completion>execute(ClientMessage message, boolean canRedo)Send client message and read resultjava.util.List<Completion>execute(ClientMessage message, Statement stmt, boolean canRedo)Send client message and read resultjava.util.List<Completion>execute(ClientMessage message, Statement stmt, int fetchSize, long maxRows, int resultSetConcurrency, int resultSetType, boolean closeOnCompletion, boolean canRedo)Send client message and read resultjava.util.List<Completion>executePipeline(ClientMessage[] messages, Statement stmt, int fetchSize, long maxRows, int resultSetConcurrency, int resultSetType, boolean closeOnCompletion, boolean canRedo)Send client messages pipelining and read resultContextgetContext()Get connection contextExceptionFactorygetExceptionFactory()Get connection exception factoryHostAddressgetHostAddress()Get connection hostjava.lang.StringgetSocketIp()Get current socket IP or null (for Pipe / unix socket)intgetSocketTimeout()get socket timeoutprivate voidhandleAuthentication(InitialHandshakePacket handshake, long clientCapabilities)private voidhandleConnectionError(java.sql.SQLException e)private voidhandleIOError(java.io.IOException e)private InitialHandshakePackethandleServerHandshake()private javax.net.ssl.SSLSockethandleSSLConnection(InitialHandshakePacket handshake, long clientCapabilities)private voidhandleSslHandshake(javax.net.ssl.SSLSocket sslSocket, javax.net.ssl.TrustManager[] trustManagers)private voidhandleTimeoutError(java.net.SocketTimeoutException e)private voidhandleTimezone()load server timezone and ensure this corresponds to client timezonestatic java.lang.StringhidePassword(java.lang.String redirectUrl)Mask the password of a redirection url (scheme://user:password@host...) so the credentials a server embeds inredirect_urlare not written to the logs.private voidinitializeContext(InitialHandshakePacket handshake, long clientCapabilities)private booleanisAutoCommitUpdateRequired(Context context, boolean canRelyOnConnectionFlag)booleanisClosed()Is client closedprivate booleanisDefaultCharsetSufficient(Context context)booleanisPrimary()is current client writer or read-onlyprivate booleanisReliableConnectionFlag(Context context)private voidpostConnectionQueries()CompletionreadPacket(ClientMessage message)Read a MySQL packet from socketCompletionreadPacket(Statement stmt, ClientMessage message, int fetchSize, long maxRows, int resultSetConcurrency, int resultSetType, boolean closeOnCompletion)Read server response packet.voidreadResponse(ClientMessage message)Read server responsejava.util.List<Completion>readResponse(Statement stmt, ClientMessage message, int fetchSize, long maxRows, int resultSetConcurrency, int resultSetType, boolean closeOnCompletion)Read server responses for a client messageprivate voidreadResults(Statement stmt, ClientMessage message, java.util.List<Completion> completions, int fetchSize, long maxRows, int resultSetConcurrency, int resultSetType, boolean closeOnCompletion)voidreadStreamingResults(java.util.List<Completion> completions, int fetchSize, long maxRows, int resultSetConcurrency, int resultSetType, boolean closeOnCompletion)Read resultsvoidredirect(java.lang.String redirectUrl)private booleanredirectByDefault()Without permitRedirect, redirection is followed only on a fully verified TLS connection.private booleanrequiresHostnameVerification(SslMode sslMode)voidreset()Reset connectionprivate voidsendHandshakeResponse(InitialHandshakePacket handshake, long clientCapabilities, Credential credential, java.lang.String authType)intsendQuery(ClientMessage message)Send client message to serverprivate voidsendSslRequest(InitialHandshakePacket handshake, long clientCapabilities)voidsetReadOnly(boolean readOnly)Switch to a writer/read-only connection, no effet on mono-connectionvoidsetSocketTimeout(int milliseconds)Set socket timeoutprivate longsetupClientCapabilities(InitialHandshakePacket handshake)private voidsetupCompression(java.io.InputStream in, java.io.OutputStream out, long clientCapabilities, long threadId)private voidsetupConnection(boolean skipPostCommands)private voidthrowHandshakeError(ReadableByteBuf buf)private voidupdateThreadIds(InitialHandshakePacket handshake)private static booleanvalidateFingerPrint(AuthenticationPlugin authPlugin, byte[] validationHash, byte[] fingerPrint, Credential credential, byte[] seed)private voidvalidateServerSslCapability()private voidverifyHostname(javax.net.ssl.SSLSocket sslSocket, TlsSocketPlugin socketPlugin)
-
-
-
Field Detail
-
logger
private static final Logger logger
-
MAX_AUTHENTICATION_SWITCH
private static final int MAX_AUTHENTICATION_SWITCH
maximum number of authentication switch requests a server may send during connection- See Also:
- Constant Field Values
-
exceptionFactory
protected final ExceptionFactory exceptionFactory
connection exception factory
-
REDIRECT_PATTERN
private static final java.util.regex.Pattern REDIRECT_PATTERN
-
socket
private java.net.Socket socket
connection socket: the TLS socket once TLS is negotiated, the transport socket before
-
unixSocketTransport
private boolean unixSocketTransport
whether the transport is a unix domain socket (a MitM-proof connection method)
-
sequence
private final MutableByte sequence
-
compressionSequence
private final MutableByte compressionSequence
-
lock
private final ClosableLock lock
-
conf
private Configuration conf
-
authPlugin
private AuthenticationPlugin authPlugin
-
hostAddress
private HostAddress hostAddress
-
disablePipeline
private final boolean disablePipeline
-
context
protected Context context
connection context
-
writer
protected Writer writer
packet writer
-
closed
private boolean closed
-
reader
private Reader reader
-
certFingerprint
private byte[] certFingerprint
-
streamStmt
private Statement streamStmt
-
streamMsg
private ClientMessage streamMsg
-
socketTimeout
private int socketTimeout
-
connectDeadlineNs
private final long connectDeadlineNs
-
redirectConsumer
private final java.util.function.Consumer<java.lang.String> redirectConsumer
-
-
Constructor Detail
-
StandardClient
public StandardClient(Configuration conf, HostAddress hostAddress, ClosableLock lock, boolean skipPostCommands) throws java.sql.SQLException
Constructor- Parameters:
conf- configurationhostAddress- hostlock- thread lockerskipPostCommands- must connection post command be skipped- Throws:
java.sql.SQLException- if connection fails
-
-
Method Detail
-
setupConnection
private void setupConnection(boolean skipPostCommands) throws java.sql.SQLException, java.io.IOException- Throws:
java.sql.SQLExceptionjava.io.IOException
-
setupCompression
private void setupCompression(java.io.InputStream in, java.io.OutputStream out, long clientCapabilities, long threadId)
-
handleSSLConnection
private javax.net.ssl.SSLSocket handleSSLConnection(InitialHandshakePacket handshake, long clientCapabilities) throws java.sql.SQLException, java.io.IOException
- Throws:
java.sql.SQLExceptionjava.io.IOException
-
updateThreadIds
private void updateThreadIds(InitialHandshakePacket handshake)
-
determineSslMode
private SslMode determineSslMode(Configuration conf)
-
validateServerSslCapability
private void validateServerSslCapability() throws java.sql.SQLException- Throws:
java.sql.SQLException
-
sendSslRequest
private void sendSslRequest(InitialHandshakePacket handshake, long clientCapabilities) throws java.io.IOException
- Throws:
java.io.IOException
-
createSslSocket
private javax.net.ssl.SSLSocket createSslSocket(Configuration conf, TlsSocketPlugin socketPlugin, javax.net.ssl.TrustManager[] trustManagers) throws java.sql.SQLException, java.io.IOException
- Throws:
java.sql.SQLExceptionjava.io.IOException
-
configureSslSocket
private void configureSslSocket(javax.net.ssl.SSLSocket sslSocket, Configuration conf) throws java.sql.SQLException- Throws:
java.sql.SQLException
-
handleSslHandshake
private void handleSslHandshake(javax.net.ssl.SSLSocket sslSocket, javax.net.ssl.TrustManager[] trustManagers) throws java.io.IOException- Throws:
java.io.IOException
-
requiresHostnameVerification
private boolean requiresHostnameVerification(SslMode sslMode)
-
verifyHostname
private void verifyHostname(javax.net.ssl.SSLSocket sslSocket, TlsSocketPlugin socketPlugin) throws java.sql.SQLException- Throws:
java.sql.SQLException
-
configureTimeout
private void configureTimeout() throws java.sql.SQLException- Throws:
java.sql.SQLException
-
handleServerHandshake
private InitialHandshakePacket handleServerHandshake() throws java.sql.SQLException, java.io.IOException
- Throws:
java.sql.SQLExceptionjava.io.IOException
-
throwHandshakeError
private void throwHandshakeError(ReadableByteBuf buf) throws java.sql.SQLException
- Throws:
java.sql.SQLException
-
setupClientCapabilities
private long setupClientCapabilities(InitialHandshakePacket handshake)
-
initializeContext
private void initializeContext(InitialHandshakePacket handshake, long clientCapabilities)
-
handleAuthentication
private void handleAuthentication(InitialHandshakePacket handshake, long clientCapabilities) throws java.io.IOException, java.sql.SQLException
- Throws:
java.io.IOExceptionjava.sql.SQLException
-
determineAuthType
private java.lang.String determineAuthType(InitialHandshakePacket handshake)
-
handleConnectionError
private void handleConnectionError(java.sql.SQLException e) throws java.sql.SQLException- Throws:
java.sql.SQLException
-
handleTimeoutError
private void handleTimeoutError(java.net.SocketTimeoutException e) throws java.sql.SQLTimeoutException- Throws:
java.sql.SQLTimeoutException
-
handleIOError
private void handleIOError(java.io.IOException e) throws java.sql.SQLException- Throws:
java.sql.SQLException
-
sendHandshakeResponse
private void sendHandshakeResponse(InitialHandshakePacket handshake, long clientCapabilities, Credential credential, java.lang.String authType) throws java.io.IOException
- Throws:
java.io.IOException
-
connectDeadlineReached
static boolean connectDeadlineReached(long deadlineNs, int connectTimeout)Indicate if the connection phase has exhausted the connectTimeout budget. connectTimeout is applied as a socket timeout during connection, so it bounds each individual read, but not their number: without this check a malicious server can keep a client in the authentication phase forever by sending an endless stream of authentication switch requests.- Parameters:
deadlineNs- monotonic deadline (System.nanoTime()based)connectTimeout- configured connect timeout, in milliseconds, zero meaning no timeout- Returns:
- true if connectTimeout is set and the deadline is reached
-
authenticationHandler
public void authenticationHandler(Credential credential, HostAddress hostAddress) throws java.io.IOException, java.sql.SQLException
- Parameters:
credential- credentialhostAddress- host address- Throws:
java.io.IOException- if any socket error occursjava.sql.SQLException- if any other kind of issue occurs
-
validateFingerPrint
private static boolean validateFingerPrint(AuthenticationPlugin authPlugin, byte[] validationHash, byte[] fingerPrint, Credential credential, byte[] seed)
-
redirectByDefault
private boolean redirectByDefault()
Without permitRedirect, redirection is followed only on a fully verified TLS connection.
-
redirect
public void redirect(java.lang.String redirectUrl)
-
hidePassword
public static java.lang.String hidePassword(java.lang.String redirectUrl)
Mask the password of a redirection url (scheme://user:password@host...) so the credentials a server embeds inredirect_urlare not written to the logs.- Parameters:
redirectUrl- redirection url- Returns:
- url with the password component replaced by
***
-
assignStream
private void assignStream(java.io.OutputStream out, java.io.InputStream in, Configuration conf, java.lang.Long threadId)
-
destroySocket
protected void destroySocket()
Closing socket in case of Connection error after socket creation.
-
handleTimezone
private void handleTimezone() throws java.sql.SQLExceptionload server timezone and ensure this corresponds to client timezone- Throws:
java.sql.SQLException- if any socket error.
-
postConnectionQueries
private void postConnectionQueries() throws java.sql.SQLException- Throws:
java.sql.SQLException
-
createSessionVariableQuery
public java.lang.String createSessionVariableQuery(Context context)
Creates a query string for setting session variables based on context and configuration.- Parameters:
context- the connection context- Returns:
- query string for setting session variables or null if no variables need to be set
-
addAutoCommitCommand
private void addAutoCommitCommand(Context context, java.util.List<java.lang.String> commands)
-
isReliableConnectionFlag
private boolean isReliableConnectionFlag(Context context)
-
isAutoCommitUpdateRequired
private boolean isAutoCommitUpdateRequired(Context context, boolean canRelyOnConnectionFlag)
-
addTruncationCommand
private void addTruncationCommand(java.util.List<java.lang.String> commands)
-
addSessionTrackingCommand
private void addSessionTrackingCommand(Context context, java.util.List<java.lang.String> commands)
-
addTimeZoneCommand
private void addTimeZoneCommand(Context context, java.util.List<java.lang.String> commands)
-
addFixedOffsetTimeZone
private void addFixedOffsetTimeZone(java.time.ZoneId connectionZoneId, java.util.List<java.lang.String> commands)
-
addTransactionIsolationCommand
private void addTransactionIsolationCommand(Context context, java.util.List<java.lang.String> commands)
-
addReadOnlyCommand
private void addReadOnlyCommand(Context context, java.util.List<java.lang.String> commands)
-
addCharsetCommand
private void addCharsetCommand(Context context, java.util.List<java.lang.String> commands)
-
isDefaultCharsetSufficient
private boolean isDefaultCharsetSufficient(Context context)
-
addCustomSessionVariables
private void addCustomSessionVariables(java.util.List<java.lang.String> commands)
-
buildFinalQuery
private java.lang.String buildFinalQuery(java.util.List<java.lang.String> commands)
-
setReadOnly
public void setReadOnly(boolean readOnly) throws java.sql.SQLExceptionDescription copied from interface:ClientSwitch to a writer/read-only connection, no effet on mono-connection- Specified by:
setReadOnlyin interfaceClient- Parameters:
readOnly- must use read-only connection- Throws:
java.sql.SQLException- if any error occurs
-
sendQuery
public int sendQuery(ClientMessage message) throws java.sql.SQLException
Send client message to server- Parameters:
message- client message- Returns:
- number of command send
- Throws:
java.sql.SQLException- if socket error occurs
-
execute
public java.util.List<Completion> execute(ClientMessage message, boolean canRedo) throws java.sql.SQLException
Description copied from interface:ClientSend client message and read result
-
execute
public java.util.List<Completion> execute(ClientMessage message, Statement stmt, boolean canRedo) throws java.sql.SQLException
Description copied from interface:ClientSend client message and read result
-
executePipeline
public java.util.List<Completion> executePipeline(ClientMessage[] messages, Statement stmt, int fetchSize, long maxRows, int resultSetConcurrency, int resultSetType, boolean closeOnCompletion, boolean canRedo) throws java.sql.SQLException
Description copied from interface:ClientSend client messages pipelining and read result- Specified by:
executePipelinein interfaceClient- Parameters:
messages- client messagestmt- statementfetchSize- fetch sizemaxRows- maximum number of rows. 0 = allresultSetConcurrency- concurrencyresultSetType- result-set typecloseOnCompletion- close statement on completioncanRedo- can client message be redone in case of failover- Returns:
- results
- Throws:
java.sql.SQLException- if any error occurs
-
execute
public java.util.List<Completion> execute(ClientMessage message, Statement stmt, int fetchSize, long maxRows, int resultSetConcurrency, int resultSetType, boolean closeOnCompletion, boolean canRedo) throws java.sql.SQLException
Description copied from interface:ClientSend client message and read result- Specified by:
executein interfaceClient- Parameters:
message- client messagestmt- statementfetchSize- fetch sizemaxRows- maximum number of rows. 0 = allresultSetConcurrency- concurrencyresultSetType- result-set typecloseOnCompletion- close statement on completioncanRedo- can client message be redone in case of failover- Returns:
- results
- Throws:
java.sql.SQLException- if any error occurs
-
readResponse
public java.util.List<Completion> readResponse(Statement stmt, ClientMessage message, int fetchSize, long maxRows, int resultSetConcurrency, int resultSetType, boolean closeOnCompletion) throws java.sql.SQLException
Read server responses for a client message- Parameters:
stmt- statement that issue the messagemessage- client message sentfetchSize- fetch sizemaxRows- maximum number of rowsresultSetConcurrency- concurrencyresultSetType- result-set typecloseOnCompletion- close statement on resultset completion- Returns:
- list of result
- Throws:
java.sql.SQLException- if any error occurs
-
readResponse
public void readResponse(ClientMessage message) throws java.sql.SQLException
Read server response- Parameters:
message- client message that was sent- Throws:
java.sql.SQLException- if any error occurs
-
closePrepare
public void closePrepare(Prepare prepare) throws java.sql.SQLException
Description copied from interface:ClientClose prepare command- Specified by:
closePreparein interfaceClient- Parameters:
prepare- prepare command- Throws:
java.sql.SQLException- if any error occurs
-
readStreamingResults
public void readStreamingResults(java.util.List<Completion> completions, int fetchSize, long maxRows, int resultSetConcurrency, int resultSetType, boolean closeOnCompletion) throws java.sql.SQLException
Description copied from interface:ClientRead results- Specified by:
readStreamingResultsin interfaceClient- Parameters:
completions- List that will have the new resultsfetchSize- fetch sizemaxRows- maximum number of rows. 0 = allresultSetConcurrency- concurrencyresultSetType- result-set typecloseOnCompletion- close statement on completion- Throws:
java.sql.SQLException- if any error occurs
-
readResults
private void readResults(Statement stmt, ClientMessage message, java.util.List<Completion> completions, int fetchSize, long maxRows, int resultSetConcurrency, int resultSetType, boolean closeOnCompletion) throws java.sql.SQLException
- Throws:
java.sql.SQLException
-
readPacket
public Completion readPacket(ClientMessage message) throws java.sql.SQLException
Read a MySQL packet from socket- Parameters:
message- client message issuing the result- Returns:
- a mysql result
- Throws:
java.sql.SQLException- if any error occurs
-
readPacket
public Completion readPacket(Statement stmt, ClientMessage message, int fetchSize, long maxRows, int resultSetConcurrency, int resultSetType, boolean closeOnCompletion) throws java.sql.SQLException
Read server response packet.- Parameters:
stmt- current statement (null if internal)message- current messagefetchSize- default fetch sizemaxRows- maximum row numberresultSetConcurrency- concurrencyresultSetType- typecloseOnCompletion- must resultset close statement on completion- Returns:
- Completion
- Throws:
java.sql.SQLException- if any exception- See Also:
- server response packets
-
checkNotClosed
protected void checkNotClosed() throws java.sql.SQLExceptionThrow an exception if client is closed- Throws:
java.sql.SQLException- if closed
-
closeSocket
private void closeSocket()
-
isClosed
public boolean isClosed()
Description copied from interface:ClientIs client closed
-
getContext
public Context getContext()
Description copied from interface:ClientGet connection context- Specified by:
getContextin interfaceClient- Returns:
- connection context
-
abort
public void abort(java.util.concurrent.Executor executor) throws java.sql.SQLExceptionDescription copied from interface:ClientAbort current connection
-
getSocketTimeout
public int getSocketTimeout()
Description copied from interface:Clientget socket timeout- Specified by:
getSocketTimeoutin interfaceClient- Returns:
- socket timeout
-
setSocketTimeout
public void setSocketTimeout(int milliseconds) throws java.sql.SQLExceptionDescription copied from interface:ClientSet socket timeout- Specified by:
setSocketTimeoutin interfaceClient- Parameters:
milliseconds- timeout- Throws:
java.sql.SQLException- if any error occurs
-
close
public void close()
Description copied from interface:ClientClose client
-
getSocketIp
public java.lang.String getSocketIp()
Description copied from interface:ClientGet current socket IP or null (for Pipe / unix socket)- Specified by:
getSocketIpin interfaceClient- Returns:
- Socket current IP
-
isPrimary
public boolean isPrimary()
Description copied from interface:Clientis current client writer or read-only
-
getExceptionFactory
public ExceptionFactory getExceptionFactory()
Description copied from interface:ClientGet connection exception factory- Specified by:
getExceptionFactoryin interfaceClient- Returns:
- connection exception factory
-
getHostAddress
public HostAddress getHostAddress()
Description copied from interface:ClientGet connection host- Specified by:
getHostAddressin interfaceClient- Returns:
- connection host
-
-