using System; using System.IO; using System.Text; namespace ByteFX.Data.MySqlClient { internal enum PacketType { None, UpdateOrOk, ResultSchema, Last, Auth, Error, LoadDataLocal, Other } /// /// Summary description for Packet. /// internal class Packet { MemoryStream data; PacketType type = PacketType.None; Encoding encoding; public Packet() { data = new MemoryStream(); } public Packet(int len) { data = new MemoryStream(len); } public Packet(byte[] bytes) { data = new MemoryStream( bytes.Length ); data.Write( bytes, 0, bytes.Length ); data.Position = 0; } public Encoding Encoding { set { encoding = value; } get { return encoding; } } public int Length { get { return (int)data.Length; } } public PacketType Type { get { if (type == PacketType.None) ParseType(); return type; } set { type = value; } } public long Position { get { return data.Position; } set { data.Position = value; } } public void AppendPacket( Packet newPacket ) { data.Position = data.Length; byte[] bytes = newPacket.GetBytes(); data.Write( bytes, 0, bytes.Length ); } private PacketType ParseType() { byte b = ReadByte(); // a 1 byte packet with byte 0xfe means last packet if ( data.Length == 1 && b == 0xfe) type = PacketType.Last; // a first byte of 0xff means the packet is an error message else if ( b == 0xff ) type = PacketType.Error; // the first byte == 0 means an update packet or column count else if ( b == 0 ) type = PacketType.UpdateOrOk; else type = PacketType.Other; return type; } public byte[] GetBytes() { return data.ToArray(); } public void WriteByte( byte b ) { data.WriteByte( b ); } public byte ReadByte() { return (byte)data.ReadByte(); } public void ReadBytes( byte[] buffer, int offset, int len ) { data.Read( buffer, offset, len ); } public void WriteBytes( byte[] bytes, int offset, int len ) { data.Write( bytes, offset, len ); } public int ReadNBytes() { byte c = (byte)ReadByte(); if (c < 1 || c > 4) throw new MySqlException("Unexpected byte count received"); return ReadInteger((int)c); } public string ReadLenString() { int len = ReadLenInteger(); byte[] buffer = new Byte[len]; ReadBytes(buffer, 0, len); return encoding.GetString( buffer, 0, len); } /// /// WriteInteger /// /// /// public void WriteInteger( int v, int numbytes ) { int val = v; if (numbytes < 1 || numbytes > 4) throw new ArgumentOutOfRangeException("Wrong byte count for WriteInteger"); for (int x=0; x < numbytes; x++) { data.WriteByte( (byte)(val&0xff) ); val >>= 8; } } /// /// /// /// /// public int ReadInteger(int numbytes) { int val = 0; int raise = 1; for (int x=0; x < numbytes; x++) { int b = data.ReadByte(); val += (b*raise); raise *= 256; } return val; } /// /// /// /// public int ReadLenInteger() { byte c = (byte)ReadByte(); switch(c) { case 251 : return -1; case 252 : return ReadInteger(2); case 253 : return ReadInteger(3); case 254 : return ReadInteger(4); default : return c; } } public bool CanRead { get { return data.Position < data.Length; } } #region String Functions public string ReadString() { System.Text.StringBuilder sb = new System.Text.StringBuilder(); while ( CanRead ) { byte b = ReadByte(); if (b == 0) break; sb.Append( Convert.ToChar( b )); } return sb.ToString(); } public void WriteString(string v, Encoding encoding) { WriteStringNoNull(v, encoding); data.WriteByte(0); } public void WriteStringNoNull(string v, Encoding encoding) { byte[] bytes = encoding.GetBytes(v); data.Write(bytes, 0, bytes.Length); } #endregion } }