diff --git a/layer4/connection.go b/layer4/connection.go index 8625bb9..f2f4f97 100644 --- a/layer4/connection.go +++ b/layer4/connection.go @@ -207,6 +207,8 @@ func (cx *Connection) GetVar(key string) interface{} { // MatchingBytes returns all bytes currently available for matching. This is only intended for reading. // Do not write into the slice. It's a view of the internal buffer and you will likely mess up the connection. +// Use of this for matching purpose should be accompanied by corresponding error value, +// ErrConsumedAllPrefetchedBytes and ErrMatchingBufferFull, if not matched. func (cx *Connection) MatchingBytes() []byte { return cx.buf[cx.offset:] } diff --git a/modules/l4http/httpmatcher.go b/modules/l4http/httpmatcher.go index c80fa7b..35d6b54 100644 --- a/modules/l4http/httpmatcher.go +++ b/modules/l4http/httpmatcher.go @@ -82,7 +82,14 @@ func (m MatchHTTP) Match(cx *layer4.Connection) (bool, error) { var err error data := cx.MatchingBytes() - if !m.isHttp(data) { + needMore, matched := m.isHttp(data) + if needMore { + if len(data) >= layer4.MaxMatchingBytes { + return false, layer4.ErrMatchingBufferFull + } + return false, layer4.ErrConsumedAllPrefetchedBytes + } + if !matched { return false, nil } @@ -122,11 +129,13 @@ func (m MatchHTTP) Match(cx *layer4.Connection) (bool, error) { return m.matcherSets.AnyMatch(req), nil } -func (m MatchHTTP) isHttp(data []byte) bool { +// isHttp test if the buffered data looks like HTTP by looking at the first line. +// first boolean determines if more data is required +func (m MatchHTTP) isHttp(data []byte) (bool, bool) { // try to find the end of a http request line, for example " HTTP/1.1\r\n" i := bytes.IndexByte(data, 0x0a) // find first new line if i < 10 { - return false + return true, false } // assume only \n line ending start := i - 9 // position of space in front of HTTP @@ -136,7 +145,7 @@ func (m MatchHTTP) isHttp(data []byte) bool { start -= 1 end -= 1 } - return bytes.Compare(data[start:end], []byte(" HTTP/")) == 0 + return false, bytes.Compare(data[start:end], []byte(" HTTP/")) == 0 } // Parses information from a http2 request with prior knowledge (RFC 7540 Section 3.4) diff --git a/modules/l4http/httpmatcher_test.go b/modules/l4http/httpmatcher_test.go index 632b78b..61b1205 100644 --- a/modules/l4http/httpmatcher_test.go +++ b/modules/l4http/httpmatcher_test.go @@ -313,7 +313,7 @@ func TestMatchHTTP_isHttp(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - matched := MatchHTTP{}.isHttp(tc.data) + _, matched := MatchHTTP{}.isHttp(tc.data) if matched != tc.shouldMatch { t.Fatalf("test %v | matched: %v != shouldMatch: %v", tc.name, matched, tc.shouldMatch) }