package com.tesora.dve.db.mysql.libmy;
/*
* #%L
* Tesora Inc.
* Database Virtualization Engine
* %%
* Copyright (C) 2011 - 2014 Tesora Inc.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import static com.tesora.dve.db.mysql.libmy.MyProtocolDefs.MYSQL_PROTOCOL_VERSION;
import static com.tesora.dve.db.mysql.libmy.MyProtocolDefs.SERVER_STATUS_AUTOCOMMIT;
import com.tesora.dve.db.mysql.common.JavaCharsetCatalog;
import com.tesora.dve.db.mysql.common.MysqlHandshake;
import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import com.tesora.dve.db.mysql.common.MysqlAPIUtils;
import com.tesora.dve.db.mysql.portal.protocol.ClientCapabilities;
public class MyHandshakeV10 extends MyResponseMessage {
private byte protocolVersion = MYSQL_PROTOCOL_VERSION;
private String serverVersion;
private int threadID;
private String salt; // the full SALT which get broken up into the 2 scramble buffers
private String scrambleBuffer1st;
private String scrambleBuffer2nd;
private Integer scrambleBufferSize;
private byte[] serverCapabilities;
private long serverCapabilitiesasLong;
private byte serverCharset;
private short serverStatus = SERVER_STATUS_AUTOCOMMIT;
private String plugInProvidedData;
public MyHandshakeV10() {
};
public MyHandshakeV10(int connectionId, MysqlHandshake handshake) {
setThreadID(connectionId);
setServerVersion(handshake.getServerVersion());
setSalt(handshake.getSalt());
setServerCapabilities(handshake.getServerCapabilities());
setServerCharset(handshake.getServerCharSet());
setPlugInProvidedData(handshake.getPluginData());
}
public void setSalt(String salt) {
this.salt = salt;
scrambleBuffer1st = salt.substring(0,8);
scrambleBuffer2nd = salt.substring(8) + '\0';
scrambleBufferSize = scrambleBuffer1st.length() + scrambleBuffer2nd.length();
}
public String getSalt() {
if (salt == null) {
salt = scrambleBuffer1st + scrambleBuffer2nd;
}
return salt;
}
byte getServerCapabilities(short byteNum) {
return serverCapabilities[byteNum];
}
public long getServerCapabilities() {
return serverCapabilitiesasLong;
}
public void setServerCapabilities(long sc) {
serverCapabilitiesasLong = sc;
// store the capabilities flag in a byte[] to facilitate retrieval by
// byte later
serverCapabilities = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong(sc).array();
}
public String getServerVersion() {
return serverVersion;
}
public void setServerVersion(String serverVersion) {
this.serverVersion = serverVersion;
}
public byte getServerCharsetId() {
return serverCharset;
}
public void setServerCharset(byte serverCharset) {
this.serverCharset = serverCharset;
}
public String getPlugInProvidedData() {
return plugInProvidedData;
}
public void setPlugInProvidedData(String plugInProvidedData) {
this.plugInProvidedData = plugInProvidedData;
}
public int getThreadID() {
return threadID;
}
public void setThreadID(int threadID) {
this.threadID = threadID;
}
@Override
public void marshallMessage(ByteBuf cb) {
cb.writeByte(protocolVersion);
cb.writeBytes(getServerVersion().getBytes());
cb.writeZero(1);
cb.writeInt(getThreadID());
cb.writeBytes(scrambleBuffer1st.getBytes()); // Salt
cb.writeZero(1);
cb.writeByte(getServerCapabilities((byte) 0));
cb.writeByte(getServerCapabilities((byte) 1));
cb.writeByte(getServerCharsetId());
cb.writeShort(serverStatus);
cb.writeByte(getServerCapabilities((byte) 2));
cb.writeByte(getServerCapabilities((byte) 3));
cb.writeByte(scrambleBufferSize.byteValue());
cb.writeZero(10); // write 10 unused bytes
cb.writeBytes(scrambleBuffer2nd.getBytes()); // Salt
cb.writeBytes(getPlugInProvidedData().getBytes()); // payload
cb.writeZero(1);
}
@Override
public void unmarshallMessage(ByteBuf cb) {
protocolVersion = cb.readByte();
serverVersion = cb.readSlice(cb.bytesBefore((byte) 0)).toString(CharsetUtil.UTF_8);
cb.skipBytes(1); // skip the NULL terminator
threadID = cb.readInt();
scrambleBuffer1st = MysqlAPIUtils.readBytesAsString(cb, 8, CharsetUtil.ISO_8859_1);
cb.skipBytes(1);
long sc1 = cb.readUnsignedShort();
serverCharset = cb.readByte();
serverStatus = cb.readShort();
long sc2 = Long.rotateLeft(cb.readUnsignedShort(),16);
setServerCapabilities(sc1 + sc2);
scrambleBufferSize = new Integer(cb.readByte());
cb.skipBytes(10); //unused bytes
scrambleBuffer2nd = cb.readSlice(cb.bytesBefore((byte) 0)).toString(CharsetUtil.ISO_8859_1);
cb.skipBytes(1);
if ( (serverCapabilitiesasLong & ClientCapabilities.CLIENT_PLUGIN_AUTH) == ClientCapabilities.CLIENT_PLUGIN_AUTH) {
plugInProvidedData = cb.readSlice(cb.bytesBefore((byte) 0)).toString(CharsetUtil.UTF_8);
}
}
@Override
public MyMessageType getMessageType() {
return MyMessageType.SERVER_GREETING_RESPONSE;
}
public Charset getServerCharset(JavaCharsetCatalog catalog) {
return catalog.findJavaCharsetById(serverCharset);
}
}