/** * <pre> * This program is free software; you can redistribute it and/or modify it under the terms of * the GNU AFFERO GENERAL PUBLIC LICENSE as published by the Free Software Foundation; either version 3 of the License, * or (at your option) any later version. * * 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * </pre> */ package com.meidusa.amoeba.mysql.net.packet; import java.io.UnsupportedEncodingException; import com.meidusa.amoeba.net.packet.AbstractPacketBuffer; /** * From server to client during initial handshake. * * <pre> * Bytes Name * ----- ---- * 1 protocol_version * n (Null-Terminated String) server_version * 4 thread_id * 8 scramble_buff * 1 (filler) always 0x00 * 2 server_capabilities * 1 server_language * 2 server_status * 13 (filler) always 0x00 ... * 13 rest of scramble_buff (4.1) * * protocol_version: The server takes this from PROTOCOL_VERSION * in /include/mysql_version.h. Example value = 10. * * server_version: The server takes this from MYSQL_SERVER_VERSION * in /include/mysql_version.h. Example value = "4.1.1-alpha". * * thread_number: ID of the server thread for this connection. * * scramble_buff: The password mechanism uses this. The second part are the * last 13 bytes. * (See "Password functions" section elsewhere in this document.) * * server_capabilities: CLIENT_XXX options. The possible flag values at time of * writing (taken from include/mysql_com.h): * CLIENT_LONG_PASSWORD 1 // new more secure passwords * CLIENT_FOUND_ROWS 2 // Found instead of affected rows * CLIENT_LONG_FLAG 4 // Get all column flags * CLIENT_CONNECT_WITH_DB 8 // One can specify db on connect * CLIENT_NO_SCHEMA 16 // Don't allow database.table.column * CLIENT_COMPRESS 32 // Can use compression protocol * CLIENT_ODBC 64 // Odbc client * CLIENT_LOCAL_FILES 128 // Can use LOAD DATA LOCAL * CLIENT_IGNORE_SPACE 256 // Ignore spaces before '(' * CLIENT_PROTOCOL_41 512 // New 4.1 protocol * CLIENT_INTERACTIVE 1024 // This is an interactive client * CLIENT_SSL 2048 // Switch to SSL after handshake * CLIENT_IGNORE_SIGPIPE 4096 // IGNORE sigpipes * CLIENT_TRANSACTIONS 8192 // Client knows about transactions * CLIENT_RESERVED 16384 // Old flag for 4.1 protocol * CLIENT_SECURE_CONNECTION 32768 // New 4.1 authentication * CLIENT_MULTI_STATEMENTS 65536 // Enable/disable multi-stmt support * CLIENT_MULTI_RESULTS 131072 // Enable/disable multi-results * * server_language: current server character set number * * server_status: SERVER_STATUS_xxx flags: e.g. SERVER_STATUS_AUTOCOMMIT * @see http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#Handshake_Initialization_Packet * </pre> * * @author <a href=mailto:piratebase@sina.com>Struct chen</a> */ public class HandshakePacket extends AbstractPacket { public byte protocolVersion; /** n个字节 */ public String serverVersion; public long threadId; /** 8个字节 */ public String seed; public int serverCapabilities; public byte serverCharsetIndex; public int serverStatus; /** 13个字节 */ public String restOfScrambleBuff; @Override public void init(AbstractPacketBuffer myBuffer) { super.init(myBuffer); MysqlPacketBuffer buffer = (MysqlPacketBuffer) myBuffer; this.protocolVersion = buffer.readByte(); this.serverVersion = buffer.readString(); threadId = buffer.readLong(); this.seed = buffer.readString(); this.serverCapabilities = 0; if (buffer.getPosition() < buffer.getBufLength()) { this.serverCapabilities = buffer.readInt(); } /* New protocol with 16 bytes to describe server characteristics */ this.serverCharsetIndex = buffer.readByte(); this.serverStatus = buffer.readInt(); buffer.setPosition(buffer.getPosition() + 13); restOfScrambleBuff = buffer.readString(); } @Override public void write2Buffer(AbstractPacketBuffer mysqlpacketBuffer) throws UnsupportedEncodingException { super.write2Buffer(mysqlpacketBuffer); MysqlPacketBuffer buffer = (MysqlPacketBuffer) mysqlpacketBuffer; buffer.writeByte(protocolVersion); buffer.writeString(serverVersion, CODE_PAGE_1252); buffer.writeLong(threadId); buffer.writeString(seed); buffer.writeInt(serverCapabilities); buffer.writeByte(serverCharsetIndex); buffer.writeInt(serverStatus); buffer.writeBytesNoNull(new byte[13]); buffer.writeString(restOfScrambleBuff); } protected int calculatePacketSize() { int packLength = super.calculatePacketSize(); int serverVersionLength = (serverVersion != null) ? serverVersion.length() : 0; packLength += 1 + (serverVersionLength + 8 + 13) * 2 + 8 + 2 + 1 + 2; return packLength; } protected void showServerCapabilities() { if (logger.isDebugEnabled()) { StringBuilder builder = new StringBuilder(); builder.append("\n"); builder.append("==============================Server Flag===============================\n"); builder.append("CLIENT_LONG_PASSWORD:" + (serverCapabilities & CLIENT_LONG_PASSWORD) + "\n"); builder.append("CLIENT_FOUND_ROWS:" + (serverCapabilities & CLIENT_FOUND_ROWS) + "\n"); builder.append("CLIENT_LONG_FLAG:" + (serverCapabilities & CLIENT_LONG_FLAG) + "\n"); builder.append("CLIENT_CONNECT_WITH_DB:" + (serverCapabilities & CLIENT_CONNECT_WITH_DB) + "\n"); builder.append("CLIENT_NO_SCHEMA:" + (serverCapabilities & CLIENT_NO_SCHEMA) + "\n"); builder.append("CLIENT_COMPRESS:" + (serverCapabilities & CLIENT_COMPRESS) + "\n"); builder.append("CLIENT_ODBC:" + (serverCapabilities & CLIENT_ODBC) + "\n"); builder.append("CLIENT_LOCAL_FILES:" + (serverCapabilities & CLIENT_LOCAL_FILES) + "\n"); builder.append("CLIENT_IGNORE_SPACE:" + (serverCapabilities & CLIENT_IGNORE_SPACE) + "\n"); builder.append("CLIENT_PROTOCOL_41:" + (serverCapabilities & CLIENT_PROTOCOL_41) + "\n"); builder.append("CLIENT_INTERACTIVE:" + (serverCapabilities & CLIENT_INTERACTIVE) + "\n"); builder.append("CLIENT_SSL:" + (serverCapabilities & CLIENT_SSL) + "\n"); builder.append("CLIENT_IGNORE_SIGPIPE:" + (serverCapabilities & CLIENT_IGNORE_SIGPIPE) + "\n"); builder.append("CLIENT_TRANSACTIONS:" + (serverCapabilities & CLIENT_TRANSACTIONS) + "\n"); builder.append("CLIENT_RESERVED:" + (serverCapabilities & CLIENT_RESERVED) + "\n"); builder.append("CLIENT_SECURE_CONNECTION:" + (serverCapabilities & CLIENT_SECURE_CONNECTION) + "\n"); builder.append("CLIENT_MULTI_STATEMENTS:" + (serverCapabilities & CLIENT_MULTI_STATEMENTS) + "\n"); builder.append("CLIENT_MULTI_RESULTS:" + (serverCapabilities & CLIENT_MULTI_RESULTS) + "\n"); builder.append("==========================END Server Flag===============================\n"); logger.debug(builder.toString()); } } }