/* * * Copyright 2018 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package conn import ( "encoding/binary" "errors" "fmt" ) const ( // GcmTagSize is the GCM tag size is the difference in length between // plaintext and ciphertext. From crypto/cipher/gcm.go in Go crypto // library. GcmTagSize = 16 ) // ErrAuth occurs on authentication failure. var ErrAuth = errors.New("message authentication failed") // SliceForAppend takes a slice and a requested number of bytes. It returns a // slice with the contents of the given slice followed by that many bytes and a // second slice that aliases into it and contains only the extra bytes. If the // original slice has sufficient capacity then no allocation is performed. func SliceForAppend(in []byte, n int) (head, tail []byte) { if total := len(in) + n; cap(in) >= total { head = in[:total] } else { head = make([]byte, total) copy(head, in) } tail = head[len(in):] return head, tail } // ParseFramedMsg parse the provided buffer and returns a frame of the format // msgLength+msg and any remaining bytes in that buffer. func ParseFramedMsg(b []byte, maxLen uint32) ([]byte, []byte, error) { // If the size field is not complete, return the provided buffer as // remaining buffer. if len(b) < MsgLenFieldSize { return nil, b, nil } msgLenField := b[:MsgLenFieldSize] length := binary.LittleEndian.Uint32(msgLenField) if length > maxLen { return nil, nil, fmt.Errorf("received the frame length %d larger than the limit %d", length, maxLen) } if len(b) < int(length)+4 { // account for the first 4 msg length bytes. // Frame is not complete yet. return nil, b, nil } return b[:MsgLenFieldSize+length], b[MsgLenFieldSize+length:], nil }