📄 mysqlpacketbuffer.java
字号:
/*
* This program is free software; you can redistribute it and/or modify it under the terms of
* the GNU 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 General Public License for more details.
* You should have received a copy of the GNU 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.
*/
package com.meidusa.amoeba.mysql.net.packet;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.sql.SQLException;
import com.meidusa.amoeba.mysql.io.Constants;
import com.meidusa.amoeba.mysql.io.MySqlPacketConstant;
import com.meidusa.amoeba.mysql.util.MysqlStringUtil;
import com.meidusa.amoeba.mysql.util.SingleByteCharsetConverter;
import com.meidusa.amoeba.net.Connection;
import com.meidusa.amoeba.net.DatabaseConnection;
import com.meidusa.amoeba.net.packet.AbstractPacketBuffer;
import com.meidusa.amoeba.util.StringUtil;
/**
*
* 该类负责 发送、接收 socket 输入流,并且可以根据包头信息,构造出ByteBuffer
* @author <a href=mailto:piratebase@sina.com>Struct chen</a>
*/
public class MysqlPacketBuffer extends AbstractPacketBuffer{
static final int MAX_BYTES_TO_DUMP = 512;
static final int NO_LENGTH_LIMIT = -1;
static final long NULL_LENGTH = -1;
protected boolean wasMultiPacket = false;
/**
* buf 中含包头信息
* @param buf
*/
public MysqlPacketBuffer(byte[] buf) {
super(buf);
this.position = MySqlPacketConstant.HEADER_SIZE;
}
public void init(Connection conn){
super.init(conn);
}
public DatabaseConnection getConnection(){
return (DatabaseConnection)this.conn;
}
public int getPacketLength(){
if(buffer == null || buffer.length <4){
return 0;
}else{
int packetLength = (buffer[0] & 0xff) +
((buffer[1] & 0xff) << 8) +
((buffer[2] & 0xff) << 16);
return packetLength;
}
}
public static int getPacketLength(byte[] byteBuffer){
if(byteBuffer == null || byteBuffer.length <4){
return 0;
}else{
int packetLength = (byteBuffer[0] & 0xff) +
((byteBuffer[1] & 0xff) << 8) +
((byteBuffer[2] & 0xff) << 16);
return packetLength;
}
}
public MysqlPacketBuffer(int size) {
super(size);
this.position = MySqlPacketConstant.HEADER_SIZE;
}
final void clear() {
this.position = MySqlPacketConstant.HEADER_SIZE;
}
final void dump() {
dump(getBufLength());
}
final String dump(int numBytes) {
return StringUtil.dumpAsHex(getBytes(0,
numBytes > getBufLength() ? getBufLength() : numBytes),
numBytes > getBufLength() ? getBufLength() : numBytes);
}
final String dumpClampedBytes(int numBytes) {
int numBytesToDump = numBytes < MAX_BYTES_TO_DUMP ? numBytes
: MAX_BYTES_TO_DUMP;
String dumped = StringUtil.dumpAsHex(getBytes(0,
numBytesToDump > getBufLength() ? getBufLength()
: numBytesToDump),
numBytesToDump > getBufLength() ? getBufLength()
: numBytesToDump);
if (numBytesToDump < numBytes) {
return dumped + " ....(packet exceeds max. dump length)";
}
return dumped;
}
final void dumpHeader() {
for (int i = 0; i < MySqlPacketConstant.HEADER_SIZE; i++) {
String hexVal = Integer.toHexString(readByte(i) & 0xff);
if (hexVal.length() == 1) {
hexVal = "0" + hexVal; //$NON-NLS-1$
}
System.out.print(hexVal + " "); //$NON-NLS-1$
}
}
final void dumpNBytes(int start, int nBytes) {
StringBuffer asciiBuf = new StringBuffer();
for (int i = start; (i < (start + nBytes)) && (i < getBufLength()); i++) {
String hexVal = Integer.toHexString(readByte(i) & 0xff);
if (hexVal.length() == 1) {
hexVal = "0" + hexVal; //$NON-NLS-1$
}
System.out.print(hexVal + " "); //$NON-NLS-1$
if ((readByte(i) > 32) && (readByte(i) < 127)) {
asciiBuf.append((char) readByte(i));
} else {
asciiBuf.append("."); //$NON-NLS-1$
}
asciiBuf.append(" "); //$NON-NLS-1$
}
System.out.println(" " + asciiBuf.toString()); //$NON-NLS-1$
}
protected void ensureCapacity(int additionalData){
if ((this.position + additionalData) > getBufLength()) {
if ((this.position + additionalData) < this.buffer.length) {
// byteBuffer.length is != getBufLength() all of the time
// due to re-using of packets (we don't shrink them)
//
// If we can, don't re-alloc, just set buffer length
// to size of current buffer
setBufLength(this.buffer.length);
} else {
//
// Otherwise, re-size, and pad so we can avoid
// allocing again in the near future
//
int newLength = this.position + (int)(additionalData * 1.5) + 1;
while(newLength<this.position + additionalData +1){
newLength = (int) (newLength * 1.5);
}
byte[] newBytes = new byte[newLength];
System.arraycopy(this.buffer, 0, newBytes, 0,
this.buffer.length);
this.buffer = newBytes;
setBufLength(this.buffer.length);
}
}
}
/**
* Skip over a length-encoded string
*
* @return The position past the end of the string
*/
public int fastSkipLenString() {
long len = this.readFieldLength();
this.position += len;
return (int) len;
}
public void fastSkipLenByteArray() {
long len = this.readFieldLength();
if (len == NULL_LENGTH || len == 0) {
return;
}
this.position += len;
}
protected final byte[] getBufferSource() {
return this.buffer;
}
int getBufLength() {
return this.length;
}
/**
* Returns the array of bytes this Buffer is using to read from.
*
* @return byte array being read from
*/
public byte[] getByteBuffer() {
return this.buffer;
}
public final byte[] getBytes(int len) {
byte[] b = new byte[len];
System.arraycopy(this.buffer, this.position, b, 0, len);
this.position += len; // update cursor
return b;
}
public byte[] getBytes(int offset, int len) {
byte[] dest = new byte[len];
System.arraycopy(this.buffer, offset, dest, 0, len);
return dest;
}
int getCapacity() {
return this.buffer.length;
}
final boolean isLastDataPacket() {
return ((getBufLength() < 9) && ((this.buffer[4] & 0xff) == 254));
}
final long newReadLength() {
int sw = this.buffer[this.position++] & 0xff;
switch (sw) {
case 251:
return 0;
case 252:
return readInt();
case 253:
return readLongInt();
case 254: // changed for 64 bit lengths
return readLongLong();
default:
return sw;
}
}
final long readFieldLength() {
int sw = this.buffer[this.position++] & 0xff;
switch (sw) {
case 251:
return NULL_LENGTH;
case 252:
return readInt();
case 253:
return readLongInt();
case 254:
return readLongLong();
default:
return sw;
}
}
final int readInt() {
byte[] b = this.buffer; // a little bit optimization
return (b[this.position++] & 0xff) | ((b[this.position++] & 0xff) << 8);
}
final int readIntAsLong() {
byte[] b = this.buffer;
return (b[this.position++] & 0xff) | ((b[this.position++] & 0xff) << 8)
| ((b[this.position++] & 0xff) << 16)
| ((b[this.position++] & 0xff) << 24);
}
final byte[] readLenByteArray(int offset) {
long len = this.readFieldLength();
if (len == NULL_LENGTH) {
return null;
}
if (len == 0) {
return Constants.EMPTY_BYTE_ARRAY;
}
this.position += offset;
return getBytes((int) len);
}
final long readLength() {
int sw = this.buffer[this.position++] & 0xff;
switch (sw) {
case 251:
return 0;
case 252:
return readInt();
case 253:
return readLongInt();
case 254:
return readLong();
default:
return sw;
}
}
final long readLong() {
byte[] b = this.buffer;
return ((long) b[this.position++] & 0xff)
| (((long) b[this.position++] & 0xff) << 8)
| ((long) (b[this.position++] & 0xff) << 16)
| ((long) (b[this.position++] & 0xff) << 24);
}
final int readLongInt() {
byte[] b = this.buffer;
return (b[this.position++] & 0xff) | ((b[this.position++] & 0xff) << 8)
| ((b[this.position++] & 0xff) << 16);
}
final long readLongLong() {
byte[] b = this.buffer;
return (b[this.position++] & 0xff)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -