1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-09-14 07:58:16 -04:00
v2fly/external/github.com/lucas-clemente/quic-go/internal/wire/connection_close_frame.go
2019-01-17 15:33:18 +01:00

82 lines
2.3 KiB
Go

package wire
import (
"bytes"
"io"
"v2ray.com/core/external/github.com/lucas-clemente/quic-go/internal/protocol"
"v2ray.com/core/external/github.com/lucas-clemente/quic-go/internal/qerr"
"v2ray.com/core/external/github.com/lucas-clemente/quic-go/internal/utils"
)
// A ConnectionCloseFrame is a CONNECTION_CLOSE frame
type ConnectionCloseFrame struct {
IsApplicationError bool
ErrorCode qerr.ErrorCode
ReasonPhrase string
}
func parseConnectionCloseFrame(r *bytes.Reader, version protocol.VersionNumber) (*ConnectionCloseFrame, error) {
typeByte, err := r.ReadByte()
if err != nil {
return nil, err
}
f := &ConnectionCloseFrame{IsApplicationError: typeByte == 0x1d}
ec, err := utils.BigEndian.ReadUint16(r)
if err != nil {
return nil, err
}
f.ErrorCode = qerr.ErrorCode(ec)
// read the Frame Type, if this is not an application error
if !f.IsApplicationError {
if _, err := utils.ReadVarInt(r); err != nil {
return nil, err
}
}
var reasonPhraseLen uint64
reasonPhraseLen, err = utils.ReadVarInt(r)
if err != nil {
return nil, err
}
// shortcut to prevent the unnecessary allocation of dataLen bytes
// if the dataLen is larger than the remaining length of the packet
// reading the whole reason phrase would result in EOF when attempting to READ
if int(reasonPhraseLen) > r.Len() {
return nil, io.EOF
}
reasonPhrase := make([]byte, reasonPhraseLen)
if _, err := io.ReadFull(r, reasonPhrase); err != nil {
// this should never happen, since we already checked the reasonPhraseLen earlier
return nil, err
}
f.ReasonPhrase = string(reasonPhrase)
return f, nil
}
// Length of a written frame
func (f *ConnectionCloseFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
length := 1 + 2 + utils.VarIntLen(uint64(len(f.ReasonPhrase))) + protocol.ByteCount(len(f.ReasonPhrase))
if !f.IsApplicationError {
length++ // for the frame type
}
return length
}
func (f *ConnectionCloseFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
if f.IsApplicationError {
b.WriteByte(0x1d)
} else {
b.WriteByte(0x1c)
}
utils.BigEndian.WriteUint16(b, uint16(f.ErrorCode))
if !f.IsApplicationError {
utils.WriteVarInt(b, 0)
}
utils.WriteVarInt(b, uint64(len(f.ReasonPhrase)))
b.WriteString(f.ReasonPhrase)
return nil
}