Feature(Go): Screen frame relay end-to-end with graceful client BYE (Phase 4)

This commit is contained in:
yuanyuanxiang
2026-05-18 01:00:56 +02:00
parent b1f229706c
commit f013512c06
10 changed files with 999 additions and 74 deletions

View File

@@ -20,6 +20,19 @@ type Parser struct {
codec *Codec
}
// findHTTPBodyOffset returns the byte offset of the HTTP body — i.e. one past
// the first `\r\n\r\n` separator. Returns -1 if the separator isn't present
// yet (caller should wait for more data). Matches the C++ UnMaskHttp scan in
// common/mask.h.
func findHTTPBodyOffset(data []byte) int {
for i := 0; i+4 <= len(data); i++ {
if data[i] == '\r' && data[i+1] == '\n' && data[i+2] == '\r' && data[i+3] == '\n' {
return i + 4
}
}
return -1
}
// NewParser creates a new parser
func NewParser() *Parser {
return &Parser{
@@ -38,6 +51,22 @@ func (p *Parser) Close() {
func (p *Parser) Parse(ctx *connection.Context) ([]byte, error) {
buf := ctx.InBuffer
// Strip optional HTTP-mask wrapper. The client may disguise each outbound
// chunk as a `POST /<random> HTTP/1.1\r\n...\r\n\r\n` envelope followed
// by the real binary body (see common/mask.h: HttpMask). Each chunk
// carries its own envelope so we strip every time we see the prefix.
if buf.Len() >= 5 {
head := buf.Peek(5)
if len(head) == 5 && head[0] == 'P' && head[1] == 'O' && head[2] == 'S' && head[3] == 'T' && head[4] == ' ' {
bodyOffset := findHTTPBodyOffset(buf.Bytes())
if bodyOffset < 0 {
// Headers not fully arrived yet — wait for more bytes.
return nil, ErrNeedMore
}
buf.Skip(bodyOffset)
}
}
// Need at least minimum bytes to determine protocol
if buf.Len() < MinComLen {
return nil, ErrNeedMore