前言
该RPC反对 TCP KCP UNIX 所以咱们要对协定进行设计
https://github.com/dollarkill...
定义握手协定
握手逻辑:
- 建设链接 通过非对称加密 传输 aes 密钥给服务端 (携带token)
- 服务端 验证 token 并记录 aes 密钥 前面与客户端交互 都采纳对称加密
起始符 | keySize | tokenSize | errorSize | key | token | err | |
---|---|---|---|---|---|---|---|
0x09 | 4 | 4 | 4 | xxx | xxx | xxx | xxx |
type Handshake struct { Key []byte // aes 加密 KEY Token []byte // AUTH 校验应用 Error []byte // 谬误填充}
编码
func EncodeHandshake(key, token, err []byte) []byte { buf := make([]byte, 13+len(key)+len(token)+len(err)) buf[0] = LightHandshakeSt binary.LittleEndian.PutUint32(buf[1:5], uint32(len(key))) binary.LittleEndian.PutUint32(buf[5:9], uint32(len(token))) binary.LittleEndian.PutUint32(buf[9:13], uint32(len(err))) st := 13 endI := st + len(key) copy(buf[st:endI], key) st = endI endI = st + len(token) copy(buf[st:endI], token) st = endI endI = st + len(err) copy(buf[st:endI], err) return buf}
解码
func (h *Handshake) Handshake(r io.Reader) error { headerByte := make([]byte, 13) // 读取标记位 _, err := io.ReadFull(r, headerByte[:1]) if err != nil { return err } if headerByte[0] != LightHandshakeSt { return errors.New("NO Light Handshake") } // 读取剩下的 _, err = io.ReadFull(r, headerByte[1:]) if err != nil { return err } // 解析头 keySize := binary.LittleEndian.Uint32(headerByte[1:5]) tokenSize := binary.LittleEndian.Uint32(headerByte[5:9]) errorSize := binary.LittleEndian.Uint32(headerByte[9:13]) bodyData := make([]byte, keySize+tokenSize+errorSize) _, err = io.ReadFull(r, bodyData) if err != nil { return err } var st uint32 = 0 endIdx := keySize key := make([]byte, keySize) copy(key, bodyData[st:endIdx]) h.Key = key st = endIdx endIdx = st + tokenSize token := make([]byte, tokenSize) copy(token, bodyData[st:endIdx]) h.Token = token st = endIdx endIdx = st + errorSize errStr := make([]byte, errorSize) copy(errStr, bodyData[st:endIdx]) h.Error = errStr return nil}
定义传输协定
/** 协定设计 起始符 : 版本号 : crc32校验 : magicNumberSize: serverNameSize : serverMethodSize : metaDataSize : payloadSize: respType : compressorType : serializationType : magicNumber : serverName : serverMethod : metaData : payload 0x05 : 0x01 : 4 : 4 : 4 : 4 : 4 : 4 : 1 : 1 : 1 : xxx : xxx : xxx : xxx : xxx*/type Message struct { Header *Header MagicNumber string ServiceName string ServiceMethod string MetaData []byte Payload []byte}type Header struct { St byte Version byte Crc32 uint32 MagicNumberSize uint32 ServerNameSize uint32 ServerMethodSize uint32 MetaDataSize uint32 PayloadSize uint32 RespType byte CompressorType byte SerializationType byte}
编码
// EncodeMessage 根底编码func EncodeMessage(magicStr string, server, method, metaData []byte, respType, compressorType, serializationType byte, payload []byte) (magic string, data []byte, err error) { var magicNumber = []byte(magicStr) if magicStr == "" { magicNumber = []byte(xid.New().String()) } bufSize := HeadSize + len(server) + len(method) + len(metaData) + len(payload) + len(magicNumber) buf := make([]byte, bufSize) buf[0] = LightSt buf[1] = byte(V1) binary.LittleEndian.PutUint32(buf[6:10], uint32(len(magicNumber))) binary.LittleEndian.PutUint32(buf[10:14], uint32(len(server))) binary.LittleEndian.PutUint32(buf[14:18], uint32(len(method))) binary.LittleEndian.PutUint32(buf[18:22], uint32(len(metaData))) binary.LittleEndian.PutUint32(buf[22:26], uint32(len(payload))) buf[26] = respType buf[27] = compressorType buf[28] = serializationType st := HeadSize endI := st + len(magicNumber) copy(buf[st:endI], magicNumber) st = endI endI = st + len(server) copy(buf[st:endI], server) st = endI endI = st + len(method) copy(buf[st:endI], method) st = endI endI = st + len(metaData) copy(buf[st:endI], metaData) st = endI endI = st + len(payload) copy(buf[st:endI], payload) if Crc32 { u := crc32.ChecksumIEEE(buf[6:]) binary.LittleEndian.PutUint32(buf[2:6], u) } return string(magicNumber), buf, nil}
解码
func (m *Protocol) IODecode(r io.Reader) (*Message, error) { headerByte := make([]byte, HeadSize) // 读取标记位 _, err := io.ReadFull(r, headerByte[:1]) if err != nil { return nil, err } if headerByte[0] != LightSt { log.Println(headerByte) return nil, errors.New("NO Light") } // 读取剩下的 _, err = io.ReadFull(r, headerByte[1:]) if err != nil { return nil, err } // 解析 header header, err := DecodeHeader(headerByte) if err != nil { return nil, err } bodyLen := header.MagicNumberSize + header.ServerNameSize + header.ServerMethodSize + header.MetaDataSize + header.PayloadSize bodyData := make([]byte, bodyLen) _, err = io.ReadFull(r, bodyData) if err != nil { return nil, err } msg, err := DecodeMessageV2(bodyData, header, 0) if err != nil { return nil, err } return msg, nil}func DecodeHeader(data []byte) (*Header, error) { var header Header header.St = data[0] header.Version = data[1] header.Crc32 = binary.LittleEndian.Uint32(data[2:6]) if Crc32 { u := crc32.ChecksumIEEE(data[6:]) if header.Crc32 != u { return nil, errors.New("CRC Calibration") } } header.MagicNumberSize = binary.LittleEndian.Uint32(data[6:10]) header.ServerNameSize = binary.LittleEndian.Uint32(data[10:14]) header.ServerMethodSize = binary.LittleEndian.Uint32(data[14:18]) header.MetaDataSize = binary.LittleEndian.Uint32(data[18:22]) header.PayloadSize = binary.LittleEndian.Uint32(data[22:26]) header.RespType = data[26] header.CompressorType = data[27] header.SerializationType = data[28] return &header, nil}// DecodeMessage 残缺Decodefunc DecodeMessage(data []byte) (*Message, error) { header, err := DecodeHeader(data) if err != nil { return nil, err } return DecodeMessageV2(data, header, HeadSize)}func DecodeMessageV2(data []byte, header *Header, headSize uint32) (*Message, error) { var result Message result.Header = header var st uint32 = headSize endI := st + header.MagicNumberSize les := endI - st magicNumber := make([]byte, les) copy(magicNumber, data[st:endI]) result.MagicNumber = string(magicNumber) st = endI endI = st + header.ServerNameSize les = endI - st serverName := make([]byte, les) copy(serverName, data[st:endI]) result.ServiceName = string(serverName) st = endI endI = st + header.ServerMethodSize les = endI - st serverMethodSize := make([]byte, les) copy(serverMethodSize, data[st:endI]) result.ServiceMethod = string(serverMethodSize) st = endI endI = st + header.MetaDataSize les = endI - st metaDataSize := make([]byte, les) copy(metaDataSize, data[st:endI]) result.MetaData = metaDataSize st = endI endI = st + header.PayloadSize les = endI - st payloadSize := make([]byte, les) copy(payloadSize, data[st:endI]) result.Payload = payloadSize return &result, nil}