package io.mycat.server;
import io.mycat.net.BufferArray;
import io.mycat.net.Connection;
import io.mycat.net.NetSystem;
import io.mycat.server.packet.AuthPacket;
import io.mycat.server.packet.ErrorPacket;
import io.mycat.server.packet.HandshakePacket;
import io.mycat.server.packet.util.CharsetUtil;
import io.mycat.server.packet.util.SecurityUtil;
import java.io.UnsupportedEncodingException;
import java.nio.channels.SocketChannel;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* MySQL Front connection
*
* @author wuzhih
*
*/
public class GenalMySQLConnection extends Connection {
public static final int maxPacketSize = 16 * 1024 * 1024;
protected final AtomicBoolean isQuit = new AtomicBoolean(false);
protected byte[] seed;
protected String user;
protected volatile String schema;
protected volatile int txIsolation;
protected volatile boolean autocommit;
protected volatile boolean txInterrupted;
protected volatile String txInterrputMsg = "";
protected long lastInsertId;
protected volatile String oldSchema;
protected long clientFlags;
protected String password;
protected boolean isAccepted;
protected boolean isAuthenticated;
protected volatile String charset;
protected volatile int charsetIndex;
protected HandshakePacket handshake;
protected boolean isSupportCompress = false;
public GenalMySQLConnection(SocketChannel channel) {
super(channel);
this.txInterrupted = false;
this.autocommit = true;
}
public int getTxIsolation() {
return txIsolation;
}
public void setTxIsolation(int txIsolation) {
this.txIsolation = txIsolation;
}
public boolean isAutocommit() {
return autocommit;
}
public boolean isAuthenticated() {
return isAuthenticated;
}
public boolean isSupportCompress() {
return isSupportCompress;
}
public void setSupportCompress(boolean isSupportCompress) {
this.isSupportCompress = isSupportCompress;
}
public void setAutocommit(boolean autocommit) {
this.autocommit = autocommit;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public long getLastInsertId() {
return lastInsertId;
}
public void setLastInsertId(long lastInsertId) {
this.lastInsertId = lastInsertId;
}
public void setAuthenticated(boolean isAuthenticated) {
this.isAuthenticated = isAuthenticated;
}
public void writeErrMessage(int errno, String msg) {
ErrorPacket err = new ErrorPacket();
err.packetId = 1;
err.errno = errno;
err.message = encodeString(msg, charset);
err.write(this);
}
public String getUser() {
return user;
}
public int getCharsetIndex() {
return charsetIndex;
}
public void setUser(String user) {
this.user = user;
}
public String getSchema() {
return schema;
}
public final static byte[] encodeString(String src, String charset) {
if (src == null) {
return null;
}
if (charset == null) {
return src.getBytes();
}
try {
return src.getBytes(charset);
} catch (UnsupportedEncodingException e) {
return src.getBytes();
}
}
public void setSchema(String newSchema) {
String curSchema = schema;
if (curSchema == null) {
this.schema = newSchema;
this.oldSchema = newSchema;
} else {
this.oldSchema = curSchema;
this.schema = newSchema;
}
}
public byte[] getSeed() {
return seed;
}
public boolean setCharsetIndex(int ci) {
String charset = CharsetUtil.getCharset(ci);
if (charset != null) {
return setCharset(charset);
} else {
return false;
}
}
public String getCharset() {
return charset;
}
public boolean setCharset(String charset) {
//修复PHP字符集设置错误, 如: set names 'utf8'
if ( charset != null ) {
charset = charset.replace("'", "");
}
int ci = CharsetUtil.getIndex(charset);
if (ci > 0) {
this.charset = charset.equalsIgnoreCase("utf8mb4") ? "utf8"
: charset;
this.charsetIndex = ci;
return true;
} else {
return false;
}
}
/**
* 设置是否需要中断当前事务
*/
public void setTxInterrupt(String txInterrputMsg) {
if (!autocommit && !txInterrupted) {
txInterrupted = true;
this.txInterrputMsg = txInterrputMsg;
}
}
public boolean isTxInterrupted() {
return txInterrupted;
}
public HandshakePacket getHandshake() {
return handshake;
}
public void setHandshake(HandshakePacket handshake) {
this.handshake = handshake;
}
private static byte[] passwd(String pass, HandshakePacket hs)
throws NoSuchAlgorithmException {
if (pass == null || pass.length() == 0) {
return null;
}
byte[] passwd = pass.getBytes();
int sl1 = hs.seed.length;
int sl2 = hs.restOfScrambleBuff.length;
byte[] seed = new byte[sl1 + sl2];
System.arraycopy(hs.seed, 0, seed, 0, sl1);
System.arraycopy(hs.restOfScrambleBuff, 0, seed, sl1, sl2);
return SecurityUtil.scramble411(passwd, seed);
}
public void authenticate() {
AuthPacket packet = new AuthPacket();
packet.packetId = 1;
packet.clientFlags = clientFlags;
packet.maxPacketSize = maxPacketSize;
packet.charsetIndex = this.charsetIndex;
packet.user = user;
try {
packet.password = passwd(password, handshake);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e.getMessage());
}
packet.database = schema;
BufferArray bufferArray = NetSystem.getInstance().getBufferPool()
.allocateArray();
packet.write(bufferArray);
// write to connection
this.write(bufferArray);
}
}