func (mc *mysqlConn) readHandshakePacket() (data []byte, plugin string, err error) {
	data, err = mc.readPacket()
	if err != nil {
		if err == ErrInvalidConn {
			return nil, "", driver.ErrBadConn
		}
		return
	}
	if data[0] == iERR {
		return nil, "", mc.handleErrorPacket(data)
	}
	if data[0] < minProtocolVersion {
		return nil, "", fmt.Errorf(
			"unsupported protocol version %d. Version %d or higher is required",
			data[0],
			minProtocolVersion,
		)
	}
	pos := 1 + bytes.IndexByte(data[1:], 0x00) + 1 + 4
	authData := data[pos : pos+8]
	pos += 8 + 1
	mc.flags = clientFlag(binary.LittleEndian.Uint16(data[pos : pos+2]))
	if mc.flags&clientProtocol41 == 0 {
		return nil, "", ErrOldProtocol
	}
	if mc.flags&clientSSL == 0 && mc.cfg.tls != nil {
		if mc.cfg.TLSConfig == "preferred" {
			mc.cfg.tls = nil
		} else {
			return nil, "", ErrNoTLS
		}
	}
	pos += 2
	if len(data) > pos {
		pos += 1 + 2 + 2 + 1 + 10
		authData = append(authData, data[pos:pos+12]...)
		pos += 13
		if end := bytes.IndexByte(data[pos:], 0x00); end != -1 {
			plugin = string(data[pos : pos+end])
		} else {
			plugin = string(data[pos:])
		}
		var b [20]byte
		copy(b[:], authData)
		return b[:], plugin, nil
	}
	var b [8]byte
	copy(b[:], authData)
	return b[:], plugin, nil
}
****************************************************************************
Initialization Process                            *
****************************************************************************
Handshake Initialization Packet
http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
package mysql
import (
	"bytes"
	"crypto/tls"
	"database/sql/driver"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"math"
	"time"
)
func (mc *mysqlConn) readPacket() ([]byte, error) {
	var prevData []byte
	for {
		data, err := mc.buf.readNext(4)
		if err != nil {
			if cerr := mc.canceled.Value(); cerr != nil {
				return nil, cerr
			}
			errLog.Print(err)
			mc.Close()
			return nil, ErrInvalidConn
		}
		pktLen := int(uint32(data[0]) | uint32(data[1])<<8 | uint32(data[2])<<16)
		if data[3] != mc.sequence {
			if data[3] > mc.sequence {
				return nil, ErrPktSyncMul
			}
			return nil, ErrPktSync
		}
		mc.sequence++
		if pktLen == 0 {
			if prevData == nil {
				errLog.Print(ErrMalformPkt)
				mc.Close()
				return nil, ErrInvalidConn
			}
			return prevData, nil
		}
		data, err = mc.buf.readNext(pktLen)
		if err != nil {
			if cerr := mc.canceled.Value(); cerr != nil {
				return nil, cerr
			}
			errLog.Print(err)
			mc.Close()
			return nil, ErrInvalidConn
		}
		if pktLen < maxPacketSize {
			if prevData == nil {
				return data, nil
			}
			return append(prevData, data...), nil
		}
		prevData = append(prevData, data...)
	}
}
func (mc *mysqlConn) writePacket(data []byte) error {
	pktLen := len(data) - 4
	if pktLen > mc.maxAllowedPacket {
		return ErrPktTooLarge
	}
	if mc.reset {
		mc.reset = false
		conn := mc.netConn
		if mc.rawConn != nil {
			conn = mc.rawConn
		}
		var err error
		if mc.cfg.ReadTimeout != 0 {
			err = conn.SetReadDeadline(time.Time{})
		}
		if err == nil && mc.cfg.CheckConnLiveness {
			err = connCheck(conn)
		}
		if err != nil {
			errLog.Print("closing bad idle connection: ", err)
			mc.Close()
			return driver.ErrBadConn
		}
	}
	for {
		var size int
		if pktLen >= maxPacketSize {
			data[0] = 0xff
			data[1] = 0xff
			data[2] = 0xff
			size = maxPacketSize
		} else {
			data[0] = byte(pktLen)
			data[1] = byte(pktLen >> 8)
			data[2] = byte(pktLen >> 16)
			size = pktLen
		}
		data[3] = mc.sequence
		if mc.writeTimeout > 0 {
			if err := mc.netConn.SetWriteDeadline(time.Now().Add(mc.writeTimeout)); err != nil {
				return err
			}
		}
		n, err := mc.netConn.Write(data[:4+size])
		if err == nil && n == 4+size {
			mc.sequence++
			if size != maxPacketSize {
				return nil
			}
			pktLen -= size
			data = data[size:]
			continue
		}
		if err == nil {  
			mc.cleanup()
			errLog.Print(ErrMalformPkt)
		} else {
			if cerr := mc.canceled.Value(); cerr != nil {
				return cerr
			}
			if n == 0 && pktLen == len(data)-4 {
				return errBadConnNoWrite
			}
			mc.cleanup()
			errLog.Print(err)
		}
		return ErrInvalidConn
	}
}