mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
99 lines
2.2 KiB
Go
99 lines
2.2 KiB
Go
|
// Read a generic "framed" packet consisting of a header and a
|
||
|
// This is used for both TLS Records and TLS Handshake Messages
|
||
|
package mint
|
||
|
|
||
|
type framing interface {
|
||
|
headerLen() int
|
||
|
defaultReadLen() int
|
||
|
frameLen(hdr []byte) (int, error)
|
||
|
}
|
||
|
|
||
|
const (
|
||
|
kFrameReaderHdr = 0
|
||
|
kFrameReaderBody = 1
|
||
|
)
|
||
|
|
||
|
type frameNextAction func(f *frameReader) error
|
||
|
|
||
|
type frameReader struct {
|
||
|
details framing
|
||
|
state uint8
|
||
|
header []byte
|
||
|
body []byte
|
||
|
working []byte
|
||
|
writeOffset int
|
||
|
remainder []byte
|
||
|
}
|
||
|
|
||
|
func newFrameReader(d framing) *frameReader {
|
||
|
hdr := make([]byte, d.headerLen())
|
||
|
return &frameReader{
|
||
|
d,
|
||
|
kFrameReaderHdr,
|
||
|
hdr,
|
||
|
nil,
|
||
|
hdr,
|
||
|
0,
|
||
|
nil,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func dup(a []byte) []byte {
|
||
|
r := make([]byte, len(a))
|
||
|
copy(r, a)
|
||
|
return r
|
||
|
}
|
||
|
|
||
|
func (f *frameReader) needed() int {
|
||
|
tmp := (len(f.working) - f.writeOffset) - len(f.remainder)
|
||
|
if tmp < 0 {
|
||
|
return 0
|
||
|
}
|
||
|
return tmp
|
||
|
}
|
||
|
|
||
|
func (f *frameReader) addChunk(in []byte) {
|
||
|
// Append to the buffer.
|
||
|
logf(logTypeFrameReader, "Appending %v", len(in))
|
||
|
f.remainder = append(f.remainder, in...)
|
||
|
}
|
||
|
|
||
|
func (f *frameReader) process() (hdr []byte, body []byte, err error) {
|
||
|
for f.needed() == 0 {
|
||
|
logf(logTypeFrameReader, "%v bytes needed for next block", len(f.working)-f.writeOffset)
|
||
|
// Fill out our working block
|
||
|
copied := copy(f.working[f.writeOffset:], f.remainder)
|
||
|
f.remainder = f.remainder[copied:]
|
||
|
f.writeOffset += copied
|
||
|
if f.writeOffset < len(f.working) {
|
||
|
logf(logTypeFrameReader, "Read would have blocked 1")
|
||
|
return nil, nil, WouldBlock
|
||
|
}
|
||
|
// Reset the write offset, because we are now full.
|
||
|
f.writeOffset = 0
|
||
|
|
||
|
// We have read a full frame
|
||
|
if f.state == kFrameReaderBody {
|
||
|
logf(logTypeFrameReader, "Returning frame hdr=%#x len=%d buffered=%d", f.header, len(f.body), len(f.remainder))
|
||
|
f.state = kFrameReaderHdr
|
||
|
f.working = f.header
|
||
|
return dup(f.header), dup(f.body), nil
|
||
|
}
|
||
|
|
||
|
// We have read the header
|
||
|
bodyLen, err := f.details.frameLen(f.header)
|
||
|
if err != nil {
|
||
|
return nil, nil, err
|
||
|
}
|
||
|
logf(logTypeFrameReader, "Processed header, body len = %v", bodyLen)
|
||
|
|
||
|
f.body = make([]byte, bodyLen)
|
||
|
f.working = f.body
|
||
|
f.writeOffset = 0
|
||
|
f.state = kFrameReaderBody
|
||
|
}
|
||
|
|
||
|
logf(logTypeFrameReader, "Read would have blocked 2")
|
||
|
return nil, nil, WouldBlock
|
||
|
}
|