Skip to content

Commit 1ffa518

Browse files
committed
fix(BinaryLogClient): use writeBuffered exclusively & adjust packetNum for SSL switch auth
1 parent d945684 commit 1ffa518

File tree

2 files changed

+17
-24
lines changed

2 files changed

+17
-24
lines changed

src/main/java/com/github/shyiko/mysql/binlog/BinaryLogClient.java

+15-12
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ private GreetingPacket receiveGreeting() throws IOException {
646646
}
647647

648648
private void enableHeartbeat() throws IOException {
649-
channel.write(new QueryCommand("set @master_heartbeat_period=" + heartbeatInterval * 1000000));
649+
channel.writeBuffered(new QueryCommand("set @master_heartbeat_period=" + heartbeatInterval * 1000000));
650650
byte[] statementResult = channel.read();
651651
if (statementResult[0] == (byte) 0xFF /* error */) {
652652
byte[] bytes = Arrays.copyOfRange(statementResult, 1, statementResult.length);
@@ -669,7 +669,7 @@ private void requestBinaryLogStream() throws IOException {
669669
dumpBinaryLogCommand = new DumpBinaryLogCommand(serverId, binlogFilename, binlogPosition);
670670
}
671671
}
672-
channel.write(dumpBinaryLogCommand);
672+
channel.writeBuffered(dumpBinaryLogCommand);
673673
}
674674

675675
private void ensureEventDataDeserializer(EventType eventType,
@@ -692,6 +692,8 @@ private void ensureEventDataDeserializer(EventType eventType,
692692
private void authenticate(GreetingPacket greetingPacket) throws IOException {
693693
int collation = greetingPacket.getServerCollation();
694694
int packetNumber = 1;
695+
696+
boolean usingSSLSocket = false;
695697
if (sslMode != SSLMode.DISABLED) {
696698
boolean serverSupportsSSL = (greetingPacket.getServerCapabilities() & ClientCapabilities.SSL) != 0;
697699
if (!serverSupportsSSL && (sslMode == SSLMode.REQUIRED || sslMode == SSLMode.VERIFY_CA ||
@@ -701,7 +703,7 @@ private void authenticate(GreetingPacket greetingPacket) throws IOException {
701703
if (serverSupportsSSL) {
702704
SSLRequestCommand sslRequestCommand = new SSLRequestCommand();
703705
sslRequestCommand.setCollation(collation);
704-
channel.write(sslRequestCommand, packetNumber++);
706+
channel.writeBuffered(sslRequestCommand, packetNumber++);
705707
SSLSocketFactory sslSocketFactory =
706708
this.sslSocketFactory != null ?
707709
this.sslSocketFactory :
@@ -710,12 +712,13 @@ private void authenticate(GreetingPacket greetingPacket) throws IOException {
710712
DEFAULT_VERIFY_CA_SSL_MODE_SOCKET_FACTORY;
711713
channel.upgradeToSSL(sslSocketFactory,
712714
sslMode == SSLMode.VERIFY_IDENTITY ? new TLSHostnameVerifier() : null);
715+
usingSSLSocket = true;
713716
}
714717
}
715718
AuthenticateCommand authenticateCommand = new AuthenticateCommand(schema, username, password,
716719
greetingPacket.getScramble());
717720
authenticateCommand.setCollation(collation);
718-
channel.write(authenticateCommand, packetNumber);
721+
channel.writeBuffered(authenticateCommand, packetNumber);
719722
byte[] authenticationResult = channel.read();
720723
if (authenticationResult[0] != (byte) 0x00 /* ok */) {
721724
if (authenticationResult[0] == (byte) 0xFF /* error */) {
@@ -724,14 +727,14 @@ private void authenticate(GreetingPacket greetingPacket) throws IOException {
724727
throw new AuthenticationException(errorPacket.getErrorMessage(), errorPacket.getErrorCode(),
725728
errorPacket.getSqlState());
726729
} else if (authenticationResult[0] == (byte) 0xFE) {
727-
switchAuthentication(authenticationResult);
730+
switchAuthentication(authenticationResult, usingSSLSocket);
728731
} else {
729732
throw new AuthenticationException("Unexpected authentication result (" + authenticationResult[0] + ")");
730733
}
731734
}
732735
}
733736

734-
private void switchAuthentication(byte[] authenticationResult) throws IOException {
737+
private void switchAuthentication(byte[] authenticationResult, boolean usingSSLSocket) throws IOException {
735738
/*
736739
Azure-MySQL likes to tell us to switch authentication methods, even though
737740
we haven't advertised that we support any. It uses this for some-odd
@@ -745,7 +748,7 @@ private void switchAuthentication(byte[] authenticationResult) throws IOExceptio
745748
String scramble = buffer.readZeroTerminatedString();
746749

747750
Command switchCommand = new AuthenticateNativePasswordCommand(scramble, password);
748-
channel.writeBuffered(switchCommand, 3);
751+
channel.writeBuffered(switchCommand, (usingSSLSocket? 4 : 3));
749752
byte[] authResult = channel.read();
750753

751754
if (authResult[0] != (byte) 0x00) {
@@ -787,7 +790,7 @@ public void run() {
787790
connectionLost = System.currentTimeMillis() - eventLastSeen > keepAliveInterval;
788791
} else {
789792
try {
790-
channel.write(new PingCommand());
793+
channel.writeBuffered(new PingCommand());
791794
} catch (IOException e) {
792795
connectionLost = true;
793796
}
@@ -891,7 +894,7 @@ public boolean isConnected() {
891894
}
892895

893896
private String fetchGtidPurged() throws IOException {
894-
channel.write(new QueryCommand("show global variables like 'gtid_purged'"));
897+
channel.writeBuffered(new QueryCommand("show global variables like 'gtid_purged'"));
895898
ResultSetRowPacket[] resultSet = readResultSet();
896899
if (resultSet.length != 0) {
897900
return resultSet[0].getValue(1).toUpperCase();
@@ -901,7 +904,7 @@ private String fetchGtidPurged() throws IOException {
901904

902905
private void fetchBinlogFilenameAndPosition() throws IOException {
903906
ResultSetRowPacket[] resultSet;
904-
channel.write(new QueryCommand("show master status"));
907+
channel.writeBuffered(new QueryCommand("show master status"));
905908
resultSet = readResultSet();
906909
if (resultSet.length == 0) {
907910
throw new IOException("Failed to determine binlog filename/position");
@@ -912,7 +915,7 @@ private void fetchBinlogFilenameAndPosition() throws IOException {
912915
}
913916

914917
private ChecksumType fetchBinlogChecksum() throws IOException {
915-
channel.write(new QueryCommand("show global variables like 'binlog_checksum'"));
918+
channel.writeBuffered(new QueryCommand("show global variables like 'binlog_checksum'"));
916919
ResultSetRowPacket[] resultSet = readResultSet();
917920
if (resultSet.length == 0) {
918921
return ChecksumType.NONE;
@@ -921,7 +924,7 @@ private ChecksumType fetchBinlogChecksum() throws IOException {
921924
}
922925

923926
private void confirmSupportOfChecksum(ChecksumType checksumType) throws IOException {
924-
channel.write(new QueryCommand("set @master_binlog_checksum= @@global.binlog_checksum"));
927+
channel.writeBuffered(new QueryCommand("set @master_binlog_checksum= @@global.binlog_checksum"));
925928
byte[] statementResult = channel.read();
926929
if (statementResult[0] == (byte) 0xFF /* error */) {
927930
byte[] bytes = Arrays.copyOfRange(statementResult, 1, statementResult.length);

src/main/java/com/github/shyiko/mysql/binlog/network/protocol/PacketChannel.java

+2-12
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,6 @@ public byte[] read() throws IOException {
6161
return inputStream.read(length);
6262
}
6363

64-
public void write(Command command, int packetNumber) throws IOException {
65-
byte[] body = command.toByteArray();
66-
outputStream.writeInteger(body.length, 3); // packet length
67-
outputStream.writeInteger(packetNumber, 1);
68-
outputStream.write(body, 0, body.length);
69-
// though it has no effect in case of default (underlying) output stream (SocketOutputStream),
70-
// it may be necessary in case of non-default one
71-
outputStream.flush();
72-
}
73-
7464
/*
7565
Azure's MySQL has bizarre network properties that force us to write an
7666
auth-response challenge in one shot, lest their hair catch on fire and
@@ -86,8 +76,8 @@ public void writeBuffered(Command command, int packetNumber) throws IOException
8676
socket.getOutputStream().write(buffer.toByteArray());
8777
}
8878

89-
public void write(Command command) throws IOException {
90-
write(command, 0);
79+
public void writeBuffered(Command command) throws IOException {
80+
writeBuffered(command, 0);
9181
}
9282

9383
public void upgradeToSSL(SSLSocketFactory sslSocketFactory, HostnameVerifier hostnameVerifier) throws IOException {

0 commit comments

Comments
 (0)