app-init
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
package mysqlserver
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
const (
|
||||
ProtocolVersion = 10
|
||||
ServerVersion = "8.0.0-mysql-tunnel"
|
||||
AuthPluginNative = "mysql_native_password"
|
||||
AuthPluginSHA2 = "caching_sha2_password"
|
||||
|
||||
MaxPacketSize = 16 << 20
|
||||
)
|
||||
|
||||
const (
|
||||
ComQuit byte = 0x01
|
||||
ComInitDB byte = 0x02
|
||||
ComQuery byte = 0x03
|
||||
ComFieldList byte = 0x04
|
||||
ComPing byte = 0x0e
|
||||
ComStmtPrepare byte = 0x16
|
||||
ComStmtExecute byte = 0x17
|
||||
ComStmtClose byte = 0x19
|
||||
ComResetConnection byte = 0x1f
|
||||
)
|
||||
|
||||
const (
|
||||
clientLongPassword uint32 = 1
|
||||
clientFoundRows uint32 = 1 << 1
|
||||
clientLongFlag uint32 = 1 << 2
|
||||
clientConnectWithDB uint32 = 1 << 3
|
||||
clientProtocol41 uint32 = 1 << 9
|
||||
clientSSL uint32 = 1 << 11
|
||||
clientTransactions uint32 = 1 << 13
|
||||
clientSecureConnection uint32 = 1 << 15
|
||||
clientMultiStatements uint32 = 1 << 16
|
||||
clientMultiResults uint32 = 1 << 17
|
||||
clientPSMultiResults uint32 = 1 << 18
|
||||
clientPluginAuth uint32 = 1 << 19
|
||||
clientConnectAttrs uint32 = 1 << 20
|
||||
clientPluginAuthLenencClientData uint32 = 1 << 21
|
||||
clientSessionTrack uint32 = 1 << 23
|
||||
clientDeprecateEOF uint32 = 1 << 24
|
||||
)
|
||||
|
||||
const (
|
||||
serverStatusAutocommit uint16 = 0x0002
|
||||
)
|
||||
|
||||
const (
|
||||
charsetUTF8MB4 uint8 = 45
|
||||
charsetBinary uint8 = 63
|
||||
)
|
||||
|
||||
const (
|
||||
typeDecimal byte = 0
|
||||
typeTiny byte = 1
|
||||
typeShort byte = 2
|
||||
typeLong byte = 3
|
||||
typeFloat byte = 4
|
||||
typeDouble byte = 5
|
||||
typeNull byte = 6
|
||||
typeTimestamp byte = 7
|
||||
typeLongLong byte = 8
|
||||
typeInt24 byte = 9
|
||||
typeDate byte = 10
|
||||
typeTime byte = 11
|
||||
typeDatetime byte = 12
|
||||
typeYear byte = 13
|
||||
typeJSON byte = 245
|
||||
typeNewDecimal byte = 246
|
||||
typeTinyBlob byte = 249
|
||||
typeMediumBlob byte = 250
|
||||
typeLongBlob byte = 251
|
||||
typeBlob byte = 252
|
||||
typeVarString byte = 253
|
||||
typeString byte = 254
|
||||
)
|
||||
|
||||
const (
|
||||
flagNotNull uint16 = 1
|
||||
flagPriKey uint16 = 2
|
||||
flagUniqueKey uint16 = 4
|
||||
flagMultipleKey uint16 = 8
|
||||
flagBlob uint16 = 16
|
||||
flagUnsigned uint16 = 32
|
||||
flagZerofill uint16 = 64
|
||||
flagBinary uint16 = 128
|
||||
flagEnum uint16 = 256
|
||||
flagAutoIncrement uint16 = 512
|
||||
flagTimestamp uint16 = 1024
|
||||
flagSet uint16 = 2048
|
||||
)
|
||||
|
||||
const (
|
||||
errAccessDenied uint16 = 1045
|
||||
errUnknownCommand uint16 = 1047
|
||||
errNoDB uint16 = 1046
|
||||
errParseError uint16 = 1064
|
||||
errUnknown uint16 = 1105
|
||||
errNotSupported uint16 = 1235
|
||||
)
|
||||
|
||||
const (
|
||||
markerOK byte = 0x00
|
||||
markerEOF byte = 0xfe
|
||||
markerERR byte = 0xff
|
||||
markerNull byte = 0xfb
|
||||
)
|
||||
|
||||
var serverCapabilities = clientLongPassword | clientFoundRows | clientLongFlag |
|
||||
clientConnectWithDB | clientProtocol41 | clientTransactions | clientSecureConnection |
|
||||
clientMultiResults | clientPluginAuth | clientPluginAuthLenencClientData |
|
||||
clientConnectAttrs | clientDeprecateEOF | clientSessionTrack
|
||||
|
||||
func appendU24(dst []byte, n uint32) []byte {
|
||||
return append(dst, byte(n), byte(n>>8), byte(n>>16))
|
||||
}
|
||||
|
||||
func appendU32(dst []byte, n uint32) []byte {
|
||||
b := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(b, n)
|
||||
return append(dst, b...)
|
||||
}
|
||||
|
||||
func appendU16(dst []byte, n uint16) []byte {
|
||||
return append(dst, byte(n), byte(n>>8))
|
||||
}
|
||||
|
||||
func appendNUL(dst []byte, s string) []byte {
|
||||
dst = append(dst, s...)
|
||||
return append(dst, 0)
|
||||
}
|
||||
|
||||
func appendLenencInt(dst []byte, n uint64) []byte {
|
||||
switch {
|
||||
case n < 251:
|
||||
return append(dst, byte(n))
|
||||
case n < 1<<16:
|
||||
return append(dst, 0xfc, byte(n), byte(n>>8))
|
||||
case n < 1<<24:
|
||||
return append(dst, 0xfd, byte(n), byte(n>>8), byte(n>>16))
|
||||
default:
|
||||
b := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(b, n)
|
||||
return append(append(dst, 0xfe), b...)
|
||||
}
|
||||
}
|
||||
|
||||
func appendLenencString(dst []byte, s []byte) []byte {
|
||||
dst = appendLenencInt(dst, uint64(len(s)))
|
||||
return append(dst, s...)
|
||||
}
|
||||
|
||||
func readU24(b []byte) uint32 {
|
||||
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16
|
||||
}
|
||||
|
||||
func readLenencInt(b []byte, off int) (uint64, int, error) {
|
||||
if off >= len(b) {
|
||||
return 0, off, io.ErrUnexpectedEOF
|
||||
}
|
||||
switch b[off] {
|
||||
case 0xfb:
|
||||
return 0, off + 1, fmt.Errorf("NULL lenenc")
|
||||
case 0xfc:
|
||||
if off+3 > len(b) {
|
||||
return 0, off, io.ErrUnexpectedEOF
|
||||
}
|
||||
return uint64(b[off+1]) | uint64(b[off+2])<<8, off + 3, nil
|
||||
case 0xfd:
|
||||
if off+4 > len(b) {
|
||||
return 0, off, io.ErrUnexpectedEOF
|
||||
}
|
||||
return uint64(b[off+1]) | uint64(b[off+2])<<8 | uint64(b[off+3])<<16, off + 4, nil
|
||||
case 0xfe:
|
||||
if off+9 > len(b) {
|
||||
return 0, off, io.ErrUnexpectedEOF
|
||||
}
|
||||
return binary.LittleEndian.Uint64(b[off+1 : off+9]), off + 9, nil
|
||||
default:
|
||||
return uint64(b[off]), off + 1, nil
|
||||
}
|
||||
}
|
||||
|
||||
func readLenencString(b []byte, off int) ([]byte, int, error) {
|
||||
n, off, err := readLenencInt(b, off)
|
||||
if err != nil {
|
||||
return nil, off, err
|
||||
}
|
||||
end := off + int(n)
|
||||
if end > len(b) {
|
||||
return nil, off, io.ErrUnexpectedEOF
|
||||
}
|
||||
return b[off:end], end, nil
|
||||
}
|
||||
|
||||
func readNUL(b []byte, off int) (string, int, error) {
|
||||
for i := off; i < len(b); i++ {
|
||||
if b[i] == 0 {
|
||||
return string(b[off:i]), i + 1, nil
|
||||
}
|
||||
}
|
||||
return string(b[off:]), len(b), nil
|
||||
}
|
||||
|
||||
func sqlState(errno uint16) string {
|
||||
switch errno {
|
||||
case errAccessDenied:
|
||||
return "28000"
|
||||
case errParseError:
|
||||
return "42000"
|
||||
case errNoDB:
|
||||
return "3D000"
|
||||
case errUnknownCommand, errNotSupported:
|
||||
return "HY000"
|
||||
default:
|
||||
return "HY000"
|
||||
}
|
||||
}
|
||||
|
||||
func encodeOK(affected, lastInsertID uint64, status, warnings uint16) []byte {
|
||||
b := []byte{markerOK}
|
||||
b = appendLenencInt(b, affected)
|
||||
b = appendLenencInt(b, lastInsertID)
|
||||
b = appendU16(b, status)
|
||||
b = appendU16(b, warnings)
|
||||
return b
|
||||
}
|
||||
|
||||
func encodeERR(errno uint16, msg string) []byte {
|
||||
b := []byte{markerERR}
|
||||
b = appendU16(b, errno)
|
||||
b = append(b, '#')
|
||||
state := sqlState(errno)
|
||||
if len(state) != 5 {
|
||||
state = "HY000"
|
||||
}
|
||||
b = append(b, state...)
|
||||
b = append(b, msg...)
|
||||
return b
|
||||
}
|
||||
|
||||
func encodeEOF(warnings, status uint16) []byte {
|
||||
b := []byte{markerEOF}
|
||||
b = appendU16(b, warnings)
|
||||
b = appendU16(b, status)
|
||||
return b
|
||||
}
|
||||
|
||||
func isNumericType(t byte) bool {
|
||||
switch t {
|
||||
case typeDecimal, typeTiny, typeShort, typeLong, typeFloat, typeDouble,
|
||||
typeNull, typeLongLong, typeInt24, typeYear, typeNewDecimal, typeBit:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const typeBit byte = 16
|
||||
Reference in New Issue
Block a user